blather 0.6.2 → 0.7.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 (78) hide show
  1. data/.rspec +3 -0
  2. data/.travis.yml +1 -8
  3. data/CHANGELOG.md +230 -0
  4. data/Guardfile +4 -4
  5. data/README.md +2 -8
  6. data/Rakefile +14 -27
  7. data/blather.gemspec +8 -18
  8. data/lib/blather.rb +1 -0
  9. data/lib/blather/client/client.rb +8 -0
  10. data/lib/blather/roster.rb +7 -0
  11. data/lib/blather/stanza/iq/roster.rb +1 -1
  12. data/lib/blather/stanza/message/muc_user.rb +2 -0
  13. data/lib/blather/stanza/muc/muc_user_base.rb +4 -3
  14. data/lib/blather/stanza/presence.rb +12 -14
  15. data/lib/blather/stanza/presence/c.rb +58 -62
  16. data/lib/blather/stanza/presence/muc.rb +14 -10
  17. data/lib/blather/stanza/presence/muc_user.rb +47 -36
  18. data/lib/blather/stanza/presence/status.rb +106 -101
  19. data/lib/blather/stanza/presence/subscription.rb +59 -60
  20. data/lib/blather/stream.rb +1 -3
  21. data/lib/blather/stream/features/resource.rb +0 -1
  22. data/lib/blather/version.rb +1 -2
  23. data/lib/blather/xmpp_node.rb +24 -3
  24. data/spec/blather/client/client_spec.rb +64 -64
  25. data/spec/blather/client/dsl/pubsub_spec.rb +127 -127
  26. data/spec/blather/client/dsl_spec.rb +11 -11
  27. data/spec/blather/errors/sasl_error_spec.rb +3 -3
  28. data/spec/blather/errors/stanza_error_spec.rb +26 -26
  29. data/spec/blather/errors/stream_error_spec.rb +22 -22
  30. data/spec/blather/errors_spec.rb +7 -7
  31. data/spec/blather/file_transfer_spec.rb +16 -18
  32. data/spec/blather/jid_spec.rb +29 -29
  33. data/spec/blather/roster_item_spec.rb +18 -18
  34. data/spec/blather/roster_spec.rb +18 -18
  35. data/spec/blather/stanza/discos/disco_info_spec.rb +56 -57
  36. data/spec/blather/stanza/discos/disco_items_spec.rb +33 -33
  37. data/spec/blather/stanza/iq/command_spec.rb +57 -57
  38. data/spec/blather/stanza/iq/ibb_spec.rb +27 -39
  39. data/spec/blather/stanza/iq/ping_spec.rb +13 -9
  40. data/spec/blather/stanza/iq/query_spec.rb +16 -16
  41. data/spec/blather/stanza/iq/roster_spec.rb +29 -30
  42. data/spec/blather/stanza/iq/s5b_spec.rb +10 -13
  43. data/spec/blather/stanza/iq/si_spec.rb +20 -23
  44. data/spec/blather/stanza/iq/vcard_spec.rb +22 -25
  45. data/spec/blather/stanza/iq_spec.rb +12 -12
  46. data/spec/blather/stanza/message/muc_user_spec.rb +36 -36
  47. data/spec/blather/stanza/message_spec.rb +56 -56
  48. data/spec/blather/stanza/presence/c_spec.rb +17 -7
  49. data/spec/blather/stanza/presence/muc_spec.rb +8 -8
  50. data/spec/blather/stanza/presence/muc_user_spec.rb +23 -23
  51. data/spec/blather/stanza/presence/status_spec.rb +42 -30
  52. data/spec/blather/stanza/presence/subscription_spec.rb +22 -23
  53. data/spec/blather/stanza/presence_spec.rb +72 -34
  54. data/spec/blather/stanza/pubsub/affiliations_spec.rb +12 -12
  55. data/spec/blather/stanza/pubsub/create_spec.rb +10 -10
  56. data/spec/blather/stanza/pubsub/event_spec.rb +31 -31
  57. data/spec/blather/stanza/pubsub/items_spec.rb +21 -21
  58. data/spec/blather/stanza/pubsub/publish_spec.rb +21 -21
  59. data/spec/blather/stanza/pubsub/retract_spec.rb +20 -20
  60. data/spec/blather/stanza/pubsub/subscribe_spec.rb +17 -17
  61. data/spec/blather/stanza/pubsub/subscription_spec.rb +28 -28
  62. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +11 -11
  63. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +22 -22
  64. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +9 -9
  65. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +9 -9
  66. data/spec/blather/stanza/pubsub_owner_spec.rb +6 -6
  67. data/spec/blather/stanza/pubsub_spec.rb +16 -16
  68. data/spec/blather/stanza/x_spec.rb +53 -53
  69. data/spec/blather/stanza_spec.rb +39 -39
  70. data/spec/blather/stream/client_spec.rb +133 -133
  71. data/spec/blather/stream/component_spec.rb +7 -7
  72. data/spec/blather/stream/parser_spec.rb +24 -24
  73. data/spec/blather/stream/ssl_spec.rb +7 -7
  74. data/spec/blather/xmpp_node_spec.rb +17 -7
  75. data/spec/blather_spec.rb +4 -4
  76. data/spec/spec_helper.rb +6 -54
  77. metadata +53 -68
  78. data/CHANGELOG +0 -220
