shingara-blather 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
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