blather 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. data/LICENSE +1 -1
  2. data/README.rdoc +41 -12
  3. data/examples/echo.rb +1 -1
  4. data/examples/execute.rb +0 -5
  5. data/examples/pubsub/cli.rb +64 -0
  6. data/examples/pubsub/ping_pong.rb +18 -0
  7. data/examples/rosterprint.rb +14 -0
  8. data/examples/xmpp4r/echo.rb +35 -0
  9. data/lib/blather.rb +35 -12
  10. data/lib/blather/client.rb +1 -1
  11. data/lib/blather/client/client.rb +19 -13
  12. data/lib/blather/client/dsl.rb +16 -0
  13. data/lib/blather/client/dsl/pubsub.rb +133 -0
  14. data/lib/blather/core_ext/active_support.rb +1 -117
  15. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +117 -0
  16. data/lib/blather/core_ext/nokogiri.rb +35 -0
  17. data/lib/blather/errors.rb +3 -20
  18. data/lib/blather/errors/sasl_error.rb +3 -1
  19. data/lib/blather/errors/stanza_error.rb +10 -17
  20. data/lib/blather/errors/stream_error.rb +11 -14
  21. data/lib/blather/jid.rb +1 -0
  22. data/lib/blather/roster.rb +9 -0
  23. data/lib/blather/roster_item.rb +6 -1
  24. data/lib/blather/stanza.rb +35 -18
  25. data/lib/blather/stanza/disco.rb +7 -1
  26. data/lib/blather/stanza/disco/disco_info.rb +45 -33
  27. data/lib/blather/stanza/disco/disco_items.rb +32 -21
  28. data/lib/blather/stanza/iq.rb +13 -8
  29. data/lib/blather/stanza/iq/query.rb +16 -8
  30. data/lib/blather/stanza/iq/roster.rb +33 -22
  31. data/lib/blather/stanza/message.rb +20 -31
  32. data/lib/blather/stanza/presence.rb +3 -5
  33. data/lib/blather/stanza/presence/status.rb +13 -21
  34. data/lib/blather/stanza/presence/subscription.rb +11 -16
  35. data/lib/blather/stanza/pubsub.rb +63 -0
  36. data/lib/blather/stanza/pubsub/affiliations.rb +50 -0
  37. data/lib/blather/stanza/pubsub/create.rb +43 -0
  38. data/lib/blather/stanza/pubsub/errors.rb +9 -0
  39. data/lib/blather/stanza/pubsub/event.rb +77 -0
  40. data/lib/blather/stanza/pubsub/items.rb +63 -0
  41. data/lib/blather/stanza/pubsub/publish.rb +58 -0
  42. data/lib/blather/stanza/pubsub/retract.rb +53 -0
  43. data/lib/blather/stanza/pubsub/subscribe.rb +42 -0
  44. data/lib/blather/stanza/pubsub/subscription.rb +66 -0
  45. data/lib/blather/stanza/pubsub/subscriptions.rb +55 -0
  46. data/lib/blather/stanza/pubsub/unsubscribe.rb +42 -0
  47. data/lib/blather/stanza/pubsub_owner.rb +41 -0
  48. data/lib/blather/stanza/pubsub_owner/delete.rb +34 -0
  49. data/lib/blather/stanza/pubsub_owner/purge.rb +34 -0
  50. data/lib/blather/stream.rb +76 -168
  51. data/lib/blather/stream/client.rb +1 -2
  52. data/lib/blather/stream/component.rb +9 -5
  53. data/lib/blather/stream/features.rb +53 -0
  54. data/lib/blather/stream/features/resource.rb +63 -0
  55. data/lib/blather/stream/{sasl.rb → features/sasl.rb} +53 -52
  56. data/lib/blather/stream/features/session.rb +44 -0
  57. data/lib/blather/stream/features/tls.rb +28 -0
  58. data/lib/blather/stream/parser.rb +70 -46
  59. data/lib/blather/xmpp_node.rb +113 -52
  60. data/spec/blather/client/client_spec.rb +44 -58
  61. data/spec/blather/client/dsl/pubsub_spec.rb +465 -0
  62. data/spec/blather/client/dsl_spec.rb +19 -6
  63. data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
  64. data/spec/blather/errors/sasl_error_spec.rb +8 -8
  65. data/spec/blather/errors/stanza_error_spec.rb +25 -33
  66. data/spec/blather/errors/stream_error_spec.rb +21 -16
  67. data/spec/blather/errors_spec.rb +4 -11
  68. data/spec/blather/jid_spec.rb +31 -30
  69. data/spec/blather/roster_item_spec.rb +34 -23
  70. data/spec/blather/roster_spec.rb +27 -12
  71. data/spec/blather/stanza/discos/disco_info_spec.rb +61 -42
  72. data/spec/blather/stanza/discos/disco_items_spec.rb +47 -35
  73. data/spec/blather/stanza/iq/query_spec.rb +34 -11
  74. data/spec/blather/stanza/iq/roster_spec.rb +47 -30
  75. data/spec/blather/stanza/iq_spec.rb +19 -14
  76. data/spec/blather/stanza/message_spec.rb +30 -17
  77. data/spec/blather/stanza/presence/status_spec.rb +43 -20
  78. data/spec/blather/stanza/presence/subscription_spec.rb +41 -21
  79. data/spec/blather/stanza/presence_spec.rb +34 -21
  80. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  81. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  82. data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
  83. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  84. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  85. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  86. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  87. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  88. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  89. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
  90. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  91. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  92. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  93. data/spec/blather/stanza/pubsub_spec.rb +62 -0
  94. data/spec/blather/stanza_spec.rb +53 -38
  95. data/spec/blather/stream/client_spec.rb +231 -88
  96. data/spec/blather/stream/component_spec.rb +14 -5
  97. data/spec/blather/stream/parser_spec.rb +145 -0
  98. data/spec/blather/xmpp_node_spec.rb +192 -96
  99. data/spec/fixtures/pubsub.rb +311 -0
  100. data/spec/spec_helper.rb +5 -4
  101. metadata +54 -18
  102. data/Rakefile +0 -139
  103. data/ext/extconf.rb +0 -65
  104. data/ext/push_parser.c +0 -209
  105. data/lib/blather/core_ext/libxml.rb +0 -28
  106. data/lib/blather/stream/resource.rb +0 -48
  107. data/lib/blather/stream/session.rb +0 -36
  108. data/lib/blather/stream/stream_handler.rb +0 -39
  109. data/lib/blather/stream/tls.rb +0 -33
  110. data/spec/blather/core_ext/libxml_spec.rb +0 -58
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  Blather
2
2
 
