shingara-blather 0.4.8
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.md +162 -0
- data/examples/echo.rb +18 -0
- data/examples/execute.rb +16 -0
- data/examples/ping_pong.rb +37 -0
- data/examples/print_hierarchy.rb +76 -0
- data/examples/rosterprint.rb +14 -0
- data/examples/stream_only.rb +27 -0
- data/examples/xmpp4r/echo.rb +35 -0
- data/lib/blather/client/client.rb +310 -0
- data/lib/blather/client/dsl/pubsub.rb +170 -0
- data/lib/blather/client/dsl.rb +264 -0
- data/lib/blather/client.rb +87 -0
- data/lib/blather/core_ext/nokogiri.rb +40 -0
- data/lib/blather/errors/sasl_error.rb +43 -0
- data/lib/blather/errors/stanza_error.rb +107 -0
- data/lib/blather/errors/stream_error.rb +82 -0
- data/lib/blather/errors.rb +69 -0
- data/lib/blather/jid.rb +142 -0
- data/lib/blather/roster.rb +111 -0
- data/lib/blather/roster_item.rb +122 -0
- data/lib/blather/stanza/disco/disco_info.rb +176 -0
- data/lib/blather/stanza/disco/disco_items.rb +132 -0
- data/lib/blather/stanza/disco.rb +25 -0
- data/lib/blather/stanza/iq/query.rb +53 -0
- data/lib/blather/stanza/iq/roster.rb +179 -0
- data/lib/blather/stanza/iq.rb +138 -0
- data/lib/blather/stanza/message.rb +332 -0
- data/lib/blather/stanza/presence/status.rb +212 -0
- data/lib/blather/stanza/presence/subscription.rb +101 -0
- data/lib/blather/stanza/presence.rb +163 -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 +123 -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 +134 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +81 -0
- data/lib/blather/stanza/pubsub/unsubscribe.rb +68 -0
- data/lib/blather/stanza/pubsub.rb +129 -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/pubsub_owner.rb +51 -0
- data/lib/blather/stanza.rb +149 -0
- data/lib/blather/stream/client.rb +31 -0
- data/lib/blather/stream/component.rb +38 -0
- data/lib/blather/stream/features/resource.rb +63 -0
- data/lib/blather/stream/features/sasl.rb +187 -0
- data/lib/blather/stream/features/session.rb +44 -0
- data/lib/blather/stream/features/tls.rb +28 -0
- data/lib/blather/stream/features.rb +53 -0
- data/lib/blather/stream/parser.rb +102 -0
- data/lib/blather/stream.rb +231 -0
- data/lib/blather/xmpp_node.rb +218 -0
- data/lib/blather.rb +78 -0
- data/spec/blather/client/client_spec.rb +559 -0
- data/spec/blather/client/dsl/pubsub_spec.rb +462 -0
- data/spec/blather/client/dsl_spec.rb +143 -0
- data/spec/blather/core_ext/nokogiri_spec.rb +83 -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/jid_spec.rb +87 -0
- data/spec/blather/roster_item_spec.rb +96 -0
- data/spec/blather/roster_spec.rb +103 -0
- data/spec/blather/stanza/discos/disco_info_spec.rb +226 -0
- data/spec/blather/stanza/discos/disco_items_spec.rb +148 -0
- data/spec/blather/stanza/iq/query_spec.rb +64 -0
- data/spec/blather/stanza/iq/roster_spec.rb +140 -0
- data/spec/blather/stanza/iq_spec.rb +45 -0
- data/spec/blather/stanza/message_spec.rb +132 -0
- data/spec/blather/stanza/presence/status_spec.rb +132 -0
- data/spec/blather/stanza/presence/subscription_spec.rb +105 -0
- data/spec/blather/stanza/presence_spec.rb +66 -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 +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 +67 -0
- data/spec/blather/stanza_spec.rb +116 -0
- data/spec/blather/stream/client_spec.rb +1011 -0
- data/spec/blather/stream/component_spec.rb +95 -0
- data/spec/blather/stream/parser_spec.rb +145 -0
- data/spec/blather/xmpp_node_spec.rb +231 -0
- data/spec/fixtures/pubsub.rb +311 -0
- data/spec/spec_helper.rb +43 -0
- metadata +249 -0
@@ -0,0 +1,212 @@
|
|
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
|
+
VALID_STATES = [:away, :chat, :dnd, :xa].freeze
|
79
|
+
|
80
|
+
include Comparable
|
81
|
+
|
82
|
+
register :status, :status
|
83
|
+
|
84
|
+
# Create a new Status stanza
|
85
|
+
#
|
86
|
+
# @param [<:away, :chat, :dnd, :xa>] state the state of the status
|
87
|
+
# @param [#to_s] message a message to send with the status
|
88
|
+
def self.new(state = nil, message = nil)
|
89
|
+
node = super()
|
90
|
+
node.state = state
|
91
|
+
node.message = message
|
92
|
+
node
|
93
|
+
end
|
94
|
+
|
95
|
+
# Check if the state is available
|
96
|
+
#
|
97
|
+
# @return [true, false]
|
98
|
+
def available?
|
99
|
+
self.state == :available
|
100
|
+
end
|
101
|
+
|
102
|
+
# Check if the state is away
|
103
|
+
#
|
104
|
+
# @return [true, false]
|
105
|
+
def away?
|
106
|
+
self.state == :away
|
107
|
+
end
|
108
|
+
|
109
|
+
# Check if the state is chat
|
110
|
+
#
|
111
|
+
# @return [true, false]
|
112
|
+
def chat?
|
113
|
+
self.state == :chat
|
114
|
+
end
|
115
|
+
|
116
|
+
# Check if the state is dnd
|
117
|
+
#
|
118
|
+
# @return [true, false]
|
119
|
+
def dnd?
|
120
|
+
self.state == :dnd
|
121
|
+
end
|
122
|
+
|
123
|
+
# Check if the state is xa
|
124
|
+
#
|
125
|
+
# @return [true, false]
|
126
|
+
def xa?
|
127
|
+
self.state == :xa
|
128
|
+
end
|
129
|
+
|
130
|
+
# Set the type attribute
|
131
|
+
# Ensures type is nil or :unavailable
|
132
|
+
#
|
133
|
+
# @param [<:unavailable, nil>] type the type
|
134
|
+
def type=(type)
|
135
|
+
if type && type.to_sym != :unavailable
|
136
|
+
raise ArgumentError, "Invalid type (#{type}). Must be nil or unavailable"
|
137
|
+
end
|
138
|
+
super
|
139
|
+
end
|
140
|
+
|
141
|
+
# Set the state
|
142
|
+
# Ensure state is one of :available, :away, :chat, :dnd, :xa or nil
|
143
|
+
#
|
144
|
+
# @param [<:available, :away, :chat, :dnd, :xa, nil>] state
|
145
|
+
def state=(state) # :nodoc:
|
146
|
+
state = state.to_sym if state
|
147
|
+
state = nil if state == :available
|
148
|
+
if state && !VALID_STATES.include?(state)
|
149
|
+
raise ArgumentError, "Invalid Status (#{state}), use: #{VALID_STATES*' '}"
|
150
|
+
end
|
151
|
+
|
152
|
+
set_content_for :show, state
|
153
|
+
end
|
154
|
+
|
155
|
+
# Get the state of the status
|
156
|
+
#
|
157
|
+
# @return [<:available, :away, :chat, :dnd, :xa>]
|
158
|
+
def state
|
159
|
+
state = type || content_from(:show)
|
160
|
+
state = :available if state.blank?
|
161
|
+
state.to_sym
|
162
|
+
end
|
163
|
+
|
164
|
+
# Set the priority of the status
|
165
|
+
# Ensures priority is between -128 and 127
|
166
|
+
#
|
167
|
+
# @param [Fixnum<-128...127>] new_priority
|
168
|
+
def priority=(new_priority) # :nodoc:
|
169
|
+
if new_priority && !(-128..127).include?(new_priority.to_i)
|
170
|
+
raise ArgumentError, 'Priority must be between -128 and +127'
|
171
|
+
end
|
172
|
+
set_content_for :priority, new_priority
|
173
|
+
end
|
174
|
+
|
175
|
+
# Get the priority of the status
|
176
|
+
#
|
177
|
+
# @return [Fixnum<-128...127>]
|
178
|
+
def priority
|
179
|
+
read_content(:priority).to_i
|
180
|
+
end
|
181
|
+
|
182
|
+
# Get the status message
|
183
|
+
#
|
184
|
+
# @return [String, nil]
|
185
|
+
def message
|
186
|
+
read_content :status
|
187
|
+
end
|
188
|
+
|
189
|
+
# Set the status message
|
190
|
+
#
|
191
|
+
# @param [String, nil] message
|
192
|
+
def message=(message)
|
193
|
+
set_content_for :status, message
|
194
|
+
end
|
195
|
+
|
196
|
+
# Compare status based on priority
|
197
|
+
# raises an error if the JIDs aren't the same
|
198
|
+
#
|
199
|
+
# @param [Blather::Stanza::Presence::Status] o
|
200
|
+
# @return [true,false]
|
201
|
+
def <=>(o)
|
202
|
+
unless self.from && o.from && self.from.stripped == o.from.stripped
|
203
|
+
raise ArgumentError, "Cannot compare status from different JIDs: #{[self.from, o.from].inspect}"
|
204
|
+
end
|
205
|
+
self.priority <=> o.priority
|
206
|
+
end
|
207
|
+
|
208
|
+
end #Status
|
209
|
+
|
210
|
+
end #Presence
|
211
|
+
end #Stanza
|
212
|
+
end #Blather
|
@@ -0,0 +1,101 @@
|
|
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
|
+
# @private
|
29
|
+
def inherit(node)
|
30
|
+
inherit_attrs node.attributes
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set the to value on the stanza
|
35
|
+
#
|
36
|
+
# @param [Blather::JID, #to_s] to a JID to subscribe to
|
37
|
+
def to=(to)
|
38
|
+
super JID.new(to).stripped
|
39
|
+
end
|
40
|
+
|
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]
|
47
|
+
def approve!
|
48
|
+
self.type = :subscribed
|
49
|
+
reply_if_needed!
|
50
|
+
end
|
51
|
+
|
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]
|
58
|
+
def refuse!
|
59
|
+
self.type = :unsubscribed
|
60
|
+
reply_if_needed!
|
61
|
+
end
|
62
|
+
|
63
|
+
# Transform the stanza into an unsubscribe stanza
|
64
|
+
# makes unsubscribing simple
|
65
|
+
#
|
66
|
+
# @return [self]
|
67
|
+
def unsubscribe!
|
68
|
+
self.type = :unsubscribe
|
69
|
+
reply_if_needed!
|
70
|
+
end
|
71
|
+
|
72
|
+
# Transform the stanza into a cancel stanza
|
73
|
+
# makes canceling simple
|
74
|
+
#
|
75
|
+
# @return [self]
|
76
|
+
def cancel!
|
77
|
+
self.type = :unsubscribed
|
78
|
+
reply_if_needed!
|
79
|
+
end
|
80
|
+
|
81
|
+
# Transform the stanza into a request stanza
|
82
|
+
# makes requests simple
|
83
|
+
#
|
84
|
+
# @return [self]
|
85
|
+
def request!
|
86
|
+
self.type = :subscribe
|
87
|
+
reply_if_needed!
|
88
|
+
end
|
89
|
+
|
90
|
+
# Check if the stanza is a request
|
91
|
+
#
|
92
|
+
# @return [true, false]
|
93
|
+
def request?
|
94
|
+
self.type == :subscribe
|
95
|
+
end
|
96
|
+
|
97
|
+
end #Subscription
|
98
|
+
|
99
|
+
end #Presence
|
100
|
+
end #Stanza
|
101
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Blather
|
2
|
+
class Stanza
|
3
|
+
|
4
|
+
# # Presence Stanza
|
5
|
+
#
|
6
|
+
# [RFC 3921 Section 2.2 - Presence Syntax](http://xmpp.org/rfcs/rfc3921.html#stanzas-presence)
|
7
|
+
#
|
8
|
+
# Within Blather most of the interaction with Presence stanzas will be
|
9
|
+
# through one of its child classes: Status or Subscription.
|
10
|
+
#
|
11
|
+
# Presence stanzas are used to express an entity's current network
|
12
|
+
# availability (offline or online, along with various sub-states of the
|
13
|
+
# latter and optional user-defined descriptive text), and to notify other
|
14
|
+
# entities of that availability. Presence stanzas are also used to negotiate
|
15
|
+
# and manage subscriptions to the presence of other entities.
|
16
|
+
#
|
17
|
+
# ## "Type" Attribute
|
18
|
+
#
|
19
|
+
# The `type` attribute of a presence stanza is optional. A presence stanza
|
20
|
+
# that does not possess a `type` attribute is used to signal to the server
|
21
|
+
# that the sender is online and available for communication. If included,
|
22
|
+
# the `type` attribute specifies a lack of availability, a request to manage
|
23
|
+
# a subscription to another entity's presence, a request for another
|
24
|
+
# entity's current presence, or an error related to a previously-sent
|
25
|
+
# presence stanza. If included, the `type` attribute must have one of the
|
26
|
+
# following values:
|
27
|
+
#
|
28
|
+
# * `:unavailable` -- Signals that the entity is no longer available for
|
29
|
+
# communication
|
30
|
+
#
|
31
|
+
# * `:subscribe` -- The sender wishes to subscribe to the recipient's
|
32
|
+
# presence.
|
33
|
+
#
|
34
|
+
# * `:subscribed` -- The sender has allowed the recipient to receive their
|
35
|
+
# presence.
|
36
|
+
#
|
37
|
+
# * `:unsubscribe` -- The sender is unsubscribing from another entity's
|
38
|
+
# presence.
|
39
|
+
#
|
40
|
+
# * `:unsubscribed` -- The subscription request has been denied or a
|
41
|
+
# previously-granted subscription has been cancelled.
|
42
|
+
#
|
43
|
+
# * `:probe` -- A request for an entity's current presence; should be
|
44
|
+
# generated only by a server on behalf of a user.
|
45
|
+
#
|
46
|
+
# * `:error` -- An error has occurred regarding processing or delivery of a
|
47
|
+
# previously-sent presence stanza.
|
48
|
+
#
|
49
|
+
# Blather provides a helper for each possible type:
|
50
|
+
#
|
51
|
+
# Presence#unavailabe?
|
52
|
+
# Presence#unavailable?
|
53
|
+
# Presence#subscribe?
|
54
|
+
# Presence#subscribed?
|
55
|
+
# Presence#unsubscribe?
|
56
|
+
# Presence#unsubscribed?
|
57
|
+
# Presence#probe?
|
58
|
+
# Presence#error?
|
59
|
+
#
|
60
|
+
# Blather treats the `type` attribute like a normal ruby object attribute
|
61
|
+
# providing a getter and setter. The default `type` is nil.
|
62
|
+
#
|
63
|
+
# presence = Presence.new
|
64
|
+
# presence.type # => nil
|
65
|
+
# presence.type = :unavailable
|
66
|
+
# presence.unavailable? # => true
|
67
|
+
# presence.error? # => false
|
68
|
+
#
|
69
|
+
# presence.type = :invalid # => RuntimeError
|
70
|
+
#
|
71
|
+
# @handler :presence
|
72
|
+
class Presence < Stanza
|
73
|
+
VALID_TYPES = [ :unavailable,
|
74
|
+
:subscribe,
|
75
|
+
:subscribed,
|
76
|
+
:unsubscribe,
|
77
|
+
:unsubscribed,
|
78
|
+
:probe,
|
79
|
+
:error].freeze
|
80
|
+
|
81
|
+
register :presence
|
82
|
+
|
83
|
+
# Creates a class based on the presence type
|
84
|
+
# either a Status or Subscription object is created based
|
85
|
+
# on the type attribute.
|
86
|
+
# If neither is found it instantiates a Presence object
|
87
|
+
def self.import(node) # :nodoc:
|
88
|
+
klass = case node['type']
|
89
|
+
when nil, 'unavailable' then Status
|
90
|
+
when /subscribe/ then Subscription
|
91
|
+
else self
|
92
|
+
end
|
93
|
+
klass.new.inherit(node)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Ensure element_name is "presence" for all subclasses
|
97
|
+
def self.new
|
98
|
+
super :presence
|
99
|
+
end
|
100
|
+
|
101
|
+
# Check if the IQ is of type :unavailable
|
102
|
+
#
|
103
|
+
# @return [true, false]
|
104
|
+
def unavailable?
|
105
|
+
self.type == :unavailable
|
106
|
+
end
|
107
|
+
|
108
|
+
# Check if the IQ is of type :subscribe
|
109
|
+
#
|
110
|
+
# @return [true, false]
|
111
|
+
def subscribe?
|
112
|
+
self.type == :subscribe
|
113
|
+
end
|
114
|
+
|
115
|
+
# Check if the IQ is of type :subscribed
|
116
|
+
#
|
117
|
+
# @return [true, false]
|
118
|
+
def subscribed?
|
119
|
+
self.type == :subscribed
|
120
|
+
end
|
121
|
+
|
122
|
+
# Check if the IQ is of type :unsubscribe
|
123
|
+
#
|
124
|
+
# @return [true, false]
|
125
|
+
def unsubscribe?
|
126
|
+
self.type == :unsubscribe
|
127
|
+
end
|
128
|
+
|
129
|
+
# Check if the IQ is of type :unsubscribed
|
130
|
+
#
|
131
|
+
# @return [true, false]
|
132
|
+
def unsubscribed?
|
133
|
+
self.type == :unsubscribed
|
134
|
+
end
|
135
|
+
|
136
|
+
# Check if the IQ is of type :probe
|
137
|
+
#
|
138
|
+
# @return [true, false]
|
139
|
+
def probe?
|
140
|
+
self.type == :probe
|
141
|
+
end
|
142
|
+
|
143
|
+
# Check if the IQ is of type :error
|
144
|
+
#
|
145
|
+
# @return [true, false]
|
146
|
+
def error?
|
147
|
+
self.type == :error
|
148
|
+
end
|
149
|
+
|
150
|
+
# Ensures type is one of Blather::Stanza::Presence::VALID_TYPES
|
151
|
+
#
|
152
|
+
# @param [#to_sym] type the Presence type. Must be one of VALID_TYPES
|
153
|
+
def type=(type)
|
154
|
+
if type && !VALID_TYPES.include?(type.to_sym)
|
155
|
+
raise ArgumentError, "Invalid Type (#{type}), use: #{VALID_TYPES*' '}"
|
156
|
+
end
|
157
|
+
super
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end #Stanza
|
163
|
+
end
|
@@ -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
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Blather
|
2
|
+
class Stanza
|
3
|
+
class PubSub
|
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
|
10
|
+
class Create < PubSub
|
11
|
+
register :pubsub_create, :create, self.registered_ns
|
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
|
18
|
+
def self.new(type = :set, host = nil, node = nil)
|
19
|
+
new_node = super(type, host)
|
20
|
+
new_node.create_node
|
21
|
+
new_node.configure_node
|
22
|
+
new_node.node = node
|
23
|
+
new_node
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the name of the node to create
|
27
|
+
#
|
28
|
+
# @return [String, nil]
|
29
|
+
def node
|
30
|
+
create_node[:node]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set the name of the node to create
|
34
|
+
#
|
35
|
+
# @param [String, nil] node
|
36
|
+
def node=(node)
|
37
|
+
create_node[:node] = node
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get or create the actual create node on the stanza
|
41
|
+
#
|
42
|
+
# @return [Balther::XMPPNode]
|
43
|
+
def create_node
|
44
|
+
unless create_node = pubsub.find_first('ns:create', :ns => self.class.registered_ns)
|
45
|
+
self.pubsub << (create_node = XMPPNode.new('create', self.document))
|
46
|
+
create_node.namespace = self.pubsub.namespace
|
47
|
+
end
|
48
|
+
create_node
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get or create the actual configure node on the stanza
|
52
|
+
#
|
53
|
+
# @return [Blather::XMPPNode]
|
54
|
+
def configure_node
|
55
|
+
unless configure_node = pubsub.find_first('ns:configure', :ns => self.class.registered_ns)
|
56
|
+
self.pubsub << (configure_node = XMPPNode.new('configure', self.document))
|
57
|
+
configure_node.namespace = self.pubsub.namespace
|
58
|
+
end
|
59
|
+
configure_node
|
60
|
+
end
|
61
|
+
end # Create
|
62
|
+
|
63
|
+
end # PubSub
|
64
|
+
end # Stanza
|
65
|
+
end # Blather
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Blather
|
2
|
+
class Stanza
|
3
|
+
|
4
|
+
# # PusSub Error Stanza
|
5
|
+
#
|
6
|
+
# @private
|
7
|
+
class PubSubErrors < PubSub
|
8
|
+
def node
|
9
|
+
read_attr :node
|
10
|
+
end
|
11
|
+
|
12
|
+
def node=(node)
|
13
|
+
write_attr :node, node
|
14
|
+
end
|
15
|
+
end # PubSubErrors
|
16
|
+
|
17
|
+
end # Stanza
|
18
|
+
end # Blather
|