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.
@@ -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