blather 0.4.7 → 0.4.8

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 (59) hide show
  1. data/README.md +162 -0
  2. data/examples/{print_heirarchy.rb → print_hierarchy.rb} +5 -5
  3. data/examples/stream_only.rb +27 -0
  4. data/lib/blather.rb +4 -0
  5. data/lib/blather/client/client.rb +91 -73
  6. data/lib/blather/client/dsl.rb +156 -32
  7. data/lib/blather/client/dsl/pubsub.rb +86 -54
  8. data/lib/blather/core_ext/active_support.rb +9 -9
  9. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +2 -2
  10. data/lib/blather/core_ext/nokogiri.rb +12 -7
  11. data/lib/blather/errors.rb +25 -14
  12. data/lib/blather/errors/sasl_error.rb +21 -3
  13. data/lib/blather/errors/stanza_error.rb +37 -21
  14. data/lib/blather/errors/stream_error.rb +27 -17
  15. data/lib/blather/jid.rb +79 -24
  16. data/lib/blather/roster.rb +39 -21
  17. data/lib/blather/roster_item.rb +43 -21
  18. data/lib/blather/stanza.rb +88 -40
  19. data/lib/blather/stanza/disco.rb +12 -2
  20. data/lib/blather/stanza/disco/disco_info.rb +112 -20
  21. data/lib/blather/stanza/disco/disco_items.rb +81 -12
  22. data/lib/blather/stanza/iq.rb +94 -38
  23. data/lib/blather/stanza/iq/query.rb +16 -22
  24. data/lib/blather/stanza/iq/roster.rb +98 -20
  25. data/lib/blather/stanza/message.rb +266 -111
  26. data/lib/blather/stanza/presence.rb +118 -42
  27. data/lib/blather/stanza/presence/status.rb +140 -60
  28. data/lib/blather/stanza/presence/subscription.rb +44 -10
  29. data/lib/blather/stanza/pubsub.rb +70 -15
  30. data/lib/blather/stanza/pubsub/affiliations.rb +36 -7
  31. data/lib/blather/stanza/pubsub/create.rb +26 -4
  32. data/lib/blather/stanza/pubsub/errors.rb +13 -4
  33. data/lib/blather/stanza/pubsub/event.rb +56 -10
  34. data/lib/blather/stanza/pubsub/items.rb +46 -6
  35. data/lib/blather/stanza/pubsub/publish.rb +52 -7
  36. data/lib/blather/stanza/pubsub/retract.rb +45 -6
  37. data/lib/blather/stanza/pubsub/subscribe.rb +30 -4
  38. data/lib/blather/stanza/pubsub/subscription.rb +74 -6
  39. data/lib/blather/stanza/pubsub/subscriptions.rb +35 -9
  40. data/lib/blather/stanza/pubsub/unsubscribe.rb +30 -4
  41. data/lib/blather/stanza/pubsub_owner.rb +17 -7
  42. data/lib/blather/stanza/pubsub_owner/delete.rb +23 -5
  43. data/lib/blather/stanza/pubsub_owner/purge.rb +23 -5
  44. data/lib/blather/stream.rb +96 -29
  45. data/lib/blather/stream/parser.rb +6 -9
  46. data/lib/blather/xmpp_node.rb +101 -153
  47. data/spec/blather/client/client_spec.rb +1 -1
  48. data/spec/blather/errors_spec.rb +5 -5
  49. data/spec/blather/stanza/message_spec.rb +56 -0
  50. data/spec/blather/stanza/presence/status_spec.rb +1 -1
  51. data/spec/blather/stanza_spec.rb +3 -3
  52. data/spec/blather/xmpp_node_spec.rb +19 -74
  53. metadata +6 -10
  54. data/README.rdoc +0 -185
  55. data/examples/drb_client.rb +0 -5
  56. data/examples/ping.rb +0 -11
  57. data/examples/pong.rb +0 -6
  58. data/examples/pubsub/cli.rb +0 -64
  59. data/examples/pubsub/ping_pong.rb +0 -18
@@ -2,9 +2,22 @@ module Blather
2
2
  class Stanza
3
3
  class Presence
4
4
 
5
+ # # Subscription Stanza
6
+ #
7
+ # [RFC 3921 Section 8 - Integration of Roster Items and Presence Subscriptions](http://xmpp.org/rfcs/rfc3921.html#rfc.section.8)
8
+ #
9
+ # Blather handles subscription request/response through this class. It
10
+ # provides a set of helper methods to quickly transform the stanza into a
11
+ # response.
12
+ #
13
+ # @handler :subscription
5
14
  class Subscription < Presence
6
15
  register :subscription, :subscription
