Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to Asterisk renderer to say numbers. #260

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/punchblock/translator/asterisk.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# encoding: utf-8

require 'celluloid'
require 'celluloid/autostart'
require 'ruby_ami'

module Punchblock
Expand Down
2 changes: 1 addition & 1 deletion lib/punchblock/translator/asterisk/call.rb
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def execute_agi_command(command, *params)
agi = AGICommand.new Punchblock.new_uuid, channel, command, *params
response = Celluloid::Future.new
register_tmp_handler :ami, [{name: 'AsyncAGI', [:[], 'SubEvent'] => 'Exec'}, {name: 'AsyncAGIExec'}], [{[:[], 'CommandID'] => agi.id}, {[:[], 'CommandId'] => agi.id}] do |event|
response.signal Celluloid::SuccessResponse.new(nil, event)
response.signal Celluloid::Internals::Response::Success.new(nil, event)
end
agi.execute @ami_client
event = response.value
Expand Down
42 changes: 29 additions & 13 deletions lib/punchblock/translator/asterisk/component/output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ def execute

case rendering_engine.to_sym
when :asterisk
validate_audio_only
validate_audio_or_number_only
setup_for_native

repeat_times.times do
render_docs.each do |doc|
playback(filenames(doc).values) || raise(PlaybackError)
play_doc_asterisk(doc)
end
end
when :native_or_unimrcp
Expand Down Expand Up @@ -119,9 +119,13 @@ def send_progress_if_necessary
@call.send_progress if @early
end

def validate_audio_only
# Validates if the input document contains only audio files, or numbers. Raises UnrendernableDocError if the document isn't valid.
def validate_audio_or_number_only
render_docs.each do |doc|
filenames doc, -> { raise UnrenderableDocError, 'The provided document could not be rendered. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details.' }
doc.value.children.each do |node|
next if RubySpeech::SSML::Audio === node || (RubySpeech::SSML::SayAs === node && all_numbers?(node.text) ) || (String === node && !node.include?(' '))
raise UnrenderableDocError, 'The provided document could not be rendered. When using Asterisk rendering the document must contain either numbers, or links to audio files. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details'
end
end
end

Expand All @@ -136,20 +140,27 @@ def path_for_audio_node(node)
end
end

def filenames(doc, check_audio_only_policy = -> {})
names = {}
def play_doc_asterisk(doc)
doc.value.children.each do |node|
case node
when RubySpeech::SSML::Audio
names[node] = path_for_audio_node node
playback([path_for_audio_node(node)]) || raise(PlaybackError)
when String
check_audio_only_policy.call if node.include?(' ')
names[nil] = node
else
check_audio_only_policy.call
playback([node]) || raise(PlaybackError)
when RubySpeech::SSML::SayAs
if all_numbers?(node.text)
say_number(node.text)
else
raise UnrenderableDocError, 'The provided document could not be rendered. When using Asterisk rendering the document must contain either numbers, or links to audio files. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details'
end
else
raise UnrenderableDocError, 'The provided document could not be rendered. When using Asterisk rendering the document must contain either numbers, or links to audio files. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details'
end
end
names
end

def all_numbers?(input)
!!(/^[0-9]+$/ =~ input)
end

def playback_options(paths)
Expand All @@ -164,6 +175,11 @@ def playback(paths)
@call.channel_var('PLAYBACKSTATUS') != 'FAILED'
end

def say_number(number)
return true if @stopped
@call.execute_agi_command 'EXEC SayNumber', number
end

def fallback_doc(original, failed_audio_node)
children = failed_audio_node.nokogiri_children
copied_doc original, children
Expand Down Expand Up @@ -229,4 +245,4 @@ def finish_reason
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/punchblock/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# encoding: utf-8

module Punchblock
VERSION = "2.7.5"
VERSION = "2.7.12"
end
12 changes: 6 additions & 6 deletions punchblock.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ Gem::Specification.new do |s|

s.required_rubygems_version = Gem::Requirement.new(">= 1.3.7") if s.respond_to? :required_rubygems_version=