@@ -85,27 +85,25 @@ class Stanza
85
85
  # either a Status or Subscription object is created based
86
86
  # on the type attribute.
87
87
  # If neither is found it instantiates a Presence object
88
- def self.import(node) # :nodoc:
89
- klass = nil
90
- node.children.detect do |e|
88
+ def self.import(node, *decorators) # :nodoc:
89
+ node.children.each do |e|
91
90
  ns = e.namespace ? e.namespace.href : nil
92
- klass = class_from_registration(e.element_name, ns)
91
+ klass = class_from_registration e.element_name, ns
92
+ decorators << klass if klass
93
93
  end
94
94
 
95
- if klass && klass != self
96
- klass.import(node)
97
- else
98
- klass ||= case node['type']
99
- when nil, 'unavailable' then Status
100
- when /subscribe/ then Subscription
101
- else self
102
- end
103
- klass.new.inherit(node)
95
+ case node['type']
96
+ when nil, 'unavailable'
97
+ decorators << Status
98
+ when /subscribe/
99
+ decorators << Subscription
104
100
  end
101
+
102
+ super
105
103
  end
106
104
 
107
105
  # Ensure element_name is "presence" for all subclasses
108
- def self.new
106
+ def self.new(*args)
109
107
  super :presence
110
108
  end
111
109
 
@@ -22,82 +22,78 @@ class Presence
22
22
  new_node.hash = hash
23
23
  new_node.node = node
24
24
  new_node.ver = ver
25
- new_node
25
+ parse new_node.to_xml
26
26
  end
27
27
 
28
- def self.import(node)
29
- self.new.inherit(node)
30
- end
31
-
32
- # @private
33
- def inherit(node)
34
- inherit_attrs node.attributes
35
- self
36
- end
28
+ module InstanceMethods
37
29
 
38
- # Get the name of the node
39
- #
40
- # @return [String, nil]
41
- def node
42
- c[:node]
43
- end
30
+ # @private
31
+ def inherit(node)
32
+ c.remove
33
+ super
34
+ self
35
+ end
44
36
 
45
- # Set the name of the node
46
- #
47
- # @param [String, nil] node the new node name
48
- def node=(node)
49
- c[:node] = node
50
- end
37
+ # Get the name of the node
38
+ #
39
+ # @return [String, nil]
40
+ def node
41
+ c[:node]
42
+ end
51
43
 
52
- # Get the name of the hash
53
- #
54
- # @return [Symbol, nil]
55
- def hash
56
- c[:hash].to_sym
57
- end
44
+ # Set the name of the node
45
+ #
46
+ # @param [String, nil] node the new node name
47
+ def node=(node)
48
+ c[:node] = node
49
+ end
58
50
 
59
- # Set the name of the hash
60
- #
61
- # @param [String, nil] hash the new hash name
62
- def hash=(hash)
63
- if hash && !VALID_HASH_TYPES.include?(hash.to_s)
64
- raise ArgumentError, "Invalid Hash Type (#{hash}), use: #{VALID_HASH_TYPES*' '}"
51
+ # Get the name of the hash
52
+ #
53
+ # @return [Symbol, nil]
54
+ def hash
55
+ c[:hash] && c[:hash].to_sym
65
56
  end
66
- c[:hash] = hash
67
- end
68
57
 