7
16
 
17
+ # Create a new Subscription stanza
18
+ #
19
+ # @param [Blather::JID, #to_s] to the JID to subscribe to
20
+ # @param [Symbol, nil] type the subscription type
8
21
  def self.new(to = nil, type = nil)
9
22
  node = super()
10
23
  node.to = to
@@ -12,50 +25,71 @@ class Presence
12
25
  node
13
26
  end
14
27
 
28
+ # @private
15
29
  def inherit(node)
16
30
  inherit_attrs node.attributes
17
31
  self
18
32
  end
19
33
 
34
+ # Set the to value on the stanza
35
+ #
36
+ # @param [Blather::JID, #to_s] to a JID to subscribe to
20
37
  def to=(to)
21
38
  super JID.new(to).stripped
22
39
  end
23
40
 
24
- ##
25
- # Create an approve stanza
41
+ # Transform the stanza into an approve stanza
42
+ # makes approving requests simple
43
+ #
44
+ # @example approve an incoming request
45
+ # subscription(:request?) { |s| write_to_stream s.approve! }
46
+ # @return [self]
26
47
  def approve!
27
48
  self.type = :subscribed
28
49
  reply_if_needed!
29
50
  end
30
51
 
31
- ##
32
- # Create a refuse stanza
52
+ # Transform the stanza into a refuse stanza
53
+ # makes refusing requests simple
54
+ #
55
+ # @example refuse an incoming request
56
+ # subscription(:request?) { |s| write_to_stream s.refuse! }
57
+ # @return [self]
33
58
  def refuse!
34
59
  self.type = :unsubscribed
35
60
  reply_if_needed!
36
61
  end
37
62
 
38
- ##
39
- # Create an unsubscribe stanza
63
+ # Transform the stanza into an unsubscribe stanza
64
+ # makes unsubscribing simple
65
+ #
66
+ # @return [self]
40
67
  def unsubscribe!
41
68
  self.type = :unsubscribe
42
69
  reply_if_needed!
43
70
  end
44
71
 
45
- ##
46
- # Create a cancel stanza
72
+ # Transform the stanza into a cancel stanza
73
+ # makes canceling simple
74
+ #
75
+ # @return [self]
47
76
  def cancel!
48
77
  self.type = :unsubscribed
49
78
  reply_if_needed!
50
79
  end
51
80
 
52
- ##
53
- # Create a request stanza
81
+ # Transform the stanza into a request stanza
82
+ # makes requests simple
83
+ #
84
+ # @return [self]
54
85
  def request!
55
86
  self.type = :subscribe
56
87
  reply_if_needed!
57
88
  end
58
89
 
90
+ # Check if the stanza is a request
91
+ #
92
+ # @return [true, false]
59
93
  def request?
60
94
  self.type == :subscribe
61
95
  end
@@ -1,19 +1,34 @@
1
1
  module Blather
2
2
  class Stanza
3
3
 
4
+ # # Pubsub Stanza
5
+ #
6
+ # [XEP-0060 - Publish-Subscribe](http://xmpp.org/extensions/xep-0060.html)
7
+ #
8
+ # The base class for all PubSub nodes. This provides helper methods common to
9
+ # all PubSub nodes.
10
+ #
11
+ # @handler :pubsub_node
4
12
  class PubSub < Iq
5
13
  register :pubsub_node, :pubsub, 'http://jabber.org/protocol/pubsub'
6
14
 
15
+ # @private
7
16
  def self.import(node)
8
17
  klass = nil
9
18
  if pubsub = node.document.find_first('//ns:pubsub', :ns => self.registered_ns)
10
- pubsub.children.each { |e| break if klass = class_from_registration(e.element_name, (e.namespace.href if e.namespace)) }
19
+ pubsub.children.detect do |e|
20
+ ns = e.namespace ? e.namespace.href : nil
21
+ klass = class_from_registration(e.element_name, ns)
22
+ end
11
23
  end
12
24
  (klass || self).new(node[:type]).inherit(node)
13
25
  end
14
26
 
15
- ##
16
- # Ensure the namespace is set to the query node
27
+ # Overwrites the parent constructor to ensure a pubsub node is present.
28
+ # Also allows the addition of a host attribute
29
+ #
30
+ # @param [<Blather::Stanza::Iq::VALID_TYPES>] type the IQ type
31
+ # @param [String, nil] host the host the node should be sent to
17
32
  def self.new(type = nil, host = nil)
18
33
  new_node = super type
19
34
  new_node.to = host
@@ -21,13 +36,18 @@ class Stanza
21
36
  new_node
22
37
  end
23
38
 
