shingara-blather 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 (100) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +162 -0
  3. data/examples/echo.rb +18 -0
  4. data/examples/execute.rb +16 -0
  5. data/examples/ping_pong.rb +37 -0
  6. data/examples/print_hierarchy.rb +76 -0
  7. data/examples/rosterprint.rb +14 -0
  8. data/examples/stream_only.rb +27 -0
  9. data/examples/xmpp4r/echo.rb +35 -0
  10. data/lib/blather/client/client.rb +310 -0
  11. data/lib/blather/client/dsl/pubsub.rb +170 -0
  12. data/lib/blather/client/dsl.rb +264 -0
  13. data/lib/blather/client.rb +87 -0
  14. data/lib/blather/core_ext/nokogiri.rb +40 -0
  15. data/lib/blather/errors/sasl_error.rb +43 -0
  16. data/lib/blather/errors/stanza_error.rb +107 -0
  17. data/lib/blather/errors/stream_error.rb +82 -0
  18. data/lib/blather/errors.rb +69 -0
  19. data/lib/blather/jid.rb +142 -0
  20. data/lib/blather/roster.rb +111 -0
  21. data/lib/blather/roster_item.rb +122 -0
  22. data/lib/blather/stanza/disco/disco_info.rb +176 -0
  23. data/lib/blather/stanza/disco/disco_items.rb +132 -0
  24. data/lib/blather/stanza/disco.rb +25 -0
  25. data/lib/blather/stanza/iq/query.rb +53 -0
  26. data/lib/blather/stanza/iq/roster.rb +179 -0
  27. data/lib/blather/stanza/iq.rb +138 -0
  28. data/lib/blather/stanza/message.rb +332 -0
  29. data/lib/blather/stanza/presence/status.rb +212 -0
  30. data/lib/blather/stanza/presence/subscription.rb +101 -0
  31. data/lib/blather/stanza/presence.rb +163 -0
  32. data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
  33. data/lib/blather/stanza/pubsub/create.rb +65 -0
  34. data/lib/blather/stanza/pubsub/errors.rb +18 -0
  35. data/lib/blather/stanza/pubsub/event.rb +123 -0
  36. data/lib/blather/stanza/pubsub/items.rb +103 -0
  37. data/lib/blather/stanza/pubsub/publish.rb +103 -0
  38. data/lib/blather/stanza/pubsub/retract.rb +92 -0
  39. data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
  40. data/lib/blather/stanza/pubsub/subscription.rb +134 -0
  41. data/lib/blather/stanza/pubsub/subscriptions.rb +81 -0
  42. data/lib/blather/stanza/pubsub/unsubscribe.rb +68 -0
  43. data/lib/blather/stanza/pubsub.rb +129 -0
  44. data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
  45. data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
  46. data/lib/blather/stanza/pubsub_owner.rb +51 -0
  47. data/lib/blather/stanza.rb +149 -0
  48. data/lib/blather/stream/client.rb +31 -0
  49. data/lib/blather/stream/component.rb +38 -0
  50. data/lib/blather/stream/features/resource.rb +63 -0
  51. data/lib/blather/stream/features/sasl.rb +187 -0
  52. data/lib/blather/stream/features/session.rb +44 -0
  53. data/lib/blather/stream/features/tls.rb +28 -0
  54. data/lib/blather/stream/features.rb +53 -0
  55. data/lib/blather/stream/parser.rb +102 -0
  56. data/lib/blather/stream.rb +231 -0
  57. data/lib/blather/xmpp_node.rb +218 -0
  58. data/lib/blather.rb +78 -0
  59. data/spec/blather/client/client_spec.rb +559 -0
  60. data/spec/blather/client/dsl/pubsub_spec.rb +462 -0
  61. data/spec/blather/client/dsl_spec.rb +143 -0
  62. data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
  63. data/spec/blather/errors/sasl_error_spec.rb +33 -0
  64. data/spec/blather/errors/stanza_error_spec.rb +129 -0
  65. data/spec/blather/errors/stream_error_spec.rb +108 -0
  66. data/spec/blather/errors_spec.rb +33 -0
  67. data/spec/blather/jid_spec.rb +87 -0
  68. data/spec/blather/roster_item_spec.rb +96 -0
  69. data/spec/blather/roster_spec.rb +103 -0
  70. data/spec/blather/stanza/discos/disco_info_spec.rb +226 -0
  71. data/spec/blather/stanza/discos/disco_items_spec.rb +148 -0
  72. data/spec/blather/stanza/iq/query_spec.rb +64 -0
  73. data/spec/blather/stanza/iq/roster_spec.rb +140 -0
  74. data/spec/blather/stanza/iq_spec.rb +45 -0
  75. data/spec/blather/stanza/message_spec.rb +132 -0
  76. data/spec/blather/stanza/presence/status_spec.rb +132 -0
  77. data/spec/blather/stanza/presence/subscription_spec.rb +105 -0
  78. data/spec/blather/stanza/presence_spec.rb +66 -0
  79. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  80. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  81. data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
  82. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  83. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  84. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  85. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  86. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  87. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  88. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
  89. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  90. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  91. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  92. data/spec/blather/stanza/pubsub_spec.rb +67 -0
  93. data/spec/blather/stanza_spec.rb +116 -0
  94. data/spec/blather/stream/client_spec.rb +1011 -0
  95. data/spec/blather/stream/component_spec.rb +95 -0
  96. data/spec/blather/stream/parser_spec.rb +145 -0
  97. data/spec/blather/xmpp_node_spec.rb +231 -0
  98. data/spec/fixtures/pubsub.rb +311 -0
  99. data/spec/spec_helper.rb +43 -0
  100. 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