lib/matrioska/app_runner.rb in matrioska-0.2.1 vs lib/matrioska/app_runner.rb in matrioska-0.3.0

- old
+ new

@@ -1,33 +1,41 @@ module Matrioska class AppRunner include Adhearsion::CallController::Utility + VALID_DIGITS = /[^0-9*#]/ + def initialize(call) @call = call + register_runner_with_call @app_map = {} - @running = false end def start + if started? && running? + logger.warn "Already-active runner #{self} received start event." + return + end + @state = :started - logger.debug "MATRIOSKA START CALLED" - unless @running - @component = Punchblock::Component::Input.new mode: :dtmf, grammar: { value: grammar_accept } - logger.debug "MATRIOSKA STARTING LISTENER" - @component.register_event_handler Punchblock::Event::Complete do |event| - handle_input_complete event - end - @call.write_and_await_response @component if @call.active? + logger.debug "MATRIOSKA STARTING LISTENER" + @component = Punchblock::Component::Input.new mode: :dtmf, inter_digit_timeout: Adhearsion.config[:matrioska].timeout * 1_000, grammar: { value: build_grammar } + @component.register_event_handler Punchblock::Event::Complete do |event| + handle_input_complete event end + @call.write_and_await_response @component if @call.alive? && @call.active? end def stop! @state = :stopped - @component.stop! if @component && @component.executing? + @component.stop! if running? end + def running? + !!(@component && @component.executing?) + end + def status @state end def started? @@ -36,38 +44,38 @@ def stopped? @state == :stopped end - def map_app(digit, controller = nil, &block) - digit = digit.to_s + def map_app(pattern, controller = nil, &block) + pattern = pattern.to_s range = "1234567890*#" - unless range.include?(digit) && digit.size == 1 - raise ArgumentError, "The first argument should be a single digit String or number in the range 1234567890*#" + if VALID_DIGITS.match(pattern) + raise ArgumentError, "The first argument should be a String or number containing only 1234567890*#" end payload = if block_given? raise ArgumentError, "You cannot specify both a block and a controller name." if controller.is_a? Class block else raise ArgumentError, "You need to provide a block or a controller name." unless controller.is_a? Class controller end - @app_map[digit] = payload + @app_map[pattern] = payload end def handle_input_complete(event) if @state == :stopped - logger.warn "Stopped runner #{self} received event." + logger.warn "Stopped runner #{self} received stop event." return end logger.debug "MATRIOSKA HANDLING INPUT" result = event.reason.respond_to?(:utterance) ? event.reason.utterance : nil digit = parse_dtmf result - match_and_run digit unless @running + match_and_run digit end private def app_map @@ -75,16 +83,15 @@ end def match_and_run(digit) if match = @app_map[digit] logger.debug "MATRIOSKA #match_and_run called with #{digit}" - @running = true callback = lambda do |call| @running = false - logger.debug "MATRIOSKA CALLBACK RESTARTING LISTENER" - if call.active? - start unless stopped? + if call.alive? && call.active? && started? + logger.debug "MATRIOSKA CALLBACK RESTARTING LISTENER" + start else logger.debug "MATRIOSKA CALLBACK NOT DOING ANYTHING BECAUSE CALL IS DEAD" end end @@ -102,7 +109,28 @@ start end rescue Adhearsion::Call::Hangup logger.debug "Matrioska terminated because the call was disconnected" end + + def build_grammar + current_app_map = app_map + RubySpeech::GRXML.draw mode: :dtmf, root: 'options' do + rule id: 'options', scope: 'public' do + one_of do + current_app_map.keys.each do |index| + item do + index + end + end + end + end + end + end + + def register_runner_with_call + @call[:matrioska_runners] ||= [] + @call[:matrioska_runners] << self + end + end end