24
- ##
25
- # Kill the pubsub node before running inherit
39
+ # Overrides the parent to ensure the current pubsub node is destroyed before
40
+ # inheritting the new content
41
+ #
42
+ # @private
26
43
  def inherit(node)
27
44
  remove_children :pubsub
28
45
  super
29
46
  end
30
47
 
48
+ # Get or create the pubsub node on the stanza
49
+ #
50
+ # @return [Blather::XMPPNode]
31
51
  def pubsub
32
52
  p = find_first('ns:pubsub', :ns => self.class.registered_ns) ||
33
53
  find_first('pubsub', :ns => self.class.registered_ns)
@@ -38,9 +58,21 @@ class Stanza
38
58
  end
39
59
  p
40
60
  end
41
- end
61
+ end # PubSub
42
62
 
63
+ # # PubSubItem Fragment
64
+ #
65
+ # This fragment is found in many places throughout the pubsub spec
66
+ # This is a convenience class to attach methods to the node
43
67
  class PubSubItem < XMPPNode
68
+ ATOM_NS = 'http://www.w3.org/2005/Atom'.freeze
69
+
70
+ # Create a new PubSubItem
71
+ #
72
+ # @param [String, nil] id the id of the stanza
73
+ # @param [#to_s, nil] payload the payload to attach to this item.
74
+ # @param [XML::Document, nil] document the document the node should be
75
+ # attached to. This should be the document of the parent PubSub node.
44
76
  def self.new(id = nil, payload = nil, document = nil)
45
77
  new_node = super 'item', document
46
78
  new_node.id = id
@@ -48,27 +80,50 @@ class Stanza
48
80
  new_node
49
81
  end
50
82
 
51
- attribute_accessor :id
83
+ # Get the item's ID
84
+ #
85
+ # @return [String, nil]
86
+ def id
87
+ read_attr :id
88
+ end
52
89
 
53
- def payload=(payload = nil)
54
- self.entry.content = payload
90
+ # Set the item's ID
91
+ #
92
+ # @param [#to_s] id the new ID
93
+ def id=(id)
94
+ write_attr :id, id
55
95
  end
56
96
 
97
+ # Get the item's payload
98
+ #
99
+ # To get the XML representation use #entry
100
+ #
101
+ # @return [String, nil]
57
102
  def payload
58
103
  self.entry.content.empty? ? nil : content
59
104
  end
60
105
 
106
+ # Set the item's payload
107
+ #
108
+ # @param [String, nil] payload the payload
109
+ def payload=(payload)
110
+ self.entry.content = payload
111
+ end
112
+
113
+ # Get or create the entry node
114
+ #
115
+ # @return [Blather::XMPPNode]
61
116
  def entry
62
- e = find_first('ns:entry', :ns => 'http://www.w3.org/2005/Atom') ||
63
- find_first('entry', :ns => 'http://www.w3.org/2005/Atom')
117
+ e = find_first('ns:entry', :ns => ATOM_NS) ||
118
+ find_first('entry', :ns => ATOM_NS)
64
119
 
65
120
  unless e
66
121
  self << (e = XMPPNode.new('entry', self.document))
67
- e.namespace = 'http://www.w3.org/2005/Atom'
122
+ e.namespace = ATOM_NS
68
123
  end
69
124
  e
70
125
  end
71
- end
126
+ end # PubSubItem
72
127
 
73
- end #Stanza
74
- end #Blather
128
+ end # Stanza
129
+ end # Blather
@@ -2,39 +2,68 @@ module Blather
2
2
  class Stanza
3
3
  class PubSub
4
4
 
5
+ # # PubSub Affiliations Stanza
6
+ #
7
+ # [XEP-0060 Section 8.9 - Manage Affiliations](http://xmpp.org/extensions/xep-0060.html#owner-affiliations)
8
+ #
9
+ # @handler :pubsub_affiliations
5
10
  class Affiliations < PubSub
6
11
  register :pubsub_affiliations, :affiliations, self.registered_ns
7
12
 
8
13
  include Enumerable
9
14
  alias_method :find, :xpath
10
15
 
16
+ # Overrides the parent to ensure an affiliation node is created
17
+ # @private
11
18
  def self.new(type = nil, host = nil)
12
19
  new_node = super
13
20
  new_node.affiliations
14
21
  new_node
15
22
  end
16
23
 
17
- ##
18
24
  # Kill the affiliations node before running inherit
25
+ # @private
19
26
  def inherit(node)
20
27
  affiliations.remove
21
28
  super
22
29
  end
23
30
 
31
+ # Get or create the affiliations node
32
+ #
33
+ # @return [Blather::XMPPNode]
24
34
  def affiliations
