tp-blather 0.8.2
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/.autotest +13 -0
- data/.gemtest +0 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +249 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE +22 -0
- data/README.md +413 -0
- data/Rakefile +20 -0
- data/TODO.md +2 -0
- data/blather.gemspec +51 -0
- data/examples/certs/README +20 -0
- data/examples/certs/ca-bundle.crt +3987 -0
- data/examples/echo.rb +19 -0
- data/examples/execute.rb +17 -0
- data/examples/ping_pong.rb +38 -0
- data/examples/print_hierarchy.rb +77 -0
- data/examples/rosterprint.rb +15 -0
- data/examples/stream_only.rb +28 -0
- data/examples/trusted_echo.rb +21 -0
- data/examples/xmpp4r/echo.rb +36 -0
- data/lib/blather.rb +112 -0
- data/lib/blather/cert_store.rb +53 -0
- data/lib/blather/client.rb +95 -0
- data/lib/blather/client/client.rb +345 -0
- data/lib/blather/client/dsl.rb +320 -0
- data/lib/blather/client/dsl/pubsub.rb +174 -0
- data/lib/blather/core_ext/eventmachine.rb +125 -0
- data/lib/blather/core_ext/ipaddr.rb +20 -0
- data/lib/blather/errors.rb +69 -0
- data/lib/blather/errors/sasl_error.rb +44 -0
- data/lib/blather/errors/stanza_error.rb +110 -0
- data/lib/blather/errors/stream_error.rb +84 -0
- data/lib/blather/file_transfer.rb +107 -0
- data/lib/blather/file_transfer/ibb.rb +68 -0
- data/lib/blather/file_transfer/s5b.rb +114 -0
- data/lib/blather/jid.rb +141 -0
- data/lib/blather/roster.rb +118 -0
- data/lib/blather/roster_item.rb +146 -0
- data/lib/blather/stanza.rb +167 -0
- data/lib/blather/stanza/disco.rb +32 -0
- data/lib/blather/stanza/disco/capabilities.rb +161 -0
- data/lib/blather/stanza/disco/disco_info.rb +205 -0
- data/lib/blather/stanza/disco/disco_items.rb +134 -0
- data/lib/blather/stanza/iq.rb +144 -0
- data/lib/blather/stanza/iq/command.rb +339 -0
- data/lib/blather/stanza/iq/ibb.rb +86 -0
- data/lib/blather/stanza/iq/ping.rb +50 -0
- data/lib/blather/stanza/iq/query.rb +53 -0
- data/lib/blather/stanza/iq/roster.rb +185 -0
- data/lib/blather/stanza/iq/s5b.rb +208 -0
- data/lib/blather/stanza/iq/si.rb +415 -0
- data/lib/blather/stanza/iq/vcard.rb +149 -0
- data/lib/blather/stanza/message.rb +428 -0
- data/lib/blather/stanza/message/muc_user.rb +119 -0
- data/lib/blather/stanza/muc/muc_user_base.rb +54 -0
- data/lib/blather/stanza/presence.rb +172 -0
- data/lib/blather/stanza/presence/c.rb +100 -0
- data/lib/blather/stanza/presence/muc.rb +35 -0
- data/lib/blather/stanza/presence/muc_user.rb +147 -0
- data/lib/blather/stanza/presence/status.rb +218 -0
- data/lib/blather/stanza/presence/subscription.rb +100 -0
- data/lib/blather/stanza/pubsub.rb +119 -0
- data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
- data/lib/blather/stanza/pubsub/create.rb +65 -0
- data/lib/blather/stanza/pubsub/errors.rb +18 -0
- data/lib/blather/stanza/pubsub/event.rb +139 -0
- data/lib/blather/stanza/pubsub/items.rb +103 -0
- data/lib/blather/stanza/pubsub/publish.rb +103 -0
- data/lib/blather/stanza/pubsub/retract.rb +92 -0
- data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
- data/lib/blather/stanza/pubsub/subscription.rb +135 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +83 -0
- data/lib/blather/stanza/pubsub/unsubscribe.rb +84 -0
- data/lib/blather/stanza/pubsub_owner.rb +51 -0
- data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
- data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
- data/lib/blather/stanza/x.rb +416 -0
- data/lib/blather/stream.rb +266 -0
- data/lib/blather/stream/client.rb +32 -0
- data/lib/blather/stream/component.rb +39 -0
- data/lib/blather/stream/features.rb +70 -0
- data/lib/blather/stream/features/register.rb +38 -0
- data/lib/blather/stream/features/resource.rb +63 -0
- data/lib/blather/stream/features/sasl.rb +190 -0
- data/lib/blather/stream/features/session.rb +45 -0
- data/lib/blather/stream/features/tls.rb +29 -0
- data/lib/blather/stream/parser.rb +102 -0
- data/lib/blather/version.rb +3 -0
- data/lib/blather/xmpp_node.rb +94 -0
- data/spec/blather/client/client_spec.rb +687 -0
- data/spec/blather/client/dsl/pubsub_spec.rb +492 -0
- data/spec/blather/client/dsl_spec.rb +266 -0
- data/spec/blather/errors/sasl_error_spec.rb +33 -0
- data/spec/blather/errors/stanza_error_spec.rb +129 -0
- data/spec/blather/errors/stream_error_spec.rb +108 -0
- data/spec/blather/errors_spec.rb +33 -0
- data/spec/blather/file_transfer_spec.rb +135 -0
- data/spec/blather/jid_spec.rb +87 -0
- data/spec/blather/roster_item_spec.rb +134 -0
- data/spec/blather/roster_spec.rb +107 -0
- data/spec/blather/stanza/discos/disco_info_spec.rb +247 -0
- data/spec/blather/stanza/discos/disco_items_spec.rb +154 -0
- data/spec/blather/stanza/iq/command_spec.rb +206 -0
- data/spec/blather/stanza/iq/ibb_spec.rb +124 -0
- data/spec/blather/stanza/iq/ping_spec.rb +45 -0
- data/spec/blather/stanza/iq/query_spec.rb +64 -0
- data/spec/blather/stanza/iq/roster_spec.rb +139 -0
- data/spec/blather/stanza/iq/s5b_spec.rb +57 -0
- data/spec/blather/stanza/iq/si_spec.rb +98 -0
- data/spec/blather/stanza/iq/vcard_spec.rb +93 -0
- data/spec/blather/stanza/iq_spec.rb +61 -0
- data/spec/blather/stanza/message/muc_user_spec.rb +152 -0
- data/spec/blather/stanza/message_spec.rb +282 -0
- data/spec/blather/stanza/presence/c_spec.rb +56 -0
- data/spec/blather/stanza/presence/muc_spec.rb +37 -0
- data/spec/blather/stanza/presence/muc_user_spec.rb +83 -0
- data/spec/blather/stanza/presence/status_spec.rb +144 -0
- data/spec/blather/stanza/presence/subscription_spec.rb +102 -0
- data/spec/blather/stanza/presence_spec.rb +125 -0
- 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 +98 -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 +74 -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 +68 -0
- data/spec/blather/stanza/x_spec.rb +231 -0
- data/spec/blather/stanza_spec.rb +134 -0
- data/spec/blather/stream/client_spec.rb +1090 -0
- data/spec/blather/stream/component_spec.rb +108 -0
- data/spec/blather/stream/parser_spec.rb +152 -0
- data/spec/blather/stream/ssl_spec.rb +32 -0
- data/spec/blather/xmpp_node_spec.rb +47 -0
- data/spec/blather_spec.rb +34 -0
- data/spec/fixtures/pubsub.rb +311 -0
- data/spec/spec_helper.rb +17 -0
- data/yard/templates/default/class/html/handlers.erb +18 -0
- data/yard/templates/default/class/setup.rb +10 -0
- data/yard/templates/default/class/text/handlers.erb +1 -0
- metadata +459 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
class Presence
|
|
4
|
+
|
|
5
|
+
# # Status Stanza
|
|
6
|
+
#
|
|
7
|
+
# [RFC 3921 Section 2.2.2 - Presence Child Elements](http://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2)
|
|
8
|
+
#
|
|
9
|
+
# Presence stanzas are used to express an entity's current network
|
|
10
|
+
# availability (offline or online, along with various sub-states of the
|
|
11
|
+
# latter and optional user-defined descriptive text), and to notify other
|
|
12
|
+
# entities of that availability.
|
|
13
|
+
#
|
|
14
|
+
# ## "State" Attribute
|
|
15
|
+
#
|
|
16
|
+
# The `state` attribute determains the availability of the entity and can be
|
|
17
|
+
# one of the following:
|
|
18
|
+
#
|
|
19
|
+
# * `:available` -- The entity or resource is available
|
|
20
|
+
#
|
|
21
|
+
# * `:away` -- The entity or resource is temporarily away.
|
|
22
|
+
#
|
|
23
|
+
# * `:chat` -- The entity or resource is actively interested in chatting.
|
|
24
|
+
#
|
|
25
|
+
# * `:dnd` -- The entity or resource is busy (dnd = "Do Not Disturb").
|
|
26
|
+
#
|
|
27
|
+
# * `:xa` -- The entity or resource is away for an extended period (xa =
|
|
28
|
+
# "eXtended Away").
|
|
29
|
+
#
|
|
30
|
+
# Blather provides a helper for each possible state:
|
|
31
|
+
#
|
|
32
|
+
# Status#available?
|
|
33
|
+
# Status#away?
|
|
34
|
+
# Status#chat?
|
|
35
|
+
# Status#dnd?
|
|
36
|
+
# Status#xa?
|
|
37
|
+
#
|
|
38
|
+
# Blather treats the `type` attribute like a normal ruby object attribute
|
|
39
|
+
# providing a getter and setter. The default `type` is `available`.
|
|
40
|
+
#
|
|
41
|
+
# status = Status.new
|
|
42
|
+
# status.state # => :available
|
|
43
|
+
# status.available? # => true
|
|
44
|
+
# status.state = :away
|
|
45
|
+
# status.away? # => true
|
|
46
|
+
# status.available? # => false
|
|
47
|
+
# status
|
|
48
|
+
# status.state = :invalid # => RuntimeError
|
|
49
|
+
#
|
|
50
|
+
# ## "Type" Attribute
|
|
51
|
+
#
|
|
52
|
+
# The `type` attribute is inherited from Presence, but limits the value to
|
|
53
|
+
# either `nil` or `:unavailable` as these are the only types that relate to
|
|
54
|
+
# Status.
|
|
55
|
+
#
|
|
56
|
+
# ## "Priority" Attribute
|
|
57
|
+
#
|
|
58
|
+
# The `priority` attribute sets the priority of the status for the entity
|
|
59
|
+
# and must be an integer between -128 and 127.
|
|
60
|
+
#
|
|
61
|
+
# ## "Message" Attribute
|
|
62
|
+
#
|
|
63
|
+
# The optional `message` element contains XML character data specifying a
|
|
64
|
+
# natural-language description of availability status. It is normally used
|
|
65
|
+
# in conjunction with the show element to provide a detailed description of
|
|
66
|
+
# an availability state (e.g., "In a meeting").
|
|
67
|
+
#
|
|
68
|
+
# Blather treats the `message` attribute like a normal ruby object attribute
|
|
69
|
+
# providing a getter and setter. The default `message` is nil.
|
|
70
|
+
#
|
|
71
|
+
# status = Status.new
|
|
72
|
+
# status.message # => nil
|
|
73
|
+
# status.message = "gone!"
|
|
74
|
+
# status.message # => "gone!"
|
|
75
|
+
#
|
|
76
|
+
# @handler :status
|
|
77
|
+
class Status < Presence
|
|
78
|
+
# @private
|
|
79
|
+
VALID_STATES = [:away, :chat, :dnd, :xa].freeze
|
|
80
|
+
VALID_TYPES = [:unavailable].freeze
|
|
81
|
+
|
|
82
|
+
include Comparable
|
|
83
|
+
|
|
84
|
+
register :status, :status
|
|
85
|
+
|
|
86
|
+
# Create a new Status stanza
|
|
87
|
+
#
|
|
88
|
+
# @param [<:away, :chat, :dnd, :xa>] state the state of the status
|
|
89
|
+
# @param [#to_s] message a message to send with the status
|
|
90
|
+
def self.new(state = nil, message = nil)
|
|
91
|
+
node = super()
|
|
92
|
+
node.state = state
|
|
93
|
+
node.message = message
|
|
94
|
+
node
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
module InstanceMethods
|
|
98
|
+
|
|
99
|
+
# Check if the state is available
|
|
100
|
+
#
|
|
101
|
+
# @return [true, false]
|
|
102
|
+
def available?
|
|
103
|
+
self.state == :available
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Check if the state is away
|
|
107
|
+
#
|
|
108
|
+
# @return [true, false]
|
|
109
|
+
def away?
|
|
110
|
+
self.state == :away
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Check if the state is chat
|
|
114
|
+
#
|
|
115
|
+
# @return [true, false]
|
|
116
|
+
def chat?
|
|
117
|
+
self.state == :chat
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Check if the state is dnd
|
|
121
|
+
#
|
|
122
|
+
# @return [true, false]
|
|
123
|
+
def dnd?
|
|
124
|
+
self.state == :dnd
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Check if the state is xa
|
|
128
|
+
#
|
|
129
|
+
# @return [true, false]
|
|
130
|
+
def xa?
|
|
131
|
+
self.state == :xa
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Set the state
|
|
135
|
+
# Ensure state is one of :available, :away, :chat, :dnd, :xa or nil
|
|
136
|
+
#
|
|
137
|
+
# @param [<:available, :away, :chat, :dnd, :xa, nil>] state
|
|
138
|
+
def state=(state) # :nodoc:
|
|
139
|
+
state = state.to_sym if state
|
|
140
|
+
state = nil if state == :available
|
|
141
|
+
if state && !VALID_STATES.include?(state)
|
|
142
|
+
raise ArgumentError, "Invalid Status (#{state}), use: #{VALID_STATES*' '}"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
set_content_for :show, state
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Get the state of the status
|
|
149
|
+
#
|
|
150
|
+
# @return [<:available, :away, :chat, :dnd, :xa>]
|
|
151
|
+
def state
|
|
152
|
+
state = type || content_from(:show)
|
|
153
|
+
state = :available if state.blank?
|
|
154
|
+
state.to_sym
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Set the priority of the status
|
|
158
|
+
# Ensures priority is between -128 and 127
|
|
159
|
+
#
|
|
160
|
+
# @param [Fixnum<-128...127>] new_priority
|
|
161
|
+
def priority=(new_priority) # :nodoc:
|
|
162
|
+
if new_priority && !(-128..127).include?(new_priority.to_i)
|
|
163
|
+
raise ArgumentError, 'Priority must be between -128 and +127'
|
|
164
|
+
end
|
|
165
|
+
set_content_for :priority, new_priority
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Get the priority of the status
|
|
169
|
+
#
|
|
170
|
+
# @return [Fixnum<-128...127>]
|
|
171
|
+
def priority
|
|
172
|
+
read_content(:priority).to_i
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Get the status message
|
|
176
|
+
#
|
|
177
|
+
# @return [String, nil]
|
|
178
|
+
def message
|
|
179
|
+
read_content :status
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Set the status message
|
|
183
|
+
#
|
|
184
|
+
# @param [String, nil] message
|
|
185
|
+
def message=(message)
|
|
186
|
+
set_content_for :status, message
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Compare status based on priority and state:
|
|
190
|
+
# unavailable status is always less valuable than others
|
|
191
|
+
# Raises an error if the JIDs aren't the same
|
|
192
|
+
#
|
|
193
|
+
# @param [Blather::Stanza::Presence::Status] o
|
|
194
|
+
# @return [true,false]
|
|
195
|
+
def <=>(o)
|
|
196
|
+
if self.from || o.from
|
|
197
|
+
unless self.from.stripped == o.from.stripped
|
|
198
|
+
raise ArgumentError, "Cannot compare status from different JIDs: #{[self.from, o.from].inspect}"
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
if (self.type.nil? && o.type.nil?) || (!self.type.nil? && !o.type.nil?)
|
|
203
|
+
self.priority <=> o.priority
|
|
204
|
+
elsif self.type.nil? && !o.type.nil?
|
|
205
|
+
1
|
|
206
|
+
elsif !self.type.nil? && o.type.nil?
|
|
207
|
+
-1
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
include InstanceMethods
|
|
213
|
+
|
|
214
|
+
end #Status
|
|
215
|
+
|
|
216
|
+
end #Presence
|
|
217
|
+
end #Stanza
|
|
218
|
+
end #Blather
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
class Presence
|
|
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
|
|
14
|
+
class Subscription < Presence
|
|
15
|
+
register :subscription, :subscription
|
|
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
|
|
21
|
+
def self.new(to = nil, type = nil)
|
|
22
|
+
node = super()
|
|
23
|
+
node.to = to
|
|
24
|
+
node.type = type
|
|
25
|
+
node
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module InstanceMethods
|
|
29
|
+
|
|
30
|
+
# Set the to value on the stanza
|
|
31
|
+
#
|
|
32
|
+
# @param [Blather::JID, #to_s] to a JID to subscribe to
|
|
33
|
+
def to=(to)
|
|
34
|
+
super JID.new(to).stripped
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Transform the stanza into an approve stanza
|
|
38
|
+
# makes approving requests simple
|
|
39
|
+
#
|
|
40
|
+
# @example approve an incoming request
|
|
41
|
+
# subscription(:request?) { |s| write_to_stream s.approve! }
|
|
42
|
+
# @return [self]
|
|
43
|
+
def approve!
|
|
44
|
+
self.type = :subscribed
|
|
45
|
+
reply_if_needed!
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Transform the stanza into a refuse stanza
|
|
49
|
+
# makes refusing requests simple
|
|
50
|
+
#
|
|
51
|
+
# @example refuse an incoming request
|
|
52
|
+
# subscription(:request?) { |s| write_to_stream s.refuse! }
|
|
53
|
+
# @return [self]
|
|
54
|
+
def refuse!
|
|
55
|
+
self.type = :unsubscribed
|
|
56
|
+
reply_if_needed!
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Transform the stanza into an unsubscribe stanza
|
|
60
|
+
# makes unsubscribing simple
|
|
61
|
+
#
|
|
62
|
+
# @return [self]
|
|
63
|
+
def unsubscribe!
|
|
64
|
+
self.type = :unsubscribe
|
|
65
|
+
reply_if_needed!
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Transform the stanza into a cancel stanza
|
|
69
|
+
# makes canceling simple
|
|
70
|
+
#
|
|
71
|
+
# @return [self]
|
|
72
|
+
def cancel!
|
|
73
|
+
self.type = :unsubscribed
|
|
74
|
+
reply_if_needed!
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Transform the stanza into a request stanza
|
|
78
|
+
# makes requests simple
|
|
79
|
+
#
|
|
80
|
+
# @return [self]
|
|
81
|
+
def request!
|
|
82
|
+
self.type = :subscribe
|
|
83
|
+
reply_if_needed!
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Check if the stanza is a request
|
|
87
|
+
#
|
|
88
|
+
# @return [true, false]
|
|
89
|
+
def request?
|
|
90
|
+
self.type == :subscribe
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
include InstanceMethods
|
|
95
|
+
|
|
96
|
+
end #Subscription
|
|
97
|
+
|
|
98
|
+
end #Presence
|
|
99
|
+
end #Stanza
|
|
100
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
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
|
|
12
|
+
class PubSub < Iq
|
|
13
|
+
register :pubsub_node, :pubsub, 'http://jabber.org/protocol/pubsub'
|
|
14
|
+
|
|
15
|
+
# @private
|
|
16
|
+
def self.import(node)
|
|
17
|
+
klass = nil
|
|
18
|
+
if pubsub = node.document.find_first('//ns:pubsub', :ns => self.registered_ns)
|
|
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
|
|
23
|
+
end
|
|
24
|
+
(klass || self).new(node[:type]).inherit(node)
|
|
25
|
+
end
|
|
26
|
+
|
|
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
|
|
32
|
+
def self.new(type = nil, host = nil)
|
|
33
|
+
new_node = super type
|
|
34
|
+
new_node.to = host
|
|
35
|
+
new_node.pubsub
|
|
36
|
+
new_node
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Overrides the parent to ensure the current pubsub node is destroyed before
|
|
40
|
+
# inheritting the new content
|
|
41
|
+
#
|
|
42
|
+
# @private
|
|
43
|
+
def inherit(node)
|
|
44
|
+
remove_children :pubsub
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Get or create the pubsub node on the stanza
|
|
49
|
+
#
|
|
50
|
+
# @return [Blather::XMPPNode]
|
|
51
|
+
def pubsub
|
|
52
|
+
p = find_first('ns:pubsub', :ns => self.class.registered_ns) ||
|
|
53
|
+
find_first('pubsub', :ns => self.class.registered_ns)
|
|
54
|
+
|
|
55
|
+
unless p
|
|
56
|
+
self << (p = XMPPNode.new('pubsub', self.document))
|
|
57
|
+
p.namespace = self.class.registered_ns
|
|
58
|
+
end
|
|
59
|
+
p
|
|
60
|
+
end
|
|
61
|
+
end # PubSub
|
|
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
|
|
67
|
+
class PubSubItem < XMPPNode
|
|
68
|
+
# Create a new PubSubItem
|
|
69
|
+
#
|
|
70
|
+
# @param [String, nil] id the id of the stanza
|
|
71
|
+
# @param [#to_s, nil] payload the payload to attach to this item.
|
|
72
|
+
# @param [XML::Document, nil] document the document the node should be
|
|
73
|
+
# attached to. This should be the document of the parent PubSub node.
|
|
74
|
+
def self.new(id = nil, payload = nil, document = nil)
|
|
75
|
+
new_node = super 'item', document
|
|
76
|
+
new_node.id = id
|
|
77
|
+
new_node.payload = payload if payload
|
|
78
|
+
new_node
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Get the item's ID
|
|
82
|
+
#
|
|
83
|
+
# @return [String, nil]
|
|
84
|
+
def id
|
|
85
|
+
read_attr :id
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Set the item's ID
|
|
89
|
+
#
|
|
90
|
+
# @param [#to_s] id the new ID
|
|
91
|
+
def id=(id)
|
|
92
|
+
write_attr :id, id
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
alias_method :payload_node, :child
|
|
96
|
+
|
|
97
|
+
# Get the item's payload
|
|
98
|
+
#
|
|
99
|
+
# @return [String, nil]
|
|
100
|
+
def payload
|
|
101
|
+
children.empty? ? nil : children.to_s
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Set the item's payload
|
|
105
|
+
#
|
|
106
|
+
# @param [String, XMPPNode, nil] payload the payload
|
|
107
|
+
def payload=(payload)
|
|
108
|
+
children.map &:remove
|
|
109
|
+
return unless payload
|
|
110
|
+
if payload.is_a?(String)
|
|
111
|
+
self.content = payload
|
|
112
|
+
else
|
|
113
|
+
self << payload
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end # PubSubItem
|
|
117
|
+
|
|
118
|
+
end # Stanza
|
|
119
|
+
end # Blather
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
class PubSub
|
|
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
|
|
10
|
+
class Affiliations < PubSub
|
|
11
|
+
register :pubsub_affiliations, :affiliations, self.registered_ns
|
|
12
|
+
|
|
13
|
+
include Enumerable
|
|
14
|
+
alias_method :find, :xpath
|
|
15
|
+
|
|
16
|
+
# Overrides the parent to ensure an affiliation node is created
|
|
17
|
+
# @private
|
|
18
|
+
def self.new(type = nil, host = nil)
|
|
19
|
+
new_node = super
|
|
20
|
+
new_node.affiliations
|
|
21
|
+
new_node
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Kill the affiliations node before running inherit
|
|
25
|
+
# @private
|
|
26
|
+
def inherit(node)
|
|
27
|
+
affiliations.remove
|
|
28
|
+
super
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Get or create the affiliations node
|
|
32
|
+
#
|
|
33
|
+
# @return [Blather::XMPPNode]
|
|
34
|
+
def affiliations
|
|
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
|
|
39
|
+
aff
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Convenience method for iterating over the list
|
|
43
|
+
#
|
|
44
|
+
# @see #list for the format of the yielded input
|
|
45
|
+
def each(&block)
|
|
46
|
+
list.each &block
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Get the number of affiliations
|
|
50
|
+
#
|
|
51
|
+
# @return [Fixnum]
|
|
52
|
+
def size
|
|
53
|
+
list.size
|
|
54
|
+
end
|
|
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>>]
|
|
67
|
+
def list
|
|
68
|
+
items = affiliations.find('//ns:affiliation', :ns => self.class.registered_ns)
|
|
69
|
+
items.inject({}) do |hash, item|
|
|
70
|
+
hash[item[:affiliation].to_sym] ||= []
|
|
71
|
+
hash[item[:affiliation].to_sym] << item[:node]
|
|
72
|
+
hash
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end # Affiliations
|
|
76
|
+
|
|
77
|
+
end # PubSub
|
|
78
|
+
end # Stanza
|
|
79
|
+
end # Blather
|