s.add_runtime_dependency %q<nokogiri>, ["~> 1.5", ">= 1.5.6"]
s.add_runtime_dependency %q<blather>, ["~> 1.0"]
s.add_runtime_dependency %q<activesupport>, [">= 3.0.0", "< 5.0.0"]
s.add_runtime_dependency %q<nokogiri>
s.add_runtime_dependency %q<blather>
s.add_runtime_dependency %q<activesupport>, [">= 3.0.0", "<= 6.1"]
s.add_runtime_dependency %q<state_machine>, ["~> 1.0"]
s.add_runtime_dependency %q<future-resource>, ["~> 1.0"]
s.add_runtime_dependency %q<has-guarded-handlers>, ["~> 1.5"]
s.add_runtime_dependency %q<celluloid>, ["~> 0.15.2"]
s.add_runtime_dependency %q<ruby_ami>, ["~> 2.2"]
s.add_runtime_dependency %q<ruby_speech>, ["~> 2.3"]
s.add_runtime_dependency %q<celluloid>
s.add_runtime_dependency %q<ruby_ami>
s.add_runtime_dependency %q<ruby_speech>, ["~> 3.0"]
s.add_runtime_dependency %q<virtus>, ["~> 1.0"]
s.add_runtime_dependency %q<ruby_jid>, ["~> 1.0"]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def send_ami_events_for_dtmf(digit)
end

context "if output fails to start" do
let(:output_response) { ProtocolError.new.setup 'unrenderable document error', 'The provided document could not be rendered. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details.' }
let(:output_response) { ProtocolError.new.setup 'unrenderable document error', 'The provided document could not be rendered. When using Asterisk rendering the document must contain either numbers, or links to audio files. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details' }

let :ssml_doc do
RubySpeech::SSML.draw do
Expand Down
47 changes: 44 additions & 3 deletions spec/punchblock/translator/asterisk/component/output_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,10 @@ def expect_playback_noanswer
expect(mock_call).to receive(:execute_agi_command).once.with('EXEC Playback', audio_filename + ',noanswer').and_return code: 200
end

def expect_say_number(number)
expect(mock_call).to receive(:execute_agi_command).once.with('EXEC SayNumber', number).and_return code: 200
end

let(:audio_filename) { 'tt-monkeys' }

let :ssml_doc do
Expand Down Expand Up @@ -703,7 +707,8 @@ def mock_call.answered?

it 'should playback all audio files using Playback' do
latch = CountDownLatch.new 2
expect_playback [audio_filename1, audio_filename2].join('&')
expect_playback audio_filename1
expect_playback audio_filename2
expect_answered
subject.execute
latch.wait 2
Expand All @@ -712,7 +717,8 @@ def mock_call.answered?

it 'should send a complete event after the final file has finished playback' do
expect_answered
expect_playback [audio_filename1, audio_filename2].join('&')
expect_playback audio_filename1
expect_playback audio_filename2
latch = CountDownLatch.new 1
expect(original_command).to receive(:add_event).once { |e|
expect(e.reason).to be_a Punchblock::Component::Output::Complete::Finish
Expand All @@ -723,6 +729,41 @@ def mock_call.answered?
end
end

context 'with an audio file and a number' do
let(:audio_filename) { 'filename' }
let :ssml_doc do
RubySpeech::SSML.draw do
audio :src => audio_filename
say_as(:interpret_as => :cardinal) { '1234' }
end
end

it 'should playback an audio file, and say a number' do
expect_answered
expect_playback audio_filename
expect_say_number '1234'
subject.execute
end
end

context 'with an audio file and a number+text' do
let(:audio_filename) { 'filename' }
let :ssml_doc do
RubySpeech::SSML.draw do
audio :src => audio_filename
say_as(:interpret_as => :cardinal) { '1234X5' }
end
end

it "should return an unrenderable document error" do
subject.execute
error = ProtocolError.new.setup 'unrenderable document error', 'The provided document could not be rendered. When using Asterisk rendering the document must contain either numbers, or links to audio files. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details'
expect(original_command.response(0.1)).to eq(error)
end
end



context "with an SSML document containing elements other than <audio/>" do
let :ssml_doc do
RubySpeech::SSML.draw do
Expand All @@ -732,7 +773,7 @@ def mock_call.answered?

it "should return an unrenderable document error" do
subject.execute
error = ProtocolError.new.setup 'unrenderable document error', 'The provided document could not be rendered. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details.'
error = ProtocolError.new.setup 'unrenderable document error', 'The provided document could not be rendered. When using Asterisk rendering the document must contain either numbers, or links to audio files. See http://adhearsion.com/docs/common_problems#unrenderable-document-error for details'
expect(original_command.response(0.1)).to eq(error)
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require 'punchblock'
require 'countdownlatch'
require 'logger'
require 'celluloid'
require 'celluloid/autostart'
require 'coveralls'
require 'ruby_ami'
Coveralls.wear!
Expand Down