adhearsion 2.0.0.beta1 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/.travis.yml +2 -4
  2. data/CHANGELOG.md +34 -4
  3. data/README.markdown +2 -1
  4. data/Rakefile +22 -1
  5. data/adhearsion.gemspec +1 -0
  6. data/bin/ahn +0 -2
  7. data/features/cli_daemon.feature +2 -0
  8. data/features/cli_restart.feature +19 -0
  9. data/features/cli_start.feature +4 -6
  10. data/features/cli_stop.feature +3 -0
  11. data/features/step_definitions/app_generator_steps.rb +2 -0
  12. data/features/step_definitions/cli_steps.rb +2 -0
  13. data/features/support/aruba_helper.rb +2 -0
  14. data/features/support/env.rb +8 -46
  15. data/features/support/utils.rb +2 -0
  16. data/lib/adhearsion.rb +4 -6
  17. data/lib/adhearsion/call.rb +71 -17
  18. data/lib/adhearsion/call_controller.rb +25 -14
  19. data/lib/adhearsion/call_controller/dial.rb +34 -15
  20. data/lib/adhearsion/call_controller/input.rb +186 -144
  21. data/lib/adhearsion/call_controller/output.rb +10 -6
  22. data/lib/adhearsion/call_controller/record.rb +11 -13
  23. data/lib/adhearsion/call_controller/utility.rb +2 -0
  24. data/lib/adhearsion/calls.rb +4 -2
  25. data/lib/adhearsion/cli.rb +4 -0
  26. data/lib/adhearsion/cli_commands.rb +8 -2
  27. data/lib/adhearsion/configuration.rb +7 -3
  28. data/lib/adhearsion/console.rb +17 -17
  29. data/lib/adhearsion/events.rb +10 -4
  30. data/lib/adhearsion/foundation.rb +9 -0
  31. data/lib/adhearsion/foundation/custom_daemonizer.rb +3 -1
  32. data/lib/adhearsion/foundation/exception_handler.rb +2 -0
  33. data/lib/adhearsion/foundation/libc.rb +2 -0
  34. data/lib/adhearsion/foundation/object.rb +3 -0
  35. data/lib/adhearsion/foundation/thread_safety.rb +5 -11
  36. data/lib/adhearsion/generators.rb +2 -0
  37. data/lib/adhearsion/generators/app/app_generator.rb +2 -0
  38. data/lib/adhearsion/generators/app/templates/README.md +9 -0
  39. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +38 -16
  40. data/lib/adhearsion/generators/app/templates/config/environment.rb +2 -0
  41. data/lib/adhearsion/generators/app/templates/lib/simon_game.rb +5 -3
  42. data/lib/adhearsion/generators/controller/controller_generator.rb +2 -0
  43. data/lib/adhearsion/generators/controller/templates/lib/controller.rb +2 -0
  44. data/lib/adhearsion/generators/controller/templates/spec/controller_spec.rb +2 -0
  45. data/lib/adhearsion/generators/generator.rb +3 -1
  46. data/lib/adhearsion/generators/plugin/plugin_generator.rb +2 -0
  47. data/lib/adhearsion/initializer.rb +31 -17
  48. data/lib/adhearsion/linux_proc_name.rb +2 -0
  49. data/lib/adhearsion/logging.rb +5 -3
  50. data/lib/adhearsion/menu_dsl.rb +2 -0
  51. data/lib/adhearsion/menu_dsl/calculated_match.rb +2 -0
  52. data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +2 -0
  53. data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +2 -0
  54. data/lib/adhearsion/menu_dsl/match_calculator.rb +2 -0
  55. data/lib/adhearsion/menu_dsl/menu.rb +58 -4
  56. data/lib/adhearsion/menu_dsl/menu_builder.rb +14 -1
  57. data/lib/adhearsion/menu_dsl/range_match_calculator.rb +4 -1
  58. data/lib/adhearsion/menu_dsl/string_match_calculator.rb +2 -0
  59. data/lib/adhearsion/outbound_call.rb +2 -0
  60. data/lib/adhearsion/plugin.rb +9 -7
  61. data/lib/adhearsion/plugin/collection.rb +3 -1
  62. data/lib/adhearsion/plugin/initializer.rb +3 -1
  63. data/lib/adhearsion/process.rb +8 -2
  64. data/lib/adhearsion/punchblock_plugin.rb +3 -1
  65. data/lib/adhearsion/punchblock_plugin/initializer.rb +34 -11
  66. data/lib/adhearsion/router.rb +4 -2
  67. data/lib/adhearsion/router/route.rb +2 -0
  68. data/lib/adhearsion/script_ahn_loader.rb +2 -0
  69. data/lib/adhearsion/tasks.rb +2 -0
  70. data/lib/adhearsion/tasks/configuration.rb +2 -0
  71. data/lib/adhearsion/tasks/debugging.rb +8 -0
  72. data/lib/adhearsion/tasks/environment.rb +2 -0
  73. data/lib/adhearsion/tasks/plugins.rb +2 -0
  74. data/lib/adhearsion/tasks/testing.rb +2 -0
  75. data/lib/adhearsion/version.rb +3 -1
  76. data/pre-commit +2 -0
  77. data/spec/adhearsion/call_controller/dial_spec.rb +114 -25
  78. data/spec/adhearsion/call_controller/input_spec.rb +192 -169
  79. data/spec/adhearsion/call_controller/output_spec.rb +26 -12
  80. data/spec/adhearsion/call_controller/record_spec.rb +29 -77
  81. data/spec/adhearsion/call_controller/utility_spec.rb +69 -0
  82. data/spec/adhearsion/call_controller_spec.rb +90 -15
  83. data/spec/adhearsion/call_spec.rb +92 -24
  84. data/spec/adhearsion/calls_spec.rb +9 -7
  85. data/spec/adhearsion/configuration_spec.rb +58 -56
  86. data/spec/adhearsion/console_spec.rb +4 -2
  87. data/spec/adhearsion/events_spec.rb +9 -7
  88. data/spec/adhearsion/generators_spec.rb +3 -1
  89. data/spec/adhearsion/initializer_spec.rb +16 -14
  90. data/spec/adhearsion/logging_spec.rb +11 -9
  91. data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +6 -4
  92. data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +6 -4
  93. data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +3 -1
  94. data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +2 -0
  95. data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +42 -11
  96. data/spec/adhearsion/menu_dsl/menu_spec.rb +197 -36
  97. data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +4 -2
  98. data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +5 -3
  99. data/spec/adhearsion/outbound_call_spec.rb +7 -5
  100. data/spec/adhearsion/plugin_spec.rb +19 -15
  101. data/spec/adhearsion/process_spec.rb +12 -7
  102. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +35 -15
  103. data/spec/adhearsion/punchblock_plugin_spec.rb +4 -1
  104. data/spec/adhearsion/router/route_spec.rb +8 -6
  105. data/spec/adhearsion/router_spec.rb +12 -10
  106. data/spec/adhearsion_spec.rb +13 -2
  107. data/spec/capture_warnings.rb +33 -0
  108. data/spec/spec_helper.rb +4 -0
  109. data/spec/support/call_controller_test_helpers.rb +2 -4
  110. data/spec/support/initializer_stubs.rb +8 -5
  111. data/spec/support/logging_helpers.rb +2 -0
  112. data/spec/support/punchblock_mocks.rb +2 -0
  113. metadata +84 -71
  114. data/EVENTS +0 -11
  115. data/lib/adhearsion/call_controller/menu.rb +0 -124
  116. data/lib/adhearsion/foundation/all.rb +0 -8
  117. data/spec/adhearsion/call_controller/menu_spec.rb +0 -120
  118. data/spec/adhearsion/menu_dsl_spec.rb +0 -12
