em-xmpp 0.0.10 → 0.0.11
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/.gitignore +1 -0
- data/README.md +157 -18
- data/bin/xmig +1099 -0
- data/lib/em-xmpp/connection.rb +1 -0
- data/lib/em-xmpp/context.rb +444 -38
- data/lib/em-xmpp/conversation.rb +105 -0
- data/lib/em-xmpp/entity.rb +759 -31
- data/lib/em-xmpp/handler.rb +16 -0
- data/lib/em-xmpp/helpers.rb +207 -0
- data/lib/em-xmpp/jid.rb +2 -1
- data/lib/em-xmpp/namespaces.rb +25 -0
- data/lib/em-xmpp/version.rb +1 -1
- data/samples/hello.rb +25 -4
- metadata +12 -9
data/lib/em-xmpp/handler.rb
CHANGED
@@ -43,6 +43,14 @@ module EM::Xmpp
|
|
43
43
|
ctx.bit!(:error) if iq.error?
|
44
44
|
ctx
|
45
45
|
end
|
46
|
+
on_decorator('//xmlns:pubsub', 'xmlns' => PubSub) do |ctx|
|
47
|
+
ctx.bit!(:pubsub)
|
48
|
+
ctx
|
49
|
+
end
|
50
|
+
on_decorator('//xmlns:event', 'xmlns' => PubSubEvent) do |ctx|
|
51
|
+
ctx.bit!(:pubsubevent)
|
52
|
+
ctx
|
53
|
+
end
|
46
54
|
on_decorator('//xmlns:delay', 'xmlns' => Delay) do |ctx|
|
47
55
|
ctx.bit!(:delay)
|
48
56
|
ctx
|
@@ -63,6 +71,10 @@ module EM::Xmpp
|
|
63
71
|
ctx.bit!(:command)
|
64
72
|
ctx
|
65
73
|
end
|
74
|
+
on_decorator('//xmlns:data', 'xmlns' => BoB) do |ctx|
|
75
|
+
ctx.bit!(:bob)
|
76
|
+
ctx
|
77
|
+
end
|
66
78
|
on_decorator('//xmlns:x', 'xmlns' => DataForms) do |ctx|
|
67
79
|
ctx.bit!(:dataforms)
|
68
80
|
ctx
|
@@ -79,6 +91,10 @@ module EM::Xmpp
|
|
79
91
|
ctx.bit!(:streaminitiation)
|
80
92
|
ctx
|
81
93
|
end
|
94
|
+
on_decorator('//xmlns:open | //xmlns:data | //xmlns:close', 'xmlns' => IBB) do |ctx|
|
95
|
+
ctx.bit!(:ibb)
|
96
|
+
ctx
|
97
|
+
end
|
82
98
|
on_decorator('//xmlns:query', 'xmlns' => ByteStreams) do |ctx|
|
83
99
|
ctx.bit!(:bytestreams)
|
84
100
|
ctx
|
data/lib/em-xmpp/helpers.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
|
2
2
|
require 'em-xmpp/nodes'
|
3
|
+
require 'em-xmpp/conversation'
|
3
4
|
module EM::Xmpp
|
4
5
|
module Helpers
|
5
6
|
include EM::Xmpp::Namespaces
|
@@ -16,5 +17,211 @@ module EM::Xmpp
|
|
16
17
|
|
17
18
|
Fiber.yield
|
18
19
|
end
|
20
|
+
|
21
|
+
attr_reader :conversations
|
22
|
+
|
23
|
+
def framework_ready(*args,&blk)
|
24
|
+
@conversations = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def start_conversation(ctx,key,state=nil,&blk)
|
28
|
+
EM::Xmpp::Conversation.start(ctx,state) do |conv|
|
29
|
+
conversations[key] = conv
|
30
|
+
blk.call conv
|
31
|
+
conversations.delete key
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def conversation(key)
|
36
|
+
@conversations[key]
|
37
|
+
end
|
38
|
+
|
39
|
+
DataFormState = Struct.new(:form, :answers, :current_idx, :user_input) do
|
40
|
+
def current_field
|
41
|
+
form.fields[current_idx]
|
42
|
+
end
|
43
|
+
|
44
|
+
def current_values
|
45
|
+
current_field.values
|
46
|
+
end
|
47
|
+
|
48
|
+
def current_answer
|
49
|
+
answers.fields[current_idx]
|
50
|
+
end
|
51
|
+
|
52
|
+
def current_response_values
|
53
|
+
if current_answer
|
54
|
+
current_answer.values
|
55
|
+
else
|
56
|
+
current_values
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def dataform_conversation(initial_ctx,&blk)
|
62
|
+
form = initial_ctx.env['dataform']
|
63
|
+
answers = EM::Xmpp::Context::Contexts::Dataforms::Form.new('submit',[],nil,nil)
|
64
|
+
state = DataFormState.new(form, answers, 0, nil)
|
65
|
+
|
66
|
+
start_conversation(initial_ctx,:dataform,state) do |conv|
|
67
|
+
conv.prepare_callbacks(:start, :ask, :user_answer, :confirm, :submit, :cancel, &blk)
|
68
|
+
finalize = :submit
|
69
|
+
|
70
|
+
conv.callback(:start)
|
71
|
+
|
72
|
+
catch :cancel do
|
73
|
+
fields = state.form.fields.dup
|
74
|
+
cnt = fields.size
|
75
|
+
idx = 0
|
76
|
+
until (idx + 1) > cnt
|
77
|
+
state.current_idx = idx
|
78
|
+
conv.callback(:ask)
|
79
|
+
state.user_input = conv.delay.ctx
|
80
|
+
cb_action = conv.callback(:user_answer)
|
81
|
+
state.user_input = nil
|
82
|
+
|
83
|
+
case cb_action
|
84
|
+
when :previous
|
85
|
+
idx -= 1
|
86
|
+
idx = [0,idx].max
|
87
|
+
when :next, :modified
|
88
|
+
idx += 1
|
89
|
+
when :repeat
|
90
|
+
#don't touch index
|
91
|
+
when :cancel
|
92
|
+
finalize = :cancel
|
93
|
+
throw :cancel
|
94
|
+
else
|
95
|
+
raise RuntimeError, "no such data-form action: #{cb_action}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
conv.callback(:confirm)
|
100
|
+
state.user_input = conv.delay.ctx
|
101
|
+
end
|
102
|
+
conv.callback(finalize)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
CommandFlash = Struct.new(:level, :msg)
|
107
|
+
CommandState = Struct.new(:spec, :status, :current_idx, :flash, :last_answer, :result) do
|
108
|
+
def current_step
|
109
|
+
spec.step current_idx
|
110
|
+
end
|
111
|
+
def form
|
112
|
+
current_step.form
|
113
|
+
end
|
114
|
+
def can_complete?
|
115
|
+
spec.can_complete_command? current_idx
|
116
|
+
end
|
117
|
+
def can_prev?
|
118
|
+
spec.has_previous_command? current_idx
|
119
|
+
end
|
120
|
+
def can_next?
|
121
|
+
spec.has_next_command? current_idx
|
122
|
+
end
|
123
|
+
def finished?
|
124
|
+
spec.finished?(current_idx)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
LinearCommandsSpec = Struct.new(:steps) do
|
128
|
+
def step(idx)
|
129
|
+
steps[idx]
|
130
|
+
end
|
131
|
+
def finished?(idx)
|
132
|
+
(idx + 1) > steps.size
|
133
|
+
end
|
134
|
+
def has_previous_command?(idx)
|
135
|
+
idx > 0
|
136
|
+
end
|
137
|
+
def has_next_command?(idx)
|
138
|
+
idx + 1 < steps.size
|
139
|
+
end
|
140
|
+
def can_complete_command?(idx)
|
141
|
+
not has_next_command?(idx)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
CommandStep = Struct.new(:form) do
|
145
|
+
end
|
146
|
+
|
147
|
+
def start_command_conversation(ctx,key,sess_id,spec,&blk)
|
148
|
+
query = ctx.bit(:command)
|
149
|
+
|
150
|
+
state = CommandState.new(spec, :completed, 0, nil, nil, nil)
|
151
|
+
|
152
|
+
start_conversation(ctx,key,state) do |conv|
|
153
|
+
conv.prepare_callbacks(:start, :answer, :cancel, &blk)
|
154
|
+
|
155
|
+
conv.callback(:start)
|
156
|
+
|
157
|
+
catch :cancel do
|
158
|
+
until state.finished?
|
159
|
+
state.status = 'executing'
|
160
|
+
|
161
|
+
reply = query.reply do |iq|
|
162
|
+
iq.command(:xmlns => EM::Xmpp::Namespaces::Commands, :sessionid => sess_id, :node => query.node, :status => state.status) do |cmd|
|
163
|
+
cmd.actions do |n|
|
164
|
+
n.prev if state.can_prev?
|
165
|
+
n.complete if state.can_complete?
|
166
|
+
n.next if state.can_next?
|
167
|
+
end
|
168
|
+
build_form(cmd, state.form,'form')
|
169
|
+
cmd.note({:type => state.flash.level}, state.flash.msg) if state.flash
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
user_answer = conv.send_stanza reply
|
174
|
+
state.last_answer = user_answer
|
175
|
+
action = user_answer.ctx.bit(:command).action
|
176
|
+
|
177
|
+
case action
|
178
|
+
when 'cancel'
|
179
|
+
conv.callback(:cancel)
|
180
|
+
state.status = 'cancel'
|
181
|
+
throw :cancel
|
182
|
+
else
|
183
|
+
conv.callback(:answer)
|
184
|
+
end
|
185
|
+
end #end of until
|
186
|
+
|
187
|
+
state.status = 'completed'
|
188
|
+
end
|
189
|
+
|
190
|
+
finalizer = state.last_answer.ctx.bit(:command).reply do |iq|
|
191
|
+
iq.command(:xmlns => EM::Xmpp::Namespaces::Commands, :sessionid => sess_id, :node => query.node, :status => state.status) do |cmd|
|
192
|
+
cmd.note({:type => state.flash.level}, state.flash.msg) if state.flash
|
193
|
+
build_form(cmd, state.result,'result') if state.result
|
194
|
+
end
|
195
|
+
end
|
196
|
+
send_stanza finalizer
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def build_form(xml,form,type='submit')
|
201
|
+
xml.x(:xmlns => DataForms, :type => type) do |x|
|
202
|
+
x.title form.title if form.title
|
203
|
+
x.instructions form.instructions if form.instructions
|
204
|
+
form.fields.each do |field|
|
205
|
+
args = {'var' => field.var}
|
206
|
+
args = args.merge('type' => field.type) unless field.type.nil? or field.type.empty?
|
207
|
+
args = args.merge('label' => field.label) unless field.label.nil? or field.label.empty?
|
208
|
+
x.field(args) do |f|
|
209
|
+
(field.options||[]).each do |opt_value|
|
210
|
+
f.option do |o|
|
211
|
+
o.value opt_value
|
212
|
+
end
|
213
|
+
end
|
214
|
+
(field.values||[]).each do |value|
|
215
|
+
f.value value
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def build_submit_form(xml,form)
|
223
|
+
build_form(xml,form,'submit')
|
224
|
+
end
|
225
|
+
|
19
226
|
end
|
20
227
|
end
|
data/lib/em-xmpp/jid.rb
CHANGED
data/lib/em-xmpp/namespaces.rb
CHANGED
@@ -25,6 +25,11 @@ module EM::Xmpp
|
|
25
25
|
Roster = 'jabber:iq:roster'
|
26
26
|
#XMPP commands
|
27
27
|
Commands = "http://jabber.org/protocol/commands"
|
28
|
+
#avatar
|
29
|
+
AvatarData = "urn:xmpp:avatar:data"
|
30
|
+
AvatarMetaData = "urn:xmpp:avatar:metadata"
|
31
|
+
#attention
|
32
|
+
Attention = "urn:xmpp:attention:0"
|
28
33
|
#entity nicknames
|
29
34
|
Nick = "http://jabber.org/protocol/nick"
|
30
35
|
#entity activity
|
@@ -39,14 +44,32 @@ module EM::Xmpp
|
|
39
44
|
Delay = "urn:xmpp:delay"
|
40
45
|
#Jabber Data forms
|
41
46
|
DataForms = 'jabber:x:data'
|
47
|
+
#Pubsub
|
48
|
+
PubSub = 'http://jabber.org/protocol/pubsub'
|
49
|
+
#Pubsub#owner
|
50
|
+
PubSubOwner = 'http://jabber.org/protocol/pubsub#owner'
|
51
|
+
#Pubsub#subscribe-authorization
|
52
|
+
PubSubSubscribeAuthorization = 'http://jabber.org/protocol/pubsub#subscribe_authorization'
|
53
|
+
#Pubsub#get-pending
|
54
|
+
PubSubGetPending = 'http://jabber.org/protocol/pubsub#get-pending'
|
55
|
+
#Pubsub#event
|
56
|
+
PubSubEvent = 'http://jabber.org/protocol/pubsub#event'
|
57
|
+
#Multi user chat
|
58
|
+
Muc = 'http://jabber.org/protocol/muc'
|
42
59
|
#Multi user chat - simple user
|
43
60
|
MucUser = 'http://jabber.org/protocol/muc#user'
|
61
|
+
#Multi user chat - admin
|
62
|
+
MucAdmin = 'http://jabber.org/protocol/muc#admin'
|
44
63
|
#Multi user chat - owner
|
45
64
|
MucOwner = 'http://jabber.org/protocol/muc#owner'
|
46
65
|
#Multi user chat - roomconfig
|
47
66
|
MucRoomconfig = 'http://jabber.org/protocol/muc#roomconfig'
|
48
67
|
#Stream initiation offer
|
49
68
|
StreamInitiation = 'http://jabber.org/protocol/si'
|
69
|
+
#Bits of Binary (bob)
|
70
|
+
BoB = 'urn:xmpp:bob'
|
71
|
+
#In-Band Bytestreams
|
72
|
+
IBB = 'http://jabber.org/protocol/ibb'
|
50
73
|
#FileTransfer
|
51
74
|
FileTransfer = 'http://jabber.org/protocol/si/profile/file-transfer'
|
52
75
|
#Feature Negotiation
|
@@ -55,5 +78,7 @@ module EM::Xmpp
|
|
55
78
|
ByteStreams = 'http://jabber.org/protocol/bytestreams'
|
56
79
|
#Extension for Fast byte stream transfers
|
57
80
|
FastByteStreams = 'http://affinix.com/jabber/stream'
|
81
|
+
#xhtml-im
|
82
|
+
XhtmlIM = 'http://jabber.org/protocol/xhtml-im'
|
58
83
|
end
|
59
84
|
end
|
data/lib/em-xmpp/version.rb
CHANGED
data/samples/hello.rb
CHANGED
@@ -15,7 +15,9 @@ module RosterClient
|
|
15
15
|
attr_reader :roster
|
16
16
|
|
17
17
|
include EM::Xmpp::Helpers
|
18
|
+
|
18
19
|
def ready
|
20
|
+
super #setup helpers
|
19
21
|
puts "***** #{@jid} ready"
|
20
22
|
|
21
23
|
on_presence do |ctx|
|
@@ -37,11 +39,30 @@ module RosterClient
|
|
37
39
|
msg = ctx.bit :message
|
38
40
|
|
39
41
|
puts "**** message from #{msg.from}"
|
40
|
-
|
41
|
-
|
42
|
-
|
42
|
+
|
43
|
+
key = msg.from.to_s
|
44
|
+
|
45
|
+
conv = conversation(key)
|
46
|
+
|
47
|
+
if conv
|
48
|
+
conv.resume ctx
|
49
|
+
else
|
50
|
+
x = rand(300)
|
51
|
+
y = rand(300)
|
52
|
+
start_conversation(ctx, key) do |c|
|
53
|
+
rep = c.send_stanza(msg.reply{|xml| xml.body("how much is #{x} - #{y} ?")}, 5)
|
54
|
+
greeting = if rep.interrupted?
|
55
|
+
if rep.ctx.bit(:message).body == (x - y).to_s
|
56
|
+
"great!"
|
57
|
+
else
|
58
|
+
"wrong: #{x - y}"
|
59
|
+
end
|
60
|
+
else
|
61
|
+
"too slow, laggard"
|
62
|
+
end
|
63
|
+
self.send_stanza(msg.reply{|xml| xml.body(greeting)})
|
64
|
+
end
|
43
65
|
end
|
44
|
-
send_stanza hello
|
45
66
|
|
46
67
|
ctx #returns a ctx for subsequent handlers if any
|
47
68
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-xmpp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-26 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
16
|
-
requirement: &
|
16
|
+
requirement: &2151825840 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2151825840
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: nokogiri
|
27
|
-
requirement: &
|
27
|
+
requirement: &2151814740 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2151814740
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: ruby-sasl
|
38
|
-
requirement: &
|
38
|
+
requirement: &2151812280 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,11 +43,12 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2151812280
|
47
47
|
description: XMPP client for event machine
|
48
48
|
email:
|
49
49
|
- crapooze@gmail.com
|
50
|
-
executables:
|
50
|
+
executables:
|
51
|
+
- xmig
|
51
52
|
extensions: []
|
52
53
|
extra_rdoc_files: []
|
53
54
|
files:
|
@@ -56,12 +57,14 @@ files:
|
|
56
57
|
- LICENSE
|
57
58
|
- README.md
|
58
59
|
- Rakefile
|
60
|
+
- bin/xmig
|
59
61
|
- em-xmpp.gemspec
|
60
62
|
- lib/em-xmpp.rb
|
61
63
|
- lib/em-xmpp/cert_store.rb
|
62
64
|
- lib/em-xmpp/connection.rb
|
63
65
|
- lib/em-xmpp/connector.rb
|
64
66
|
- lib/em-xmpp/context.rb
|
67
|
+
- lib/em-xmpp/conversation.rb
|
65
68
|
- lib/em-xmpp/entity.rb
|
66
69
|
- lib/em-xmpp/handler.rb
|
67
70
|
- lib/em-xmpp/helpers.rb
|