adhearsion 2.0.0.beta1 → 2.0.0.rc1

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.
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
-