25
- aff = pubsub.find_first('pubsub_ns:affiliations', :pubsub_ns => self.class.registered_ns)
26
- self.pubsub << (aff = XMPPNode.new('affiliations', self.document)) unless aff
35
+ aff = pubsub.find_first('ns:affiliations', :ns => self.class.registered_ns)
36
+ unless aff
37
+ self.pubsub << (aff = XMPPNode.new('affiliations', self.document))
38
+ end
27
39
  aff
28
40
  end
29
41
 
42
+ # Convenience method for iterating over the list
43
+ #
44
+ # @see #list for the format of the yielded input
30
45
  def each(&block)
31
46
  list.each &block
32
47
  end
33
48
 
49
+ # Get the number of affiliations
50
+ #
51
+ # @return [Fixnum]
34
52
  def size
35
53
  list.size
36
54
  end
37
55
 
56
+ # Get the hash of affilations as affiliation-type => [nodes]
57
+ #
58
+ # @example
59
+ #
60
+ # { :owner => ['node1', 'node2'],
61
+ # :publisher => ['node3'],
62
+ # :outcast => ['node4'],
63
+ # :member => ['node5'],
64
+ # :none => ['node6'] }
65
+ #
66
+ # @return [Hash<String => Array<String>>]
38
67
  def list
39
68
  items = affiliations.find('//ns:affiliation', :ns => self.class.registered_ns)
40
69
  items.inject({}) do |hash, item|
@@ -43,8 +72,8 @@ class PubSub
43
72
  hash
44
73
  end
45
74
  end
46
- end #Affiliations
75
+ end # Affiliations
47
76
 
48
- end #PubSub
49
- end #Stanza
50
- end #Blather
77
+ end # PubSub
78
+ end # Stanza
79
+ end # Blather
@@ -2,9 +2,19 @@ module Blather
2
2
  class Stanza
3
3
  class PubSub
4
4
 
5
+ # # PubSub Create Stanza
6
+ #
7
+ # [XEP-0060 Section 8.1 - Create a Node](http://xmpp.org/extensions/xep-0060.html#owner-create)
8
+ #
9
+ # @handler :pubsub_create
5
10
  class Create < PubSub
6
11
  register :pubsub_create, :create, self.registered_ns
7
12
 
13
+ # Create a new Create Stanza
14
+ #
15
+ # @param [<Blather::Stanza::Iq::VALID_TYPES>] type the node type
16
+ # @param [String, nil] host the host to send the request to
17
+ # @param [String, nil] node the name of the node to create
8
18
  def self.new(type = :set, host = nil, node = nil)
9
19
  new_node = super(type, host)
10
20
  new_node.create_node
@@ -13,14 +23,23 @@ class PubSub
13
23
  new_node
14
24
  end
15
25
 
26
+ # Get the name of the node to create
27
+ #
28
+ # @return [String, nil]
16
29
  def node
17
30
  create_node[:node]
18
31
  end
19
32
 
33
+ # Set the name of the node to create
34
+ #
35
+ # @param [String, nil] node
20
36
  def node=(node)
21
37
  create_node[:node] = node
22
38
  end
23
39
 
40
+ # Get or create the actual create node on the stanza
41
+ #
42
+ # @return [Balther::XMPPNode]
24
43
  def create_node
25
44
  unless create_node = pubsub.find_first('ns:create', :ns => self.class.registered_ns)
26
45
  self.pubsub << (create_node = XMPPNode.new('create', self.document))
@@ -29,6 +48,9 @@ class PubSub
29
48
  create_node
30
49
  end
31
50
 
51
+ # Get or create the actual configure node on the stanza
52
+ #
53
+ # @return [Blather::XMPPNode]
32
54
  def configure_node
33
55
  unless configure_node = pubsub.find_first('ns:configure', :ns => self.class.registered_ns)
34
56
  self.pubsub << (configure_node = XMPPNode.new('configure', self.document))
@@ -36,8 +58,8 @@ class PubSub
36
58
  end
37
59
  configure_node
38
60
  end
39
- end #Retract
61
+ end # Create
40
62
 
41
- end #PubSub
42
- end #Stanza
43
- end #Blather
63
+ end # PubSub
64
+ end # Stanza
65
+ end # Blather
@@ -1,9 +1,18 @@
1
1
  module Blather
2
2
  class Stanza
3
3
 
4
+ # # PusSub Error Stanza
5
+ #
6
+ # @private
4
7
  class PubSubErrors < PubSub
5
- attribute_accessor :node, :to_sym => false
6
- end
8
+ def node
9
+ read_attr :node
10
+ end
7
11
 
