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.
- data/LICENSE +1 -1
- data/README.rdoc +41 -12
- data/examples/echo.rb +1 -1
- data/examples/execute.rb +0 -5
- data/examples/pubsub/cli.rb +64 -0
- data/examples/pubsub/ping_pong.rb +18 -0
- data/examples/rosterprint.rb +14 -0
- data/examples/xmpp4r/echo.rb +35 -0
- data/lib/blather.rb +35 -12
- data/lib/blather/client.rb +1 -1
- data/lib/blather/client/client.rb +19 -13
- data/lib/blather/client/dsl.rb +16 -0
- data/lib/blather/client/dsl/pubsub.rb +133 -0
- data/lib/blather/core_ext/active_support.rb +1 -117
- data/lib/blather/core_ext/active_support/inheritable_attributes.rb +117 -0
- data/lib/blather/core_ext/nokogiri.rb +35 -0
- data/lib/blather/errors.rb +3 -20
- data/lib/blather/errors/sasl_error.rb +3 -1
- data/lib/blather/errors/stanza_error.rb +10 -17
- data/lib/blather/errors/stream_error.rb +11 -14
- data/lib/blather/jid.rb +1 -0
- data/lib/blather/roster.rb +9 -0
- data/lib/blather/roster_item.rb +6 -1
- data/lib/blather/stanza.rb +35 -18
- data/lib/blather/stanza/disco.rb +7 -1
- data/lib/blather/stanza/disco/disco_info.rb +45 -33
- data/lib/blather/stanza/disco/disco_items.rb +32 -21
- data/lib/blather/stanza/iq.rb +13 -8
- data/lib/blather/stanza/iq/query.rb +16 -8
- data/lib/blather/stanza/iq/roster.rb +33 -22
- data/lib/blather/stanza/message.rb +20 -31
- data/lib/blather/stanza/presence.rb +3 -5
- data/lib/blather/stanza/presence/status.rb +13 -21
- data/lib/blather/stanza/presence/subscription.rb +11 -16
- data/lib/blather/stanza/pubsub.rb +63 -0
- data/lib/blather/stanza/pubsub/affiliations.rb +50 -0
- data/lib/blather/stanza/pubsub/create.rb +43 -0
- data/lib/blather/stanza/pubsub/errors.rb +9 -0
- data/lib/blather/stanza/pubsub/event.rb +77 -0
- data/lib/blather/stanza/pubsub/items.rb +63 -0
- data/lib/blather/stanza/pubsub/publish.rb +58 -0
- data/lib/blather/stanza/pubsub/retract.rb +53 -0
- data/lib/blather/stanza/pubsub/subscribe.rb +42 -0
- data/lib/blather/stanza/pubsub/subscription.rb +66 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +55 -0
- data/lib/blather/stanza/pubsub/unsubscribe.rb +42 -0
- data/lib/blather/stanza/pubsub_owner.rb +41 -0
- data/lib/blather/stanza/pubsub_owner/delete.rb +34 -0
- data/lib/blather/stanza/pubsub_owner/purge.rb +34 -0
- data/lib/blather/stream.rb +76 -168
- data/lib/blather/stream/client.rb +1 -2
- data/lib/blather/stream/component.rb +9 -5
- data/lib/blather/stream/features.rb +53 -0
- data/lib/blather/stream/features/resource.rb +63 -0
- data/lib/blather/stream/{sasl.rb → features/sasl.rb} +53 -52
- data/lib/blather/stream/features/session.rb +44 -0
- data/lib/blather/stream/features/tls.rb +28 -0
- data/lib/blather/stream/parser.rb +70 -46
- data/lib/blather/xmpp_node.rb +113 -52
- data/spec/blather/client/client_spec.rb +44 -58
- data/spec/blather/client/dsl/pubsub_spec.rb +465 -0
- data/spec/blather/client/dsl_spec.rb +19 -6
- data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
- data/spec/blather/errors/sasl_error_spec.rb +8 -8
- data/spec/blather/errors/stanza_error_spec.rb +25 -33
- data/spec/blather/errors/stream_error_spec.rb +21 -16
- data/spec/blather/errors_spec.rb +4 -11
- data/spec/blather/jid_spec.rb +31 -30
- data/spec/blather/roster_item_spec.rb +34 -23
- data/spec/blather/roster_spec.rb +27 -12
- data/spec/blather/stanza/discos/disco_info_spec.rb +61 -42
- data/spec/blather/stanza/discos/disco_items_spec.rb +47 -35
- data/spec/blather/stanza/iq/query_spec.rb +34 -11
- data/spec/blather/stanza/iq/roster_spec.rb +47 -30
- data/spec/blather/stanza/iq_spec.rb +19 -14
- data/spec/blather/stanza/message_spec.rb +30 -17
- data/spec/blather/stanza/presence/status_spec.rb +43 -20
- data/spec/blather/stanza/presence/subscription_spec.rb +41 -21
- data/spec/blather/stanza/presence_spec.rb +34 -21
- data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
- data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
- data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
- data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
- data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
- data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
- data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
- data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
- data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
- data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
- data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
- data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
- data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
- data/spec/blather/stanza/pubsub_spec.rb +62 -0
- data/spec/blather/stanza_spec.rb +53 -38
- data/spec/blather/stream/client_spec.rb +231 -88
- data/spec/blather/stream/component_spec.rb +14 -5
- data/spec/blather/stream/parser_spec.rb +145 -0
- data/spec/blather/xmpp_node_spec.rb +192 -96
- data/spec/fixtures/pubsub.rb +311 -0
- data/spec/spec_helper.rb +5 -4
- metadata +54 -18
- data/Rakefile +0 -139
- data/ext/extconf.rb +0 -65
- data/ext/push_parser.c +0 -209
- data/lib/blather/core_ext/libxml.rb +0 -28
- data/lib/blather/stream/resource.rb +0 -48
- data/lib/blather/stream/session.rb +0 -36
- data/lib/blather/stream/stream_handler.rb +0 -39
- data/lib/blather/stream/tls.rb +0 -33
- data/spec/blather/core_ext/libxml_spec.rb +0 -58
data/lib/blather/jid.rb
CHANGED
data/lib/blather/roster.rb
CHANGED
|
@@ -71,6 +71,15 @@ module Blather
|
|
|
71
71
|
@items.dup
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
##
|
|
75
|
+
# A hash of items keyed by group
|
|
76
|
+
def grouped
|
|
77
|
+
self.inject(Hash.new{|h,k|h[k]=[]}) do |hash, item|
|
|
78
|
+
item[1].groups.each { |group| hash[group] << item[1] }
|
|
79
|
+
hash
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
74
83
|
private
|
|
75
84
|
def self.key(jid)
|
|
76
85
|
JID.new(jid).stripped.to_s
|
data/lib/blather/roster_item.rb
CHANGED
|
@@ -13,6 +13,11 @@ module Blather
|
|
|
13
13
|
attr_accessor :name,
|
|
14
14
|
:groups
|
|
15
15
|
|
|
16
|
+
def self.new(item)
|
|
17
|
+
return item if item.is_a?(self)
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
|
|
16
21
|
##
|
|
17
22
|
# item:: can be a JID, String (a@b) or a Stanza
|
|
18
23
|
def initialize(item)
|
|
@@ -29,7 +34,7 @@ module Blather
|
|
|
29
34
|
self.name = item[:name]
|
|
30
35
|
self.subscription = item[:subscription]
|
|
31
36
|
self.ask = item[:ask]
|
|
32
|
-
item.groups.each { |g|
|
|
37
|
+
item.groups.each { |g| @groups << g }
|
|
33
38
|
end
|
|
34
39
|
|
|
35
40
|
@groups = [nil] if @groups.empty?
|
data/lib/blather/stanza.rb
CHANGED
|
@@ -14,12 +14,12 @@ module Blather
|
|
|
14
14
|
# that inherits Stanza can register a callback for itself
|
|
15
15
|
# which is added to a list and iterated over when looking for
|
|
16
16
|
# a callback to use
|
|
17
|
-
def self.register(
|
|
18
|
-
@@handler_list <<
|
|
17
|
+
def self.register(handler, name = nil, ns = nil)
|
|
18
|
+
@@handler_list << handler
|
|
19
19
|
self.handler_heirarchy ||= []
|
|
20
|
-
self.handler_heirarchy.unshift
|
|
20
|
+
self.handler_heirarchy.unshift handler
|
|
21
21
|
|
|
22
|
-
name = name || self.
|
|
22
|
+
name = name || self.registered_name || handler
|
|
23
23
|
super name, ns
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -44,24 +44,32 @@ module Blather
|
|
|
44
44
|
##
|
|
45
45
|
# Automatically set the stanza's ID
|
|
46
46
|
# and attach it to a document so XPath searching works
|
|
47
|
-
def
|
|
48
|
-
super
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
self.id = self.class.next_id
|
|
47
|
+
def self.new(name = nil)
|
|
48
|
+
node = super
|
|
49
|
+
node.name = name.to_s if name
|
|
50
|
+
node
|
|
52
51
|
end
|
|
53
52
|
|
|
54
53
|
##
|
|
55
|
-
# Helper method to
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
# Helper method to generate stanza guard methods
|
|
55
|
+
#
|
|
56
|
+
# attribute_helpers_for(:type, [:subscribe, :unsubscribe])
|
|
57
|
+
#
|
|
58
|
+
# This generates "subscribe?" and "unsubscribe?" methods that return
|
|
59
|
+
# true if self.type == :subscribe or :unsubscribe, respectively.
|
|
60
|
+
def self.attribute_helpers_for(attr, values)
|
|
61
|
+
[values].flatten.each do |v|
|
|
62
|
+
define_method("#{v}?") { __send__(attr) == v }
|
|
63
|
+
end
|
|
58
64
|
end
|
|
59
65
|
|
|
66
|
+
attribute_helpers_for(:type, :error)
|
|
67
|
+
|
|
60
68
|
##
|
|
61
69
|
# Copies itself then swaps from and to
|
|
62
70
|
# then returns the new stanza
|
|
63
71
|
def reply
|
|
64
|
-
self.
|
|
72
|
+
self.dup.reply!
|
|
65
73
|
end
|
|
66
74
|
|
|
67
75
|
##
|
|
@@ -71,23 +79,23 @@ module Blather
|
|
|
71
79
|
self
|
|
72
80
|
end
|
|
73
81
|
|
|
74
|
-
attribute_accessor :id
|
|
82
|
+
attribute_accessor :id
|
|
75
83
|
|
|
76
84
|
attribute_writer :to, :from
|
|
77
85
|
|
|
78
86
|
##
|
|
79
87
|
# returns:: JID created from the "to" value of the stanza
|
|
80
88
|
def to
|
|
81
|
-
JID.new(
|
|
89
|
+
JID.new(self[:to]) if self[:to]
|
|
82
90
|
end
|
|
83
91
|
|
|
84
92
|
##
|
|
85
93
|
# returns:: JID created from the "from" value of the stanza
|
|
86
94
|
def from
|
|
87
|
-
JID.new(
|
|
95
|
+
JID.new(self[:from]) if self[:from]
|
|
88
96
|
end
|
|
89
97
|
|
|
90
|
-
attribute_accessor :type
|
|
98
|
+
attribute_accessor :type, :call => :to_sym
|
|
91
99
|
|
|
92
100
|
##
|
|
93
101
|
# Transform the stanza into a stanza error
|
|
@@ -96,5 +104,14 @@ module Blather
|
|
|
96
104
|
def as_error(name, type, text = nil, extras = [])
|
|
97
105
|
StanzaError.new self, name, type, text, extras
|
|
98
106
|
end
|
|
107
|
+
|
|
108
|
+
protected
|
|
109
|
+
def reply_if_needed!
|
|
110
|
+
unless @reversed_endpoints
|
|
111
|
+
reply!
|
|
112
|
+
@reversed_endpoints = true
|
|
113
|
+
end
|
|
114
|
+
self
|
|
115
|
+
end
|
|
99
116
|
end
|
|
100
|
-
end
|
|
117
|
+
end
|
data/lib/blather/stanza/disco.rb
CHANGED
|
@@ -7,64 +7,76 @@ class Stanza
|
|
|
7
7
|
class DiscoInfo < Disco
|
|
8
8
|
register :disco_info, nil, 'http://jabber.org/protocol/disco#info'
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
super type
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
query << (id.is_a?(Identity) ? id : Identity.new(id[:name], id[:type], id[:category]))
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
[features].flatten.each do |feature|
|
|
20
|
-
query << (feature.is_a?(Feature) ? feature : Feature.new(feature))
|
|
21
|
-
end
|
|
10
|
+
def self.new(type = nil, node = nil, identities = [], features = [])
|
|
11
|
+
new_node = super type
|
|
12
|
+
new_node.node = node
|
|
13
|
+
[identities].flatten.each { |id| new_node.query << Identity.new(id) }
|
|
14
|
+
[features].flatten.each { |feature| new_node.query << Feature.new(feature) }
|
|
15
|
+
new_node
|
|
22
16
|
end
|
|
23
17
|
|
|
24
18
|
##
|
|
25
19
|
# List of identity objects
|
|
26
20
|
def identities
|
|
27
|
-
|
|
28
|
-
identities = query.find('query_ns:identity', :query_ns => self.class.ns) if identities.empty?
|
|
29
|
-
identities.map { |i| Identity.new i }
|
|
21
|
+
query.find('//query_ns:identity', :query_ns => self.class.registered_ns).map { |i| Identity.new i }
|
|
30
22
|
end
|
|
31
23
|
|
|
32
24
|
##
|
|
33
25
|
# List of feature objects
|
|
34
26
|
def features
|
|
35
|
-
|
|
36
|
-
features = query.find('query_ns:feature', :query_ns => self.class.ns) if features.empty?
|
|
37
|
-
features.map { |i| Feature.new i }
|
|
27
|
+
query.find('//query_ns:feature', :query_ns => self.class.registered_ns).map { |i| Feature.new i }
|
|
38
28
|
end
|
|
39
29
|
|
|
40
30
|
class Identity < XMPPNode
|
|
41
|
-
attribute_accessor :category, :type
|
|
42
|
-
attribute_accessor :name
|
|
31
|
+
attribute_accessor :category, :type, :call => :to_sym
|
|
32
|
+
attribute_accessor :name
|
|
43
33
|
|
|
44
|
-
def
|
|
45
|
-
super :identity
|
|
34
|
+
def self.new(name, type = nil, category = nil)
|
|
35
|
+
new_node = super :identity
|
|
46
36
|
|
|
47
|
-
|
|
48
|
-
|
|
37
|
+
case name
|
|
38
|
+
when Nokogiri::XML::Node
|
|
39
|
+
new_node.inherit name
|
|
40
|
+
when Hash
|
|
41
|
+
new_node.name = name[:name]
|
|
42
|
+
new_node.type = name[:type]
|
|
43
|
+
new_node.category = name[:category]
|
|
49
44
|
else
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
new_node.name = name
|
|
46
|
+
new_node.type = type
|
|
47
|
+
new_node.category = category
|
|
53
48
|
end
|
|
49
|
+
new_node
|
|
54
50
|
end
|
|
51
|
+
|
|
52
|
+
def eql?(o)
|
|
53
|
+
raise "Cannot compare #{self.class} with #{o.class}" unless o.is_a?(self.class)
|
|
54
|
+
o.name == self.name &&
|
|
55
|
+
o.type == self.type &&
|
|
56
|
+
o.category == self.category
|
|
57
|
+
end
|
|
58
|
+
alias_method :==, :eql?
|
|
55
59
|
end
|
|
56
60
|
|
|
57
61
|
class Feature < XMPPNode
|
|
58
|
-
attribute_accessor :var
|
|
62
|
+
attribute_accessor :var
|
|
59
63
|
|
|
60
|
-
def
|
|
61
|
-
super :feature
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
def self.new(var)
|
|
65
|
+
new_node = super :feature
|
|
66
|
+
case var
|
|
67
|
+
when Nokogiri::XML::Node
|
|
68
|
+
new_node.inherit var
|
|
64
69
|
else
|
|
65
|
-
|
|
70
|
+
new_node.var = var
|
|
66
71
|
end
|
|
72
|
+
new_node
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def eql?(o)
|
|
76
|
+
raise "Cannot compare #{self.class} with #{o.class}" unless o.is_a?(self.class)
|
|
77
|
+
o.var == self.var
|
|
67
78
|
end
|
|
79
|
+
alias_method :==, :eql?
|
|
68
80
|
end
|
|
69
81
|
end
|
|
70
82
|
|
|
@@ -4,47 +4,58 @@ class Stanza
|
|
|
4
4
|
class DiscoItems < Disco
|
|
5
5
|
register :disco_items, nil, 'http://jabber.org/protocol/disco#items'
|
|
6
6
|
|
|
7
|
-
def
|
|
8
|
-
super type
|
|
9
|
-
|
|
10
|
-
[items].flatten.each
|
|
11
|
-
|
|
12
|
-
end
|
|
7
|
+
def self.new(type = nil, node = nil, items = [])
|
|
8
|
+
new_node = super type
|
|
9
|
+
new_node.node = node
|
|
10
|
+
[items].flatten.each { |item| new_node.query << Item.new(item) }
|
|
11
|
+
new_node
|
|
13
12
|
end
|
|
14
13
|
|
|
15
14
|
def items
|
|
16
|
-
|
|
17
|
-
items = query.find('query_ns:item', :query_ns => self.class.ns) if items.empty?
|
|
18
|
-
items.map { |i| Item.new i }
|
|
15
|
+
query.find('//query_ns:item', :query_ns => self.class.registered_ns).map { |i| Item.new i }
|
|
19
16
|
end
|
|
20
17
|
|
|
21
18
|
def node=(node)
|
|
22
|
-
query
|
|
19
|
+
query[:node] = node
|
|
23
20
|
end
|
|
24
21
|
|
|
25
22
|
def node
|
|
26
|
-
query
|
|
23
|
+
query[:node]
|
|
27
24
|
end
|
|
28
25
|
|
|
29
26
|
class Item < XMPPNode
|
|
30
|
-
def
|
|
31
|
-
super :item
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
def self.new(jid, node = nil, name = nil)
|
|
28
|
+
new_node = super :item
|
|
29
|
+
|
|
30
|
+
case jid
|
|
31
|
+
when Nokogiri::XML::Node
|
|
32
|
+
new_node.inherit jid
|
|
33
|
+
when Hash
|
|
34
|
+
new_node.jid = jid[:jid]
|
|
35
|
+
new_node.node = jid[:node]
|
|
36
|
+
new_node.name = jid[:name]
|
|
35
37
|
else
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
new_node.jid = jid
|
|
39
|
+
new_node.node = node
|
|
40
|
+
new_node.name = name
|
|
39
41
|
end
|
|
42
|
+
new_node
|
|
40
43
|
end
|
|
41
44
|
|
|
42
45
|
def jid
|
|
43
|
-
(j =
|
|
46
|
+
(j = self[:jid]) ? JID.new(j) : nil
|
|
44
47
|
end
|
|
45
48
|
attribute_writer :jid
|
|
46
49
|
|
|
47
|
-
attribute_accessor :node, :name
|
|
50
|
+
attribute_accessor :node, :name
|
|
51
|
+
|
|
52
|
+
def eql?(o)
|
|
53
|
+
raise "Cannot compare #{self.class} with #{o.class}" unless o.is_a?(self.class)
|
|
54
|
+
o.jid == self.jid &&
|
|
55
|
+
o.node == self.node &&
|
|
56
|
+
o.name == self.name
|
|
57
|
+
end
|
|
58
|
+
alias_method :==, :eql?
|
|
48
59
|
end
|
|
49
60
|
end
|
|
50
61
|
|
data/lib/blather/stanza/iq.rb
CHANGED
|
@@ -9,17 +9,22 @@ class Stanza
|
|
|
9
9
|
register :iq
|
|
10
10
|
|
|
11
11
|
def self.import(node)
|
|
12
|
-
raise(ArgumentError, "Import missmatch #{[node.element_name, self.name].inspect}") if node.element_name != self.name.to_s
|
|
13
12
|
klass = nil
|
|
14
|
-
node.children.each { |e| break if klass = class_from_registration(e.element_name, e.namespace) }
|
|
15
|
-
|
|
13
|
+
node.children.each { |e| break if klass = class_from_registration(e.element_name, (e.namespace.href if e.namespace)) }
|
|
14
|
+
|
|
15
|
+
if klass && klass != self
|
|
16
|
+
klass.import(node)
|
|
17
|
+
else
|
|
18
|
+
new(node[:type]).inherit(node)
|
|
19
|
+
end
|
|
16
20
|
end
|
|
17
21
|
|
|
18
|
-
def
|
|
19
|
-
super :iq
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
def self.new(type = nil, to = nil, id = nil)
|
|
23
|
+
node = super :iq
|
|
24
|
+
node.type = type || :get
|
|
25
|
+
node.to = to
|
|
26
|
+
node.id = id || self.next_id
|
|
27
|
+
node
|
|
23
28
|
end
|
|
24
29
|
|
|
25
30
|
VALID_TYPES.each do |valid_type|
|
|
@@ -6,16 +6,17 @@ class Iq
|
|
|
6
6
|
register :query, :query
|
|
7
7
|
|
|
8
8
|
##
|
|
9
|
-
# Ensure the
|
|
10
|
-
def
|
|
11
|
-
super
|
|
12
|
-
query
|
|
9
|
+
# Ensure the query node is created
|
|
10
|
+
def self.new(type = nil)
|
|
11
|
+
node = super
|
|
12
|
+
node.query
|
|
13
|
+
node
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
##
|
|
16
17
|
# Kill the query node before running inherit
|
|
17
18
|
def inherit(node)
|
|
18
|
-
query.remove
|
|
19
|
+
query.remove
|
|
19
20
|
super
|
|
20
21
|
end
|
|
21
22
|
|
|
@@ -23,9 +24,16 @@ class Iq
|
|
|
23
24
|
# Query node accessor
|
|
24
25
|
# This will ensure there actually is a query node
|
|
25
26
|
def query
|
|
26
|
-
q =
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
q = if self.class.registered_ns
|
|
28
|
+
find_first('query_ns:query', :query_ns => self.class.registered_ns)
|
|
29
|
+
else
|
|
30
|
+
find_first('query')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
unless q
|
|
34
|
+
(self << (q = XMPPNode.new('query', self.document)))
|
|
35
|
+
q.namespace = self.class.registered_ns
|
|
36
|
+
end
|
|
29
37
|
q
|
|
30
38
|
end
|
|
31
39
|
|
|
@@ -7,9 +7,10 @@ class Iq
|
|
|
7
7
|
|
|
8
8
|
##
|
|
9
9
|
# Any new items are added to the query
|
|
10
|
-
def
|
|
11
|
-
super type
|
|
12
|
-
query << item if item
|
|
10
|
+
def self.new(type = nil, item = nil)
|
|
11
|
+
node = super type
|
|
12
|
+
node.query << item if item
|
|
13
|
+
node
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
##
|
|
@@ -17,19 +18,17 @@ class Iq
|
|
|
17
18
|
# Creates RosterItem objects out of each roster item as well.
|
|
18
19
|
def inherit(node)
|
|
19
20
|
# remove the current set of nodes
|
|
20
|
-
|
|
21
|
+
remove_children :item
|
|
21
22
|
super
|
|
22
23
|
# transmogrify nodes into RosterItems
|
|
23
|
-
items.each { |i| query << RosterItem.new(i); i.remove
|
|
24
|
+
items.each { |i| query << RosterItem.new(i); i.remove }
|
|
24
25
|
self
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
##
|
|
28
29
|
# Roster items
|
|
29
30
|
def items
|
|
30
|
-
|
|
31
|
-
items = query.find('//query_ns:item', :query_ns => self.class.ns) if items.empty?
|
|
32
|
-
items.map { |i| RosterItem.new(i) }
|
|
31
|
+
query.find('//ns:item', :ns => self.class.registered_ns).map { |i| RosterItem.new(i) }
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
class RosterItem < XMPPNode
|
|
@@ -38,42 +37,54 @@ class Iq
|
|
|
38
37
|
# [name] name alias of the given JID
|
|
39
38
|
# [subscription] subscription type
|
|
40
39
|
# [ask] ask subscription sub-state
|
|
41
|
-
def
|
|
42
|
-
super :item
|
|
40
|
+
def self.new(jid = nil, name = nil, subscription = nil, ask = nil)
|
|
41
|
+
new_node = super :item
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
case jid
|
|
44
|
+
when Nokogiri::XML::Node
|
|
45
|
+
new_node.inherit jid
|
|
46
|
+
when Hash
|
|
47
|
+
new_node.jid = jid[:jid]
|
|
48
|
+
new_node.name = jid[:name]
|
|
49
|
+
new_node.subscription = jid[:subscription]
|
|
50
|
+
new_node.ask = jid[:ask]
|
|
46
51
|
else
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
new_node.jid = jid
|
|
53
|
+
new_node.name = name
|
|
54
|
+
new_node.subscription = subscription
|
|
55
|
+
new_node.ask = ask
|
|
51
56
|
end
|
|
57
|
+
new_node
|
|
52
58
|
end
|
|
53
59
|
|
|
54
60
|
##
|
|
55
61
|
# Roster item's JID
|
|
56
62
|
def jid
|
|
57
|
-
(j =
|
|
63
|
+
(j = self[:jid]) ? JID.new(j) : nil
|
|
58
64
|
end
|
|
59
65
|
attribute_writer :jid
|
|
60
66
|
|
|
61
|
-
attribute_accessor :name
|
|
67
|
+
attribute_accessor :name
|
|
62
68
|
|
|
63
|
-
attribute_accessor :subscription, :ask
|
|
69
|
+
attribute_accessor :subscription, :ask, :call => :to_sym
|
|
64
70
|
|
|
65
71
|
##
|
|
66
72
|
# The groups roster item belongs to
|
|
67
73
|
def groups
|
|
68
|
-
find(
|
|
74
|
+
find('child::*[local-name()="group"]').map { |g| g.content }
|
|
69
75
|
end
|
|
70
76
|
|
|
71
77
|
##
|
|
72
78
|
# Set the roster item's groups
|
|
73
79
|
# must be an array
|
|
74
80
|
def groups=(new_groups)
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
remove_children :group
|
|
82
|
+
if new_groups
|
|
83
|
+
new_groups.uniq.each do |g|
|
|
84
|
+
self << (group = XMPPNode.new(:group, self.document))
|
|
85
|
+
group.content = g
|
|
86
|
+
end
|
|
87
|
+
end
|
|
77
88
|
end
|
|
78
89
|
|
|
79
90
|
##
|