mojodna-switchboard 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/README.markdown +31 -0
  2. data/bin/switchboard +35 -0
  3. data/examples/election_results.rb +61 -0
  4. data/lib/switchboard/colors.rb +10 -0
  5. data/lib/switchboard/commands/command.rb +85 -0
  6. data/lib/switchboard/commands/config/config.rb +20 -0
  7. data/lib/switchboard/commands/config.rb +1 -0
  8. data/lib/switchboard/commands/default.rb +47 -0
  9. data/lib/switchboard/commands/help/help.rb +15 -0
  10. data/lib/switchboard/commands/help.rb +1 -0
  11. data/lib/switchboard/commands/pubsub/pubsub.rb +16 -0
  12. data/lib/switchboard/commands/pubsub/subscribe.rb +35 -0
  13. data/lib/switchboard/commands/pubsub/subscriptions.rb +32 -0
  14. data/lib/switchboard/commands/pubsub/unsubscribe.rb +31 -0
  15. data/lib/switchboard/commands/pubsub.rb +4 -0
  16. data/lib/switchboard/commands/roster/add.rb +26 -0
  17. data/lib/switchboard/commands/roster/list.rb +24 -0
  18. data/lib/switchboard/commands/roster/remove.rb +29 -0
  19. data/lib/switchboard/commands/roster/roster.rb +7 -0
  20. data/lib/switchboard/commands/roster.rb +4 -0
  21. data/lib/switchboard/commands.rb +6 -0
  22. data/lib/switchboard/core.rb +324 -0
  23. data/lib/switchboard/instance_exec.rb +16 -0
  24. data/lib/switchboard/jacks/auto_accept.rb +16 -0
  25. data/lib/switchboard/jacks/debug.rb +17 -0
  26. data/lib/switchboard/jacks/notify.rb +15 -0
  27. data/lib/switchboard/jacks/oauth_pubsub.rb +50 -0
  28. data/lib/switchboard/jacks/roster_debug.rb +23 -0
  29. data/lib/switchboard/jacks.rb +5 -0
  30. data/lib/switchboard/oauth/request_proxy/mock_request.rb +21 -0
  31. data/lib/switchboard/settings.rb +32 -0
  32. data/lib/switchboard/switchboard.rb +5 -0
  33. data/lib/switchboard/version.rb +3 -0
  34. data/lib/switchboard/xmpp4r/pubsub/helper/oauth_service_helper.rb +107 -0
  35. data/lib/switchboard.rb +1 -0
  36. data/switchboard.gemspec +14 -0
  37. metadata +113 -0
