punchblock 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -0
- data/lib/punchblock.rb +2 -1
- data/lib/punchblock/component/tropo.rb +0 -3
- data/lib/punchblock/connection/xmpp.rb +9 -16
- data/lib/punchblock/disconnected_error.rb +16 -0
- data/lib/punchblock/version.rb +1 -1
- data/punchblock.gemspec +1 -1
- data/spec/punchblock/connection/xmpp_spec.rb +12 -12
- data/spec/punchblock/event/complete_spec.rb +2 -2
- metadata +43 -51
- data/lib/punchblock/component/tropo/ask.rb +0 -199
- data/lib/punchblock/component/tropo/say.rb +0 -113
- data/lib/punchblock/component/tropo/transfer.rb +0 -178
- data/spec/punchblock/component/tropo/ask_spec.rb +0 -181
- data/spec/punchblock/component/tropo/say_spec.rb +0 -172
- data/spec/punchblock/component/tropo/transfer_spec.rb +0 -154
@@ -1,199 +0,0 @@
|
|
1
|
-
module Punchblock
|
2
|
-
module Component
|
3
|
-
module Tropo
|
4
|
-
class Ask < ComponentNode
|
5
|
-
register :ask, :ask
|
6
|
-
|
7
|
-
##
|
8
|
-
# Create an ask message
|
9
|
-
#
|
10
|
-
# @param [Hash] options for asking/prompting a specific call
|
11
|
-
# @option options [Choices, Hash] :choices to allow the user to input
|
12
|
-
# @option options [Prompt, Hash, Optional] :prompt to play/read to the caller as the question
|
13
|
-
# @option options [Symbol, Optional] :mode by which to accept input. Can be :speech, :dtmf or :any
|
14
|
-
# @option options [Integer, Optional] :timeout to wait for user input
|
15
|
-
# @option options [Boolean, Optional] :bargein wether or not to allow the caller to begin their response before the prompt finishes
|
16
|
-
# @option options [String, Optional] :recognizer to use for speech recognition
|
17
|
-
# @option options [String, Optional] :terminator by which to signal the end of input
|
18
|
-
# @option options [Float, Optional] :min_confidence with which to consider a response acceptable
|
19
|
-
#
|
20
|
-
# @return [Command::Ask] a formatted Rayo ask command
|
21
|
-
#
|
22
|
-
# @example
|
23
|
-
# ask :prompt => {:text => 'Please enter your postal code.', :voice => 'simon'},
|
24
|
-
# :choices => {:value => '[5 DIGITS]'},
|
25
|
-
# :timeout => 30,
|
26
|
-
# :recognizer => 'es-es'
|
27
|
-
#
|
28
|
-
# returns:
|
29
|
-
# <ask xmlns="urn:xmpp:tropo:ask:1" timeout="30" recognizer="es-es">
|
30
|
-
# <prompt voice='simon'>Please enter your postal code.</prompt>
|
31
|
-
# <choices content-type="application/grammar+voxeo">[5 DIGITS]</choices>
|
32
|
-
# </ask>
|
33
|
-
#
|
34
|
-
def self.new(options = {})
|
35
|
-
super().tap do |new_node|
|
36
|
-
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
##
|
41
|
-
# @return [Boolean] wether or not to allow the caller to begin their response before the prompt finishes
|
42
|
-
#
|
43
|
-
def bargein
|
44
|
-
read_attr(:bargein) == "true"
|
45
|
-
end
|
46
|
-
|
47
|
-
##
|
48
|
-
# @param [Boolean] bargein wether or not to allow the caller to begin their response before the prompt finishes
|
49
|
-
#
|
50
|
-
def bargein=(bargein)
|
51
|
-
write_attr :bargein, bargein.to_s
|
52
|
-
end
|
53
|
-
|
54
|
-
##
|
55
|
-
# @return [Float] Confidence with which to consider a response acceptable
|
56
|
-
#
|
57
|
-
def min_confidence
|
58
|
-
read_attr 'min-confidence', :to_f
|
59
|
-
end
|
60
|
-
|
61
|
-
##
|
62
|
-
# @param [Float] min_confidence with which to consider a response acceptable
|
63
|
-
#
|
64
|
-
def min_confidence=(min_confidence)
|
65
|
-
write_attr 'min-confidence', min_confidence
|
66
|
-
end
|
67
|
-
|
68
|
-
##
|
69
|
-
# @return [Symbol] mode by which to accept input. Can be :speech, :dtmf or :any
|
70
|
-
#
|
71
|
-
def mode
|
72
|
-
read_attr :mode, :to_sym
|
73
|
-
end
|
74
|
-
|
75
|
-
##
|
76
|
-
# @param [Symbol] mode by which to accept input. Can be :speech, :dtmf or :any
|
77
|
-
#
|
78
|
-
def mode=(mode)
|
79
|
-
write_attr :mode, mode
|
80
|
-
end
|
81
|
-
|
82
|
-
##
|
83
|
-
# @return [String] recognizer to use for speech recognition
|
84
|
-
#
|
85
|
-
def recognizer
|
86
|
-
read_attr :recognizer
|
87
|
-
end
|
88
|
-
|
89
|
-
##
|
90
|
-
# @param [String] recognizer to use for speech recognition
|
91
|
-
#
|
92
|
-
def recognizer=(recognizer)
|
93
|
-
write_attr :recognizer, recognizer
|
94
|
-
end
|
95
|
-
|
96
|
-
##
|
97
|
-
# @return [String] terminator by which to signal the end of input
|
98
|
-
#
|
99
|
-
def terminator
|
100
|
-
read_attr :terminator
|
101
|
-
end
|
102
|
-
|
103
|
-
##
|
104
|
-
# @param [String] terminator by which to signal the end of input
|
105
|
-
#
|
106
|
-
def terminator=(terminator)
|
107
|
-
write_attr :terminator, terminator
|
108
|
-
end
|
109
|
-
|
110
|
-
##
|
111
|
-
# @return [Integer] timeout to wait for user input
|
112
|
-
#
|
113
|
-
def timeout
|
114
|
-
read_attr :timeout, :to_i
|
115
|
-
end
|
116
|
-
|
117
|
-
##
|
118
|
-
# @param [Integer] timeout to wait for user input
|
119
|
-
#
|
120
|
-
def timeout=(timeout)
|
121
|
-
write_attr :timeout, timeout
|
122
|
-
end
|
123
|
-
|
124
|
-
##
|
125
|
-
# @return [Prompt] the prompt by which to introduce the question
|
126
|
-
#
|
127
|
-
def prompt
|
128
|
-
Prompt.new find_first('//ns:prompt', :ns => self.registered_ns)
|
129
|
-
end
|
130
|
-
|
131
|
-
##
|
132
|
-
# @param [Hash] p
|
133
|
-
# @option p [String] :text to read the caller via TTS as the question
|
134
|
-
# @option p [String] :voice to use for speech synthesis
|
135
|
-
#
|
136
|
-
def prompt=(p)
|
137
|
-
remove_children :prompt
|
138
|
-
p = Prompt.new(p) unless p.is_a?(Prompt)
|
139
|
-
self << p
|
140
|
-
end
|
141
|
-
|
142
|
-
class Prompt < MediaNode
|
143
|
-
register :prompt, :ask
|
144
|
-
end
|
145
|
-
|
146
|
-
##
|
147
|
-
# @return [Choices] the choices available
|
148
|
-
#
|
149
|
-
def choices
|
150
|
-
node = find_first 'ns:choices', :ns => self.class.registered_ns
|
151
|
-
Choices.new node if node
|
152
|
-
end
|
153
|
-
|
154
|
-
##
|
155
|
-
# @param [Hash] choices
|
156
|
-
# @option choices [String] :content_type
|
157
|
-
# @option choices [String] :value the choices available
|
158
|
-
#
|
159
|
-
def choices=(choices)
|
160
|
-
return unless choices
|
161
|
-
remove_children :choices
|
162
|
-
choices = Choices.new(choices) unless choices.is_a?(Choices)
|
163
|
-
self << choices
|
164
|
-
end
|
165
|
-
|
166
|
-
def inspect_attributes # :nodoc:
|
167
|
-
[:bargein, :min_confidence, :mode, :recognizer, :terminator, :timeout, :prompt, :choices] + super
|
168
|
-
end
|
169
|
-
|
170
|
-
class Choices < Input::Grammar
|
171
|
-
##
|
172
|
-
# @param [Hash] options
|
173
|
-
# @option options [String] :content_type
|
174
|
-
# @option options [String] :value the choices available
|
175
|
-
#
|
176
|
-
def self.new(options = {})
|
177
|
-
super(options).tap do |new_node|
|
178
|
-
new_node.name = 'choices'
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end # Choices
|
182
|
-
|
183
|
-
class Complete
|
184
|
-
class Success < Input::Complete::Success
|
185
|
-
register :success, :ask_complete
|
186
|
-
end
|
187
|
-
|
188
|
-
class NoMatch < Input::Complete::NoMatch
|
189
|
-
register :nomatch, :ask_complete
|
190
|
-
end
|
191
|
-
|
192
|
-
class NoInput < Input::Complete::NoInput
|
193
|
-
register :noinput, :ask_complete
|
194
|
-
end
|
195
|
-
end # Complete
|
196
|
-
end # Ask
|
197
|
-
end # Tropo
|
198
|
-
end # Command
|
199
|
-
end # Punchblock
|
@@ -1,113 +0,0 @@
|
|
1
|
-
module Punchblock
|
2
|
-
module Component
|
3
|
-
module Tropo
|
4
|
-
class Say < ComponentNode
|
5
|
-
register :say, :say
|
6
|
-
|
7
|
-
include MediaContainer
|
8
|
-
|
9
|
-
##
|
10
|
-
# Creates an Rayo Say command
|
11
|
-
#
|
12
|
-
# @param [Hash] options
|
13
|
-
# @option options [String, Optional] :text to speak back
|
14
|
-
# @option options [String, Optional] :voice with which to render TTS
|
15
|
-
# @option options [String, Optional] :ssml document to render TTS
|
16
|
-
#
|
17
|
-
# @return [Command::Say] an Rayo "say" command
|
18
|
-
#
|
19
|
-
# @example
|
20
|
-
# say :text => 'Hello brown cow.'
|
21
|
-
#
|
22
|
-
# returns:
|
23
|
-
# <say xmlns="urn:xmpp:tropo:say:1">Hello brown cow.</say>
|
24
|
-
#
|
25
|
-
def self.new(options = {})
|
26
|
-
super().tap do |new_node|
|
27
|
-
case options
|
28
|
-
when Hash
|
29
|
-
new_node.voice = options.delete(:voice) if options[:voice]
|
30
|
-
new_node.ssml = options.delete(:ssml) if options[:ssml]
|
31
|
-
new_node << options.delete(:text) if options[:text]
|
32
|
-
when Nokogiri::XML::Element
|
33
|
-
new_node.inherit options
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
state_machine :state do
|
39
|
-
event :paused do
|
40
|
-
transition :executing => :paused
|
41
|
-
end
|
42
|
-
|
43
|
-
event :resumed do
|
44
|
-
transition :paused => :executing
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Pauses a running Say
|
49
|
-
#
|
50
|
-
# @return [Command::Say::Pause] an Rayo pause message for the current Say
|
51
|
-
#
|
52
|
-
# @example
|
53
|
-
# say_obj.pause_action.to_xml
|
54
|
-
#
|
55
|
-
# returns:
|
56
|
-
# <pause xmlns="urn:xmpp:tropo:say:1"/>
|
57
|
-
def pause_action
|
58
|
-
Pause.new :component_id => component_id, :call_id => call_id
|
59
|
-
end
|
60
|
-
|
61
|
-
##
|
62
|
-
# Sends an Rayo pause message for the current Say
|
63
|
-
#
|
64
|
-
def pause!
|
65
|
-
raise InvalidActionError, "Cannot pause a Say that is not executing" unless executing?
|
66
|
-
pause_action.tap do |action|
|
67
|
-
result = write_action action
|
68
|
-
paused! if result
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
##
|
73
|
-
# Create an Rayo resume message for the current Say
|
74
|
-
#
|
75
|
-
# @return [Command::Say::Resume] an Rayo resume message
|
76
|
-
#
|
77
|
-
# @example
|
78
|
-
# say_obj.resume_action.to_xml
|
79
|
-
#
|
80
|
-
# returns:
|
81
|
-
# <resume xmlns="urn:xmpp:tropo:say:1"/>
|
82
|
-
def resume_action
|
83
|
-
Resume.new :component_id => component_id, :call_id => call_id
|
84
|
-
end
|
85
|
-
|
86
|
-
##
|
87
|
-
# Sends an Rayo resume message for the current Say
|
88
|
-
#
|
89
|
-
def resume!
|
90
|
-
raise InvalidActionError, "Cannot resume a Say that is not paused." unless paused?
|
91
|
-
resume_action.tap do |action|
|
92
|
-
result = write_action action
|
93
|
-
resumed! if result
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
class Pause < CommandNode # :nodoc:
|
98
|
-
register :pause, :say
|
99
|
-
end
|
100
|
-
|
101
|
-
class Resume < CommandNode # :nodoc:
|
102
|
-
register :resume, :say
|
103
|
-
end
|
104
|
-
|
105
|
-
class Complete
|
106
|
-
class Success < Event::Complete::Reason
|
107
|
-
register :success, :say_complete
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end # Say
|
111
|
-
end # Tropo
|
112
|
-
end # Command
|
113
|
-
end # Punchblock
|
@@ -1,178 +0,0 @@
|
|
1
|
-
module Punchblock
|
2
|
-
module Component
|
3
|
-
module Tropo
|
4
|
-
class Transfer < ComponentNode
|
5
|
-
register :transfer, :transfer
|
6
|
-
|
7
|
-
include HasHeaders
|
8
|
-
|
9
|
-
##
|
10
|
-
# Creates an Rayo transfer command
|
11
|
-
#
|
12
|
-
# @param [Hash] options for transferring a call
|
13
|
-
# @option options [String, Array[String]] :to The destination(s) for the call transfer (ie - tel:+14155551212 or sip:you@sip.tropo.com). Can be an array to hunt.
|
14
|
-
# @option options [String] :from The caller ID for the call transfer (ie - tel:+14155551212 or sip:you@sip.tropo.com)
|
15
|
-
# @option options [String, Optional] :terminator The string key press required to abort the transfer.
|
16
|
-
# @option options [Integer, Optional] :timeout How long to wait - in seconds - for an answer, busy signal, or other event to occur.
|
17
|
-
# @option options [Boolean, Optional] :answer_on_media If set to true, the call will be considered "answered" and audio will begin playing as soon as media is received from the far end (ringing / busy signal / etc)
|
18
|
-
# @option options [Symbol, Optional] :media Rules for handling media. Can be :direct, where parties negotiate media directly, or :bridge where the media server will bridge audio, allowing media features like recording and ASR.
|
19
|
-
# @option options [Ring, Hash, Optional] :ring to play to the caller untill connected
|
20
|
-
#
|
21
|
-
# @return [Message::Transfer] an Rayo "transfer" message
|
22
|
-
#
|
23
|
-
# @example
|
24
|
-
# Transfer.new(:to => 'sip:you@yourdomain.com', :from => 'sip:myapp@mydomain.com', :terminator => '#').to_xml
|
25
|
-
#
|
26
|
-
# returns:
|
27
|
-
# <transfer xmlns="urn:xmpp:tropo:transfer:1" from="sip:myapp@mydomain.com" terminator="#">
|
28
|
-
# <to>sip:you@yourdomain.com</to>
|
29
|
-
# </transfer>
|
30
|
-
#
|
31
|
-
def self.new(options = {})
|
32
|
-
super().tap do |new_node|
|
33
|
-
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
##
|
38
|
-
# @return [Array[String]] The destination(s) for the call transfer
|
39
|
-
#
|
40
|
-
def to
|
41
|
-
find('ns:to', :ns => self.class.registered_ns).map &:text
|
42
|
-
end
|
43
|
-
|
44
|
-
##
|
45
|
-
# @param [String, Array[String]] :to The destination(s) for the call transfer (ie - tel:+14155551212 or sip:you@sip.tropo.com). Can be an array to hunt.
|
46
|
-
#
|
47
|
-
def to=(transfer_to)
|
48
|
-
find('//ns:to', :ns => self.class.registered_ns).each &:remove
|
49
|
-
if transfer_to
|
50
|
-
[transfer_to].flatten.each do |i|
|
51
|
-
to = RayoNode.new :to
|
52
|
-
to << i
|
53
|
-
self << to
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
##
|
59
|
-
# @return [String] The caller ID for the call transfer
|
60
|
-
#
|
61
|
-
def from
|
62
|
-
read_attr :from
|
63
|
-
end
|
64
|
-
|
65
|
-
##
|
66
|
-
# @param [String, Array[String]] :to The destination(s) for the call transfer (ie - tel:+14155551212 or sip:you@sip.tropo.com). Can be an array to hunt.
|
67
|
-
#
|
68
|
-
def from=(transfer_from)
|
69
|
-
write_attr :from, transfer_from
|
70
|
-
end
|
71
|
-
|
72
|
-
##
|
73
|
-
# @return [String] The string key press required to abort the transfer.
|
74
|
-
#
|
75
|
-
def terminator
|
76
|
-
read_attr :terminator
|
77
|
-
end
|
78
|
-
|
79
|
-
##
|
80
|
-
# @param [String] terminator The string key press required to abort the transfer.
|
81
|
-
#
|
82
|
-
def terminator=(terminator)
|
83
|
-
write_attr :terminator, terminator
|
84
|
-
end
|
85
|
-
|
86
|
-
##
|
87
|
-
# @return [Integer] How long to wait - in seconds - for an answer, busy signal, or other event to occur.
|
88
|
-
#
|
89
|
-
def timeout
|
90
|
-
read_attr :timeout, :to_i
|
91
|
-
end
|
92
|
-
|
93
|
-
##
|
94
|
-
# @param [Integer] timeout How long to wait - in seconds - for an answer, busy signal, or other event to occur.
|
95
|
-
#
|
96
|
-
def timeout=(timeout)
|
97
|
-
write_attr :timeout, timeout
|
98
|
-
end
|
99
|
-
|
100
|
-
##
|
101
|
-
# @return [Boolean] If true, the call will be considered "answered" and audio will begin playing as soon as media is received from the far end (ringing / busy signal / etc)
|
102
|
-
#
|
103
|
-
def answer_on_media
|
104
|
-
read_attr('answer-on-media') == 'true'
|
105
|
-
end
|
106
|
-
|
107
|
-
##
|
108
|
-
# @param [Boolean] aom If set to true, the call will be considered "answered" and audio will begin playing as soon as media is received from the far end (ringing / busy signal / etc)
|
109
|
-
#
|
110
|
-
def answer_on_media=(aom)
|
111
|
-
write_attr 'answer-on-media', aom.to_s
|
112
|
-
end
|
113
|
-
|
114
|
-
##
|
115
|
-
# @return [Symbol] Rules for handling media. Can be :direct, where parties negotiate media directly, or :bridge where the media server will bridge audio, allowing media features like recording and ASR.
|
116
|
-
#
|
117
|
-
def media
|
118
|
-
read_attr 'media', :to_sym
|
119
|
-
end
|
120
|
-
|
121
|
-
##
|
122
|
-
# @param [Symbol] media Rules for handling media. Can be :direct, where parties negotiate media directly, or :bridge where the media server will bridge audio, allowing media features like recording and ASR.
|
123
|
-
#
|
124
|
-
def media=(media)
|
125
|
-
write_attr 'media', media
|
126
|
-
end
|
127
|
-
|
128
|
-
##
|
129
|
-
# @return [Ring] the ringer to play to the caller while transferring
|
130
|
-
#
|
131
|
-
def ring
|
132
|
-
node = find_first '//ns:ring', :ns => self.registered_ns
|
133
|
-
Ring.new node if node
|
134
|
-
end
|
135
|
-
|
136
|
-
##
|
137
|
-
# @param [Hash] ring
|
138
|
-
# @option ring [String] :text Text to speak to the caller as an announcement
|
139
|
-
# @option ring [String] :url URL to play to the caller as an announcement
|
140
|
-
#
|
141
|
-
def ring=(ring)
|
142
|
-
ring = Ring.new(ring) unless ring.is_a?(Ring)
|
143
|
-
self << ring
|
144
|
-
end
|
145
|
-
|
146
|
-
class Ring < Say
|
147
|
-
register :ring, :transfer
|
148
|
-
end
|
149
|
-
|
150
|
-
def inspect_attributes # :nodoc:
|
151
|
-
[:to, :from, :terminator, :timeout, :answer_on_media] + super
|
152
|
-
end
|
153
|
-
|
154
|
-
class Complete
|
155
|
-
class Success < Event::Complete::Reason
|
156
|
-
register :success, :transfer_complete
|
157
|
-
end
|
158
|
-
|
159
|
-
class Timeout < Event::Complete::Reason
|
160
|
-
register :timeout, :transfer_complete
|
161
|
-
end
|
162
|
-
|
163
|
-
class Terminator < Event::Complete::Reason
|
164
|
-
register :terminator, :transfer_complete
|
165
|
-
end
|
166
|
-
|
167
|
-
class Busy < Event::Complete::Reason
|
168
|
-
register :busy, :transfer_complete
|
169
|
-
end
|
170
|
-
|
171
|
-
class Reject < Event::Complete::Reason
|
172
|
-
register :reject, :transfer_complete
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end # Transfer
|
176
|
-
end # Tropo
|
177
|
-
end # Command
|
178
|
-
end # Punchblock
|