3
- Copyright (c) 2008 Jeff Smick
3
+ Copyright (c) 2009 Jeff Smick
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
@@ -1,11 +1,11 @@
1
1
  = Blather
2
2
 
3
- An evented XMPP library
3
+ XMPP DSL (and more) for Ruby written on EventMachine and Nokogiri.
4
4
 
5
5
  == Features
6
6
 
7
7
  * evented architecture
8
- * uses libxml
8
+ * uses Nokogiri
9
9
  * simplified starting point
10
10
 
11
11
  == Project Pages
@@ -18,11 +18,7 @@ GitHub Docs:: http://docs.github.com/sprsquish/blather
18
18
 
19
19
  RubyForge:: http://rubyforge.org/projects/squishtech
20
20
 
21
- RDocs:: http://squishtech.rubyforge.org/blather/
22
-
23
- == Author
24
-
25
- Jeff Smick <sprsquish@gmail.com>
21
+ RDocs:: http://squishtech.rubyforge.org/blather
26
22
 
27
23
  = Usage
28
24
 
@@ -32,7 +28,7 @@ Jeff Smick <sprsquish@gmail.com>
32
28
 
33
29
  == Example
34
30
 
35
- See the /examples directory for more advanced examples.
31
+ See the examples directory for more advanced examples.
36
32
 