data/README.markdown ADDED
@@ -0,0 +1,31 @@
1
+ # Switchboard
2
+
3
+ Switchboard is both a toolkit for assembling XMPP clients as well as a set of
4
+ command-line tools for interacting with XMPP servers.
5
+
6
+ ## Getting Started
7
+
8
+ Install it:
9
+
10
+ $ gem install mojodna-switchboard -s http://gems.github.com
11
+
12
+ Configure it:
13
+
14
+ $ switchboard config jid jid@example.com
15
+ $ switchboard config password pa55word
16
+ $ switchboard config oauth.consumer_key asdf
17
+ $ switchboard config oauth.consumer_secret qwerty
18
+ $ switchboard config oauth.token asdf
19
+ $ switchboard config oauth.token_secret qwerty
20
+ $ switchboard config oauth.general_token asdf
21
+ $ switchboard config oauth.general_token_secret qwerty
22
+ $ switchboard config pubsub.server fireeagle.com
23
+
24
+ _Settings will be stored in `$HOME/.switchboardrc`_
25
+
26
+ Run it:
27
+
28
+ $ switchboard <command> <args>
29
+ $ switchboard roster list
30
+ $ switchboard roster add fireeagle.com
31
+ $ ...
data/bin/switchboard ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ require 'switchboard'
3
+ require 'optparse'
4
+
5
+ command = ARGV.clone.options do |opts|
6
+ # opts.banner = "Usage: example.rb [options]"
7
+
8
+ command = Switchboard::Commands::Default
9
+ command.options(opts)
10
+
11
+ cmd = []
12
+ argv = []
13
+
14
+ # force optparse into being a command parser
15
+ opts.order! do |arg|
16
+ cmd << arg
17
+
18
+ if c = Switchboard::COMMANDS[cmd * "_"]
19
+ command = c
20
+ command.options(opts)
21
+ elsif c = Switchboard::COMMANDS["_" + cmd * "_"]
22
+ command = c
23
+ else
24
+ # unrecognized, unclaimed argument; keep as ARGV
25
+ argv << arg
26
+ end
27
+ end
28
+
29
+ # correct ARGV to match unrecognized, unclaimed arguments
30
+ ARGV.reject! { |v| !argv.include?(v) }
31
+
32
+ command
33
+ end
34
+
35
+ command.run!
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fire_hydrant'
3
+ require 'rexml/document'
4
+ require 'open-uri'
5
+
6
+ hydrant = FireHydrant.new(YAML.load(File.read("fire_hydrant.yml"))) do
7
+ old_votes = load_results
8
+
9
+ while(!shutdown?) do
10
+ # load the results feed
11
+ votes = load_results
12
+ diff = nil
13
+
14
+ # loop through and compare it to the old results
15
+ votes.each do |state, cand|
16
+ cand.each do |c, val|
17
+ unless old_votes[state][c] == val
18
+ diff ||= "Electoral results changed"
19
+ diff << "\n#{state} - #{c}: #{old_votes[state][c].inspect} => #{val.inspect}"
20
+ end
21
+ end
22
+ end
23
+
24
+ if diff
25
+ puts diff
26
+ broadcast(diff)
27
+ end
28
+
29
+ # set this as old_votes
30
+ old_votes = votes
31
+
32
+ # wait 5 minutes
33
+ puts "-----"
34
+ sleep 300
35
+ end
36
+ end
37
+
38
+ hydrant.jack!(AutoAcceptJack, NotifyJack)
39
+
40
+ def hydrant.load_results(url = "http://d.yimg.com/b/data/us/news/xml/elections/2008a/pres.xml")
41
+ doc = REXML::Document.new(open(url))
42
+ nodes = doc.elements.collect("//state") { |node| [node.attributes["name"].downcase, node.elements.collect("cand") { |cand| [cand.attributes["name"].downcase, cand.attributes["PopPct"].to_f, cand.attributes["PopVote"].to_i] }] }
43
+
44
+ votes = {}
45
+ nodes.each do |state, results|
46
+ votes[state] = {}
47
+ results.each do |cand, pct, vote|
48
+ votes[state][cand] = [pct, vote]
49
+ end
50
+ end
51
+
52
+ votes
53
+ end
54
+
55
+ def hydrant.broadcast(msg)
56
+ roster.items.each do |jid, item|
57
+ client.send(Jabber::Message.new(jid, msg))
58
+ end
59
+ end
60
+
61
+ hydrant.run!
@@ -0,0 +1,10 @@
1
+ class String
2
+ def red; colorize(self, "\e[1m\e[31m"); end
3
+ def green; colorize(self, "\e[1m\e[32m"); end
4
+ def dark_green; colorize(self, "\e[32m"); end
5
+ def yellow; colorize(self, "\e[1m\e[33m"); end
6
+ def blue; colorize(self, "\e[1m\e[34m"); end
7
+ def dark_blue; colorize(self, "\e[34m"); end
8
+ def purple; colorize(self, "\e[1m\e[35m"); end
9
+ def colorize(text, color_code) "#{color_code}#{text}\e[0m" end
10
+ end
@@ -0,0 +1,85 @@
1
+ module Switchboard
2
+ COMMANDS = {}
3
+
4
+ def self.commands(command = nil)
5
+ if command
6
+ COMMANDS.select { |k,v| k =~ /^#{command.to_command_name("_")}_/ }
7
+ else
8
+ COMMANDS.reject { |k,v| k =~ /_/ }
9
+ end
10
+ end
11
+
12
+ def self.hide_command(command)
13
+ COMMANDS["_#{command.to_command_name("_")}"] = unregister_command(command)
14
+ end
15
+
16
+ def self.register_command(command)
17
+ COMMANDS[command.to_command_name("_")] = command
18
+ end
19
+
20
+ def self.unregister_command(command)
21
+ COMMANDS.delete(command.to_command_name("_"))
22
+ end
23
+
24
+
25
+ module Commands
26
+ end
27
+
28
+ class Command
29
+ def self.description(description = nil)
30
+ @description = description if description
31
+ @description
32
+ end
33
+
34
+ def self.help
35
+ "No help is available for this command (#{self.to_command_name})."
36
+ end
37
+
38
+ # TODO consider accepting a block in subclasses
39
+ def self.options(opts)
40
+ @options = opts
41
+ @options.banner = "Usage: #{opts.program_name} [options] #{self.to_command_name} [options] [args]"
42
+ @options
43
+ end
44
+
45
+ def self.run!
46
+ puts self.options(OptionParser.new).help
47
+ commands = Switchboard.commands(self)
48
+
49
+ if commands.any?
50
+ puts
51
+ puts "Available commands:"
52
+ commands.each do |name, command|
53
+ puts " #{command.to_command.ljust(15)}#{command.description}"
54
+ command.options(OptionParser.new).summarize do |line|
55
+ puts " " * 16 + line
56
+ end
57
+ end
58
+ puts
59
+ puts "See '#{@options.program_name} help COMMAND' for more information on a specific command."
60
+ end
61
+ end
62
+
63
+ def self.to_command
64
+ self.name.gsub("Switchboard::Commands::", "").split("::").last.downcase
65
+ end
66
+
67
+ def self.to_command_name(delimiter = " ")
68
+ self.name.gsub("Switchboard::Commands::", "").split("::").map { |c| c.downcase } * delimiter
69
+ end
70
+
71
+ private
72
+
73
+ def self.hide!
74
+ Switchboard.hide_command(self)
75
+ end
76
+
77
+ def self.inherited(klass)
78
+ Switchboard.register_command(klass) if klass.name =~ /^Switchboard::Commands/
79
+ end
80
+
81
+ def self.unregister!
82
+ Switchboard.unregister_command(self)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,20 @@
1
+ module Switchboard
2
+ module Commands
3
+ class Config < Switchboard::Command
4
+ description "Get and set global options"
5
+
6
+ def self.run!
7
+ settings = Switchboard::Settings.new
8
+ if ARGV.empty?
9
+ super
10
+ elsif ARGV.length == 1
11
+ puts settings.get(ARGV.shift)
12
+ elsif ARGV.length == 2
13
+ settings.set!(ARGV.shift, ARGV.shift)
14
+ else
15
+ puts "error: More than one value for the key #{ARGV.shift}: #{ARGV * " "}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1 @@
1
+ require 'switchboard/commands/config/config'
@@ -0,0 +1,47 @@
1
+ module Switchboard
2
+ class Command
3
+ OPTIONS = {}
4
+ DEFAULT_OPTIONS = {
5
+ # :detach => false,
6
+ "debug" => false,
7
+ "oauth" => false,
8
+ "resource" => "switchboard"
9
+ }
10
+ end
11
+ module Commands
12
+ class Default < Switchboard::Command
13
+ unregister!
14
+
15
+ def self.options(opts)
16
+ super(opts)
17
+
18
+ opts.banner = "Usage: #{opts.program_name} [options] COMMAND [options] [args]"
19
+
20
+ # opts.on("-d", "--daemon", "Make server run as a daemon.") { OPTIONS[:detach] = true }
21
+ # opts.on("-l", "--log=path", String, "Specifies a path to log script output.") { |v| OPTIONS[:log] = v }
22
+ # opts.on("-p", "--pidfile=path", String,
23
+ # "Specifies a pidfile to use.") { |v| OPTIONS[:pidfile] = v }
24
+ # opts.on("-v", "--[no-]verbose", "Run verbosely") { |v| OPTIONS[:verbose] = v }
25
+
26
+ opts.separator ""
27
+
28
+ opts.on_tail("-h", "--help", "Show this help message.") { puts opts; exit }
29
+ opts.on_tail("--version", "Show version") { puts "switchboard version #{Switchboard::VERSION * "."}"; exit }
30
+ end
31
+
32
+ def self.run!
33
+ puts self.options(OptionParser.new).help
34
+ puts
35
+ puts "Available commands:"
36
+ Switchboard.commands.each do |name, command|
37
+ puts " #{command.to_command.ljust(15)}#{command.description}"
38
+ command.options(OptionParser.new).summarize do |line|
39
+ puts " " * 16 + line
40
+ end
41
+ end
42
+ puts
43
+ puts "See '#{@options.program_name} help COMMAND' for more information on a specific command."
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ module Switchboard
2
+ module Commands
3
+ class Help < Switchboard::Command
4
+ hide!
5
+
6
+ def self.run!
7
+ if ARGV.any?
8
+ puts Switchboard::COMMANDS[ARGV * "_"].help
9
+ else
10
+ Switchboard::Commands::Default.run!
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1 @@
1
+ require 'switchboard/commands/help/help'
@@ -0,0 +1,16 @@
1
+ module Switchboard
2
+ module Commands
3
+ class PubSub < Switchboard::Command
4
+ description "Pubsub node manipulation"
5
+
6
+ def self.help
7
+ "These are the more extensive instructions for using the pubsub command."
8
+ end
9
+
10
+ def self.options(opts)
11
+ super(opts)
12
+ # opts.on("--oauth", "Sign requests using OAuth.") { OPTIONS[:oauth] = true }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,35 @@
1
+ module Switchboard
2
+ module Commands
3
+ class PubSub
4
+ class Subscribe < Switchboard::Command
5
+ description "Subscribe to a pubsub node"
6
+
7
+ def self.run!
8
+ # TODO override settings with values from the command line
9
+ switchboard = Switchboard::Core.new do
10
+ # this executes in the main loop, so it doesn't really matter that this runs in a different thread
11
+ defer :subscribed do
12
+ begin
13
+ pubsub.subscribe_to("/api/0.1/user/#{settings["oauth.token"]}", oauth_consumer, oauth_token)
14
+ rescue Jabber::ServerError => e
15
+ puts e
16
+ end
17
+ end
18
+
19
+ # define here or as hydrant.subscriptions_received
20
+ def subscribed(subscription)
21
+ if subscription.subscription == :subscribed
22
+ puts "Subscribe successful."
23
+ else
24
+ puts "Subscribe failed!".red
25
+ end
26
+ end
27
+ end
28
+
29
+ switchboard.plug!(OAuthPubSubJack)
30
+ switchboard.run!
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ module Switchboard
2
+ module Commands
3
+ class PubSub
4
+ class Subscriptions < Switchboard::Command
5
+ description "List pubsub subscriptions"
6
+
7
+ def self.run!
8
+ # TODO override settings with values from the command line
9
+ switchboard = Switchboard::Core.new do
10
+ # this executes in the main loop, so it doesn't really matter that this runs in a different thread
11
+ defer :subscriptions_received do
12
+ begin
13
+ pubsub.get_subscriptions_from_all_nodes(oauth_consumer, general_token)
14
+ rescue Jabber::ServerError => e
15
+ puts e
16
+ end
17
+ end
18
+
19
+ # define here or as hydrant.subscriptions_received
20
+ def subscriptions_received(subscriptions)
21
+ puts "Subscriptions:"
22
+ puts subscriptions.collect { |subscription| "#{subscription.jid} => #{subscription.node}" } * "\n"
23
+ end
24
+ end
25
+
26
+ switchboard.plug!(OAuthPubSubJack)
27
+ switchboard.run!
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ module Switchboard
2
+ module Commands
3
+ class PubSub
4
+ class Unsubscribe < Switchboard::Command
5
+ description "Unsubscribe from a pubsub node"
6
+
7
+ def self.run!
8
+ # TODO override settings with values from the command line
9
+ switchboard = Switchboard::Core.new do
10
+ # this executes in the main loop, so it doesn't really matter that this runs in a different thread
11
+ defer :unsubscribed do
12
+ begin
13
+ pubsub.unsubscribe_from("/api/0.1/user/#{settings["oauth.token"]}", oauth_consumer, oauth_token)
14
+ rescue Jabber::ServerError => e
15
+ puts e
16
+ end
17
+ end
18
+
19
+ # define here or as hydrant.subscriptions_received
20
+ def unsubscribed(successful)
21
+ puts "Unsubscribe was successful." if successful
22
+ end
23
+ end
24
+
25
+ switchboard.plug!(OAuthPubSubJack)
26
+ switchboard.run!
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,4 @@
1
+ require 'switchboard/commands/pubsub/pubsub'
2
+ require 'switchboard/commands/pubsub/subscribe'
3
+ require 'switchboard/commands/pubsub/subscriptions'
4
+ require 'switchboard/commands/pubsub/unsubscribe'
@@ -0,0 +1,26 @@
1
+ module Switchboard
2
+ module Commands
3
+ class Roster
4
+ class Add < Switchboard::Command
5
+ description "Add a JID to your roster"
6
+
7
+ def self.run!
8
+ # TODO override settings with values from the command line
9
+ switchboard = Switchboard::Core.new do
10
+ # add the server as a contact if it wasn't already added
11
+ ARGV.each do |jid|
12
+ if roster.find(jid).empty?
13
+ puts "Adding #{jid} to my roster..."
14
+ roster.add(jid, nil, true)
15
+ end
16
+ end
17
+ end
18
+
19
+ switchboard.plug!(AutoAcceptJack)
20
+
21
+ switchboard.run!
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ module Switchboard
2
+ module Commands
3
+ class Roster
4
+ class List < Switchboard::Command
5
+ description "List all roster items"
6
+
7
+ def self.run!
8
+ # TODO override settings with values from the command line
9
+ switchboard = Switchboard::Core.new do
10
+ if roster.items.any?
11
+ puts "#{settings["jid"]}'s roster:"
12
+ puts roster.items.keys.map { |jid| jid.to_s } * "\n"
13
+ else
14
+ puts "#{settings["jid"]}'s roster is empty."
15
+ end
16
+ end
17
+
18
+ switchboard.plug!(AutoAcceptJack)
19
+ switchboard.run!
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ module Switchboard
2
+ module Commands
3
+ class Roster
4
+ class Remove < Switchboard::Command
5
+ description "Remove a JID from your roster"
6
+
7
+ def self.options(opts)
8
+ super(opts)
9
+ # opts.on("-l", "--log=path", String, "Specifies a path to log script output.") { |v| OPTIONS[:log] = v }
10
+ end
11
+
12
+ def self.run!
13
+ # TODO override settings with values from the command line
14
+ switchboard = Switchboard::Core.new do
15
+ ARGV.each do |jid|
16
+ if (items = roster.find(jid)).any?
17
+ item = items.values.first
18
+ puts "Removing #{item.jid.to_s} from my roster..."
19
+ item.remove
20
+ end
21
+ end
22
+ end
23
+
24
+ switchboard.run!
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ module Switchboard
2
+ module Commands
3
+ class Roster < Switchboard::Command
4
+ description "Roster manipulation"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ require 'switchboard/commands/roster/roster'
2
+ require 'switchboard/commands/roster/add'
3
+ require 'switchboard/commands/roster/list'
4
+ require 'switchboard/commands/roster/remove'
@@ -0,0 +1,6 @@
1
+ require 'switchboard/commands/command'
2
+ require 'switchboard/commands/config'
3
+ require 'switchboard/commands/default'
4
+ require 'switchboard/commands/help'
5
+ require 'switchboard/commands/pubsub'
6
+ require 'switchboard/commands/roster'