em-xmpp 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -5,7 +5,8 @@ module EM::Xmpp
5
5
  def self.parse(str)
6
6
  s1,s2 = str.split('@',2)
7
7
  if s2.nil?
8
- self.new(nil, s1, nil)
8
+ s1,s3 = s1.split('/',2)
9
+ self.new(nil, s1, s3)
9
10
  else
10
11
  s2,s3 = s2.split('/',2)
11
12
  self.new(s1,s2,s3)
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Em
2
2
  module Xmpp
3
- VERSION = "0.0.10"
3
+ VERSION = "0.0.11"
4
4
  end
5
5
  end
@@ -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
- puts msg.body
41
- hello = msg.reply do |rep|
42
- rep.body "hello world"
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.10
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-01-23 00:00:00.000000000Z
12
+ date: 2013-02-26 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
16
- requirement: &2156077160 !ruby/object:Gem::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: *2156077160
24
+ version_requirements: *2151825840
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: nokogiri
27
- requirement: &2156076480 !ruby/object:Gem::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: *2156076480
35
+ version_requirements: *2151814740
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: ruby-sasl
38
- requirement: &2156075840 !ruby/object:Gem::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: *2156075840
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