69
- # Get the ver
70
- #
71
- # @return [String, nil]
72
- def ver
73
- c[:ver]
74
- end
58
+ # Set the name of the hash
59
+ #
60
+ # @param [String, nil] hash the new hash name
61
+ def hash=(hash)
62
+ if hash && !VALID_HASH_TYPES.include?(hash.to_s)
63
+ raise ArgumentError, "Invalid Hash Type (#{hash}), use: #{VALID_HASH_TYPES*' '}"
64
+ end
65
+ c[:hash] = hash
66
+ end
75
67
 
76
- # Set the ver
77
- #
78
- # @param [String, nil] ver the new ver
79
- def ver=(ver)
80
- c[:ver] = ver
81
- end
68
+ # Get the ver
69
+ #
70
+ # @return [String, nil]
71
+ def ver
72
+ c[:ver]
73
+ end
82
74
 
83
- # C node accessor
84
- # If a c node exists it will be returned.
85
- # Otherwise a new node will be created and returned
86
- #
87
- # @return [Blather::XMPPNode]
88
- def c
89
- c = if self.class.registered_ns
90
- find_first('ns:c', :ns => self.class.registered_ns)
91
- else
92
- find_first('c')
75
+ # Set the ver
76
+ #
77
+ # @param [String, nil] ver the new ver
78
+ def ver=(ver)
79
+ c[:ver] = ver
93
80
  end
94
81
 
95
- unless c
96
- (self << (c = XMPPNode.new('c', self.document)))
97
- c.namespace = self.class.registered_ns
82
+ # C node accessor
83
+ # If a c node exists it will be returned.
84
+ # Otherwise a new node will be created and returned
85
+ #
86
+ # @return [Blather::XMPPNode]
87
+ def c
88
+ unless c = find_first('ns:c', :ns => C.registered_ns)
89
+ self << (c = XMPPNode.new('c', self.document))
90
+ c.namespace = self.class.registered_ns
91
+ end
92
+ c
98
93
  end
99
- c
100
94
  end
95
+
96
+ include InstanceMethods
101
97
  end # C
102
98
  end #Presence
103
99
  end #Stanza
@@ -11,19 +11,23 @@ class Presence
11
11
  new_node
12
12
  end
13
13
 
14
- def inherit(node)
15
- muc.remove
16
- super
17
- self
18
- end
14
+ module InstanceMethods
15
+ def inherit(node)
16
+ muc.remove
17
+ super
18
+ self
19
+ end
19
20
 
20
- def muc
21
- unless muc = find_first('ns:x', :ns => self.class.registered_ns)
22
- self << (muc = XMPPNode.new('x', self.document))
23
- muc.namespace = self.class.registered_ns
21
+ def muc
22
+ unless muc = find_first('ns:x', :ns => MUC.registered_ns)
23
+ self << (muc = XMPPNode.new('x', self.document))
24
+ muc.namespace = self.class.registered_ns
25
+ end
26
+ muc
24
27
  end
25
- muc
26
28
  end
29
+
30
+ include InstanceMethods
27
31
  end # MUC
28
32
 
29
33
  end # Presence
@@ -4,59 +4,70 @@ module Blather
4
4
  class Stanza
5
5
  class Presence
6
6
 
7
- class MUCUser < Status
7
+ class MUCUser < Presence
8
8
  include Blather::Stanza::MUC::MUCUserBase
9
9
 
10
- def affiliation
11
- item.affiliation
10
+ def self.decorator_modules
11
+ super + [Blather::Stanza::MUC::MUCUserBase]
12
12
  end
13
13
 
14
- def affiliation=(val)
15
- item.affiliation = val
16
- end
14
+ register :muc_user_presence, :x, MUC_USER_NAMESPACE
17
15
 
18
- def role
19
- item.role
20
- end
16
+ module InstanceMethods
21
17
 
22
- def role=(val)
23
- item.role = val
24
- end
18
+ def affiliation
19
+ item.affiliation
20
+ end
25
21
 
26
- def jid
27
- item.jid
28
- end
22
+ def affiliation=(val)
23
+ item.affiliation = val
24
+ end
29
25
 
30
- def jid=(val)
31
- item.jid = val
32
- end
26
+ def role
27
+ item.role
28
+ end
33
29
 
34
- def status_codes
35
- status.map &:code
36
- end
30
+ def role=(val)
31
+ item.role = val
32
+ end
37
33
 
38
- def status_codes=(val)
39
- muc_user.remove_children :status
40
- val.each do |code|
41
- muc_user << Status.new(code)
34
+ def jid
35
+ item.jid
42
36
  end
43
- end
44
37
 
