punchblock 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/.document +5 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.markdown +31 -0
  7. data/Rakefile +23 -0
  8. data/assets/ozone/ask-1.0.xsd +56 -0
  9. data/assets/ozone/conference-1.0.xsd +17 -0
  10. data/assets/ozone/ozone-1.0.xsd +127 -0
  11. data/assets/ozone/say-1.0.xsd +24 -0
  12. data/assets/ozone/transfer-1.0.xsd +32 -0
  13. data/bin/punchblock-console +125 -0
  14. data/lib/punchblock/command/accept.rb +30 -0
  15. data/lib/punchblock/command/answer.rb +30 -0
  16. data/lib/punchblock/command/dial.rb +88 -0
  17. data/lib/punchblock/command/hangup.rb +25 -0
  18. data/lib/punchblock/command/join.rb +81 -0
  19. data/lib/punchblock/command/mute.rb +7 -0
  20. data/lib/punchblock/command/redirect.rb +49 -0
  21. data/lib/punchblock/command/reject.rb +61 -0
  22. data/lib/punchblock/command/unjoin.rb +50 -0
  23. data/lib/punchblock/command/unmute.rb +7 -0
  24. data/lib/punchblock/command.rb +16 -0
  25. data/lib/punchblock/command_node.rb +46 -0
  26. data/lib/punchblock/component/input.rb +320 -0
  27. data/lib/punchblock/component/output.rb +449 -0
  28. data/lib/punchblock/component/record.rb +216 -0
  29. data/lib/punchblock/component/tropo/ask.rb +197 -0
  30. data/lib/punchblock/component/tropo/conference.rb +328 -0
  31. data/lib/punchblock/component/tropo/say.rb +113 -0
  32. data/lib/punchblock/component/tropo/transfer.rb +178 -0
  33. data/lib/punchblock/component/tropo.rb +12 -0
  34. data/lib/punchblock/component.rb +73 -0
  35. data/lib/punchblock/connection.rb +209 -0
  36. data/lib/punchblock/core_ext/blather/stanza/presence.rb +11 -0
  37. data/lib/punchblock/core_ext/blather/stanza.rb +26 -0
  38. data/lib/punchblock/dsl.rb +46 -0
  39. data/lib/punchblock/event/answered.rb +7 -0
  40. data/lib/punchblock/event/complete.rb +65 -0
  41. data/lib/punchblock/event/dtmf.rb +19 -0
  42. data/lib/punchblock/event/end.rb +15 -0
  43. data/lib/punchblock/event/info.rb +15 -0
  44. data/lib/punchblock/event/joined.rb +50 -0
  45. data/lib/punchblock/event/offer.rb +29 -0
  46. data/lib/punchblock/event/ringing.rb +7 -0
  47. data/lib/punchblock/event/unjoined.rb +50 -0
  48. data/lib/punchblock/event.rb +16 -0
  49. data/lib/punchblock/generic_connection.rb +18 -0
  50. data/lib/punchblock/has_headers.rb +34 -0
  51. data/lib/punchblock/header.rb +47 -0
  52. data/lib/punchblock/media_container.rb +39 -0
  53. data/lib/punchblock/media_node.rb +17 -0
  54. data/lib/punchblock/protocol_error.rb +16 -0
  55. data/lib/punchblock/rayo_node.rb +88 -0
  56. data/lib/punchblock/ref.rb +26 -0
  57. data/lib/punchblock/version.rb +3 -0
  58. data/lib/punchblock.rb +42 -0
  59. data/log/.gitkeep +0 -0
  60. data/punchblock.gemspec +42 -0
  61. data/spec/punchblock/command/accept_spec.rb +13 -0
  62. data/spec/punchblock/command/answer_spec.rb +13 -0
  63. data/spec/punchblock/command/dial_spec.rb +54 -0
  64. data/spec/punchblock/command/hangup_spec.rb +13 -0
  65. data/spec/punchblock/command/join_spec.rb +21 -0
  66. data/spec/punchblock/command/mute_spec.rb +11 -0
  67. data/spec/punchblock/command/redirect_spec.rb +19 -0
  68. data/spec/punchblock/command/reject_spec.rb +43 -0
  69. data/spec/punchblock/command/unjoin_spec.rb +19 -0
  70. data/spec/punchblock/command/unmute_spec.rb +11 -0
  71. data/spec/punchblock/command_node_spec.rb +80 -0
  72. data/spec/punchblock/component/input_spec.rb +188 -0
  73. data/spec/punchblock/component/output_spec.rb +531 -0
  74. data/spec/punchblock/component/record_spec.rb +235 -0
  75. data/spec/punchblock/component/tropo/ask_spec.rb +183 -0
  76. data/spec/punchblock/component/tropo/conference_spec.rb +360 -0
  77. data/spec/punchblock/component/tropo/say_spec.rb +171 -0
  78. data/spec/punchblock/component/tropo/transfer_spec.rb +153 -0
  79. data/spec/punchblock/component_spec.rb +126 -0
  80. data/spec/punchblock/connection_spec.rb +194 -0
  81. data/spec/punchblock/event/answered_spec.rb +23 -0
  82. data/spec/punchblock/event/complete_spec.rb +80 -0
  83. data/spec/punchblock/event/dtmf_spec.rb +24 -0
  84. data/spec/punchblock/event/end_spec.rb +30 -0
  85. data/spec/punchblock/event/info_spec.rb +30 -0
  86. data/spec/punchblock/event/joined_spec.rb +32 -0
  87. data/spec/punchblock/event/offer_spec.rb +35 -0
  88. data/spec/punchblock/event/ringing_spec.rb +23 -0
  89. data/spec/punchblock/event/unjoined_spec.rb +32 -0
  90. data/spec/punchblock/header_spec.rb +44 -0
  91. data/spec/punchblock/protocol_error_spec.rb +9 -0
  92. data/spec/punchblock/ref_spec.rb +21 -0
  93. data/spec/spec_helper.rb +43 -0
  94. metadata +353 -0
