punchblock 0.4.0

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.
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,81 @@
1
+ module Punchblock
2
+ module Command
3
+ class Join < CommandNode
4
+ register :join, :core
5
+
6
+ ##
7
+ # Create a join message
8
+ #
9
+ # @param [Hash] options
10
+ # @option options [String, Optional] :other_call_id the call ID to join
11
+ # @option options [String, Optional] :mixer_id the mixer name to join
12
+ # @option options [Symbol, Optional] :direction the direction in which media should flow
13
+ # @option options [Symbol, Optional] :media the method by which to negotiate media
14
+ #
15
+ # @return [Command::Join] a formatted Rayo join command
16
+ #
17
+ def self.new(options = {})
18
+ super().tap do |new_node|
19
+ case options
20
+ when Nokogiri::XML::Node
21
+ new_node.inherit options
22
+ when Hash
23
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
24
+ end
25
+ end
26
+ end
27
+
28
+ ##
29
+ # @return [String] the call ID to join
30
+ def other_call_id
31
+ read_attr :'call-id'
32
+ end
33
+
34
+ ##
35
+ # @param [String] other the call ID to join
36
+ def other_call_id=(other)
37
+ write_attr :'call-id', other
38
+ end
39
+
40
+ ##
41
+ # @return [String] the mixer name to join
42
+ def mixer_id
43
+ read_attr :'mixer-id'
44
+ end
45
+
46
+ ##
47
+ # @param [String] other the mixer name to join
48
+ def mixer_id=(other)
49
+ write_attr :'mixer-id', other
50
+ end
51
+
52
+ ##
53
+ # @return [String] the direction in which media should flow
54
+ def direction
55
+ read_attr :direction, :to_sym
56
+ end
57
+
58
+ ##
59
+ # @param [String] other the direction in which media should flow. Can be :duplex, :recv or :send
60
+ def direction=(other)
61
+ write_attr :direction, other
62
+ end
63
+
64
+ ##
65
+ # @return [String] the method by which to negotiate media
66
+ def media
67
+ read_attr :media, :to_sym
68
+ end
69
+
70
+ ##
71
+ # @param [String] other the method by which to negotiate media. Can be :direct or :bridge
72
+ def media=(other)
73
+ write_attr :media, other
74
+ end
75
+
76
+ def inspect_attributes # :nodoc:
77
+ [:other_call_id, :mixer_id, :direction, :media] + super
78
+ end
79
+ end # Join
80
+ end # Command
81
+ end # Punchblock
@@ -0,0 +1,7 @@
1
+ module Punchblock
2
+ module Command
3
+ class Mute < CommandNode
4
+ register :mute, :core
5
+ end # Mute
6
+ end # Command
7
+ end # Punchblock
@@ -0,0 +1,49 @@
1
+ module Punchblock
2
+ module Command
3
+ class Redirect < CommandNode
4
+ register :redirect, :core
5
+
6
+ include HasHeaders
7
+
8
+ ##
9
+ # Create an Rayo redirect message
10
+ #
11
+ # @param [Hash] options
12
+ # @option options [String] :to redirect target
13
+ # @option options [Array[Header], Hash, Optional] :headers SIP headers to attach to
14
+ # the new call. Can be either a hash of key-value pairs, or an array of
15
+ # Header objects.
16
+ #
17
+ # @return [Command::Redirect] a formatted Rayo redirect command
18
+ #
19
+ # @example
20
+ # Redirect.new(:to => 'tel:+14045551234').to_xml
21
+ #
22
+ # returns:
23
+ # <redirect to="tel:+14045551234" xmlns="urn:xmpp:rayo:1"/>
24
+ #
25
+ def self.new(options = {})
26
+ super().tap do |new_node|
27
+ new_node.to = options[:to]
28
+ new_node.headers = options[:headers]
29
+ end
30
+ end
31
+
32
+ ##
33
+ # @return [String] the redirect target
34
+ def to
35
+ read_attr :to
36
+ end
37
+
38
+ ##
39
+ # @param [String] redirect_to redirect target
40
+ def to=(redirect_to)
41
+ write_attr :to, redirect_to
42
+ end
43
+
44
+ def inspect_attributes # :nodoc:
45
+ [:to] + super
46
+ end
47
+ end # Redirect
48
+ end # Command
49
+ end # Punchblock
@@ -0,0 +1,61 @@
1
+ module Punchblock
2
+ module Command
3
+ class Reject < CommandNode
4
+ register :reject, :core
5
+
6
+ include HasHeaders
7
+
8
+ VALID_REASONS = [:busy, :decline, :error].freeze
9
+
10
+ ##
11
+ # Create an Rayo reject message
12
+ #
13
+ # @param [Hash] options
14
+ # @option options [Symbol] :reason for rejecting the call. Can be any one of VALID_REASONS. Defaults to :decline
15
+ # @option options [Array[Header], Hash, Optional] :headers SIP headers to attach to
16
+ # the call. Can be either a hash of key-value pairs, or an array of
17
+ # Header objects.
18
+ #
19
+ # @return [Command::Reject] a formatted Rayo reject command
20
+ #
21
+ # @example
22
+ # Reject.new(:reason => :busy).to_xml
23
+ #
24
+ # returns:
25
+ # <reject xmlns="urn:xmpp:rayo:1"><busy/></reject
26
+ #
27
+ def self.new(options = {})
28
+ super().tap do |new_node|
29
+ new_node.reason = options[:reason] || :decline
30
+ new_node.headers = options[:headers]
31
+ end
32
+ end
33
+
34
+ ##
35
+ # @return [Symbol] the reason type for rejecting a call
36
+ #
37
+ def reason
38
+ children.select { |c| c.is_a? Nokogiri::XML::Element }.first.name.to_sym
39
+ end
40
+
41
+ ##
42
+ # Set the reason for rejecting the call
43
+ #
44
+ # @param [Symbol] reject_reason Can be any one of :busy, :dclined or :error.
45
+ #
46
+ # @raises ArgumentError if reject_reason is not one of the allowed reasons
47
+ #
48
+ def reason=(reject_reason)
49
+ if reject_reason && !VALID_REASONS.include?(reject_reason.to_sym)
50
+ raise ArgumentError, "Invalid Reason (#{reject_reason}), use: #{VALID_REASONS*' '}"
51
+ end
52
+ children.each &:remove
53
+ self << RayoNode.new(reject_reason)
54
+ end
55
+
56
+ def inspect_attributes # :nodoc:
57
+ [:reason] + super
58
+ end
59
+ end # Reject
60
+ end # Command
61
+ end # Punchblock
@@ -0,0 +1,50 @@
1
+ module Punchblock
2
+ module Command
3
+ class Unjoin < CommandNode
4
+ register :unjoin, :core
5
+
6
+ ##
7
+ # Create an ujoin message
8
+ #
9
+ # @param [Hash] options
10
+ # @option options [String, Optional] :other_call_id the call ID to unjoin
11
+ # @option options [String, Optional] :mixer_id the mixer name to unjoin
12
+ #
13
+ # @return [Command::Unjoin] a formatted Rayo unjoin command
14
+ #
15
+ def self.new(options = {})
16
+ super().tap do |new_node|
17
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
18
+ end
19
+ end
20
+
21
+ ##
22
+ # @return [String] the call ID to unjoin
23
+ def other_call_id
24
+ read_attr :'call-id'
25
+ end
26
+
27
+ ##
28
+ # @param [String] other the call ID to unjoin
29
+ def other_call_id=(other)
30
+ write_attr :'call-id', other
31
+ end
32
+
33
+ ##
34
+ # @return [String] the mixer name to unjoin
35
+ def mixer_id
36
+ read_attr :'mixer-id'
37
+ end
38
+
39
+ ##
40
+ # @param [String] other the mixer name to unjoin
41
+ def mixer_id=(other)
42
+ write_attr :'mixer-id', other
43
+ end
44
+
45
+ def inspect_attributes # :nodoc:
46
+ [:other_call_id, :mixer_id] + super
47
+ end
48
+ end # Unjoin
49
+ end # Command
50
+ end # Punchblock
@@ -0,0 +1,7 @@
1
+ module Punchblock
2
+ module Command
3
+ class Unmute < CommandNode
4
+ register :unmute, :core
5
+ end # Mute
6
+ end # Command
7
+ end # Punchblock
@@ -0,0 +1,16 @@
1
+ module Punchblock
2
+ module Command
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Accept
6
+ autoload :Answer
7
+ autoload :Dial
8
+ autoload :Hangup
9
+ autoload :Join
10
+ autoload :Mute
11
+ autoload :Redirect
12
+ autoload :Reject
13
+ autoload :Unjoin
14
+ autoload :Unmute
15
+ end # Command
16
+ end # Punchblock
@@ -0,0 +1,46 @@
1
+ require 'state_machine'
2
+
3
+ module Punchblock
4
+ class CommandNode < RayoNode
5
+ def self.new(options = {})
6
+ super().tap do |new_node|
7
+ new_node.call_id = options[:call_id]
8
+ new_node.component_id = options[:component_id]
9
+ end
10
+ end
11
+
12
+ def initialize(*args)
13
+ super
14
+ @response = FutureResource.new
15
+ end
16
+
17
+ state_machine :state, :initial => :new do
18
+ event :request do
19
+ transition :new => :requested
20
+ end
21
+
22
+ event :execute do
23
+ transition :requested => :executing
24
+ end
25
+
26
+ event :complete do
27
+ transition :executing => :complete
28
+ end
29
+ end
30
+
31
+ def write_attr(*args)
32
+ raise StandardError, "Cannot alter attributes of a requested command" unless new?
33
+ super
34
+ end
35
+
36
+ def response(timeout = nil)
37
+ @response.resource timeout
38
+ end
39
+
40
+ def response=(other)
41
+ return if @response.set_yet?
42
+ @response.resource = other
43
+ execute!
44
+ end
45
+ end # CommandNode
46
+ end # Punchblock
@@ -0,0 +1,320 @@
1
+ module Punchblock
2
+ module Component
3
+ class Input < ComponentNode
4
+ register :input, :input
5
+
6
+ ##
7
+ # Create an input message
8
+ #
9
+ # @param [Hash] options for inputing/prompting a specific call
10
+ # @option options [Choices, Hash] :choices to allow the user to input
11
+ # @option options [Prompt, Hash, Optional] :prompt to play/read to the caller as the question
12
+ # @option options [Symbol, Optional] :mode by which to accept input. Can be :speech, :dtmf or :any
13
+ # @option options [Integer, Optional] :timeout to wait for user input
14
+ # @option options [Boolean, Optional] :bargein wether or not to allow the caller to begin their response before the prompt finishes
15
+ # @option options [String, Optional] :recognizer to use for speech recognition
16
+ # @option options [String, Optional] :terminator by which to signal the end of input
17
+ # @option options [Float, Optional] :min_confidence with which to consider a response acceptable
18
+ #
19
+ # @return [Command::Input] a formatted Rayo input command
20
+ #
21
+ # @example
22
+ # input :prompt => {:text => 'Please enter your postal code.', :voice => 'simon'},
23
+ # :choices => {:value => '[5 DIGITS]'},
24
+ # :timeout => 30,
25
+ # :recognizer => 'es-es'
26
+ #
27
+ # returns:
28
+ # <input xmlns="urn:xmpp:tropo:input:1" timeout="30" recognizer="es-es">
29
+ # <prompt voice='simon'>Please enter your postal code.</prompt>
30
+ # <choices content-type="application/grammar+voxeo">[5 DIGITS]</choices>
31
+ # </input>
32
+ #
33
+ def self.new(options = {})
34
+ super().tap do |new_node|
35
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
36
+ end
37
+ end
38
+
39
+ ##
40
+ # @return [Boolean] wether or not to allow the caller to begin their response before the prompt finishes
41
+ #
42
+ def max_digits
43
+ read_attr :'max-digits', :to_i
44
+ end
45
+
46
+ ##
47
+ # @param [Boolean] bargein wether or not to allow the caller to begin their response before the prompt finishes
48
+ #
49
+ def max_digits=(other)
50
+ write_attr :'max-digits', other
51
+ end
52
+
53
+ ##
54
+ # @return [Float] Confidence with which to consider a response acceptable
55
+ #
56
+ def min_confidence
57
+ read_attr 'min-confidence', :to_f
58
+ end
59
+
60
+ ##
61
+ # @param [Float] min_confidence with which to consider a response acceptable
62
+ #
63
+ def min_confidence=(min_confidence)
64
+ write_attr 'min-confidence', min_confidence
65
+ end
66
+
67
+ ##
68
+ # @return [Symbol] mode by which to accept input. Can be :speech, :dtmf or :any
69
+ #
70
+ def mode
71
+ read_attr :mode, :to_sym
72
+ end
73
+
74
+ ##
75
+ # @param [Symbol] mode by which to accept input. Can be :speech, :dtmf or :any
76
+ #
77
+ def mode=(mode)
78
+ write_attr :mode, mode
79
+ end
80
+
81
+ ##
82
+ # @return [String] recognizer to use for speech recognition
83
+ #
84
+ def recognizer
85
+ read_attr :recognizer
86
+ end
87
+
88
+ ##
89
+ # @param [String] recognizer to use for speech recognition
90
+ #
91
+ def recognizer=(recognizer)
92
+ write_attr :recognizer, recognizer
93
+ end
94
+
95
+ ##
96
+ # @return [String] terminator by which to signal the end of input
97
+ #
98
+ def terminator
99
+ read_attr :terminator
100
+ end
101
+
102
+ ##
103
+ # @param [String] terminator by which to signal the end of input
104
+ #
105
+ def terminator=(terminator)
106
+ write_attr :terminator, terminator
107
+ end
108
+
109
+ ##
110
+ # @return [Integer] timeout to wait for user input
111
+ #
112
+ def sensitivity
113
+ read_attr :sensitivity, :to_f
114
+ end
115
+
116
+ ##
117
+ # @param [Integer] timeout to wait for user input
118
+ #
119
+ def sensitivity=(other)
120
+ write_attr :sensitivity, other
121
+ end
122
+
123
+ ##
124
+ # @return [Integer] timeout to wait for user input
125
+ #
126
+ def initial_timeout
127
+ read_attr :'initial-timeout', :to_i
128
+ end
129
+
130
+ ##
131
+ # @param [Integer] timeout to wait for user input
132
+ #
133
+ def initial_timeout=(other)
134
+ write_attr :'initial-timeout', other
135
+ end
136
+
137
+ ##
138
+ # @return [Integer] timeout to wait for user input
139
+ #
140
+ def inter_digit_timeout
141
+ read_attr :'inter-digit-timeout', :to_i
142
+ end
143
+
144
+ ##
145
+ # @param [Integer] timeout to wait for user input
146
+ #
147
+ def inter_digit_timeout=(other)
148
+ write_attr :'inter-digit-timeout', other
149
+ end
150
+
151
+ ##
152
+ # @return [Integer] timeout to wait for user input
153
+ #
154
+ def term_timeout
155
+ read_attr :'term-timeout', :to_i
156
+ end
157
+
158
+ ##
159
+ # @param [Integer] timeout to wait for user input
160
+ #
161
+ def term_timeout=(other)
162
+ write_attr :'term-timeout', other
163
+ end
164
+
165
+ ##
166
+ # @return [Integer] timeout to wait for user input
167
+ #
168
+ def complete_timeout
169
+ read_attr :'complete-timeout', :to_i
170
+ end
171
+
172
+ ##
173
+ # @param [Integer] timeout to wait for user input
174
+ #
175
+ def complete_timeout=(other)
176
+ write_attr :'complete-timeout', other
177
+ end
178
+
179
+ ##
180
+ # @return [Integer] timeout to wait for user input
181
+ #
182
+ def incomplete_timeout
183
+ read_attr :'incomplete-timeout', :to_i
184
+ end
185
+
186
+ ##
187
+ # @param [Integer] timeout to wait for user input
188
+ #
189
+ def incomplete_timeout=(other)
190
+ write_attr :'incomplete-timeout', other
191
+ end
192
+
193
+ ##
194
+ # @return [Choices] the choices available
195
+ #
196
+ def grammar
197
+ Grammar.new find_first('ns:grammar', :ns => self.class.registered_ns)
198
+ end
199
+
200
+ ##
201
+ # @param [Hash] choices
202
+ # @option choices [String] :content_type
203
+ # @option choices [String] :value the choices available
204
+ #
205
+ def grammar=(other)
206
+ remove_children :grammar
207
+ grammar = Grammar.new(other) unless other.is_a?(Grammar)
208
+ self << grammar
209
+ end
210
+
211
+ def inspect_attributes # :nodoc:
212
+ [:mode, :terminator, :max_digits, :recognizer, :initial_timeout, :inter_digit_timeout, :term_timeout, :complete_timeout, :incomplete_timeout, :sensitivity, :min_confidence, :choices] + super
213
+ end
214
+
215
+ class Grammar < RayoNode
216
+ ##
217
+ # @param [Hash] options
218
+ # @option options [String] :content_type
219
+ # @option options [String] :value the choices available
220
+ #
221
+ def self.new(options = {})
222
+ super(:grammar).tap do |new_node|
223
+ case options
224
+ when Nokogiri::XML::Node
225
+ new_node.inherit options
226
+ when Hash
227
+ new_node.content_type = options[:content_type]
228
+ new_node.value = options[:value]
229
+ end
230
+ end
231
+ end
232
+
233
+ ##
234
+ # @return [String] the choice content type
235
+ #
236
+ def content_type
237
+ read_attr 'content-type'
238
+ end
239
+
240
+ ##
241
+ # @param [String] content_type Defaults to the Voxeo Simple Grammar
242
+ #
243
+ def content_type=(content_type)
244
+ write_attr 'content-type', content_type || 'application/grammar+grxml'
245
+ end
246
+
247
+ ##
248
+ # @return [String] the choices available
249
+ def value
250
+ content
251
+ end
252
+
253
+ ##
254
+ # @param [String] value the choices available
255
+ def value=(value)
256
+ Nokogiri::XML::Builder.with(self) do |xml|
257
+ xml.cdata " #{value} "
258
+ end
259
+ end
260
+
261
+ # Compare two Choices objects by content type, and value
262
+ # @param [Header] o the Choices object to compare against
263
+ # @return [true, false]
264
+ def eql?(o, *fields)
265
+ super o, *(fields + [:content_type, :value])
266
+ end
267
+
268
+ def inspect_attributes # :nodoc:
269
+ [:content_type, :value] + super
270
+ end
271
+ end # Choices
272
+
273
+ class Complete
274
+ class Success < Event::Complete::Reason
275
+ register :success, :input_complete
276
+
277
+ ##
278
+ # @return [Symbol] the mode by which the question was answered. May be :speech or :dtmf
279
+ #
280
+ def mode
281
+ read_attr :mode, :to_sym
282
+ end
283
+
284
+ ##
285
+ # @return [Float] A measure of the confidence of the result, between 0-1
286
+ #
287
+ def confidence
288
+ read_attr :confidence, :to_f
289
+ end
290
+
291
+ ##
292
+ # @return [String] An intelligent interpretation of the meaning of the response.
293
+ #
294
+ def interpretation
295
+ find_first('//ns:interpretation', :ns => self.registered_ns).text
296
+ end
297
+
298
+ ##
299
+ # @return [String] The exact response gained
300
+ #
301
+ def utterance
302
+ find_first('//ns:utterance', :ns => self.registered_ns).text
303
+ end
304
+
305
+ def inspect_attributes # :nodoc:
306
+ [:mode, :confidence, :interpretation, :utterance] + super
307
+ end
308
+ end
309
+
310
+ class NoMatch < Event::Complete::Reason
311
+ register :nomatch, :input_complete
312
+ end
313
+
314
+ class NoInput < Event::Complete::Reason
315
+ register :noinput, :input_complete
316
+ end
317
+ end # Complete
318
+ end # Input
319
+ end # Command
320
+ end # Punchblock