45
- def item
46
- if item = muc_user.find_first('ns:item', :ns => self.class.registered_ns)
47
- Item.new item
48
- else
49
- muc_user << (item = Item.new nil, nil, nil, self.document)
50
- item
38
+ def jid=(val)
39
+ item.jid = val
40
+ end
41
+
42
+ def status_codes
43
+ status.map &:code
44
+ end
45
+
46
+ def status_codes=(val)
47
+ muc_user.remove_children :status
48
+ val.each do |code|
49
+ muc_user << Status.new(code)
50
+ end
51
51
  end
52
- end
53
52
 
54
- def status
55
- muc_user.find('ns:status', :ns => self.class.registered_ns).map do |status|
56
- Status.new status
53
+ def item
54
+ if item = muc_user.find_first('ns:item', :ns => MUCUser.registered_ns)
55
+ Item.new item
56
+ else
57
+ muc_user << (item = Item.new nil, nil, nil, self.document)
58
+ item
59
+ end
60
+ end
61
+
62
+ def status
63
+ muc_user.find('ns:status', :ns => MUCUser.registered_ns).map do |status|
64
+ Status.new status
65
+ end
57
66
  end
58
67
  end
59
68
 
69
+ include InstanceMethods
70
+
60
71
  class Item < XMPPNode
61
72
  def self.new(affiliation = nil, role = nil, jid = nil, document = nil)
62
73
  new_node = super :item, document
@@ -93,127 +93,132 @@ class Presence
93
93
  node
94
94
  end
95
95
 
96
- # Check if the state is available
97
- #
98
- # @return [true, false]
99
- def available?
100
- self.state == :available
101
- end
102
-
103
- # Check if the state is away
104
- #
105
- # @return [true, false]
106
- def away?
107
- self.state == :away
108
- end
96
+ module InstanceMethods
109
97
 
110
- # Check if the state is chat
111
- #
112
- # @return [true, false]
113
- def chat?
114
- self.state == :chat
115
- end
98
+ # Check if the state is available
99
+ #
100
+ # @return [true, false]
101
+ def available?
102
+ self.state == :available
103
+ end
116
104
 
117
- # Check if the state is dnd
118
- #
119
- # @return [true, false]
120
- def dnd?
121
- self.state == :dnd
122
- end
105
+ # Check if the state is away
106
+ #
107
+ # @return [true, false]
108
+ def away?
109
+ self.state == :away
110
+ end
123
111
 
124
- # Check if the state is xa
125
- #
126
- # @return [true, false]
127
- def xa?
128
- self.state == :xa
129
- end
112
+ # Check if the state is chat
113
+ #
114
+ # @return [true, false]
115
+ def chat?
116
+ self.state == :chat
117
+ end
130
118
 
131
- # Set the type attribute
132
- # Ensures type is nil or :unavailable
133
- #
134
- # @param [<:unavailable, nil>] type the type
135
- def type=(type)
136
- if type && type.to_sym != :unavailable
137
- raise ArgumentError, "Invalid type (#{type}). Must be nil or unavailable"
119
+ # Check if the state is dnd
120
+ #
121
+ # @return [true, false]
122
+ def dnd?
123
+ self.state == :dnd
138
124
  end
139
- super
140
- end
141
125
 
142
- # Set the state
143
- # Ensure state is one of :available, :away, :chat, :dnd, :xa or nil
144
- #
145
- # @param [<:available, :away, :chat, :dnd, :xa, nil>] state
146
- def state=(state) # :nodoc:
147
- state = state.to_sym if state
148
- state = nil if state == :available
149
- if state && !VALID_STATES.include?(state)
150
- raise ArgumentError, "Invalid Status (#{state}), use: #{VALID_STATES*' '}"
126
+ # Check if the state is xa
127
+ #
128
+ # @return [true, false]
129
+ def xa?
130
+ self.state == :xa
151
131
  end
152
132
 
153
- set_content_for :show, state
154
- end
133
+ # Set the type attribute
134
+ # Ensures type is nil or :unavailable
135
+ #
136
+ # @param [<:unavailable, nil>] type the type
137
+ def type=(type)
138
+ if type && type.to_sym != :unavailable
139
+ raise ArgumentError, "Invalid type (#{type}). Must be nil or unavailable"
140
+ end
141
+ super
142
+ end
155
143
 
