blather 0.2.2 → 0.2.3
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/README.rdoc +2 -2
- data/Rakefile +30 -18
- data/ext/Makefile +149 -0
- data/ext/mkmf.log +30 -0
- data/ext/push_parser.bundle +0 -0
- data/ext/push_parser.c +231 -0
- data/ext/push_parser.o +0 -0
- data/lib/blather.rb +3 -7
- data/lib/blather/client.rb +247 -4
- data/lib/blather/roster.rb +0 -9
- data/lib/blather/stanza/{disco.rb → iq/disco.rb} +3 -1
- data/lib/blather/stanza/{disco → iq/discos}/disco_info.rb +5 -3
- data/lib/blather/stanza/{disco → iq/discos}/disco_items.rb +2 -0
- data/lib/blather/stanza/iq/query.rb +1 -1
- data/lib/blather/stanza/iq/roster.rb +2 -2
- data/lib/blather/xmpp_node.rb +1 -1
- data/spec/blather/stanza/{discos → iq/discos}/disco_info_spec.rb +12 -12
- data/spec/blather/stanza/{discos → iq/discos}/disco_items_spec.rb +1 -1
- data/spec/blather/stanza/iq/query_spec.rb +0 -7
- data/spec/blather/stanza/iq/roster_spec.rb +21 -21
- data/spec/blather/stanza/pubsub/event_spec.rb +13 -0
- data/spec/build_safe.rb +20 -0
- metadata +19 -68
- data/VERSION.yml +0 -4
- data/examples/pubsub/cli.rb +0 -64
- data/examples/pubsub/ping_pong.rb +0 -18
- data/examples/pubsub/pubsub_dsl.rb +0 -52
- data/examples/pubsub_client.rb +0 -39
- data/examples/rosterprint.rb +0 -14
- data/examples/xmpp4r/echo.rb +0 -35
- data/lib/blather/client/client.rb +0 -165
- data/lib/blather/client/dsl.rb +0 -99
- data/lib/blather/client/pubsub.rb +0 -53
- data/lib/blather/client/pubsub/node.rb +0 -27
- data/lib/blather/stanza/pubsub.rb +0 -33
- data/lib/blather/stanza/pubsub/affiliations.rb +0 -52
- data/lib/blather/stanza/pubsub/errors.rb +0 -9
- data/lib/blather/stanza/pubsub/event.rb +0 -21
- data/lib/blather/stanza/pubsub/items.rb +0 -59
- data/lib/blather/stanza/pubsub/owner.rb +0 -9
- data/lib/blather/stanza/pubsub/subscriptions.rb +0 -57
- data/spec/blather/stanza/pubsub/affiliations_spec.rb +0 -46
- data/spec/blather/stanza/pubsub/items_spec.rb +0 -59
- data/spec/blather/stanza/pubsub/subscriptions_spec.rb +0 -63
- data/spec/blather/stanza/pubsub_spec.rb +0 -26
- data/spec/fixtures/pubsub.rb +0 -157
data/ext/push_parser.o
ADDED
Binary file
|
data/lib/blather.rb
CHANGED
@@ -26,17 +26,13 @@ $:.unshift File.join(File.dirname(__FILE__), '..')
|
|
26
26
|
blather/stanza/iq
|
27
27
|
blather/stanza/iq/query
|
28
28
|
blather/stanza/iq/roster
|
29
|
-
blather/stanza/disco
|
30
|
-
blather/stanza/
|
31
|
-
blather/stanza/
|
29
|
+
blather/stanza/iq/disco
|
30
|
+
blather/stanza/iq/discos/disco_info
|
31
|
+
blather/stanza/iq/discos/disco_items
|
32
32
|
blather/stanza/message
|
33
33
|
blather/stanza/presence
|
34
34
|
blather/stanza/presence/status
|
35
35
|
blather/stanza/presence/subscription
|
36
|
-
blather/stanza/pubsub
|
37
|
-
blather/stanza/pubsub/affiliations
|
38
|
-
blather/stanza/pubsub/subscriptions
|
39
|
-
blather/stanza/pubsub/items
|
40
36
|
|
41
37
|
blather/stream
|
42
38
|
blather/stream/client
|
data/lib/blather/client.rb
CHANGED
@@ -1,13 +1,256 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), *%w[
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. blather])
|
2
|
+
|
3
|
+
module Blather #:nodoc:
|
4
|
+
|
5
|
+
class Client #:nodoc:
|
6
|
+
attr_accessor :jid,
|
7
|
+
:roster
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@state = :initializing
|
11
|
+
|
12
|
+
@status = Stanza::Presence::Status.new
|
13
|
+
@handlers = {}
|
14
|
+
@tmp_handlers = {}
|
15
|
+
@roster = Roster.new self
|
16
|
+
|
17
|
+
setup_initial_handlers
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup(jid, password, host = nil, port = 5222)
|
21
|
+
@setup = [JID.new(jid), password, host, port]
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup?
|
26
|
+
@setup.is_a?(Array) && !@setup.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
raise 'Not setup!' unless @setup.is_a?(Array)
|
31
|
+
trap(:INT) { EM.stop }
|
32
|
+
EM.run {
|
33
|
+
klass = @setup[2].node ? Blather::Stream::Client : Blather::Stream::Component
|
34
|
+
klass.start Blather.client, *@setup
|
35
|
+
}
|
36
|
+
|
37
|
+
def temporary_handler(id, &handler)
|
38
|
+
@tmp_handlers[id] = handler
|
39
|
+
end
|
40
|
+
|
41
|
+
def register_handler(type, *guards, &handler)
|
42
|
+
@handlers[type] ||= []
|
43
|
+
@handlers[type] << [guards, handler]
|
44
|
+
end
|
45
|
+
|
46
|
+
def status
|
47
|
+
@status.state
|
48
|
+
end
|
49
|
+
|
50
|
+
def status=(state)
|
51
|
+
state, msg, to = state
|
52
|
+
|
53
|
+
status = Stanza::Presence::Status.new state, msg
|
54
|
+
status.to = to
|
55
|
+
@statustatus unless to
|
56
|
+
|
57
|
+
write status
|
58
|
+
end
|
59
|
+
|
60
|
+
def write(stanza)
|
61
|
+
stanza.from ||= jid if stanza.respond_to?(:from)
|
62
|
+
@stream.send(stanza) if @stream
|
63
|
+
end
|
64
|
+
|
65
|
+
def stream_started(stream)
|
66
|
+
@stream = stream
|
67
|
+
|
68
|
+
#retreive roster
|
69
|
+
if @stream.is_a?(Stream::Component)
|
70
|
+
@state = :ready
|
71
|
+
call_handler_for :ready, nil
|
72
|
+
else
|
73
|
+
write Stanza::Iq::Roster.new
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def stop
|
78
|
+
@stream.close_connection_after_writing
|
79
|
+
end
|
80
|
+
|
81
|
+
def stopped
|
82
|
+
EM.stop
|
83
|
+
end
|
84
|
+
|
85
|
+
def call(stanza)
|
86
|
+
if handler = @tmp_handlers.delete(stanza.id)
|
87
|
+
handler.call stanza
|
88
|
+
else
|
89
|
+
stanza.handler_heirarchy.each do |type|
|
90
|
+
break if call_handler_for(type, stanza) && (stanza.is_a?(BlatherError) || stanza.type == :iq)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def call_handler_for(type, stanza)
|
96
|
+
if @handlers[type]
|
97
|
+
@handlers[type].find { |guards, handler| handler.call(stanza) unless guarded?(guards, stanza) }
|
98
|
+
true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
def setup_initial_handlers
|
104
|
+
register_handler :error do |err|
|
105
|
+
raise err
|
106
|
+
end
|
107
|
+
|
108
|
+
register_handler :iq do |iq|
|
109
|
+
write(StanzaError::ServiceUnavailable.new(iq, :cancel).to_node) if [:set, :get].include?(iq.type)
|
110
|
+
end
|
111
|
+
|
112
|
+
register_handler :status do |status|
|
113
|
+
roster[status.from].status = status if roster[status.from]
|
114
|
+
end
|
115
|
+
|
116
|
+
register_handler :roster do |node|
|
117
|
+
roster.process node
|
118
|
+
if @state == :initializing
|
119
|
+
@state = :ready
|
120
|
+
write @status
|
121
|
+
call_handler_for :ready, nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# If any of the guards returns FALSE this returns true
|
128
|
+
def guarded?(guards, stanza)
|
129
|
+
guards.find do |guard|
|
130
|
+
case guard
|
131
|
+
when Symbol
|
132
|
+
!stanza.__send__(guard)
|
133
|
+
when Array
|
134
|
+
# return FALSE if any item is TRUE
|
135
|
+
!guard.detect { |condition| !guarded?([condition], stanza) }
|
136
|
+
when Hash
|
137
|
+
# return FALSE unless any inequality is found
|
138
|
+
guard.find do |method, value|
|
139
|
+
if value.is_a?(Regexp)
|
140
|
+
!stanza.__send__(method).to_s.match(value)
|
141
|
+
else
|
142
|
+
stanza.__send__(method) != value
|
143
|
+
end
|
144
|
+
end
|
145
|
+
when Proc
|
146
|
+
!guard.call(stanza)
|
147
|
+
else
|
148
|
+
raise "Bad guard: #{guard.inspect}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end #Client
|
154
|
+
|
155
|
+
def client
|
156
|
+
@client ||= Client.new
|
157
|
+
end
|
158
|
+
module_function :client
|
159
|
+
end #Blather
|
160
|
+
|
161
|
+
##
|
162
|
+
# Prepare server settings
|
163
|
+
# setup_client [node@domain/resource], [password], [host], [port]
|
164
|
+
# host and port are optional defaulting to the domain in the JID and 5222 respectively
|
165
|
+
def setup_client(jid, password, host = nil, port = 5222)
|
166
|
+
at_exit { Blather.client.setup_client(jid, password, host, port).run }
|
167
|
+
end
|
168
|
+
|
169
|
+
def setup_component(jid, secret, host, port)
|
170
|
+
at_exit { Blather.client.setup_component(jid, secret, host, port).run }
|
171
|
+
end
|
172
|
+
|
173
|
+
##
|
174
|
+
# Shutdown the connection.
|
175
|
+
# Flushes the write buffer then stops EventMachine
|
176
|
+
def shutdown
|
177
|
+
Blather.client.stop
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Set handler for a stanza type
|
182
|
+
def handle(stanza_type, *guards, &block)
|
183
|
+
Blather.client.register_handler stanza_type, *guards, &block
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Wrapper for "handle :ready" (just a bit of syntactic sugar)
|
188
|
+
def when_ready(&block)
|
189
|
+
handle :ready, &block
|
190
|
+
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Set current status
|
194
|
+
def status(state = nil, msg = nil)
|
195
|
+
Blather.client.status = state, msg
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Direct access to the roster
|
200
|
+
def roster
|
201
|
+
Blather.client.roster
|
202
|
+
end
|
203
|
+
|
204
|
+
##
|
205
|
+
# Write data to the stream
|
206
|
+
# Anything that resonds to #to_s can be paseed to the stream
|
207
|
+
def write(stanza)
|
208
|
+
Blather.client.write(stanza)
|
209
|
+
end
|
210
|
+
|
211
|
+
##
|
212
|
+
# Helper method to make sending basic messages easier
|
213
|
+
# say [jid], [msg]
|
214
|
+
def say(to, msg)
|
215
|
+
Blather.client.write Blather::Stanza::Message.new(to, msg)
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# Wrapper to grab the current JID
|
220
|
+
def jid
|
221
|
+
Blather.client.jid
|
222
|
+
end
|
223
|
+
|
224
|
+
##
|
225
|
+
#
|
226
|
+
def discover(what, who, where, &callback)
|
227
|
+
stanza = Blather::Stanza.class_from_registration(:query, "http://jabber.org/protocol/disco##{what}").new
|
228
|
+
stanza.to = who
|
229
|
+
stanza.node = where
|
230
|
+
|
231
|
+
Blather.client.temporary_handler stanza.id, &callback
|
232
|
+
write stanza
|
233
|
+
end
|
234
|
+
|
235
|
+
##
|
236
|
+
# Checks to see if the method is part of the handlers list.
|
237
|
+
# If so it creates a handler, otherwise it'll pass it back
|
238
|
+
# to Ruby's method_missing handler
|
239
|
+
def method_missing(method, *args, &block)
|
240
|
+
if Blather::Stanza.handler_list.include?(method)
|
241
|
+
handle method, *args, &block
|
242
|
+
else
|
243
|
+
super
|
244
|
+
end
|
245
|
+
end
|
2
246
|
|
3
|
-
include Blather::DSL
|
4
247
|
|
5
248
|
at_exit do
|
6
|
-
unless client.setup?
|
249
|
+
unless Blather.client.setup?
|
7
250
|
if ARGV.length < 2
|
8
251
|
puts "Run with #{$0} user@server/resource password [host] [port]"
|
9
252
|
else
|
10
|
-
client.setup(*ARGV).run
|
253
|
+
Blather.client.setup(*ARGV).run
|
11
254
|
end
|
12
255
|
end
|
13
256
|
end
|
data/lib/blather/roster.rb
CHANGED
@@ -71,15 +71,6 @@ module Blather
|
|
71
71
|
@items.dup
|
72
72
|
end
|
73
73
|
|
74
|
-
##
|
75
|
-
# A hash of items keyed by group
|
76
|
-
def grouped
|
77
|
-
self.inject(Hash.new{|h,k|h[k]=[]}) do |hash, item|
|
78
|
-
item[1].groups.each { |group| hash[group] << item[1] }
|
79
|
-
hash
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
74
|
private
|
84
75
|
def self.key(jid)
|
85
76
|
JID.new(jid).stripped.to_s
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Blather
|
2
2
|
class Stanza
|
3
|
+
class Iq
|
3
4
|
|
4
5
|
##
|
5
6
|
# DiscoInfo object ()
|
@@ -7,11 +8,9 @@ class Stanza
|
|
7
8
|
class DiscoInfo < Disco
|
8
9
|
register :disco_info, nil, 'http://jabber.org/protocol/disco#info'
|
9
10
|
|
10
|
-
def initialize(type = nil,
|
11
|
+
def initialize(type = nil, identities = [], features = [], node = nil)
|
11
12
|
super type
|
12
13
|
|
13
|
-
self.node = node
|
14
|
-
|
15
14
|
[identities].flatten.each do |id|
|
16
15
|
query << (id.is_a?(Identity) ? id : Identity.new(id[:name], id[:type], id[:category]))
|
17
16
|
end
|
@@ -19,6 +18,8 @@ class Stanza
|
|
19
18
|
[features].flatten.each do |feature|
|
20
19
|
query << (feature.is_a?(Feature) ? feature : Feature.new(feature))
|
21
20
|
end
|
21
|
+
|
22
|
+
self.node = node
|
22
23
|
end
|
23
24
|
|
24
25
|
##
|
@@ -80,5 +81,6 @@ class Stanza
|
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
84
|
+
end #Iq
|
83
85
|
end #Stanza
|
84
86
|
end #Blather
|
@@ -27,8 +27,8 @@ class Iq
|
|
27
27
|
##
|
28
28
|
# Roster items
|
29
29
|
def items
|
30
|
-
items = query.find('
|
31
|
-
items = query.find('
|
30
|
+
items = query.find('item')
|
31
|
+
items = query.find('query_ns:item', :query_ns => self.class.ns) if items.empty?
|
32
32
|
items.map { |i| RosterItem.new(i) }
|
33
33
|
end
|
34
34
|
|
data/lib/blather/xmpp_node.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. .. .. spec_helper])
|
2
2
|
|
3
3
|
def disco_info_xml
|
4
4
|
<<-XML
|
@@ -24,7 +24,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo' do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'has a node attribute' do
|
27
|
-
n = Blather::Stanza::Iq::DiscoInfo.new nil,
|
27
|
+
n = Blather::Stanza::Iq::DiscoInfo.new nil, [], [], 'music'
|
28
28
|
n.node.must_equal 'music'
|
29
29
|
n.node = :foo
|
30
30
|
n.node.must_equal 'foo'
|
@@ -55,7 +55,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo identities' do
|
|
55
55
|
control = [ Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
|
56
56
|
Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
|
57
57
|
|
58
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
58
|
+
di = Stanza::Iq::DiscoInfo.new nil, ids
|
59
59
|
di.identities.size.must_equal 2
|
60
60
|
di.identities.each { |i| control.include?(i).must_equal true }
|
61
61
|
end
|
@@ -64,7 +64,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo identities' do
|
|
64
64
|
control = [ Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
|
65
65
|
Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
|
66
66
|
|
67
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
67
|
+
di = Stanza::Iq::DiscoInfo.new nil, control
|
68
68
|
di.identities.size.must_equal 2
|
69
69
|
di.identities.each { |i| control.include?(i).must_equal true }
|
70
70
|
end
|
@@ -72,7 +72,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo identities' do
|
|
72
72
|
it 'takes a single hash as identity' do
|
73
73
|
control = [Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
|
74
74
|
|
75
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
75
|
+
di = Stanza::Iq::DiscoInfo.new nil, {:name => 'name', :type => 'type', :category => 'category'}
|
76
76
|
di.identities.size.must_equal 1
|
77
77
|
di.identities.each { |i| control.include?(i).must_equal true }
|
78
78
|
end
|
@@ -80,7 +80,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo identities' do
|
|
80
80
|
it 'takes a single identity object as identity' do
|
81
81
|
control = [Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
|
82
82
|
|
83
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
83
|
+
di = Stanza::Iq::DiscoInfo.new nil, control.first
|
84
84
|
di.identities.size.must_equal 1
|
85
85
|
di.identities.each { |i| control.include?(i).must_equal true }
|
86
86
|
end
|
@@ -94,7 +94,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo identities' do
|
|
94
94
|
control = [ Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category]),
|
95
95
|
Stanza::Iq::DiscoInfo::Identity.new(*%w[name1 type1 category1])]
|
96
96
|
|
97
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
97
|
+
di = Stanza::Iq::DiscoInfo.new nil, ids
|
98
98
|
di.identities.size.must_equal 2
|
99
99
|
di.identities.each { |i| control.include?(i).must_equal true }
|
100
100
|
end
|
@@ -105,7 +105,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo features' do
|
|
105
105
|
features = %w[feature1 feature2 feature3]
|
106
106
|
control = features.map { |f| Stanza::Iq::DiscoInfo::Feature.new f }
|
107
107
|
|
108
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
108
|
+
di = Stanza::Iq::DiscoInfo.new nil, [], features
|
109
109
|
di.features.size.must_equal 3
|
110
110
|
di.features.each { |f| control.include?(f).must_equal true }
|
111
111
|
end
|
@@ -114,7 +114,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo features' do
|
|
114
114
|
features = %w[feature1 feature2 feature3]
|
115
115
|
control = features.map { |f| Stanza::Iq::DiscoInfo::Feature.new f }
|
116
116
|
|
117
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
117
|
+
di = Stanza::Iq::DiscoInfo.new nil, [], control
|
118
118
|
di.features.size.must_equal 3
|
119
119
|
di.features.each { |f| control.include?(f).must_equal true }
|
120
120
|
end
|
@@ -122,7 +122,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo features' do
|
|
122
122
|
it 'takes a single string' do
|
123
123
|
control = [Stanza::Iq::DiscoInfo::Feature.new('feature1')]
|
124
124
|
|
125
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
125
|
+
di = Stanza::Iq::DiscoInfo.new nil, [], 'feature1'
|
126
126
|
di.features.size.must_equal 1
|
127
127
|
di.features.each { |f| control.include?(f).must_equal true }
|
128
128
|
end
|
@@ -130,7 +130,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo features' do
|
|
130
130
|
it 'takes a single Feature object' do
|
131
131
|
control = [Stanza::Iq::DiscoInfo::Feature.new('feature1')]
|
132
132
|
|
133
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
133
|
+
di = Stanza::Iq::DiscoInfo.new nil, [], control.first
|
134
134
|
di.features.size.must_equal 1
|
135
135
|
di.features.each { |f| control.include?(f).must_equal true }
|
136
136
|
end
|
@@ -140,7 +140,7 @@ describe 'Blather::Stanza::Iq::DiscoInfo features' do
|
|
140
140
|
control = features.map { |f| Stanza::Iq::DiscoInfo::Feature.new f }
|
141
141
|
features[1] = control[1]
|
142
142
|
|
143
|
-
di = Stanza::Iq::DiscoInfo.new nil,
|
143
|
+
di = Stanza::Iq::DiscoInfo.new nil, [], features
|
144
144
|
di.features.size.must_equal 3
|
145
145
|
di.features.each { |f| control.include?(f).must_equal true }
|
146
146
|
end
|