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,144 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
|
|
4
|
+
# # Iq Stanza
|
|
5
|
+
#
|
|
6
|
+
# [RFC 3920 Section 9.2.3 - IQ Semantics](http://xmpp.org/rfcs/rfc3920.html#rfc.section.9.2.3)
|
|
7
|
+
#
|
|
8
|
+
# Info/Query, or IQ, is a request-response mechanism, similar in some ways
|
|
9
|
+
# to HTTP. The semantics of IQ enable an entity to make a request of, and
|
|
10
|
+
# receive a response from, another entity. The data content of the request
|
|
11
|
+
# and response is defined by the namespace declaration of a direct child
|
|
12
|
+
# element of the IQ element, and the interaction is tracked by the
|
|
13
|
+
# requesting entity through use of the 'id' attribute. Thus, IQ interactions
|
|
14
|
+
# follow a common pattern of structured data exchange such as get/result or
|
|
15
|
+
# set/result (although an error may be returned in reply to a request if
|
|
16
|
+
# appropriate).
|
|
17
|
+
#
|
|
18
|
+
# ## "ID" Attribute
|
|
19
|
+
#
|
|
20
|
+
# Iq Stanzas require the ID attribute be set. Blather will handle this
|
|
21
|
+
# automatically when a new Iq is created.
|
|
22
|
+
#
|
|
23
|
+
# ## "Type" Attribute
|
|
24
|
+
#
|
|
25
|
+
# * `:get` -- The stanza is a request for information or requirements.
|
|
26
|
+
#
|
|
27
|
+
# * `:set` -- The stanza provides required data, sets new values, or
|
|
28
|
+
# replaces existing values.
|
|
29
|
+
#
|
|
30
|
+
# * `:result` -- The stanza is a response to a successful get or set request.
|
|
31
|
+
#
|
|
32
|
+
# * `:error` -- An error has occurred regarding processing or delivery of a
|
|
33
|
+
# previously-sent get or set (see Stanza Errors).
|
|
34
|
+
#
|
|
35
|
+
# Blather provides a helper for each possible type:
|
|
36
|
+
#
|
|
37
|
+
# Iq#get?
|
|
38
|
+
# Iq#set?
|
|
39
|
+
# Iq#result?
|
|
40
|
+
# Iq#error?
|
|
41
|
+
#
|
|
42
|
+
# Blather treats the `type` attribute like a normal ruby object attribute
|
|
43
|
+
# providing a getter and setter. The default `type` is `get`.
|
|
44
|
+
#
|
|
45
|
+
# iq = Iq.new
|
|
46
|
+
# iq.type # => :get
|
|
47
|
+
# iq.get? # => true
|
|
48
|
+
# iq.type = :set
|
|
49
|
+
# iq.set? # => true
|
|
50
|
+
# iq.get? # => false
|
|
51
|
+
#
|
|
52
|
+
# iq.type = :invalid # => RuntimeError
|
|
53
|
+
#
|
|
54
|
+
# @handler :iq
|
|
55
|
+
class Iq < Stanza
|
|
56
|
+
# @private
|
|
57
|
+
VALID_TYPES = [:get, :set, :result, :error].freeze
|
|
58
|
+
|
|
59
|
+
register :iq
|
|
60
|
+
|
|
61
|
+
# @private
|
|
62
|
+
def self.import(node)
|
|
63
|
+
klass = nil
|
|
64
|
+
node.children.detect do |e|
|
|
65
|
+
ns = e.namespace ? e.namespace.href : nil
|
|
66
|
+
klass = class_from_registration(e.element_name, ns)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if klass && klass != self
|
|
70
|
+
klass.import(node)
|
|
71
|
+
else
|
|
72
|
+
new(node[:type]).inherit(node)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Create a new Iq
|
|
77
|
+
#
|
|
78
|
+
# @param [Symbol, nil] type the type of stanza (:get, :set, :result, :error)
|
|
79
|
+
# @param [Blather::JID, String, nil] jid the JID of the inteded recipient
|
|
80
|
+
# @param [#to_s] id the stanza's ID. Leaving this nil will set the ID to
|
|
81
|
+
# the next unique number
|
|
82
|
+
def self.new(type = nil, to = nil, id = nil)
|
|
83
|
+
node = super :iq
|
|
84
|
+
node.type = type || :get
|
|
85
|
+
node.to = to
|
|
86
|
+
node.id = id || self.next_id
|
|
87
|
+
node
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Check if the IQ is of type :get
|
|
91
|
+
#
|
|
92
|
+
# @return [true, false]
|
|
93
|
+
def get?
|
|
94
|
+
self.type == :get
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Check if the IQ is of type :set
|
|
98
|
+
#
|
|
99
|
+
# @return [true, false]
|
|
100
|
+
def set?
|
|
101
|
+
self.type == :set
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Check if the IQ is of type :result
|
|
105
|
+
#
|
|
106
|
+
# @return [true, false]
|
|
107
|
+
def result?
|
|
108
|
+
self.type == :result
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Check if the IQ is of type :error
|
|
112
|
+
#
|
|
113
|
+
# @return [true, false]
|
|
114
|
+
def error?
|
|
115
|
+
self.type == :error
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Ensures type is :get, :set, :result or :error
|
|
119
|
+
#
|
|
120
|
+
# @param [#to_sym] type the Iq type. Must be one of VALID_TYPES
|
|
121
|
+
def type=(type)
|
|
122
|
+
if type && !VALID_TYPES.include?(type.to_sym)
|
|
123
|
+
raise ArgumentError, "Invalid Type (#{type}), use: #{VALID_TYPES*' '}"
|
|
124
|
+
end
|
|
125
|
+
super
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Overrides the parent method to ensure the reply is of type :result and that
|
|
129
|
+
# all children are removed.
|
|
130
|
+
#
|
|
131
|
+
# @param [Hash] opts options to pass to reply!
|
|
132
|
+
# @option opts [Boolean] :remove_children Wether or not to remove child nodes when replying
|
|
133
|
+
#
|
|
134
|
+
# @return [self]
|
|
135
|
+
def reply!(opts = {})
|
|
136
|
+
opts = {:remove_children => true}.merge opts
|
|
137
|
+
super
|
|
138
|
+
self.type = :result
|
|
139
|
+
self
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
module Blather
|
|
2
|
+
class Stanza
|
|
3
|
+
class Iq
|
|
4
|
+
|
|
5
|
+
# # Command Stanza
|
|
6
|
+
#
|
|
7
|
+
# [XEP-0050 Ad-Hoc Commands](http://xmpp.org/extensions/xep-0050.html)
|
|
8
|
+
#
|
|
9
|
+
# This is a base class for any command based Iq stanzas. It provides a base set
|
|
10
|
+
# of methods for working with command stanzas
|
|
11
|
+
#
|
|
12
|
+
# @handler :command
|
|
13
|
+
class Command < Iq
|
|
14
|
+
# @private
|
|
15
|
+
VALID_ACTIONS = [:cancel, :execute, :complete, :next, :prev].freeze
|
|
16
|
+
# @private
|
|
17
|
+
VALID_STATUS = [:executing, :completed, :canceled].freeze
|
|
18
|
+
# @private
|
|
19
|
+
VALID_NOTE_TYPES = [:info, :warn, :error].freeze
|
|
20
|
+
|
|
21
|
+
register :command, :command, 'http://jabber.org/protocol/commands'
|
|
22
|
+
|
|
23
|
+
# Overrides the parent method to ensure a command node is created
|
|
24
|
+
#
|
|
25
|
+
# @param [:get, :set, :result, :error, nil] type the IQ type
|
|
26
|
+
# @param [String] node the name of the node
|
|
27
|
+
# @param [:cancel, :execute, :complete, :next, :prev, nil] action the command's action
|
|
28
|
+
# @return [Command] a new Command stanza
|
|
29
|
+
def self.new(type = :set, node = nil, action = :execute)
|
|
30
|
+
new_node = super type
|
|
31
|
+
new_node.command
|
|
32
|
+
new_node.node = node
|
|
33
|
+
new_node.action = action
|
|
34
|
+
new_node
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Overrides the parent method to ensure the current command node is destroyed
|
|
38
|
+
# and the action is set to execute if no action provided
|
|
39
|
+
#
|
|
40
|
+
# @see Blather::Stanza::Iq#inherit
|
|
41
|
+
def inherit(node)
|
|
42
|
+
command.remove
|
|
43
|
+
super
|
|
44
|
+
self.action = :execute unless self.action
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Overrides the parent method to ensure the reply has no action
|
|
49
|
+
#
|
|
50
|
+
# @param [Hash] opts options to pass to reply!
|
|
51
|
+
# @option opts [Boolean] :remove_children Wether or not to remove child nodes when replying
|
|
52
|
+
#
|
|
53
|
+
# @return [self]
|
|
54
|
+
def reply!(opts = {})
|
|
55
|
+
super
|
|
56
|
+
self.action = nil
|
|
57
|
+
self
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Command node accessor
|
|
61
|
+
# If a command node exists it will be returned.
|
|
62
|
+
# Otherwise a new node will be created and returned
|
|
63
|
+
#
|
|
64
|
+
# @return [Blather::XMPPNode]
|
|
65
|
+
def command
|
|
66
|
+
c = if self.class.registered_ns
|
|
67
|
+
find_first('ns:command', :ns => self.class.registered_ns)
|
|
68
|
+
else
|
|
69
|
+
find_first('command')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
unless c
|
|
73
|
+
(self << (c = XMPPNode.new('command', self.document)))
|
|
74
|
+
c.namespace = self.class.registered_ns
|
|
75
|
+
end
|
|
76
|
+
c
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Get the name of the node
|
|
80
|
+
#
|
|
81
|
+
# @return [String, nil]
|
|
82
|
+
def node
|
|
83
|
+
command[:node]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Set the name of the node
|
|
87
|
+
#
|
|
88
|
+
# @param [String, nil] node the new node name
|
|
89
|
+
def node=(node)
|
|
90
|
+
command[:node] = node
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Get the sessionid of the command
|
|
94
|
+
#
|
|
95
|
+
# @return [String, nil]
|
|
96
|
+
def sessionid
|
|
97
|
+
command[:sessionid]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Check if there is a sessionid set
|
|
101
|
+
#
|
|
102
|
+
# @return [true, false]
|
|
103
|
+
def sessionid?
|
|
104
|
+
!sessionid.nil?
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Set the sessionid of the command
|
|
108
|
+
#
|
|
109
|
+
# @param [String, nil] sessionid the new sessionid
|
|
110
|
+
def sessionid=(sessionid)
|
|
111
|
+
command[:sessionid] = Digest::SHA1.hexdigest(sessionid)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Generate a new session ID (SHA-1 hash)
|
|
115
|
+
def new_sessionid!
|
|
116
|
+
self.sessionid = "commandsession-#{id}"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Get the action of the command
|
|
120
|
+
#
|
|
121
|
+
# @return [Symbol, nil]
|
|
122
|
+
def action
|
|
123
|
+
(val = command[:action]) && val.to_sym
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Check if the command action is :cancel
|
|
127
|
+
#
|
|
128
|
+
# @return [true, false]
|
|
129
|
+
def cancel?
|
|
130
|
+
self.action == :cancel
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Check if the command action is :execute
|
|
134
|
+
#
|
|
135
|
+
# @return [true, false]
|
|
136
|
+
def execute?
|
|
137
|
+
self.action == :execute
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Check if the command action is :complete
|
|
141
|
+
#
|
|
142
|
+
# @return [true, false]
|
|
143
|
+
def complete?
|
|
144
|
+
self.action == :complete
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Check if the command action is :next
|
|
148
|
+
#
|
|
149
|
+
# @return [true, false]
|
|
150
|
+
def next?
|
|
151
|
+
self.action == :next
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Check if the command action is :prev
|
|
155
|
+
#
|
|
156
|
+
# @return [true, false]
|
|
157
|
+
def prev?
|
|
158
|
+
self.action == :prev
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Set the action of the command
|
|
162
|
+
#
|
|
163
|
+
# @param [:cancel, :execute, :complete, :next, :prev] action the new action
|
|
164
|
+
def action=(action)
|
|
165
|
+
if action && !VALID_ACTIONS.include?(action.to_sym)
|
|
166
|
+
raise ArgumentError, "Invalid Action (#{action}), use: #{VALID_ACTIONS*' '}"
|
|
167
|
+
end
|
|
168
|
+
command[:action] = action
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Get the status of the command
|
|
172
|
+
#
|
|
173
|
+
# @return [Symbol, nil]
|
|
174
|
+
def status
|
|
175
|
+
((val = command[:status]) && val.to_sym) || :executing
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Check if the command status is :executing
|
|
179
|
+
#
|
|
180
|
+
# @return [true, false]
|
|
181
|
+
def executing?
|
|
182
|
+
self.status == :executing
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Check if the command status is :completed
|
|
186
|
+
#
|
|
187
|
+
# @return [true, false]
|
|
188
|
+
def completed?
|
|
189
|
+
self.status == :completed
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Check if the command status is :canceled
|
|
193
|
+
#
|
|
194
|
+
# @return [true, false]
|
|
195
|
+
def canceled?
|
|
196
|
+
self.status == :canceled
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Set the status of the command
|
|
200
|
+
#
|
|
201
|
+
# @param [:executing, :completed, :canceled] status the new status
|
|
202
|
+
def status=(status)
|
|
203
|
+
if status && !VALID_STATUS.include?(status.to_sym)
|
|
204
|
+
raise ArgumentError, "Invalid Action (#{status}), use: #{VALID_STATUS*' '}"
|
|
205
|
+
end
|
|
206
|
+
command[:status] = status
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Command actions accessor
|
|
210
|
+
# If a command actions element exists it will be returned.
|
|
211
|
+
# Otherwise a new actions element will be created and returned
|
|
212
|
+
#
|
|
213
|
+
# @return [Blather::XMPPNode]
|
|
214
|
+
def actions
|
|
215
|
+
unless a = self.command.find_first('ns:actions', :ns => self.class.registered_ns)
|
|
216
|
+
(self.command << (a = XMPPNode.new('actions', self.document)))
|
|
217
|
+
a.namespace = self.command.namespace
|
|
218
|
+
end
|
|
219
|
+
a
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Get the command's allowed actions
|
|
223
|
+
#
|
|
224
|
+
# @return [Array<Symbol>]
|
|
225
|
+
def allowed_actions
|
|
226
|
+
([:execute] + actions.children.map { |action| action.name.to_sym }).uniq
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Get the primary allowed action
|
|
230
|
+
#
|
|
231
|
+
# @return [Symbol]
|
|
232
|
+
def primary_allowed_action
|
|
233
|
+
(actions[:execute] || :execute).to_sym
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Set the primary allowed action
|
|
237
|
+
#
|
|
238
|
+
# This must be one of :prev, :next, :complete or :execute
|
|
239
|
+
#
|
|
240
|
+
# @param [#to_sym] a the primary allowed action
|
|
241
|
+
def primary_allowed_action=(a)
|
|
242
|
+
a = a.to_sym
|
|
243
|
+
if a && ![:prev, :next, :complete, :execute].include?(a)
|
|
244
|
+
raise ArgumentError, "Invalid Action (#{a}), use: #{[:prev, :next, :complete, :execute]*' '}"
|
|
245
|
+
end
|
|
246
|
+
actions[:execute] = a
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Add allowed actions to the command
|
|
250
|
+
#
|
|
251
|
+
# @param [[:prev, :next, :complete]] allowed_actions the new allowed actions
|
|
252
|
+
def allowed_actions=(allowed_actions)
|
|
253
|
+
allowed_actions = ([allowed_actions].flatten.map(&:to_sym) + [:execute]).uniq
|
|
254
|
+
if (invalid_actions = allowed_actions - VALID_ACTIONS).size > 0
|
|
255
|
+
raise ArgumentError, "Invalid Action(s) (#{invalid_actions*' '}), use: #{VALID_ACTIONS*' '}"
|
|
256
|
+
end
|
|
257
|
+
actions.children.map(&:remove)
|
|
258
|
+
allowed_actions.each { |action| actions << XMPPNode.new(action.to_s) }
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Remove allowed actions from the command
|
|
262
|
+
#
|
|
263
|
+
# @param [[:prev, :next, :complete]] disallowed_actions the allowed actions to remove
|
|
264
|
+
def remove_allowed_actions!
|
|
265
|
+
actions.remove
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Command note accessor
|
|
269
|
+
# If a command note exists it will be returned.
|
|
270
|
+
# Otherwise a new note will be created and returned
|
|
271
|
+
#
|
|
272
|
+
# @return [Blather::XMPPNode]
|
|
273
|
+
def note
|
|
274
|
+
unless n = self.command.find_first('ns:note', :ns => self.class.registered_ns)
|
|
275
|
+
(self.command << (n = XMPPNode.new('note', self.document)))
|
|
276
|
+
n.namespace = self.command.namespace
|
|
277
|
+
end
|
|
278
|
+
n
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Get the note_type of the command
|
|
282
|
+
#
|
|
283
|
+
# @return [Symbol, nil]
|
|
284
|
+
def note_type
|
|
285
|
+
(val = note[:type]) && val.to_sym
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Check if the command status is :info
|
|
289
|
+
#
|
|
290
|
+
# @return [true, false]
|
|
291
|
+
def info?
|
|
292
|
+
self.note_type == :info
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Check if the command status is :warn
|
|
296
|
+
#
|
|
297
|
+
# @return [true, false]
|
|
298
|
+
def warn?
|
|
299
|
+
self.status == :warn
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Check if the command status is :error
|
|
303
|
+
#
|
|
304
|
+
# @return [true, false]
|
|
305
|
+
def error?
|
|
306
|
+
self.status == :error
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# Set the note_type of the command
|
|
310
|
+
#
|
|
311
|
+
# @param [:executing, :completed, :canceled] note_type the new note_type
|
|
312
|
+
def note_type=(note_type)
|
|
313
|
+
if note_type && !VALID_NOTE_TYPES.include?(note_type.to_sym)
|
|
314
|
+
raise ArgumentError, "Invalid Action (#{note_type}), use: #{VALID_NOTE_TYPES*' '}"
|
|
315
|
+
end
|
|
316
|
+
note[:type] = note_type
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Get the text of the command's note
|
|
320
|
+
def note_text
|
|
321
|
+
content_from :note
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# Set the command's note text
|
|
325
|
+
#
|
|
326
|
+
# @param [String] note_text the command's new note text
|
|
327
|
+
def note_text=(note_text)
|
|
328
|
+
set_content_for :note, note_text
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Returns the command's x:data form child
|
|
332
|
+
def form
|
|
333
|
+
X.find_or_create command
|
|
334
|
+
end
|
|
335
|
+
end #Command
|
|
336
|
+
|
|
337
|
+
end #Iq
|
|
338
|
+
end #Stanza
|
|
339
|
+
end #Blather
|