37
33
  This will auto-accept any subscription requests and echo back any chat messages.
38
34
 
@@ -73,7 +69,7 @@ The different types of guards are:
73
69
  # Equivalent to stanza.chat?
74
70
  message :chat?
75
71
 
76
- # Hash with value (:body => 'exit')
72
+ # Hash with any value (:body => 'exit')
77
73
  # Calls the key on the stanza and checks for equality
78
74
  # Equivalent to stanza.body == 'exit'
79
75
  message :body => 'exit'
@@ -99,6 +95,12 @@ The different types of guards are:
99
95
  # Equivalent to stanza.body == 'foo' || stanza.body == 'baz'
100
96
  message [{:body => 'foo'}, {:body => 'baz'}]
101
97
 
98
+ # XPath
99
+ # Runs the xpath query on the stanza and checks for results
100
+ # This guard type cannot be combined with other guards
101
+ # Equivalent to !stanza.find('/iq/ns:pubsub', :ns => 'pubsub:namespace').empty?
102
+ iq '/iq/ns:pubsub', :ns => 'pubsub:namespace'
103
+
102
104
  == On the Command Line:
103
105
 
104
106
  Default usage is:
@@ -117,11 +119,38 @@ Command line options:
117
119
 
118
120
  = TODO
119
121
 
120
- * Add XPath guard that passes the result to the handler
121
122
  * Add Disco the the DSL