8
- end #Stanza
9
- end #Blather
12
+ def node=(node)
13
+ write_attr :node, node
14
+ end
15
+ end # PubSubErrors
16
+
17
+ end # Stanza
18
+ end # Blather
@@ -2,48 +2,83 @@ module Blather
2
2
  class Stanza
3
3
  class PubSub
4
4
 
5
+ # # PubSub Event Stanza
6
+ #
7
+ # [XEP-0060](http://xmpp.org/extensions/xep-0060.html)
8
+ #
9
+ # The PubSub Event stanza is used in many places. Please see the XEP for more
10
+ # information.
11
+ #
12
+ # @handler :pubsub_event
5
13
  class Event < Message
14
+ SHIM_NS = 'http://jabber.org/protocol/shim'.freeze
15
+
6
16
  register :pubsub_event, :event, 'http://jabber.org/protocol/pubsub#event'
7
17
 
8
- ##
9
- # Ensure the event_node is created
18
+ # Ensures the event_node is created
19
+ # @private
10
20
  def self.new(type = nil)
11
21
  node = super
12
22
  node.event_node
13
23
  node
14
24
  end
15
25
 
16
- ##
17
26
  # Kill the event_node node before running inherit
27
+ # @private
18
28
  def inherit(node)
19
29
  event_node.remove
20
30
  super
21
31
  end
22
32
 
33
+ # Get the name of the node
34
+ #
35
+ # @return [String, nil]
23
36
  def node
24
37
  !purge? ? items_node[:node] : purge_node[:node]
25
38
  end
26
39
 
40
+ # Get a list of retractions
41
+ #
42
+ # @return [Array<String>]
27
43
  def retractions
28
- items_node.find('//ns:retract', :ns => self.class.registered_ns).map { |i| i[:id] }
44
+ items_node.find('//ns:retract', :ns => self.class.registered_ns).map do |i|
45
+ i[:id]
46
+ end
29
47
  end
30
48
 
49
+ # Check if this is a retractions stanza
50
+ #
51
+ # @return [Boolean]
31
52
  def retractions?
32
53
  !retractions.empty?
33
54
  end
34
55
 
56
+ # Get the list of items attached to this event
57
+ #
58
+ # @return [Array<Blather::Stanza::PubSub::PubSubItem>]
35
59
  def items
36
- items_node.find('//ns:item', :ns => self.class.registered_ns).map { |i| PubSubItem.new(nil,nil,self.document).inherit i }
60
+ items_node.find('//ns:item', :ns => self.class.registered_ns).map do |i|
61
+ PubSubItem.new(nil,nil,self.document).inherit i
62
+ end
37
63
  end
38
64
 
65
+ # Check if this stanza has items
66
+ #
67
+ # @return [Boolean]
39
68
  def items?
40
69
  !items.empty?
41
70
  end
42
71
 
72
+ # Check if this is a purge stanza
73
+ #
74
+ # @return [XML::Node, nil]
43
75
  def purge?
44
76
  purge_node
45
77
  end
46
78
 
79
+ # Get or create the actual event node
80
+ #
81
+ # @return [Blather::XMPPNode]
47
82
  def event_node
48
83
  node = find_first('//ns:event', :ns => self.class.registered_ns)
49
84
  node = find_first('//event', self.class.registered_ns) unless node
@@ -54,6 +89,9 @@ class PubSub
54
89
  node
55
90
  end
56
91
 
92
+ # Get or create the actual items node
93
+ #
94
+ # @return [Blather::XMPPNode]
57
95
  def items_node
58
96
  node = find_first('ns:event/ns:items', :ns => self.class.registered_ns)
59
97
  unless node
@@ -63,15 +101,23 @@ class PubSub
63
101
  node
64
102
  end
65
103
 
104
+ # Get the actual purge node
105
+ #
106
+ # @return [Blather::XMPPNode]
66
107
  def purge_node
67
108
  event_node.find_first('//ns:purge', :ns => self.class.registered_ns)
68
109
  end
69
110
 
111
+ # Get the subscription IDs associated with this event
112
+ #
113
+ # @return [Array<String>]
70
114
  def subscription_ids
71
- find('//ns:header[@name="SubID"]', :ns => 'http://jabber.org/protocol/shim').map { |n| n.content }
115
+ find('//ns:header[@name="SubID"]', :ns => SHIM_NS).map do |n|
116
+ n.content
117
+ end
72
118
  end
73
- end
119
+ end # Event
74
120
 
75
- end #PubSub
76
- end #Stanza
77
- end #Blather
121
+ end # PubSub
122
+ end # Stanza
123
+ end # Blather