pkoch-switchboard 0.1.1a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/History.txt +3 -0
  2. data/README.markdown +73 -0
  3. data/Rakefile +30 -0
  4. data/bin/switchboard +34 -0
  5. data/examples/echo_bot.rb +7 -0
  6. data/lib/switchboard.rb +1 -0
  7. data/lib/switchboard/client.rb +105 -0
  8. data/lib/switchboard/colors.rb +10 -0
  9. data/lib/switchboard/commands.rb +12 -0
  10. data/lib/switchboard/commands/command.rb +85 -0
  11. data/lib/switchboard/commands/config.rb +1 -0
  12. data/lib/switchboard/commands/config/config.rb +20 -0
  13. data/lib/switchboard/commands/default.rb +41 -0
  14. data/lib/switchboard/commands/disco.rb +3 -0
  15. data/lib/switchboard/commands/disco/disco.rb +13 -0
  16. data/lib/switchboard/commands/disco/info.rb +39 -0
  17. data/lib/switchboard/commands/disco/items.rb +30 -0
  18. data/lib/switchboard/commands/grep.rb +23 -0
  19. data/lib/switchboard/commands/help.rb +1 -0
  20. data/lib/switchboard/commands/help/help.rb +15 -0
  21. data/lib/switchboard/commands/last.rb +1 -0
  22. data/lib/switchboard/commands/last/last.rb +34 -0
  23. data/lib/switchboard/commands/pep.rb +3 -0
  24. data/lib/switchboard/commands/pep/location.rb +97 -0
  25. data/lib/switchboard/commands/pep/pep.rb +7 -0
  26. data/lib/switchboard/commands/pep/tune.rb +85 -0
  27. data/lib/switchboard/commands/pubsub.rb +16 -0
  28. data/lib/switchboard/commands/pubsub/affiliations.rb +34 -0
  29. data/lib/switchboard/commands/pubsub/config.rb +42 -0
  30. data/lib/switchboard/commands/pubsub/create.rb +41 -0
  31. data/lib/switchboard/commands/pubsub/delete.rb +32 -0
  32. data/lib/switchboard/commands/pubsub/info.rb +48 -0
  33. data/lib/switchboard/commands/pubsub/items.rb +40 -0
  34. data/lib/switchboard/commands/pubsub/listen.rb +20 -0
  35. data/lib/switchboard/commands/pubsub/nodes.rb +37 -0
  36. data/lib/switchboard/commands/pubsub/options.rb +40 -0
  37. data/lib/switchboard/commands/pubsub/publish.rb +53 -0
  38. data/lib/switchboard/commands/pubsub/pubsub.rb +25 -0
  39. data/lib/switchboard/commands/pubsub/purge.rb +32 -0
  40. data/lib/switchboard/commands/pubsub/retract.rb +38 -0
  41. data/lib/switchboard/commands/pubsub/subscribe.rb +34 -0
  42. data/lib/switchboard/commands/pubsub/subscriptions.rb +35 -0
  43. data/lib/switchboard/commands/pubsub/unsubscribe.rb +30 -0
  44. data/lib/switchboard/commands/register.rb +40 -0
  45. data/lib/switchboard/commands/roster.rb +5 -0
  46. data/lib/switchboard/commands/roster/add.rb +27 -0
  47. data/lib/switchboard/commands/roster/list.rb +26 -0
  48. data/lib/switchboard/commands/roster/online.rb +28 -0
  49. data/lib/switchboard/commands/roster/remove.rb +25 -0
  50. data/lib/switchboard/commands/roster/roster.rb +7 -0
  51. data/lib/switchboard/commands/unregister.rb +21 -0
  52. data/lib/switchboard/component.rb +36 -0
  53. data/lib/switchboard/core.rb +307 -0
  54. data/lib/switchboard/ext/delegate.rb +21 -0
  55. data/lib/switchboard/ext/instance_exec.rb +18 -0
  56. data/lib/switchboard/helpers/oauth_pubsub.rb +44 -0
  57. data/lib/switchboard/helpers/pubsub.rb +28 -0
  58. data/lib/switchboard/jacks.rb +8 -0
  59. data/lib/switchboard/jacks/auto_accept.rb +16 -0
  60. data/lib/switchboard/jacks/debug.rb +17 -0
  61. data/lib/switchboard/jacks/echo.rb +7 -0
  62. data/lib/switchboard/jacks/notify.rb +15 -0
  63. data/lib/switchboard/jacks/oauth_pubsub.rb +23 -0
  64. data/lib/switchboard/jacks/pubsub.rb +21 -0
  65. data/lib/switchboard/jacks/roster_debug.rb +23 -0
  66. data/lib/switchboard/settings.rb +49 -0
  67. data/lib/switchboard/switchboard.rb +12 -0
  68. data/lib/switchboard/version.rb +3 -0
  69. data/switchboard.gemspec +16 -0
  70. metadata +147 -0
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.1.0 2009-07-08
2
+
3
+ * Initial RubyForge release (Seth)
data/README.markdown ADDED
@@ -0,0 +1,73 @@
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
+ ## Docs
7
+
8
+ * [switchboard : XMPP :: curl :
9
+ HTTP](http://mojodna.net/2009/07/16/switchboard-curl-for-xmpp.html) -
10
+ command-line usage
11
+ * [Switchboard as a
12
+ Framework](http://mojodna.net/2009/07/19/switchboard-as-a-framework.html)
13
+ * [Subscribing to Wordpress.com with
14
+ Switchboard](http://mojodna.net/2009/07/21/subscribing-to-wordpress-com-with-switchboard.html)
15
+
16
+ ## Mailing List
17
+
18
+ [Switchboard Google Group](http://groups.google.com/group/switchboard)
19
+
20
+ ## Getting Started
21
+
22
+ Install it:
23
+
24
+ $ sudo gem install switchboard
25
+
26
+ Install optional dependencies for additional functionality.
27
+
28
+ OAuth PubSub support:
29
+
30
+ $ sudo gem install oauth
31
+
32
+ User Location (XEP-0080) support via Fire Eagle:
33
+
34
+ $ sudo gem install mojodna-fire-hydrant -s http://gems.github.com
35
+
36
+ _Note: you will need to set up a PubSub subscription to your location via Fire
37
+ Eagle for this to work._
38
+
39
+ User Tune (XEP-0118) support via iTunes (on Mac OS X):
40
+
41
+ $ sudo gem install rb-appscript
42
+
43
+ Configure it:
44
+
45
+ $ switchboard config jid jid@example.com
46
+ $ switchboard config password pa55word
47
+
48
+ _Settings will be stored in `$HOME/.switchboardrc`_
49
+
50
+ Run it:
51
+
52
+ $ switchboard <command> <args>
53
+ $ switchboard roster list
54
+ $ switchboard roster add fireeagle.com
55
+ $ ...
56
+
57
+ Subscribe to a node using OAuth, overriding default settings:
58
+
59
+ $ switchboard --jid subscriber@example.com --password pa55word \
60
+ pubsub --oauth \
61
+ --oauth-consumer-key <consumer key> \
62
+ --oauth-consumer-secret <consumer secret> \
63
+ --oauth-token <token> \
64
+ --oauth-token-secret <token secret> \
65
+ --server fireeagle.com \
66
+ --node "/api/0.1/user/<token>" \
67
+ subscribe
68
+
69
+ Publish iTunes' current track using User Tune (XEP-0118):
70
+
71
+ $ switchboard --resource switchtunes pep tune
72
+
73
+ _You can do this using a JID that is already online._
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require File.join("lib", "switchboard", "version")
2
+
3
+ desc "Generate the gemspec"
4
+ task :gemspec do
5
+ gemspec =<<-EOF
6
+ # this file is automatically generated
7
+ Gem::Specification.new do |s|
8
+ s.name = "switchboard"
9
+ s.version = "#{Switchboard::VERSION * "."}"
10
+ s.summary = "XMPP toolkit."
11
+ s.description = "A toolkit for assembling XMPP clients and interacting with XMPP servers."
12
+ s.authors = ["Seth Fitzsimmons", "Paulo Köch"]
13
+ s.email = ["seth@mojodna.net", "paulo.koch@gmail.com"]
14
+
15
+ s.files = #{Dir.glob("**/*").select { |f| File.file?(f) }.inspect}
16
+ s.executables = ["switchboard"]
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency("xmpp4r", [">= 0.5"])
20
+ end
21
+ EOF
22
+
23
+ open("switchboard.gemspec", "w") do |f|
24
+ f << gemspec
25
+ end
26
+
27
+ puts "gemspec successfully created."
28
+ end
29
+
30
+ task :default => :gemspec
data/bin/switchboard ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby -rubygems
2
+ require 'switchboard'
3
+ require 'switchboard/commands'
4
+ require 'optparse'
5
+
6
+ ARGV.clone.options do |opts|
7
+ # opts.banner = "Usage: example.rb [options]"
8
+
9
+ command = Switchboard::Commands::Default
10
+ command.options(opts)
11
+
12
+ cmd = []
13
+ argv = []
14
+
15
+ # force optparse into being a command parser
16
+ opts.order! do |arg|
17
+ cmd << arg
18
+
19
+ if c = Switchboard::COMMANDS[cmd * "_"]
20
+ command = c
21
+ command.options(opts)
22
+ elsif c = Switchboard::COMMANDS["_" + cmd * "_"]
23
+ command = c
24
+ else
25
+ # unrecognized, unclaimed argument; keep as ARGV
26
+ argv << arg
27
+ end
28
+ end
29
+
30
+ # correct ARGV to match unrecognized, unclaimed arguments
31
+ ARGV.reject! { |v| !argv.include?(v) }
32
+
33
+ command
34
+ end.run!
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby -rubygems
2
+
3
+ require 'switchboard'
4
+
5
+ switchboard = Switchboard::Client.new
6
+ switchboard.plug!(AutoAcceptJack, EchoJack, NotifyJack)
7
+ switchboard.run!
@@ -0,0 +1 @@
1
+ require 'switchboard/switchboard'
@@ -0,0 +1,105 @@
1
+ module Switchboard
2
+ class Client < Core
3
+ attr_reader :client, :roster, :jid
4
+
5
+ def initialize(settings = Switchboard::Settings.new, spin = true)
6
+ super(settings, spin)
7
+
8
+ # create a new JID (one should always be provided, even if it's just the
9
+ # domain component)
10
+ @jid = Jabber::JID.new(settings["jid"])
11
+
12
+ # override the resource if one was provided
13
+ @jid.resource = settings["resource"] if settings["resource"]
14
+
15
+ # instantiate the client
16
+ @client = Jabber::Client.new(@jid)
17
+
18
+ on_stream_connected do
19
+ register_roster_callbacks
20
+
21
+ # tell others that we're online
22
+ presence
23
+
24
+ defer :roster_loaded do
25
+ # wait for the roster to load
26
+ roster.wait_for_roster
27
+
28
+ # roster has now been loaded
29
+ on(:roster_loaded)
30
+ end
31
+ end
32
+ end
33
+
34
+ hook \
35
+ :roster_presence, :roster_query, :roster_subscription,
36
+ :roster_subscription_request, :roster_loaded, :roster_update
37
+
38
+ protected
39
+
40
+ def auth!
41
+ if (jid.node.nil? || settings["anonymous"]) && client.supports_anonymous?
42
+ # no node (user) component in the JID, be anonymous
43
+
44
+ client.auth_anonymous
45
+ else
46
+ client.auth(settings["password"])
47
+ end
48
+ @roster = Jabber::Roster::Helper.new(client)
49
+ rescue Jabber::ClientAuthenticationFailure => e
50
+ puts "Could not authenticate as #{settings["jid"]}"
51
+ shutdown(false)
52
+ exit 1
53
+ end
54
+
55
+ def connect!
56
+ client.connect
57
+ auth!
58
+ end
59
+
60
+ def disconnect!
61
+ presence(:unavailable)
62
+ super
63
+ end
64
+
65
+ def presence(status = nil, to = nil)
66
+ presence = Jabber::Presence.new(nil, status)
67
+ presence.to = to
68
+ client.send(presence)
69
+ end
70
+
71
+ def register_roster_callbacks
72
+ # presence from someone on my roster
73
+ roster.add_presence_callback do |item, old_presence, new_presence|
74
+ on(:roster_presence, item, old_presence, new_presence)
75
+ end
76
+
77
+ # roster query completed (rarely used)
78
+ roster.add_query_callback do |query|
79
+ on(:roster_query, query)
80
+ end
81
+
82
+ # roster subscription
83
+ roster.add_subscription_callback do |item, presence|
84
+ # confirmation that we were able to subscribe to someone else
85
+ on(:roster_subscription, item, presence)
86
+ end
87
+
88
+ roster.add_subscription_request_callback do |item, presence|
89
+ # someone wants to subscribe to me!
90
+ on(:roster_subscription_request, item, presence)
91
+ end
92
+
93
+ # roster was updated (rarely used)
94
+ roster.add_update_callback do |old_item, new_item|
95
+ # roster has been updated; don't care
96
+ # puts "update: #{old_item.inspect}, #{new_item.inspect}"
97
+ on(:roster_update, old_item, new_item)
98
+ end
99
+ end
100
+
101
+ def stream
102
+ client
103
+ end
104
+ end
105
+ end
@@ -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,12 @@
1
+ require 'switchboard/commands/command'
2
+ require 'switchboard/commands/config'
3
+ require 'switchboard/commands/default'
4
+ require 'switchboard/commands/disco'
5
+ require 'switchboard/commands/grep'
6
+ require 'switchboard/commands/help'
7
+ require 'switchboard/commands/last'
8
+ require 'switchboard/commands/pep'
9
+ require 'switchboard/commands/pubsub'
10
+ require 'switchboard/commands/register'
11
+ require 'switchboard/commands/roster'
12
+ require 'switchboard/commands/unregister'
@@ -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 @@
1
+ require 'switchboard/commands/config/config'
@@ -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,41 @@
1
+ module Switchboard
2
+ module Commands
3
+ class Default < Switchboard::Command
4
+ unregister!
5
+
6
+ def self.options(opts)
7
+ super(opts)
8
+
9
+ opts.banner = "Usage: #{opts.program_name} [options] COMMAND [options] [args]"
10
+
11
+ opts.on("-a", "--anonymous", "Connect anonymously.") { OPTIONS["anonymous"] = true }
12
+ # opts.on("-d", "--daemon", "Make server run as a daemon.") { OPTIONS["detach"] = true }
13
+ opts.on("-j", "--jid=jid", String, "Specifies the JID to use.") { |v| OPTIONS["jid"] = v }
14
+ opts.on("-r", "--resource=resource", String, "Specifies the resource to use.") { |v| OPTIONS["resource"] = v }
15
+ opts.on("-p", "--password=password", String, "Specifies the password to use.") { |v| OPTIONS["password"] = v }
16
+ # opts.on("-p", "--pidfile=path", String,
17
+ # "Specifies a pidfile to use.") { |v| OPTIONS[:pidfile] = v }
18
+ # opts.on("-v", "--[no-]verbose", "Run verbosely") { |v| OPTIONS[:verbose] = v }
19
+
20
+ opts.separator ""
21
+
22
+ opts.on_tail("-h", "--help", "Show this help message.") { puts opts; exit }
23
+ opts.on_tail("--version", "Show version.") { puts "switchboard version #{Switchboard::VERSION * "."}"; exit }
24
+ end
25
+
26
+ def self.run!
27
+ puts self.options(OptionParser.new).help
28
+ puts
29
+ puts "Available commands:"
30
+ Switchboard.commands.each do |name, command|
31
+ puts " #{command.to_command.ljust(15)}#{command.description}"
32
+ command.options(OptionParser.new).summarize do |line|
33
+ puts " " * 16 + line
34
+ end
35
+ end
36
+ puts
37
+ puts "See '#{@options.program_name} help COMMAND' for more information on a specific command."
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ require 'switchboard/commands/disco/disco'
2
+ require 'switchboard/commands/disco/items'
3
+ require 'switchboard/commands/disco/info'