punchblock 2.5.3 → 2.6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/punchblock/component/input.rb +8 -1
- data/lib/punchblock/component/output.rb +3 -0
- data/lib/punchblock/has_headers.rb +2 -2
- data/lib/punchblock/translator/asterisk/call.rb +9 -0
- data/lib/punchblock/translator/asterisk/component/mrcp_recog_prompt.rb +25 -8
- data/lib/punchblock/version.rb +1 -1
- data/spec/punchblock/component/input_spec.rb +28 -1
- data/spec/punchblock/component/output_spec.rb +15 -1
- data/spec/punchblock/translator/asterisk/call_spec.rb +65 -0
- data/spec/punchblock/translator/asterisk/component/mrcp_native_prompt_spec.rb +54 -20
- data/spec/punchblock/translator/asterisk/component/mrcp_prompt_spec.rb +90 -28
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ade03e2779ab1cdbeec2d6f3745571abc1713b81
|
|
4
|
+
data.tar.gz: accbf90369fded5cb31bb010b2fbe02c9f887ec3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4b3c942cfd4e6f6acd1dd8d2042dc0ef7cd50fb795ef2a0e96fcfa97afba700c5778c2c89637a61d79704be3f0d2f0849aea353ce269dd67fb82f293cb4a0eb3
|
|
7
|
+
data.tar.gz: 3c0ddd90d0c21bd82de65d3d792fc0d0f898acd6d2e728a2a03482c86dd001665e38e7ce5c2a881a413bb5c0e9771c85c099f33323ae2d68db7033c93733e60d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# [develop](https://github.com/adhearsion/punchblock)
|
|
2
2
|
|
|
3
|
+
# [v2.6.0](https://github.com/adhearsion/punchblock/compare/v2.5.3...v2.6.0) - [2015-02-01](https://rubygems.org/gems/punchblock/versions/2.6.0)
|
|
4
|
+
* Feature: Support recognition-timeout settings on UniMRCP-based ASR on Asterisk ([#228](https://github.com/adhearsion/punchblock/pull/228))
|
|
5
|
+
* Feature: Implement redirect command on Asterisk ([#219](https://github.com/adhearsion/punchblock/pull/219))
|
|
6
|
+
* Feature: Allow arbitrary media headers ([#237](https://github.com/adhearsion/punchblock/pull/237))
|
|
7
|
+
* Bugfix: Complete 1-to-1 mapping of UniMRCP RECOG_COMPLETION_CAUSE values to Punchblock::Complete events
|
|
8
|
+
|
|
3
9
|
# [v2.5.3](https://github.com/adhearsion/punchblock/compare/v2.5.2...v2.5.3) - [2014-09-22](https://rubygems.org/gems/punchblock/versions/2.5.3)
|
|
4
10
|
* Bugfix: Prevent Asterisk translator death due to dead DTMF recognizers ([#221](https://github.com/adhearsion/punchblock/pull/221), [adhearsion/adhearsion#479](https://github.com/adhearsion/adhearsion/issues/479))
|
|
5
11
|
* Bugfix: Be more intelligent about only stripping true file extensions off filenames for playback on Asterisk ([adhearsion/adhearsion#482](https://github.com/adhearsion/adhearsion/issues/482))
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
module Punchblock
|
|
4
4
|
module Component
|
|
5
5
|
class Input < ComponentNode
|
|
6
|
+
|
|
7
|
+
include HasHeaders
|
|
8
|
+
|
|
6
9
|
NLSML_NAMESPACE = 'http://www.ietf.org/xml/ns/mrcpv2'
|
|
7
10
|
|
|
8
11
|
register :input, :input
|
|
@@ -34,6 +37,9 @@ module Punchblock
|
|
|
34
37
|
# @return [Integer] Indicates (in the case of DTMF input) the amount of time (in milliseconds) between input digits which may expire before a timeout is triggered.
|
|
35
38
|
attribute :inter_digit_timeout, Integer
|
|
36
39
|
|
|
40
|
+
# @return [Integer] Indicates the amount of time during input that recognition will occur before a timeout is triggered.
|
|
41
|
+
attribute :recognition_timeout, Integer
|
|
42
|
+
|
|
37
43
|
attribute :grammars, Array, default: []
|
|
38
44
|
def grammars=(others)
|
|
39
45
|
super others.map { |other| Grammar.new(other) }
|
|
@@ -65,7 +71,8 @@ module Punchblock
|
|
|
65
71
|
'terminator' => terminator,
|
|
66
72
|
'sensitivity' => sensitivity,
|
|
67
73
|
'initial-timeout' => initial_timeout,
|
|
68
|
-
'inter-digit-timeout' => inter_digit_timeout
|
|
74
|
+
'inter-digit-timeout' => inter_digit_timeout,
|
|
75
|
+
'recognition-timeout' => recognition_timeout
|
|
69
76
|
}
|
|
70
77
|
end
|
|
71
78
|
|
|
@@ -11,7 +11,7 @@ module Punchblock
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def inherit(xml_node)
|
|
14
|
-
xml_node.xpath('//ns:header', ns:
|
|
14
|
+
xml_node.xpath('//ns:header', ns: RAYO_NAMESPACES[:core]).to_a.each do |header|
|
|
15
15
|
if headers.has_key?(header[:name])
|
|
16
16
|
headers[header[:name]] = [headers[header[:name]]]
|
|
17
17
|
headers[header[:name]] << header[:value]
|
|
@@ -26,7 +26,7 @@ module Punchblock
|
|
|
26
26
|
super
|
|
27
27
|
headers.each do |name, value|
|
|
28
28
|
Array(value).each do |v|
|
|
29
|
-
root.header name: name, value: v
|
|
29
|
+
root.header name: name, value: v, xmlns: RAYO_NAMESPACES[:core]
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -212,6 +212,15 @@ module Punchblock
|
|
|
212
212
|
execute_agi_command 'EXEC Congestion'
|
|
213
213
|
end
|
|
214
214
|
command.response = true
|
|
215
|
+
when Command::Redirect
|
|
216
|
+
execute_agi_command 'EXEC Transfer', command.to
|
|
217
|
+
status = channel_var 'TRANSFERSTATUS'
|
|
218
|
+
command.response = case status
|
|
219
|
+
when 'SUCCESS'
|
|
220
|
+
true
|
|
221
|
+
else
|
|
222
|
+
ProtocolError.new.setup 'error', "TRANSFERSTATUS was #{status}", id
|
|
223
|
+
end
|
|
215
224
|
when Punchblock::Component::Asterisk::AGI::Command
|
|
216
225
|
execute_component Component::Asterisk::AGICommand, command
|
|
217
226
|
when Punchblock::Component::Output
|
|
@@ -9,6 +9,16 @@ module Punchblock
|
|
|
9
9
|
module MRCPRecogPrompt
|
|
10
10
|
UniMRCPError = Class.new Punchblock::Error
|
|
11
11
|
|
|
12
|
+
MRCP_ERRORS = {
|
|
13
|
+
'004' => 'RECOGNIZE failed due to grammar load failure.',
|
|
14
|
+
'005' => 'RECOGNIZE failed due to grammar compilation failure.',
|
|
15
|
+
'006' => 'RECOGNIZE request terminated prematurely due to a recognizer error.',
|
|
16
|
+
'007' => 'RECOGNIZE request terminated because speech was too early.',
|
|
17
|
+
'009' => 'Failure accessing a URI.',
|
|
18
|
+
'010' => 'Language not supported.',
|
|
19
|
+
'016' => 'Any DEFINE-GRAMMAR error other than grammar-load-failure and grammar-compilation-failure.',
|
|
20
|
+
}
|
|
21
|
+
|
|
12
22
|
def execute
|
|
13
23
|
setup_defaults
|
|
14
24
|
validate
|
|
@@ -17,8 +27,8 @@ module Punchblock
|
|
|
17
27
|
complete
|
|
18
28
|
rescue ChannelGoneError
|
|
19
29
|
call_ended
|
|
20
|
-
rescue UniMRCPError
|
|
21
|
-
complete_with_error
|
|
30
|
+
rescue UniMRCPError => e
|
|
31
|
+
complete_with_error e.message
|
|
22
32
|
rescue RubyAMI::Error => e
|
|
23
33
|
complete_with_error "Terminated due to AMI error '#{e.message}'"
|
|
24
34
|
rescue OptionError => e
|
|
@@ -34,6 +44,7 @@ module Punchblock
|
|
|
34
44
|
|
|
35
45
|
raise OptionError, "An initial-timeout value must be -1 or a positive integer." if @initial_timeout < -1
|
|
36
46
|
raise OptionError, "An inter-digit-timeout value must be -1 or a positive integer." if @inter_digit_timeout < -1
|
|
47
|
+
raise OptionError, "A recognition-timeout value must be -1, 0, or a positive integer." if @recognition_timeout < -1
|
|
37
48
|
end
|
|
38
49
|
|
|
39
50
|
def execute_app(app, *args)
|
|
@@ -48,6 +59,7 @@ module Punchblock
|
|
|
48
59
|
opts[:spl] = input_node.language if input_node.language
|
|
49
60
|
opts[:ct] = input_node.min_confidence if input_node.min_confidence
|
|
50
61
|
opts[:sl] = input_node.sensitivity if input_node.sensitivity
|
|
62
|
+
opts[:t] = input_node.recognition_timeout if @recognition_timeout > -1
|
|
51
63
|
yield opts
|
|
52
64
|
end
|
|
53
65
|
end
|
|
@@ -55,6 +67,7 @@ module Punchblock
|
|
|
55
67
|
def setup_defaults
|
|
56
68
|
@initial_timeout = input_node.initial_timeout || -1
|
|
57
69
|
@inter_digit_timeout = input_node.inter_digit_timeout || -1
|
|
70
|
+
@recognition_timeout = input_node.recognition_timeout || -1
|
|
58
71
|
end
|
|
59
72
|
|
|
60
73
|
def grammars
|
|
@@ -84,20 +97,24 @@ module Punchblock
|
|
|
84
97
|
end
|
|
85
98
|
|
|
86
99
|
def complete
|
|
87
|
-
case @call.channel_var('RECOG_STATUS')
|
|
100
|
+
case @call.channel_var('RECOG_STATUS')
|
|
88
101
|
when 'INTERRUPTED'
|
|
89
102
|
send_complete_event Punchblock::Component::Input::Complete::NoMatch.new
|
|
90
103
|
when 'ERROR'
|
|
91
104
|
raise UniMRCPError
|
|
92
|
-
else
|
|
93
|
-
send_complete_event case @call.channel_var('RECOG_COMPLETION_CAUSE')
|
|
94
|
-
when '000'
|
|
105
|
+
else
|
|
106
|
+
send_complete_event case cause = @call.channel_var('RECOG_COMPLETION_CAUSE')
|
|
107
|
+
when '000', '008', '012'
|
|
95
108
|
nlsml = RubySpeech.parse URI.decode(@call.channel_var('RECOG_RESULT'))
|
|
96
109
|
Punchblock::Component::Input::Complete::Match.new nlsml: nlsml
|
|
97
|
-
when '001'
|
|
110
|
+
when '001', '003', '013', '014', '015'
|
|
98
111
|
Punchblock::Component::Input::Complete::NoMatch.new
|
|
99
|
-
when '002'
|
|
112
|
+
when '002', '011'
|
|
100
113
|
Punchblock::Component::Input::Complete::NoInput.new
|
|
114
|
+
when *MRCP_ERRORS.keys
|
|
115
|
+
raise UniMRCPError, MRCP_ERRORS[cause]
|
|
116
|
+
else
|
|
117
|
+
raise UniMRCPError
|
|
101
118
|
end
|
|
102
119
|
end
|
|
103
120
|
end
|
data/lib/punchblock/version.rb
CHANGED
|
@@ -19,8 +19,10 @@ module Punchblock
|
|
|
19
19
|
:language => 'en-US',
|
|
20
20
|
:initial_timeout => 2000,
|
|
21
21
|
:inter_digit_timeout => 2000,
|
|
22
|
+
:recognition_timeout => 0,
|
|
22
23
|
:sensitivity => 0.5,
|
|
23
|
-
:min_confidence => 0.5
|
|
24
|
+
:min_confidence => 0.5,
|
|
25
|
+
:headers => { 'Confidence-Threshold' => '0.5', 'Sensitivity-Level' => '0.2' }
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
describe '#grammars' do
|
|
@@ -63,6 +65,11 @@ module Punchblock
|
|
|
63
65
|
it { should be == 2000 }
|
|
64
66
|
end
|
|
65
67
|
|
|
68
|
+
describe '#recognition_timeout' do
|
|
69
|
+
subject { super().recognition_timeout }
|
|
70
|
+
it { should be == 0 }
|
|
71
|
+
end
|
|
72
|
+
|
|
66
73
|
describe '#sensitivity' do
|
|
67
74
|
subject { super().sensitivity }
|
|
68
75
|
it { should be == 0.5 }
|
|
@@ -106,6 +113,11 @@ module Punchblock
|
|
|
106
113
|
end
|
|
107
114
|
end
|
|
108
115
|
|
|
116
|
+
describe '#headers' do
|
|
117
|
+
subject { super().headers }
|
|
118
|
+
it { should be == { 'Confidence-Threshold' => '0.5', 'Sensitivity-Level' => '0.2' } }
|
|
119
|
+
end
|
|
120
|
+
|
|
109
121
|
describe "exporting to Rayo" do
|
|
110
122
|
it "should export to XML that can be understood by its parser" do
|
|
111
123
|
new_instance = RayoNode.from_xml subject.to_rayo
|
|
@@ -118,8 +130,10 @@ module Punchblock
|
|
|
118
130
|
expect(new_instance.language).to eq('en-US')
|
|
119
131
|
expect(new_instance.initial_timeout).to eq(2000)
|
|
120
132
|
expect(new_instance.inter_digit_timeout).to eq(2000)
|
|
133
|
+
expect(new_instance.recognition_timeout).to eq(0)
|
|
121
134
|
expect(new_instance.sensitivity).to eq(0.5)
|
|
122
135
|
expect(new_instance.min_confidence).to eq(0.5)
|
|
136
|
+
expect(new_instance.headers).to eq({ 'Confidence-Threshold' => '0.5', 'Sensitivity-Level' => '0.2' })
|
|
123
137
|
end
|
|
124
138
|
|
|
125
139
|
it "should wrap the grammar value in CDATA" do
|
|
@@ -148,6 +162,7 @@ module Punchblock
|
|
|
148
162
|
language="en-US"
|
|
149
163
|
initial-timeout="2000"
|
|
150
164
|
inter-digit-timeout="2000"
|
|
165
|
+
recognition-timeout="0"
|
|
151
166
|
sensitivity="0.5"
|
|
152
167
|
min-confidence="0.5">
|
|
153
168
|
<grammar content-type="application/grammar+custom">
|
|
@@ -156,6 +171,8 @@ module Punchblock
|
|
|
156
171
|
<grammar content-type="application/grammar+custom">
|
|
157
172
|
<![CDATA[ [10 DIGITS] ]]>
|
|
158
173
|
</grammar>
|
|
174
|
+
<header xmlns='urn:xmpp:rayo:1' name="Confidence-Threshold" value="0.5" />
|
|
175
|
+
<header xmlns='urn:xmpp:rayo:1' name="Sensitivity-Level" value="0.2" />
|
|
159
176
|
</input>
|
|
160
177
|
MESSAGE
|
|
161
178
|
end
|
|
@@ -204,6 +221,11 @@ module Punchblock
|
|
|
204
221
|
it { should be == 2000 }
|
|
205
222
|
end
|
|
206
223
|
|
|
224
|
+
describe '#recognition_timeout' do
|
|
225
|
+
subject { super().recognition_timeout }
|
|
226
|
+
it { should be == 0 }
|
|
227
|
+
end
|
|
228
|
+
|
|
207
229
|
describe '#sensitivity' do
|
|
208
230
|
subject { super().sensitivity }
|
|
209
231
|
it { should be == 0.5 }
|
|
@@ -222,6 +244,11 @@ module Punchblock
|
|
|
222
244
|
it { should be == [] }
|
|
223
245
|
end
|
|
224
246
|
end
|
|
247
|
+
|
|
248
|
+
describe '#headers' do
|
|
249
|
+
subject { super().headers }
|
|
250
|
+
it { should be == { 'Confidence-Threshold' => '0.5', 'Sensitivity-Level' => '0.2' } }
|
|
251
|
+
end
|
|
225
252
|
end
|
|
226
253
|
|
|
227
254
|
def grxml_doc(mode = :dtmf)
|
|
@@ -72,7 +72,8 @@ module Punchblock
|
|
|
72
72
|
:max_time => 30000,
|
|
73
73
|
:voice => 'allison',
|
|
74
74
|
:renderer => 'swift',
|
|
75
|
-
:render_document => {:value => ssml_doc}
|
|
75
|
+
:render_document => {:value => ssml_doc},
|
|
76
|
+
:headers => { 'Jump-Size' => '2', 'Kill-On-Barge-In' => 'false' }
|
|
76
77
|
end
|
|
77
78
|
|
|
78
79
|
describe '#interrupt_on' do
|
|
@@ -185,6 +186,11 @@ module Punchblock
|
|
|
185
186
|
end
|
|
186
187
|
end
|
|
187
188
|
|
|
189
|
+
describe '#headers' do
|
|
190
|
+
subject { super().headers }
|
|
191
|
+
it { should be == { 'Jump-Size' => '2', 'Kill-On-Barge-In' => 'false' } }
|
|
192
|
+
end
|
|
193
|
+
|
|
188
194
|
describe "exporting to Rayo" do
|
|
189
195
|
it "should export to XML that can be understood by its parser" do
|
|
190
196
|
new_instance = RayoNode.from_xml Nokogiri::XML(subject.to_rayo.to_xml, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root
|
|
@@ -198,6 +204,7 @@ module Punchblock
|
|
|
198
204
|
expect(new_instance.voice).to eq('allison')
|
|
199
205
|
expect(new_instance.renderer).to eq('swift')
|
|
200
206
|
expect(new_instance.render_documents).to eq([Output::Document.new(:value => ssml_doc)])
|
|
207
|
+
expect(new_instance.headers).to eq({ 'Jump-Size' => '2', 'Kill-On-Barge-In' => 'false' })
|
|
201
208
|
end
|
|
202
209
|
|
|
203
210
|
it "should wrap the document value in CDATA" do
|
|
@@ -258,6 +265,8 @@ module Punchblock
|
|
|
258
265
|
</speak>
|
|
259
266
|
]]>
|
|
260
267
|
</document>
|
|
268
|
+
<header xmlns='urn:xmpp:rayo:1' name="Jump-Size" value="2" />
|
|
269
|
+
<header xmlns='urn:xmpp:rayo:1' name="Kill-On-Barge-In" value="false" />
|
|
261
270
|
</output>
|
|
262
271
|
MESSAGE
|
|
263
272
|
end
|
|
@@ -330,6 +339,11 @@ module Punchblock
|
|
|
330
339
|
it { should be == [Output::Document.new(content_type: 'text/uri-list', value: ['http://example.com/hello.mp3', 'http://example.com/goodbye.mp3'])] }
|
|
331
340
|
end
|
|
332
341
|
end
|
|
342
|
+
|
|
343
|
+
describe '#headers' do
|
|
344
|
+
subject { super().headers }
|
|
345
|
+
it { should be == { 'Jump-Size' => '2', 'Kill-On-Barge-In' => 'false' } }
|
|
346
|
+
end
|
|
333
347
|
end
|
|
334
348
|
|
|
335
349
|
describe Output::Document do
|
|
@@ -1166,6 +1166,71 @@ module Punchblock
|
|
|
1166
1166
|
end
|
|
1167
1167
|
end
|
|
1168
1168
|
|
|
1169
|
+
context 'with a redirect command' do
|
|
1170
|
+
let(:command) { Command::Redirect.new to: 'other@place.com' }
|
|
1171
|
+
|
|
1172
|
+
let(:transferstatus) { 'SUCCESS' }
|
|
1173
|
+
let :status_event do
|
|
1174
|
+
RubyAMI::Event.new 'VarSet',
|
|
1175
|
+
"Privilege" => "dialplan,all",
|
|
1176
|
+
"Channel" => "SIP/1234-00000000",
|
|
1177
|
+
"Variable" => "TRANSFERSTATUS",
|
|
1178
|
+
"Value" => transferstatus,
|
|
1179
|
+
"Uniqueid" => "1326210224.0"
|
|
1180
|
+
end
|
|
1181
|
+
|
|
1182
|
+
before do
|
|
1183
|
+
subject.process_ami_event status_event
|
|
1184
|
+
end
|
|
1185
|
+
|
|
1186
|
+
it "should send an EXEC Transfer AGI command" do
|
|
1187
|
+
subject.should_receive(:execute_agi_command).with('EXEC Transfer', 'other@place.com').and_return code: 200
|
|
1188
|
+
subject.execute_command command
|
|
1189
|
+
command.response(0.5).should be true
|
|
1190
|
+
end
|
|
1191
|
+
|
|
1192
|
+
context "when TRANSFERSTATUS is 'FAILURE'" do
|
|
1193
|
+
let(:transferstatus) { 'FAILURE' }
|
|
1194
|
+
|
|
1195
|
+
it "should return an error" do
|
|
1196
|
+
subject.should_receive(:execute_agi_command).with('EXEC Transfer', 'other@place.com').and_return code: 200
|
|
1197
|
+
subject.execute_command command
|
|
1198
|
+
command.response(0.5).should be == ProtocolError.new.setup('error', 'TRANSFERSTATUS was FAILURE', subject.id)
|
|
1199
|
+
end
|
|
1200
|
+
end
|
|
1201
|
+
|
|
1202
|
+
context "when TRANSFERSTATUS is 'UNSUPPORTED'" do
|
|
1203
|
+
let(:transferstatus) { 'UNSUPPORTED' }
|
|
1204
|
+
|
|
1205
|
+
it "should return an error" do
|
|
1206
|
+
subject.should_receive(:execute_agi_command).with('EXEC Transfer', 'other@place.com').and_return code: 200
|
|
1207
|
+
subject.execute_command command
|
|
1208
|
+
command.response(0.5).should be == ProtocolError.new.setup('error', 'TRANSFERSTATUS was UNSUPPORTED', subject.id)
|
|
1209
|
+
end
|
|
1210
|
+
end
|
|
1211
|
+
|
|
1212
|
+
context "when the AMI commannd raises an error" do
|
|
1213
|
+
let(:message) { 'Some error' }
|
|
1214
|
+
let(:error) { RubyAMI::Error.new.tap { |e| e.message = message } }
|
|
1215
|
+
|
|
1216
|
+
before { subject.should_receive(:execute_agi_command).and_raise error }
|
|
1217
|
+
|
|
1218
|
+
it "should return an error with the message" do
|
|
1219
|
+
subject.execute_command command
|
|
1220
|
+
command.response(0.5).should be == ProtocolError.new.setup('error', message, subject.id)
|
|
1221
|
+
end
|
|
1222
|
+
|
|
1223
|
+
context "because the channel is gone" do
|
|
1224
|
+
let(:error) { ChannelGoneError }
|
|
1225
|
+
|
|
1226
|
+
it "should return an :item_not_found event for the call" do
|
|
1227
|
+
subject.execute_command command
|
|
1228
|
+
command.response(0.5).should be == ProtocolError.new.setup(:item_not_found, "Could not find a call with ID #{subject.id}", subject.id)
|
|
1229
|
+
end
|
|
1230
|
+
end
|
|
1231
|
+
end
|
|
1232
|
+
end
|
|
1233
|
+
|
|
1169
1234
|
context 'with a reject command' do
|
|
1170
1235
|
let(:command) { Command::Reject.new }
|
|
1171
1236
|
|
|
@@ -182,7 +182,7 @@ module Punchblock
|
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
context "when MRCPRecog completes" do
|
|
185
|
-
|
|
185
|
+
shared_context "with a match" do
|
|
186
186
|
let :expected_nlsml do
|
|
187
187
|
RubySpeech::NLSML.draw do
|
|
188
188
|
interpretation grammar: 'session:grammar-0', confidence: 0.43 do
|
|
@@ -201,39 +201,73 @@ module Punchblock
|
|
|
201
201
|
end
|
|
202
202
|
end
|
|
203
203
|
|
|
204
|
-
context "with a
|
|
205
|
-
|
|
204
|
+
context "with a match cause" do
|
|
205
|
+
%w{000 008 012}.each do |code|
|
|
206
|
+
context "when the MRCP recognition response code is #{code}" do
|
|
207
|
+
let(:recog_completion_cause) { code }
|
|
206
208
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
expect(mock_call).to receive(:execute_agi_command).and_return code: 200, result: 1
|
|
210
|
-
subject.execute
|
|
211
|
-
expect(original_command.complete_event(0.1).reason).to eq(expected_complete_reason)
|
|
209
|
+
it_behaves_like 'with a match'
|
|
210
|
+
end
|
|
212
211
|
end
|
|
213
212
|
end
|
|
214
213
|
|
|
215
|
-
context "with a
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
214
|
+
context "with a nomatch cause" do
|
|
215
|
+
%w{001 003 013 014 015}.each do |code|
|
|
216
|
+
context "with value #{code}" do
|
|
217
|
+
let(:recog_completion_cause) { code }
|
|
218
|
+
|
|
219
|
+
it 'should send a nomatch complete event' do
|
|
220
|
+
expected_complete_reason = Punchblock::Component::Input::Complete::NoMatch.new
|
|
221
|
+
expect(mock_call).to receive(:execute_agi_command).and_return code: 200, result: 1
|
|
222
|
+
subject.execute
|
|
223
|
+
expect(original_command.complete_event(0.1).reason).to eq(expected_complete_reason)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
223
226
|
end
|
|
224
227
|
end
|
|
225
228
|
|
|
226
|
-
context "
|
|
227
|
-
|
|
229
|
+
context "with a noinput cause" do
|
|
230
|
+
%w{002 011}.each do |code|
|
|
231
|
+
context "with value #{code}" do
|
|
232
|
+
let(:recog_completion_cause) { code }
|
|
233
|
+
|
|
234
|
+
specify do
|
|
235
|
+
expected_complete_reason = Punchblock::Component::Input::Complete::NoInput.new
|
|
236
|
+
expect(mock_call).to receive(:execute_agi_command).and_return code: 200, result: 1
|
|
237
|
+
subject.execute
|
|
238
|
+
expect(original_command.complete_event(0.1).reason).to eq(expected_complete_reason)
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
228
243
|
|
|
229
|
-
|
|
244
|
+
shared_context 'should send an error complete event' do
|
|
245
|
+
specify do
|
|
230
246
|
expect(mock_call).to receive(:execute_agi_command).and_return code: 200, result: 1
|
|
231
247
|
subject.execute
|
|
232
248
|
complete_reason = original_command.complete_event(0.1).reason
|
|
233
249
|
expect(complete_reason).to be_a Punchblock::Event::Complete::Error
|
|
234
|
-
expect(complete_reason.details).to eq("Terminated due to UniMRCP error")
|
|
235
250
|
end
|
|
236
251
|
end
|
|
252
|
+
|
|
253
|
+
context 'with an error cause' do
|
|
254
|
+
%w{004 005 006 007 009 010 016}.each do |code|
|
|
255
|
+
context "when the MRCP recognition response code is #{code}" do
|
|
256
|
+
let(:recog_completion_cause) { code }
|
|
257
|
+
it_behaves_like 'should send an error complete event'
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
context 'with an invalid cause' do
|
|
263
|
+
let(:recog_completion_cause) { '999' }
|
|
264
|
+
it_behaves_like 'should send an error complete event'
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context "when the RECOG_STATUS variable is set to 'ERROR'" do
|
|
268
|
+
let(:recog_status) { 'ERROR' }
|
|
269
|
+
it_behaves_like 'should send an error complete event'
|
|
270
|
+
end
|
|
237
271
|
end
|
|
238
272
|
|
|
239
273
|
context "when we get a RubyAMI Error" do
|
|
@@ -174,7 +174,7 @@ module Punchblock
|
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
context "when SynthAndRecog completes" do
|
|
177
|
-
|
|
177
|
+
shared_context "with a match" do
|
|
178
178
|
let :expected_nlsml do
|
|
179
179
|
RubySpeech::NLSML.draw do
|
|
180
180
|
interpretation grammar: 'session:grammar-0', confidence: 0.43 do
|
|
@@ -193,49 +193,72 @@ module Punchblock
|
|
|
193
193
|
end
|
|
194
194
|
end
|
|
195
195
|
|
|
196
|
-
context "with a
|
|
197
|
-
|
|
196
|
+
context "with a match cause" do
|
|
197
|
+
%w{000 008 012}.each do |code|
|
|
198
|
+
context "when the MRCP recognition response code is #{code}" do
|
|
199
|
+
let(:recog_completion_cause) { code }
|
|
198
200
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
201
|
+
it_behaves_like 'with a match'
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
context "with a nomatch cause" do
|
|
207
|
+
%w{001 003 013 014 015}.each do |code|
|
|
208
|
+
context "with value #{code}" do
|
|
209
|
+
let(:recog_completion_cause) { code }
|
|
210
|
+
|
|
211
|
+
it 'should send a nomatch complete event' do
|
|
212
|
+
expected_complete_reason = Punchblock::Component::Input::Complete::NoMatch.new
|
|
213
|
+
expect(mock_call).to receive(:execute_agi_command).and_return code: 200, result: 1
|
|
214
|
+
subject.execute
|
|
215
|
+
expect(original_command.complete_event(0.1).reason).to eq(expected_complete_reason)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
204
218
|
end
|
|
205
219
|
end
|
|
206
220
|
|
|
207
221
|
context "with a noinput cause" do
|
|
208
|
-
|
|
222
|
+
%w{002 011}.each do |code|
|
|
223
|
+
context "with value #{code}" do
|
|
224
|
+
let(:recog_completion_cause) { code }
|
|
225
|
+
|
|
226
|
+
specify do
|
|
227
|
+
expected_complete_reason = Punchblock::Component::Input::Complete::NoInput.new
|
|
228
|
+
expect(mock_call).to receive(:execute_agi_command).and_return code: 200, result: 1
|
|
229
|
+
subject.execute
|
|
230
|
+
expect(original_command.complete_event(0.1).reason).to eq(expected_complete_reason)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
209
235
|
|
|
210
|
-
|
|
211
|
-
|
|
236
|
+
shared_context 'should send an error complete event' do
|
|
237
|
+
specify do
|
|
212
238
|
expect(mock_call).to receive(:execute_agi_command).and_return code: 200, result: 1
|
|
213
239
|
subject.execute
|
|
214
|
-
|
|
240
|
+
complete_reason = original_command.complete_event(0.1).reason
|
|
241
|
+
expect(complete_reason).to be_a Punchblock::Event::Complete::Error
|
|
215
242
|
end
|
|
216
243
|
end
|
|
217
244
|
|
|
218
|
-
context
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
subject.execute
|
|
225
|
-
expect(original_command.complete_event(0.1).reason).to eq(expected_complete_reason)
|
|
245
|
+
context 'with an error cause' do
|
|
246
|
+
%w{004 005 006 007 009 010 016}.each do |code|
|
|
247
|
+
context "when the MRCP recognition response code is #{code}" do
|
|
248
|
+
let(:recog_completion_cause) { code }
|
|
249
|
+
it_behaves_like 'should send an error complete event'
|
|
250
|
+
end
|
|
226
251
|
end
|
|
227
252
|
end
|
|
228
253
|
|
|
254
|
+
context 'with an invalid cause' do
|
|
255
|
+
let(:recog_completion_cause) { '999' }
|
|
256
|
+
it_behaves_like 'should send an error complete event'
|
|
257
|
+
end
|
|
258
|
+
|
|
229
259
|
context "when the RECOG_STATUS variable is set to 'ERROR'" do
|
|
230
260
|
let(:recog_status) { 'ERROR' }
|
|
231
|
-
|
|
232
|
-
it "should send an error complete event" do
|
|
233
|
-
expect(mock_call).to receive(:execute_agi_command).and_return code: 200, result: 1
|
|
234
|
-
subject.execute
|
|
235
|
-
complete_reason = original_command.complete_event(0.1).reason
|
|
236
|
-
expect(complete_reason).to be_a Punchblock::Event::Complete::Error
|
|
237
|
-
expect(complete_reason.details).to eq("Terminated due to UniMRCP error")
|
|
238
|
-
end
|
|
261
|
+
it_behaves_like 'should send an error complete event'
|
|
239
262
|
end
|
|
240
263
|
end
|
|
241
264
|
|
|
@@ -511,6 +534,45 @@ module Punchblock
|
|
|
511
534
|
end
|
|
512
535
|
end
|
|
513
536
|
|
|
537
|
+
describe 'Input#recognition-timeout' do
|
|
538
|
+
context 'a positive number' do
|
|
539
|
+
let(:input_command_opts) { { recognition_timeout: 1000 } }
|
|
540
|
+
|
|
541
|
+
it 'should pass the t option to SynthAndRecog' do
|
|
542
|
+
expect_synthandrecog_with_options(/t=1000/)
|
|
543
|
+
subject.execute
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
context '0' do
|
|
548
|
+
let(:input_command_opts) { { recognition_timeout: 0 } }
|
|
549
|
+
|
|
550
|
+
it 'should pass the t option to SynthAndRecog' do
|
|
551
|
+
expect_synthandrecog_with_options(/t=0/)
|
|
552
|
+
subject.execute
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
context 'a negative number' do
|
|
557
|
+
let(:input_command_opts) { { recognition_timeout: -1000 } }
|
|
558
|
+
|
|
559
|
+
it "should return an error and not execute any actions" do
|
|
560
|
+
subject.execute
|
|
561
|
+
error = ProtocolError.new.setup 'option error', 'A recognition-timeout value must be -1, 0, or a positive integer.'
|
|
562
|
+
expect(original_command.response(0.1)).to eq(error)
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
context 'unset' do
|
|
567
|
+
let(:input_command_opts) { { recognition_timeout: nil } }
|
|
568
|
+
|
|
569
|
+
it 'should not pass any options to SynthAndRecog' do
|
|
570
|
+
expect_synthandrecog_with_options(//)
|
|
571
|
+
subject.execute
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
|
|
514
576
|
describe 'Input#inter-digit-timeout' do
|
|
515
577
|
context 'a positive number' do
|
|
516
578
|
let(:input_command_opts) { { inter_digit_timeout: 1000 } }
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: punchblock
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jason Goecke
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 2015-02-01 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: nokogiri
|
|
@@ -559,7 +559,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
559
559
|
version: 1.3.7
|
|
560
560
|
requirements: []
|
|
561
561
|
rubyforge_project: punchblock
|
|
562
|
-
rubygems_version: 2.
|
|
562
|
+
rubygems_version: 2.4.5
|
|
563
563
|
signing_key:
|
|
564
564
|
specification_version: 4
|
|
565
565
|
summary: Punchblock is a telephony middleware library
|