156
- # Get the state of the status
157
- #
158
- # @return [<:available, :away, :chat, :dnd, :xa>]
159
- def state
160
- state = type || content_from(:show)
161
- state = :available if state.blank?
162
- state.to_sym
163
- end
144
+ # Set the state
145
+ # Ensure state is one of :available, :away, :chat, :dnd, :xa or nil
146
+ #
147
+ # @param [<:available, :away, :chat, :dnd, :xa, nil>] state
148
+ def state=(state) # :nodoc:
149
+ state = state.to_sym if state
150
+ state = nil if state == :available
151
+ if state && !VALID_STATES.include?(state)
152
+ raise ArgumentError, "Invalid Status (#{state}), use: #{VALID_STATES*' '}"
153
+ end
154
+
155
+ set_content_for :show, state
156
+ end
164
157
 
165
- # Set the priority of the status
166
- # Ensures priority is between -128 and 127
167
- #
168
- # @param [Fixnum<-128...127>] new_priority
169
- def priority=(new_priority) # :nodoc:
170
- if new_priority && !(-128..127).include?(new_priority.to_i)
171
- raise ArgumentError, 'Priority must be between -128 and +127'
158
+ # Get the state of the status
159
+ #
160
+ # @return [<:available, :away, :chat, :dnd, :xa>]
161
+ def state
162
+ state = type || content_from(:show)
163
+ state = :available if state.blank?
164
+ state.to_sym
172
165
  end
173
- set_content_for :priority, new_priority
174
- end
175
166
 
176
- # Get the priority of the status
177
- #
178
- # @return [Fixnum<-128...127>]
179
- def priority
180
- read_content(:priority).to_i
181
- end
167
+ # Set the priority of the status
168
+ # Ensures priority is between -128 and 127
169
+ #
170
+ # @param [Fixnum<-128...127>] new_priority
171
+ def priority=(new_priority) # :nodoc:
172
+ if new_priority && !(-128..127).include?(new_priority.to_i)
173
+ raise ArgumentError, 'Priority must be between -128 and +127'
174
+ end
175
+ set_content_for :priority, new_priority
176
+ end
182
177
 
183
- # Get the status message
184
- #
185
- # @return [String, nil]
186
- def message
187
- read_content :status
188
- end
178
+ # Get the priority of the status
179
+ #
180
+ # @return [Fixnum<-128...127>]
181
+ def priority
182
+ read_content(:priority).to_i
183
+ end
189
184
 
190
- # Set the status message
191
- #
192
- # @param [String, nil] message
193
- def message=(message)
194
- set_content_for :status, message
195
- end
185
+ # Get the status message
186
+ #
187
+ # @return [String, nil]
188
+ def message
189
+ read_content :status
190
+ end
196
191
 
197
- # Compare status based on priority and state:
198
- # unavailable status is always less valuable than others
199
- # Raises an error if the JIDs aren't the same
200
- #
201
- # @param [Blather::Stanza::Presence::Status] o
202
- # @return [true,false]
203
- def <=>(o)
204
- unless self.from && o.from && self.from.stripped == o.from.stripped
205
- raise ArgumentError, "Cannot compare status from different JIDs: #{[self.from, o.from].inspect}"
192
+ # Set the status message
193
+ #
194
+ # @param [String, nil] message
195
+ def message=(message)
196
+ set_content_for :status, message
206
197
  end
207
198
 
208
- if (self.type.nil? && o.type.nil?) || (!self.type.nil? && !o.type.nil?)
209
- self.priority <=> o.priority
210
- elsif self.type.nil? && !o.type.nil?
211
- 1
212
- elsif !self.type.nil? && o.type.nil?
213
- -1
199
+ # Compare status based on priority and state:
200
+ # unavailable status is always less valuable than others
201
+ # Raises an error if the JIDs aren't the same
202
+ #
203
+ # @param [Blather::Stanza::Presence::Status] o
204
+ # @return [true,false]
205
+ def <=>(o)
206
+ unless self.from && o.from && self.from.stripped == o.from.stripped
207
+ raise ArgumentError, "Cannot compare status from different JIDs: #{[self.from, o.from].inspect}"
208
+ end
209
+
210
+ if (self.type.nil? && o.type.nil?) || (!self.type.nil? && !o.type.nil?)
211
+ self.priority <=> o.priority
212
+ elsif self.type.nil? && !o.type.nil?
213
+ 1
214
+ elsif !self.type.nil? && o.type.nil?
215
+ -1
216
+ end
214
217
  end
215
218
  end
216
219
 
220
+ include InstanceMethods
221
+
217
222
  end #Status
218
223
 
219
224
  end #Presence