punchblock 2.5.3 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|