@@ -0,0 +1,449 @@
1
+ module Punchblock
2
+ module Component
3
+ class Output < ComponentNode
4
+ register :output, :output
5
+
6
+ include MediaContainer
7
+
8
+ ##
9
+ # Creates an Rayo Output command
10
+ #
11
+ # @param [Hash] options
12
+ # @option options [String, Optional] :text to speak back
13
+ # @option options [String, Optional] :voice with which to render TTS
14
+ # @option options [String, Optional] :ssml document to render TTS
15
+ #
16
+ # @return [Command::Output] an Rayo "output" command
17
+ #
18
+ # @example
19
+ # output :text => 'Hello brown cow.'
20
+ #
21
+ # returns:
22
+ # <output xmlns="urn:xmpp:tropo:output:1">Hello brown cow.</output>
23
+ #
24
+ def self.new(options = {})
25
+ super().tap do |new_node|
26
+ case options
27
+ when Hash
28
+ new_node.voice = options.delete(:voice) if options[:voice]
29
+ new_node.ssml = options.delete(:ssml) if options[:ssml]
30
+ new_node << options.delete(:text) if options[:text]
31
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
32
+ when Nokogiri::XML::Element
33
+ new_node.inherit options
34
+ end
35
+ end
36
+ end
37
+
38
+ ##
39
+ # @return [String] the TTS voice to use
40
+ #
41
+ def interrupt_on
42
+ read_attr :'interrupt-on', :to_sym
43
+ end
44
+
45
+ ##
46
+ # @param [String] voice to use when rendering TTS
47
+ #
48
+ def interrupt_on=(other)
49
+ write_attr :'interrupt-on', other
50
+ end
51
+
52
+ ##
53
+ # @return [String] the TTS voice to use
54
+ #
55
+ def start_offset
56
+ read_attr :'start-offset', :to_i
57
+ end
58
+
59
+ ##
60
+ # @param [String] voice to use when rendering TTS
61
+ #
62
+ def start_offset=(other)
63
+ write_attr :'start-offset', other
64
+ end
65
+
66
+ ##
67
+ # @return [String] the TTS voice to use
68
+ #
69
+ def start_paused
70
+ read_attr(:'start-paused') == 'true'
71
+ end
72
+
73
+ ##
74
+ # @param [String] voice to use when rendering TTS
75
+ #
76
+ def start_paused=(other)
77
+ write_attr :'start-paused', other.to_s
78
+ end
79
+
80
+ ##
81
+ # @return [String] the TTS voice to use
82
+ #
83
+ def repeat_interval
84
+ read_attr :'repeat-interval', :to_i
85
+ end
86
+
87
+ ##
88
+ # @param [String] voice to use when rendering TTS
89
+ #
90
+ def repeat_interval=(other)
91
+ write_attr :'repeat-interval', other
92
+ end
93
+
94
+ ##
95
+ # @return [String] the TTS voice to use
96
+ #
97
+ def repeat_times
98
+ read_attr :'repeat-times', :to_i
99
+ end
100
+
101
+ ##
102
+ # @param [String] voice to use when rendering TTS
103
+ #
104
+ def repeat_times=(other)
105
+ write_attr :'repeat-times', other
106
+ end
107
+
108
+ ##
109
+ # @return [String] the TTS voice to use
110
+ #
111
+ def max_time
112
+ read_attr(:'max-time').to_i
113
+ end
114
+
115
+ ##
116
+ # @param [String] voice to use when rendering TTS
117
+ #
118
+ def max_time=(other)
119
+ write_attr :'max-time', other
120
+ end
121
+
122
+ state_machine :state do
123
+ event :paused do
124
+ transition :executing => :paused
125
+ end
126
+
127
+ event :resumed do
128
+ transition :paused => :executing
129
+ end
130
+ end
131
+
132
+ # Pauses a running Output
133
+ #
134
+ # @return [Command::Output::Pause] an Rayo pause message for the current Output
135
+ #
136
+ # @example
137
+ # output_obj.pause_action.to_xml
138
+ #
139
+ # returns:
140
+ # <pause xmlns="urn:xmpp:tropo:output:1"/>
141
+ def pause_action
142
+ Pause.new :component_id => component_id, :call_id => call_id
143
+ end
144
+
145
+ ##
146
+ # Sends an Rayo pause message for the current Output
147
+ #
148
+ def pause!
149
+ raise InvalidActionError, "Cannot pause a Output that is not executing" unless executing?
150
+ pause_action.tap do |action|
151
+ result = write_action action
152
+ paused! if result
153
+ end
154
+ end
155
+
156
+ ##
157
+ # Create an Rayo resume message for the current Output
158
+ #
159
+ # @return [Command::Output::Resume] an Rayo resume message
160
+ #
161
+ # @example
162
+ # output_obj.resume_action.to_xml
163
+ #
164
+ # returns:
165
+ # <resume xmlns="urn:xmpp:tropo:output:1"/>
166
+ def resume_action
167
+ Resume.new :component_id => component_id, :call_id => call_id
168
+ end
169
+
170
+ ##
171
+ # Sends an Rayo resume message for the current Output
172
+ #
173
+ def resume!
174
+ raise InvalidActionError, "Cannot resume a Output that is not paused." unless paused?
175
+ resume_action.tap do |action|
176
+ result = write_action action
177
+ resumed! if result
178
+ end
179
+ end
180
+
181
+ class Pause < CommandNode # :nodoc:
182
+ register :pause, :output
183
+ end
184
+
185
+ class Resume < CommandNode # :nodoc:
186
+ register :resume, :output
187
+ end
188
+
189
+ ##
190
+ # Creates an Rayo seek message for the current Output
191
+ #
192
+ # @return [Command::Output::Seek] a Rayo seek message
193
+ #
194
+ # @example
195
+ # output_obj.seek_action.to_xml
196
+ #
197
+ # returns:
198
+ # <seek xmlns="urn:xmpp:rayo:output:1"/>
199
+ def seek_action(options = {})
200
+ Seek.new({ :component_id => component_id, :call_id => call_id }.merge(options)).tap do |s|
201
+ s.original_component = self
202
+ end
203
+ end
204
+
205
+ ##
206
+ # Sends a Rayo seek message for the current Output
207
+ #
208
+ def seek!(options = {})
209
+ raise InvalidActionError, "Cannot seek an Output that is already seeking." if seeking?
210
+ seek_action(options).tap do |action|
211
+ write_action action
212
+ end
213
+ end
214
+
215
+ state_machine :seek_status, :initial => :not_seeking do
216
+ event :seeking do
217
+ transition :not_seeking => :seeking
218
+ end
219
+
220
+ event :stopped_seeking do
221
+ transition :seeking => :not_seeking
222
+ end
223
+ end
224
+
225
+ class Seek < CommandNode # :nodoc:
226
+ register :seek, :output
227
+
228
+ def self.new(options = {})
229
+ super.tap do |new_node|
230
+ new_node.direction = options[:direction]
231
+ new_node.amount = options[:amount]
232
+ end
233
+ end
234
+
235
+ def direction=(other)
236
+ write_attr :direction, other
237
+ end
238
+
239
+ def amount=(other)
240
+ write_attr :amount, other
241
+ end
242
+
243
+ def request!
244
+ source.seeking!
245
+ super
246
+ end
247
+
248
+ def execute!
249
+ source.stopped_seeking!
250
+ super
251
+ end
252
+ end
253
+
254
+ ##
255
+ # Creates an Rayo speed up message for the current Output
256
+ #
257
+ # @return [Command::Output::SpeedUp] a Rayo speed up message
258
+ #
259
+ # @example
260
+ # output_obj.speed_up_action.to_xml
261
+ #
262
+ # returns:
263
+ # <speed-up xmlns="urn:xmpp:rayo:output:1"/>
264
+ def speed_up_action
265
+ SpeedUp.new(:component_id => component_id, :call_id => call_id).tap do |s|
266
+ s.original_component = self
267
+ end
268
+ end
269
+
270
+ ##
271
+ # Sends a Rayo speed up message for the current Output
272
+ #
273
+ def speed_up!
274
+ raise InvalidActionError, "Cannot speed up an Output that is already speeding." unless not_speeding?
275
+ speed_up_action.tap do |action|
276
+ write_action action
277
+ end
278
+ end
279
+
280
+ ##
281
+ # Creates an Rayo slow down message for the current Output
282
+ #
283
+ # @return [Command::Output::SlowDown] a Rayo slow down message
284
+ #
285
+ # @example
286
+ # output_obj.slow_down_action.to_xml
287
+ #
288
+ # returns:
289
+ # <speed-down xmlns="urn:xmpp:rayo:output:1"/>
290
+ def slow_down_action
291
+ SlowDown.new(:component_id => component_id, :call_id => call_id).tap do |s|
292
+ s.original_component = self
293
+ end
294
+ end
295
+
296
+ ##
297
+ # Sends a Rayo slow down message for the current Output
298
+ #
299
+ def slow_down!
300
+ raise InvalidActionError, "Cannot slow down an Output that is already speeding." unless not_speeding?
301
+ slow_down_action.tap do |action|
302
+ write_action action
303
+ end
304
+ end
305
+
306
+ state_machine :speed_status, :initial => :not_speeding do
307
+ event :speeding_up do
308
+ transition :not_speeding => :speeding_up
309
+ end
310
+
311
+ event :slowing_down do
312
+ transition :not_speeding => :slowing_down
313
+ end
314
+
315
+ event :stopped_speeding do
316
+ transition [:speeding_up, :slowing_down] => :not_speeding
317
+ end
318
+ end
319
+
320
+ class SpeedUp < CommandNode # :nodoc:
321
+ register :'speed-up', :output
322
+
323
+ def request!
324
+ source.speeding_up!
325
+ super
326
+ end
327
+
328
+ def execute!
329
+ source.stopped_speeding!
330
+ super
331
+ end
332
+ end
333
+
334
+ class SlowDown < CommandNode # :nodoc:
335
+ register :'speed-down', :output
336
+
337
+ def request!
338
+ source.slowing_down!
339
+ super
340
+ end
341
+
342
+ def execute!
343
+ source.stopped_speeding!
344
+ super
345
+ end
346
+ end
347
+
348
+ ##
349
+ # Creates an Rayo volume up message for the current Output
350
+ #
351
+ # @return [Command::Output::VolumeUp] a Rayo volume up message
352
+ #
353
+ # @example
354
+ # output_obj.volume_up_action.to_xml
355
+ #
356
+ # returns:
357
+ # <volume-up xmlns="urn:xmpp:rayo:output:1"/>
358
+ def volume_up_action
359
+ VolumeUp.new(:component_id => component_id, :call_id => call_id).tap do |s|
360
+ s.original_component = self
361
+ end
362
+ end
363
+
364
+ ##
365
+ # Sends a Rayo volume up message for the current Output
366
+ #
367
+ def volume_up!
368
+ raise InvalidActionError, "Cannot volume up an Output that is already voluming." unless not_voluming?
369
+ volume_up_action.tap do |action|
370
+ write_action action
371
+ end
372
+ end
373
+
374
+ ##
375
+ # Creates an Rayo volume down message for the current Output
376
+ #
377
+ # @return [Command::Output::VolumeDown] a Rayo volume down message
378
+ #
379
+ # @example
380
+ # output_obj.volume_down_action.to_xml
381
+ #
382
+ # returns:
383
+ # <volume-down xmlns="urn:xmpp:rayo:output:1"/>
384
+ def volume_down_action
385
+ VolumeDown.new(:component_id => component_id, :call_id => call_id).tap do |s|
386
+ s.original_component = self
387
+ end
388
+ end
389
+
390
+ ##
391
+ # Sends a Rayo volume down message for the current Output
392
+ #
393
+ def volume_down!
394
+ raise InvalidActionError, "Cannot volume down an Output that is already voluming." unless not_voluming?
395
+ volume_down_action.tap do |action|
396
+ write_action action
397
+ end
398
+ end
399
+
400
+ state_machine :volume_status, :initial => :not_voluming do
401
+ event :voluming_up do
402
+ transition :not_voluming => :voluming_up
403
+ end
404
+
405
+ event :voluming_down do
406
+ transition :not_voluming => :voluming_down
407
+ end
408
+
409
+ event :stopped_voluming do
410
+ transition [:voluming_up, :voluming_down] => :not_voluming
411
+ end
412
+ end
413
+
414
+ class VolumeUp < CommandNode # :nodoc:
415
+ register :'volume-up', :output
416
+
417
+ def request!
418
+ source.voluming_up!
419
+ super
420
+ end
421
+
422
+ def execute!
423
+ source.stopped_voluming!
424
+ super
425
+ end
426
+ end
427
+
428
+ class VolumeDown < CommandNode # :nodoc:
429
+ register :'volume-down', :output
430
+
431
+ def request!
432
+ source.voluming_down!
433
+ super
434
+ end
435
+
436
+ def execute!
437
+ source.stopped_voluming!
438
+ super
439
+ end
440
+ end
441
+
442
+ class Complete
443
+ class Success < Event::Complete::Reason
444
+ register :success, :output_complete
445
+ end
446
+ end
447
+ end # Output
448
+ end # Command
449
+ end # Punchblock
@@ -0,0 +1,216 @@
1
+ module Punchblock
2
+ module Component
3
+ class Record < ComponentNode
4
+ register :record, :record
5
+
6
+ ##
7
+ # Creates an Rayo Record command
8
+ #
9
+ # @param [Hash] options
10
+ # @option options [String, Optional] :text to speak back
11
+ # @option options [String, Optional] :voice with which to render TTS
12
+ # @option options [String, Optional] :ssml document to render TTS
13
+ #
14
+ # @return [Command::Record] an Rayo "record" command
15
+ #
16
+ # @example
17
+ # record :text => 'Hello brown cow.'
18
+ #
19
+ # returns:
20
+ # <record xmlns="urn:xmpp:rayo:record:1">Hello brown cow.</record>
21
+ #
22
+ def self.new(options = {})
23
+ super().tap do |new_node|
24
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
25
+ end
26
+ end
27
+
28
+ ##
29
+ # @return [String] the codec to use for recording
30
+ #
31
+ def final_timeout
32
+ read_attr :'final-timeout', :to_i
33
+ end
34
+
35
+ ##
36
+ # @param [String] codec to use for recording
37
+ #
38
+ def final_timeout=(timeout)
39
+ write_attr :'final-timeout', timeout
40
+ end
41
+
42
+ ##
43
+ # @return [String] the codec to use for recording
44
+ #
45
+ def format
46
+ read_attr :format
47
+ end
48
+
49
+ ##
50
+ # @param [String] codec to use for recording
51
+ #
52
+ def format=(format)
53
+ write_attr :format, format
54
+ end
55
+
56
+ ##
57
+ # @return [String] the codec to use for recording
58
+ #
59
+ def initial_timeout
60
+ read_attr :'initial-timeout', :to_i
61
+ end
62
+
63
+ ##
64
+ # @param [String] codec to use for recording
65
+ #
66
+ def initial_timeout=(timeout)
67
+ write_attr :'initial-timeout', timeout
68
+ end
69
+
70
+ ##
71
+ # @return [String] the codec to use for recording
72
+ #
73
+ def max_duration
74
+ read_attr :'max-duration', :to_i
75
+ end
76
+
77
+ ##
78
+ # @param [String] codec to use for recording
79
+ #
80
+ def max_duration=(other)
81
+ write_attr :'max-duration', other
82
+ end
83
+
84
+ ##
85
+ # @return [String] the codec to use for recording
86
+ #
87
+ def start_beep
88
+ read_attr(:'start-beep') == 'true'
89
+ end
90
+
91
+ ##
92
+ # @param [String] codec to use for recording
93
+ #
94
+ def start_beep=(sb)
95
+ write_attr :'start-beep', sb
96
+ end
97
+
98
+ ##
99
+ # @return [String] the codec to use for recording
100
+ #
101
+ def stop_beep
102
+ read_attr(:'stop-beep') == 'true'
103
+ end
104
+
105
+ ##
106
+ # @param [String] codec to use for recording
107
+ #
108
+ def stop_beep=(sb)
109
+ write_attr :'stop-beep', sb
110
+ end
111
+
112
+ ##
113
+ # @return [String] the codec to use for recording
114
+ #
115
+ def start_paused
116
+ read_attr(:'start-paused') == 'true'
117
+ end
118
+
119
+ ##
120
+ # @param [String] codec to use for recording
121
+ #
122
+ def start_paused=(other)
123
+ write_attr :'start-paused', other
124
+ end
125
+
126
+ def inspect_attributes # :nodoc:
127
+ [:final_timeout, :format, :initial_timeout, :max_duration, :start_beep, :start_paused, :stop_beep] + super
128
+ end
129
+
130
+ state_machine :state do
131
+ event :paused do
132
+ transition :executing => :paused
133
+ end
134
+
135
+ event :resumed do
136
+ transition :paused => :executing
137
+ end
138
+ end
139
+
140
+ # Pauses a running Record
141
+ #
142
+ # @return [Command::Record::Pause] an Rayo pause message for the current Record
143
+ #
144
+ # @example
145
+ # record_obj.pause_action.to_xml
146
+ #
147
+ # returns:
148
+ # <pause xmlns="urn:xmpp:rayo:record:1"/>
149
+ def pause_action
150
+ Pause.new :component_id => component_id, :call_id => call_id
151
+ end
152
+
153
+ ##
154
+ # Sends an Rayo pause message for the current Record
155
+ #
156
+ def pause!
157
+ raise InvalidActionError, "Cannot pause a Record that is not executing" unless executing?
158
+ pause_action.tap do |action|
159
+ result = write_action action
160
+ paused! if result
161
+ end
162
+ end
163
+
164
+ ##
165
+ # Create an Rayo resume message for the current Record
166
+ #
167
+ # @return [Command::Record::Resume] an Rayo resume message
168
+ #
169
+ # @example
170
+ # record_obj.resume_action.to_xml
171
+ #
172
+ # returns:
173
+ # <resume xmlns="urn:xmpp:rayo:record:1"/>
174
+ def resume_action
175
+ Resume.new :component_id => component_id, :call_id => call_id
176
+ end
177
+
178
+ ##
179
+ # Sends an Rayo resume message for the current Record
180
+ #
181
+ def resume!
182
+ raise InvalidActionError, "Cannot resume a Record that is not paused." unless paused?
183
+ resume_action.tap do |action|
184
+ result = write_action action
185
+ resumed! if result
186
+ end
187
+ end
188
+
189
+ class Pause < CommandNode # :nodoc:
190
+ register :pause, :record
191
+ end
192
+
193
+ class Resume < CommandNode # :nodoc:
194
+ register :resume, :record
195
+ end
196
+
197
+ class Recording < Event
198
+ register :recording, :record_complete
199
+
200
+ def uri
201
+ read_attr :uri
202
+ end
203
+
204
+ def inspect_attributes # :nodoc:
205
+ [:uri] + super
206
+ end
207
+ end
208
+
209
+ class Complete
210
+ class Success < Event::Complete::Reason
211
+ register :success, :record_complete
212
+ end
213
+ end
214
+ end # Record
215
+ end # Command
216
+ end # Punchblock