122
- * PubSub (XEP-0060: http://xmpp.org/extensions/xep-0060.html)
123
123
  * More examples (Re-write XMPP4R examples into Blather)
124
124
 
125
+ = Author
126
+
127
+ Jeff Smick <sprsquish@gmail.com>
128
+
129
+ = Contributors
130
+
131
+ Nolan Darilek <nolan@thewordnerd.info>
132
+
125
133
  = License
126
134
 
127
- Please see LICENSE
135
+ Blather
136
+
137
+ Copyright (c) 2009 Jeff Smick
138
+
139
+ Permission is hereby granted, free of charge, to any person obtaining
140
+ a copy of this software and associated documentation files (the
141
+ "Software"), to deal in the Software without restriction, including
142
+ without limitation the rights to use, copy, modify, merge, publish,
143
+ distribute, sublicense, and/or sell copies of the Software, and to
144
+ permit persons to whom the Software is furnished to do so, subject to
145
+ the following conditions:
146
+
147
+ The above copyright notice and this permission notice shall be
148
+ included in all copies or substantial portions of the Software.
149
+
150
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
151
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
152
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
153
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
154
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
155
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
156
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'blather/client'
4
-
4
+ Blather.logger.level = Logger::DEBUG
5
5
  when_ready { puts "Connected ! send messages to #{jid.stripped}." }
6
6
 
7
7
  subscription :request? do |s|
@@ -1,11 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'blather/client'
4
- require 'blather/client/pubsub'
5
-
6
- setup 'echo@jabber.local', 'echo'
7
-
8
- Blather::LOG.level = Logger::DEBUG
9
4
 
10
5
  message :chat?, :body => 'exit' do |m|
11
6
  say m.from, 'Exiting ...'
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'blather/client'
4
+
5
+ #ls
6
+ #cd
7
+ #cat
8
+ #Blather::LOG.level = Logger::DEBUG
9
+ module CliHandler
10
+ include EM::Protocols::LineText2
11
+
12
+ def ls(node)
13
+ pubsub.node(parse_dir(node)) do |result|
14
+ cur = node.split('/')
15
+ puts
16
+ puts result.items.map { |i| (i.node.split('/') - cur).join('/') }.join("\n")
17
+ start_line
18
+ end
19
+ end
20
+
21
+ def cd(node)
22
+ @node = parse_dir(node)
23
+ start_line
24
+ end
25
+
26
+ def cat(item)
27
+ end
28
+
29
+ def connect(who)
30
+ @who = who
31
+ puts "connected to '#{who}'"
32
+ end
33
+
34
+ def exit(_)
35
+ EM.stop
36
+ end
37
+
38
+ def initialize
39
+ $stdout.sync = true
40
+ @node = ''
41
+ @who = ''
42
+ start_line
43
+ end
44
+
45
+ def start_line
46
+ puts "\n/#{@node}> "
47
+ end
48
+
49
+ def receive_line(line)
50
+ return unless line =~ /(connect|exit|ls|cd|cat)\s?(.*)/i
51
+ __send__ $1, $2
52
+ end
53
+
54
+ def parse_dir(list)
55
+ return '' if list == '/'
56
+ cur = @node.split('/')
57
+ list.split('/').each { |dir| dir == '..' ? cur.pop : (cur << dir) }
58
+ cur * '/'
59
+ end
60
+ end
61
+
62
+ setup 'echo@jabber.local', 'echo'
63
+ pubsub_host 'pubsub.jabber.local'
64
+ when_ready { EM.open_keyboard CliHandler }
@@ -0,0 +1,18 @@
1
+ setup 'ping-pong@jabber.local', 'ping-pong'
2
+
3
+ pubsub.host = 'pubsub.jabber.local'
4
+
5
+ pubsub_event :node => 'ping' do |node|
6
+ pubsub.publish 'pong', node.payload
7
+ end
8
+
9
+ pubsub_event :node => 'pong' do |node|
10
+ x = node.payload.to_i
11
+ if x > 0
12
+ pubsub.publish 'ping', (x - 1)
13
+ else
14
+ shutdown
15
+ end
16
+ end
17
+
18
+ when_ready { pubsub.publish 'ping', 3 }
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Prints out each roster entry
4
+
5
+ require 'blather/client'
6
+
7
+ when_ready do
8
+ roster.grouped.each do |group, items|
9
+ puts "#{'*'*3} #{group || 'Ungrouped'} #{'*'*3}"
10
+ items.each { |item| puts "- #{item.name} (#{item.jid})" }
11
+ puts
12
+ end
13
+ shutdown
14
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This bot will reply to every message it receives. To end the game, send 'exit'
4
+
5
+ require 'xmpp4r/client'
6
+ include Jabber
7
+
8
+ # settings
9
+ if ARGV.length != 2
10
+ puts "Run with ./echo_thread.rb user@server/resource password"
11
+ exit 1
12
+ end
13
+ myJID = JID.new(ARGV[0])
14
+ myPassword = ARGV[1]
15
+ cl = Client.new(myJID)
16
+ cl.connect
17
+ cl.auth(myPassword)
18
+ cl.send(Presence.new)
19
+ puts "Connected ! send messages to #{myJID.strip.to_s}."
20
+ mainthread = Thread.current
21
+ cl.add_message_callback do |m|
22
+ if m.type != :error
23
+ m2 = Message.new(m.from, "You sent: #{m.body}")
24
+ m2.type = m.type
25
+ cl.send(m2)
26
+ if m.body == 'exit'
27
+ m2 = Message.new(m.from, "Exiting ...")
28
+ m2.type = m.type
29
+ cl.send(m2)
30
+ mainthread.wakeup
31
+ end
32
+ end
33
+ end
34
+ Thread.stop
35
+ cl.close
@@ -1,14 +1,13 @@
1
1
  # Require the necessary files
2
- require File.join(File.dirname(__FILE__), *%w[.. ext push_parser])
3
2
  %w[
4
3
  rubygems
5
4
  eventmachine
6
- xml/libxml
5
+ nokogiri
7
6
  digest/md5
8
7
  logger
9
8
 
10
9
  blather/core_ext/active_support
11
- blather/core_ext/libxml
10
+ blather/core_ext/nokogiri
12
11
 
13
12
  blather/errors
14
13
  blather/errors/sasl_error
@@ -31,20 +30,44 @@ require File.join(File.dirname(__FILE__), *%w[.. ext push_parser])
31
30
  blather/stanza/presence/status
32
31
  blather/stanza/presence/subscription
33
32
 
33
+ blather/stanza/pubsub
34
+ blather/stanza/pubsub/affiliations
35
+ blather/stanza/pubsub/create
36
+ blather/stanza/pubsub/event
37
+ blather/stanza/pubsub/items
38
+ blather/stanza/pubsub/publish
39
+ blather/stanza/pubsub/retract
40
+ blather/stanza/pubsub/subscribe
41
+ blather/stanza/pubsub/subscription
42
+ blather/stanza/pubsub/subscriptions
43
+ blather/stanza/pubsub/unsubscribe
44
+
45
+ blather/stanza/pubsub_owner
46
+ blather/stanza/pubsub_owner/delete
47
+ blather/stanza/pubsub_owner/purge
48
+
34
49
  blather/stream
35
50
  blather/stream/client
36
51
  blather/stream/component
37
- blather/stream/stream_handler
38
52
  blather/stream/parser
39
- blather/stream/resource
40
- blather/stream/sasl
41
- blather/stream/session
42
- blather/stream/tls
53
+ blather/stream/features
54
+ blather/stream/features/resource
55
+ blather/stream/features/sasl
56
+ blather/stream/features/session
57
+ blather/stream/features/tls
43
58
  ].each { |r| require r }
44
59
 
45
- XML.indent_tree_output = false
46
-
47
60
  module Blather
48
- LOG = Logger.new($stdout) unless const_defined?(:LOG)
49
- LOG.level = Logger::INFO
61
+ @@logger = nil
62
+ def self.logger
63
+ unless @@logger
64
+ self.logger = Logger.new($stdout)
65
+ self.logger.level = Logger::INFO
66
+ end
67
+ @@logger
68
+ end
69
+
70
+ def self.logger=(logger)
71
+ @@logger = logger
72
+ end
50
73
  end
@@ -60,7 +60,7 @@ at_exit do
60
60
  if options[:log]
61
61
  log = File.new(options[:log], 'a')
62
62
  log.sync = options[:debug]
63
- Blather::LOG.level = Logger::DEBUG if options[:debug]
63
+ Blather.logger.level = Logger::DEBUG if options[:debug]
64
64
  $stdout.reopen log
65
65
  $stderr.reopen $stdout
66
66
  end
@@ -40,7 +40,8 @@ module Blather #:nodoc:
40
40
  end
41
41
 
42
42
  def setup(jid, password, host = nil, port = nil)
43
- @setup = [JID.new(jid), password]
43
+ @jid = JID.new(jid)
44
+ @setup = [@jid, password]
44
45
  @setup << host if host
45
46
  @setup << port if port
46
47
  self
@@ -63,7 +64,6 @@ module Blather #:nodoc:
63
64
  end
64
65
 
65
66
  def write(stanza)
66
- stanza.from ||= jid if stanza.respond_to?(:from)
67
67
  @stream.send(stanza) if @stream
68
68
  end
69
69
 
@@ -73,11 +73,7 @@ module Blather #:nodoc:
73
73
  end
74
74
 
75
75
  def post_init
76
- case @stream
77
- when Stream::Component then ready!
78
- when Stream::Client then client_post_init
79
- else raise "Don't know #{@stream.class} stream type. How the hell did this happen!?"
80
- end
76
+ self.jid.node ? client_post_init : ready!
81
77
  end
82
78
 
83
79
  def close
@@ -93,7 +89,7 @@ module Blather #:nodoc:
93
89
  handler.call stanza
94
90
  else
95
91
  stanza.handler_heirarchy.each do |type|
96
- break if call_handler_for(type, stanza) && (stanza.is_a?(BlatherError) || stanza.type == :iq)
92
+ break if call_handler_for(type, stanza)# && (stanza.is_a?(BlatherError) || stanza.type == :iq)
97
93
  end
98
94
  end
99
95
  end
@@ -132,8 +128,15 @@ module Blather #:nodoc:
132
128
 
133
129
  def call_handler_for(type, stanza)
134
130
  if @handlers[type]
135
- @handlers[type].find { |guards, handler| handler.call(stanza) unless guarded?(guards, stanza) }
136
- true
131
+ @handlers[type].find do |guards, handler|
132
+ if guards.first.is_a?(String)
133
+ unless (result = stanza.find(*guards)).empty?
134
+ handler.call(stanza, result)
135
+ end
136
+ elsif !guarded?(guards, stanza)
137
+ handler.call(stanza)
138
+ end
139
+ end
137
140
  end
138
141
  end
139
142
 
@@ -171,9 +174,12 @@ module Blather #:nodoc:
171
174
  def check_guards(guards)
172
175
  guards.each do |guard|
173
176
  case guard
174
- when Array then guard.each { |g| check_guards([g]) }
175
- when Symbol, Proc, Hash then nil
176
- else raise "Bad guard: #{guard.inspect}"
177
+ when Array
178
+ guard.each { |g| check_guards([g]) }
179
+ when Symbol, Proc, Hash, String
180
+ nil
181
+ else
182
+ raise "Bad guard: #{guard.inspect}"
177
183
  end
178
184
  end
179
185
  end
@@ -2,11 +2,27 @@ require File.join(File.dirname(__FILE__), 'client')
2
2
 
3
3
  module Blather
4
4
  module DSL
5
+
6
+ autoload :PubSub, File.expand_path(File.join(File.dirname(__FILE__), *%w[dsl pubsub]))
7
+
5
8
  def client
6
9
  @client ||= Client.new
7
10
  end
8
11
  module_function :client
9
12
 
13
+ def pubsub
14
+ @pubsub ||= PubSub.new jid.domain
15
+ end
16
+
17
+ ##
18
+ # Push data to the stream
19
+ # This works such that it can be chained:
20
+ # self << stanza1 << stanza2 << "raw data"
21
+ def <<(stanza)
22
+ write stanza
23
+ self
24
+ end
25
+
10
26
  ##
11
27
  # Prepare server settings
12
28
  # setup [node@domain/resource], [password], [host], [port]
@@ -0,0 +1,133 @@
1
+ module Blather
2
+ module DSL
3
+
4
+ class PubSub
5
+ attr_accessor :host
6
+
7
+ def initialize(host)
8
+ @host = host
9
+ end
10
+
11
+ ##
12
+ # Retrieve Affiliations
13
+ # Yields a hash of affiliations in the form:
14
+ # {:aff_type => ['node1', 'node2']}
15
+ def affiliations(host = nil, &callback)
16
+ request Stanza::PubSub::Affiliations.new(:get, send_to(host)), :list, callback
17
+ end
18
+
19
+ ##
20
+ # Retrieve Subscriptions
21
+ # Yields a hash of subscriptions in the form:
22
+ # {:sub_type => [{:node => 'node1', :jid => 'j@d'}]}
23
+ def subscriptions(host = nil, &callback)
24
+ request Stanza::PubSub::Subscriptions.new(:get, send_to(host)), :list, callback
25
+ end
26
+
27
+ ##
28
+ # Discover Nodes
29
+ # Yields a list of DiscoItem::Item objects
30
+ # +path+ is the node's path. Default is '/'
31
+ def nodes(path = nil, host = nil, &callback)
32
+ path ||= '/'
33
+ stanza = Stanza::DiscoItems.new(:get, path)
34
+ stanza.to = send_to(host)
35
+ request stanza, :items, callback
36
+ end
37
+
38
+ ##
39
+ # Discover node information
40
+ # Yields a DiscoInfo node
41
+ # +path+ is the node's path
42
+ def node(path, host = nil, &callback)
43
+ stanza = Stanza::DiscoInfo.new(:get, path)
44
+ stanza.to = send_to(host)
45
+ request stanza, nil, callback
46
+ end
47
+
48
+ ##
49
+ # Retrieve items for a node
50
+ # +path+ is the node's path
51
+ # +list+ can be an array of items to retrieve
52
+ # +max+ can be the maximum number of items to return
53
+ def items(path, list = [], max = nil, host = nil, &callback)
54
+ request Stanza::PubSub::Items.request(send_to(host), path, list, max), :items, callback
55
+ end
56
+
57
+ ##
58
+ # Subscribe to a node
59
+ # Yields the resulting Subscription object
60
+ # +node+ is the node to subscribe to
61
+ # +jid+ is the jid that should be used. Defaults to the stripped current JID
62
+ def subscribe(node, jid = nil, host = nil)
63
+ jid ||= DSL.client.jid.stripped
64
+ request(Stanza::PubSub::Subscribe.new(:set, send_to(host), node, jid)) { |n| yield n if block_given? }
65
+ end
66
+
67
+ ##
68
+ # Unsubscribe from a node
69
+ # Yields the resulting Unsubscribe object
70
+ # +node+ is the node to subscribe to
71
+ # +jid+ is the jid that should be used. Defaults to the stripped current JID
72
+ def unsubscribe(node, jid = nil, host = nil)
73
+ jid ||= DSL.client.jid.stripped
74
+ request(Stanza::PubSub::Unsubscribe.new(:set, send_to(host), node, jid)) { |n| yield n if block_given? }
75
+ end
76
+
77
+ ##
78
+ # Publish an item to a node
79
+ # Yields the resulting Publish node
80
+ # +node+ is the node to publish to
81
+ # +payload+ is the payload to send (see Blather::Stanza::PubSub::Publish for details)
82
+ def publish(node, payload, host = nil)
83
+ request(Stanza::PubSub::Publish.new(send_to(host), node, :set, payload)) { |n| yield n if block_given? }
84
+ end
85
+
86
+ ##
87
+ # Delete items from a node
88
+ # Yields the resulting node
89
+ # +node+ is the node to retract items from
90
+ # +ids+ is a list of ids to retract. This can also be a single id
91
+ def retract(node, ids = [], host = nil)
92
+ request(Stanza::PubSub::Retract.new(send_to(host), node, :set, ids)) { |n| yield n if block_given? }
93
+ end
94
+
95
+ ##
96
+ # Create a node
97
+ # Yields the resulting node
98
+ # This does not (yet) handle configuration
99
+ # +node+ is the node to create
100
+ def create(node, host = nil)
101
+ request(Stanza::PubSub::Create.new(:set, send_to(host), node)) { |n| yield n if block_given? }
102
+ end
103
+
104
+ ##
105
+ # Purge all node items
106
+ # Yields the resulting node
107
+ # +node+ is the node to purge
108
+ def purge(node, host = nil)
109
+ request(Stanza::PubSubOwner::Purge.new(:set, send_to(host), node)) { |n| yield n if block_given? }
110
+ end
111
+
112
+ ##
113
+ # Delete a node
114
+ # Yields the resulting node
115
+ # +node+ is the node to delete
116
+ def delete(node, host = nil)
117
+ request(Stanza::PubSubOwner::Delete.new(:set, send_to(host), node)) { |n| yield n if block_given? }
118
+ end
119
+
120
+ private
121
+ def request(node, method = nil, callback = nil, &block)
122
+ block = lambda { |node| callback.call(method ? node.__send__(method) : node) } unless block_given?
123
+ DSL.client.write_with_handler(node, &block)
124
+ end
125
+
126
+ def send_to(host = nil)
127
+ raise 'You must provide a host' unless (host ||= @host)
128
+ host
129
+ end
130
+ end
131
+
132
+ end
133
+ end