data/EVENTS DELETED
@@ -1,11 +0,0 @@
1
- # Below are a list of framework events:
2
-
3
- - after_initialized
4
- - shutdown
5
- - asterisk:
6
- - manager_interface
7
- - before_call
8
- - failed_call
9
- - hungup_call
10
-
11
- # Note: This file is valid YAML for programatic parsing.
@@ -1,124 +0,0 @@
1
- module Adhearsion
2
- class CallController
3
- module Menu
4
-
5
- # Creates and manages a multiple choice menu driven by DTMF, handling playback of prompts,
6
- # invalid input, retries and timeouts, and final failures.
7
- #
8
- # @example A complete example of the method is as follows:
9
- # menu "Welcome, ", "/opt/sounds/menu-prompt.mp3", :tries => 2, :timeout => 10 do
10
- # match 1, OperatorController
11
- #
12
- # match 10..19 do
13
- # pass DirectController
14
- # end
15
- #
16
- # match 5, 6, 9 do |exten|
17
- # play "The #{exten} extension is currently not active"
18
- # end
19
- #
20
- # match '7', OfficeController
21
- #
22
- # invalid { play "Please choose a valid extension" }
23
- # timeout { play "Input timed out, try again." }
24
- # failure { pass OperatorController }
25
- # end
26
- #
27
- # The first arguments to #menu will be a list of sounds to play, as accepted by #play, including strings for TTS, Date and Time objects, and file paths.
28
- # :tries and :timeout options respectively specify the number of tries before going into failure, and the timeout in seconds allowed on each digit input.
29
- # The most important part is the following block, which specifies how the menu will be constructed and handled.
30
- #
31
- # #match handles connecting an input pattern to a payload.
32
- # The pattern can be one or more of: an integer, a Range, a string, an Array of the possible single types.
33
- # Input is matched against patterns, and the first exact match has it's payload executed.
34
- # Matched input is passed in to the associated block, or to the controller through #options.
35
- #
36
- # Allowed payloads are the name of a controller class, in which case it is executed through its #run method, or a block.
37
- #
38
- # #invalid has its associated block executed when the input does not possibly match any pattern.
39
- # #timeout's block is run when time expires before or between input digits.
40
- # #failure runs its block when the maximum number of tries is reached without an input match.
41
- #
42
- # Execution of the current context resumes after #menu finishes. If you wish to jump to an entirely different controller, use #pass.
43
- # Menu will return :failed if failure was reached, or :done if a match was executed.
44
- #
45
- # @param [Object] A list of outputs to play, as accepted by #play
46
- # @param [Hash] options Options to use for the menu
47
- # @option options [Integer] :tries Number of tries allowed before failure
48
- # @option options [Integer] :timeout Timeout in seconds before the first and between each input digit
49
- #
50
- # @return [Symbol] :failure on failure, :done if a match is reached and executed. Will only return if control is not passed.
51
- #
52
- # @raise [ArgumentError] Raised if no block is passed in
53
- #
54
- # @see play
55
- # @see pass
56
- #
57
- def menu(*args, &block)
58
- raise ArgumentError, "You must provide a block to the #menu method." unless block_given?
59
-
60
- options = args.last.kind_of?(Hash) ? args.pop : {}
61
- sound_files = args.flatten
62
-
63
- menu_instance = MenuDSL::Menu.new options, &block
64
- result_of_menu = nil
65
-
66
- until MenuDSL::Menu::MenuResultDone === result_of_menu
67
- if menu_instance.should_continue?
68
- result_of_menu = menu_instance.continue
69
- else
70
- logger.debug "Menu failed to get valid input. Executing failure hook."
71
- menu_instance.execute_failure_hook
72
- return :failed
73
- end
74
-
75
- case result_of_menu
76
- when MenuDSL::Menu::MenuResultInvalid
77
- logger.debug "Menu get invalid input. Executing invalid hook and restarting."
78
- menu_instance.execute_invalid_hook
79
- menu_instance.restart!
80
- result_of_menu = nil
81
- when MenuDSL::Menu::MenuGetAnotherDigit
82
- next_digit = play_sound_files_for_menu menu_instance, sound_files
83
- if next_digit
84
- menu_instance << next_digit
85
- else
86
- case result_of_menu
87
- when MenuDSL::Menu::MenuGetAnotherDigitOrFinish
88
- jump_to result_of_menu.match_object, :extension => result_of_menu.new_extension
89
- return true
90
- when MenuDSL::Menu::MenuGetAnotherDigitOrTimeout
91
- logger.debug "Menu timed out. Executing timeout hook and restarting."
92
- menu_instance.execute_timeout_hook
93
- menu_instance.restart!
94
- result_of_menu = nil
95
- end
96
- end
97
- when MenuDSL::Menu::MenuResultFound
98
- logger.debug "Menu got a valid input (#{result_of_menu.new_extension}). Executing the match."
99
- jump_to result_of_menu.match_object, :extension => result_of_menu.new_extension
100
- return true
101
- end # case
102
- end # while
103
- return :done
104
- end
105
-
106
- def play_sound_files_for_menu(menu_instance, sound_files) # :nodoc:
107
- digit = nil
108
- if sound_files.any? && menu_instance.digit_buffer_empty?
109
- digit = interruptible_play *sound_files
110
- end
111
- digit || wait_for_digit(menu_instance.timeout)
112
- end
113
-
114
- def jump_to(match_object, overrides = nil) # :nodoc:
115
- if match_object.block
116
- instance_exec overrides[:extension], &match_object.block
117
- else
118
- invoke match_object.match_payload, overrides
119
- end
120
- end
121
-
122
- end # module
123
- end
124
- end
@@ -1,8 +0,0 @@
1
- require 'English'
2
- require 'tmpdir'
3
- require 'tempfile'
4
-
5
- # Require all other files here.
6
- Dir.glob File.join(File.dirname(__FILE__), "*rb") do |file|
7
- require file
8
- end
@@ -1,120 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Adhearsion
4
- class CallController
5
- describe Menu do
6
- include CallControllerTestHelpers
7
-
8
- describe "#play_sound_files_for_menu" do
9
- let(:options) { Hash.new }
10
- let(:menu_instance) { Adhearsion::MenuDSL::Menu.new(options) {} }
11
- let(:sound_file) { "press a button" }
12
- let(:sound_files) { [sound_file] }
13
-
14
- it "should play the sound files for the menu" do
15
- subject.should_receive(:interruptible_play).with(sound_file).and_return("1")
16
- subject.play_sound_files_for_menu(menu_instance, sound_files)
17
- end
18
-
19
- it "should wait for digit if nothing is pressed during playback" do
20
- subject.should_receive(:interruptible_play).with(sound_file).and_return(nil)
21
- subject.should_receive(:wait_for_digit).with(menu_instance.timeout).and_return("1")
22
- subject.play_sound_files_for_menu(menu_instance, sound_files)
23
- end
24
- end#play_sound_files_for_menu
25
-
26
- describe "#jump_to" do
27
- let(:match_object) { flexmock(Class.new) }
28
- let(:overrides) { Hash.new(:extension => "1") }
29
- let(:block) { Proc.new() {} }
30
-
31
- it "calls instance_exec if the match object has a block" do
32
- match_object.should_receive(:block).and_return(block)
33
- subject.should_receive(:instance_exec).with(overrides[:extension], block)
34
- subject.jump_to(match_object, overrides)
35
- end
36
-
37
- it "calls invoke if the match object does not have a block" do
38
- match_object.should_receive(:block).and_return(false)
39
- match_object.should_receive(:match_payload).and_return(:payload)
40
- subject.should_receive(:invoke).with(:payload, overrides)
41
- subject.jump_to(match_object, overrides)
42
- end
43
- end#jump_to
44
-
45
- describe "#menu" do
46
- let(:sound_files) { ["press", "button"] }
47
- context "menu state flow" do
48
- let(:menu_instance) do
49
- menu_instance = flexmock(MenuDSL::Menu.new({}) {})
50
- end
51
- let(:result_done) { MenuDSL::Menu::MenuResultDone.new }
52
- let(:result_invalid) { MenuDSL::Menu::MenuResultInvalid.new }
53
- let(:result_get_another_or_timeout) { MenuDSL::Menu::MenuGetAnotherDigitOrTimeout.new }
54
- let(:result_get_another_or_finish) { MenuDSL::Menu::MenuGetAnotherDigitOrFinish.new(:match_object, :new_extension) }
55
- let(:result_found) { MenuDSL::Menu::MenuResultFound.new(:match_object, :new_extension) }
56
-
57
- before(:each) do
58
- flexmock(MenuDSL::Menu).should_receive(:new).and_return(menu_instance)
59
- end
60
-
61
- it "exits the function if MenuResultDone" do
62
- menu_instance.should_receive(:should_continue?).and_return(true)
63
- menu_instance.should_receive(:continue).and_return(result_done)
64
- result = subject.menu(sound_files) {}
65
- result.should == :done
66
- end
67
-
68
- it "executes failure hook and returns :failure if menu fails" do
69
- menu_instance.should_receive(:should_continue?).and_return(false)
70
- menu_instance.should_receive(:execute_failure_hook)
71
- result = subject.menu(sound_files) {}
72
- result.should == :failed
73
- end
74
-
75
- it "executes invalid hook if input is invalid" do
76
- menu_instance.should_receive(:should_continue?).twice.and_return(true)
77
- menu_instance.should_receive(:continue).and_return(result_invalid, result_done)
78
- menu_instance.should_receive(:execute_invalid_hook)
79
- menu_instance.should_receive(:restart!)
80
- subject.menu(sound_files) {}
81
- end
82
-
83
- it "plays audio, then executes timeout hook if input times out" do
84
- menu_instance.should_receive(:should_continue?).twice.and_return(true)
85
- menu_instance.should_receive(:continue).and_return(result_get_another_or_timeout, result_done)
86
- subject.should_receive(:play_sound_files_for_menu).with(menu_instance, sound_files).and_return(nil)
87
- menu_instance.should_receive(:execute_timeout_hook)
88
- menu_instance.should_receive(:restart!)
89
- subject.menu(sound_files) {}
90
- end
91
-
92
- it "plays audio, then adds digit to digit buffer if input is received" do
93
- menu_instance.should_receive(:should_continue?).twice.and_return(true)
94
- menu_instance.should_receive(:continue).and_return(result_get_another_or_timeout, result_done)
95
- subject.should_receive(:play_sound_files_for_menu).with(menu_instance, sound_files).and_return("1")
96
- menu_instance.should_receive(:<<).with("1")
97
- subject.menu(sound_files) {}
98
- end
99
-
100
- it "plays audio, then jumps to payload when input is finished" do
101
- menu_instance.should_receive(:should_continue?).and_return(true)
102
- menu_instance.should_receive(:continue).and_return(result_get_another_or_finish)
103
- subject.should_receive(:play_sound_files_for_menu).with(menu_instance, sound_files).and_return(nil)
104
- subject.should_receive(:jump_to).with(:match_object, :extension => :new_extension)
105
- subject.menu(sound_files) {}
106
- end
107
-
108
- it "jumps to payload when result is found" do
109
- menu_instance.should_receive(:should_continue?).and_return(true)
110
- menu_instance.should_receive(:continue).and_return(result_found)
111
- subject.should_receive(:jump_to).with(:match_object, :extension => :new_extension)
112
- subject.menu(sound_files) {}
113
- end
114
- end#context
115
-
116
- end#describe
117
-
118
- end#shared
119
- end
120
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Adhearsion
4
- describe MenuDSL do
5
- it "should accept hash options"
6
-
7
- it "should accept hash options and block"
8
-
9
- it "should accept hash options and block and evaluate block"
10
- end
11
- end
12
-