adhearsion 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -3
  3. data/CHANGELOG.md +29 -0
  4. data/Gemfile +0 -2
  5. data/Guardfile +2 -2
  6. data/README.markdown +3 -6
  7. data/Rakefile +1 -1
  8. data/adhearsion.gemspec +7 -2
  9. data/features/cli_create.feature +85 -7
  10. data/features/plugin_generator.feature +4 -0
  11. data/features/step_definitions/app_generator_steps.rb +8 -1
  12. data/lib/adhearsion.rb +6 -3
  13. data/lib/adhearsion/call.rb +101 -30
  14. data/lib/adhearsion/call_controller.rb +40 -12
  15. data/lib/adhearsion/call_controller/dial.rb +119 -36
  16. data/lib/adhearsion/call_controller/input.rb +11 -5
  17. data/lib/adhearsion/call_controller/output.rb +47 -33
  18. data/lib/adhearsion/call_controller/output/async_player.rb +3 -2
  19. data/lib/adhearsion/call_controller/output/formatter.rb +7 -2
  20. data/lib/adhearsion/call_controller/output/player.rb +2 -2
  21. data/lib/adhearsion/call_controller/record.rb +16 -13
  22. data/lib/adhearsion/call_controller/utility.rb +3 -3
  23. data/lib/adhearsion/calls.rb +21 -8
  24. data/lib/adhearsion/cli_commands/ahn_command.rb +1 -0
  25. data/lib/adhearsion/configuration.rb +2 -2
  26. data/lib/adhearsion/console.rb +3 -2
  27. data/lib/adhearsion/generators.rb +7 -9
  28. data/lib/adhearsion/generators/app/app_generator.rb +12 -2
  29. data/lib/adhearsion/generators/app/templates/Gemfile.erb +7 -9
  30. data/lib/adhearsion/generators/app/templates/README.md +0 -19
  31. data/lib/adhearsion/generators/app/templates/adhearsion.erb +37 -0
  32. data/lib/adhearsion/generators/app/templates/config/environment.rb +6 -1
  33. data/lib/adhearsion/generators/app/templates/events.erb +18 -0
  34. data/lib/adhearsion/generators/app/templates/routes.erb +19 -0
  35. data/lib/adhearsion/generators/app/templates/{lib/simon_game.rb → simon_game.rb} +0 -0
  36. data/lib/adhearsion/generators/app/templates/{spec/call_controllers/simon_game_spec.rb → simon_game_spec.rb} +0 -0
  37. data/lib/adhearsion/generators/controller/controller_generator.rb +2 -2
  38. data/lib/adhearsion/generators/controller/templates/lib/{controller.rb → controller.rb.erb} +0 -0
  39. data/lib/adhearsion/generators/controller/templates/spec/{controller_spec.rb → controller_spec.rb.erb} +0 -0
  40. data/lib/adhearsion/generators/plugin/plugin_generator.rb +16 -15
  41. data/lib/adhearsion/generators/plugin/templates/gitignore +17 -0
  42. data/lib/adhearsion/generators/plugin/templates/spec/plugin-template/controller_methods_spec.rb.tt +1 -1
  43. data/lib/adhearsion/initializer.rb +14 -2
  44. data/lib/adhearsion/logging.rb +1 -0
  45. data/lib/adhearsion/outbound_call.rb +3 -7
  46. data/lib/adhearsion/punchblock_plugin/initializer.rb +3 -2
  47. data/lib/adhearsion/router/openended_route.rb +1 -1
  48. data/lib/adhearsion/router/route.rb +4 -3
  49. data/lib/adhearsion/version.rb +1 -1
  50. data/spec/adhearsion/call_controller/dial_spec.rb +811 -79
  51. data/spec/adhearsion/call_controller/output/formatter_spec.rb +13 -1
  52. data/spec/adhearsion/call_controller/output_spec.rb +35 -1
  53. data/spec/adhearsion/call_controller_spec.rb +174 -18
  54. data/spec/adhearsion/call_spec.rb +423 -39
  55. data/spec/adhearsion/calls_spec.rb +19 -3
  56. data/spec/adhearsion/outbound_call_spec.rb +88 -45
  57. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +3 -3
  58. data/spec/adhearsion/router/route_spec.rb +2 -2
  59. data/spec/spec_helper.rb +2 -0
  60. metadata +92 -77
  61. data/features/app_generator.feature +0 -49
  62. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +0 -71
  63. data/lib/adhearsion/generators/plugin/templates/.gitignore +0 -9
@@ -28,7 +28,7 @@ module Adhearsion
28
28
  klass.start args
29
29
  end
30
30
 
31
- ##
31
+ #
32
32
  # Return a ordered list of task with their class
33
33
  #
34
34
  def mappings
@@ -38,20 +38,18 @@ module Adhearsion
38
38
  ##
39
39
  # Globally add a new generator class to +ahn generate+
40
40
  #
41
- # @param [Symbol] name
42
- # key name for generator mapping
43
- # @param [Class] klass
44
- # class of generator
41
+ # @param [Symbol] name key name for generator mapping
42
+ # @param [Class] klass class of generator
45
43
  #
46
44
  # @return [Hash] generator mappings
47
45
  #
48
46
  # @example
49
- # Adhearsion::Generators.add_generator :myplugin, MyPluginGenerator
47
+ # Adhearsion::Generators.add_generator :myplugin, MyPluginGenerator
50
48
  #
51
49
  def add_generator(name, klass)
52
50
  mappings[name] = klass
53
51
  end
54
52
 
55
- end#class << self
56
- end#module
57
- end#module
53
+ end
54
+ end
55
+ end
@@ -4,19 +4,29 @@ module Adhearsion
4
4
  module Generators
5
5
  class AppGenerator < Generator
6
6
 
7
- BASEDIRS = %w( config lib script spec )
8
- EMPTYDIRS = %w( spec/support )
7
+ BASEDIRS = %w( config script spec )
8
+ EMPTYDIRS = %w( app/call_controllers lib spec/support spec/call_controllers )
9
+
10
+ class_option :empty, type: :boolean
9
11
 
10
12
  def setup_project
11
13
  self.destination_root = @generator_name
12
14
  BASEDIRS.each { |dir| directory dir }
13
15
  EMPTYDIRS.each { |dir| empty_directory dir }
16
+
14
17
  template "Gemfile.erb", "Gemfile"
18
+ template "adhearsion.erb", "config/adhearsion.rb"
19
+ template "events.erb", "config/events.rb"
20
+ template "routes.erb", "config/routes.rb"
15
21
  copy_file "gitignore", ".gitignore"
16
22
  copy_file "rspec", ".rspec"
17
23
  copy_file "Procfile"
18
24
  copy_file "Rakefile"
19
25
  copy_file "README.md"
26
+ unless options[:empty]
27
+ copy_file "simon_game.rb", "app/call_controllers/simon_game.rb"
28
+ copy_file "simon_game_spec.rb", "spec/call_controllers/simon_game_spec.rb"
29
+ end
20
30
  chmod "script/ahn", 0755
21
31
  end
22
32
  end
@@ -2,22 +2,20 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'adhearsion', '~> <%= Adhearsion::VERSION.split('.')[0,2].join('.') %>'
4
4
 
5
+ # Adhearsion depends on the Punchblock library, but here you can specify the major version your application depends on.
6
+ # Exercise care when updating the major version, since you might encounter API compatability in parts of your Adhearsion application that rely on the Punchblock API.
7
+ # On occasion, an update of Adhearsion might necessitate an update to Punchblock. You will have to manually allow that here, and take care in the upgrade.
8
+ gem 'punchblock', '~> <%= require "punchblock/version"; Punchblock::VERSION.split('.')[0,2].join('.') %>'
9
+
5
10
  # This is here by default due to deprecation of #ask and #menu.
6
11
  # See http://adhearsion.com/docs/common_problems#toc_3 for details
7
12
  gem 'adhearsion-asr'
8
13
 
9
14
  #
10
- # Here are some example plugins you might like to use. Simply
11
- # uncomment them and run `bundle install`.
15
+ # Check http://ahnhub.com for a list of plugins you can use in your app.
16
+ # To use them, simply add them here and run `bundle install`.
12
17
  #
13
18
 
14
- # gem 'adhearsion-asterisk'
15
- # gem 'adhearsion-rails'
16
- # gem 'adhearsion-activerecord'
17
- # gem 'adhearsion-ldap'
18
- # gem 'adhearsion-xmpp'
19
- # gem 'adhearsion-drb'
20
-
21
19
  group :development, :test do
22
20
  gem 'rspec'
23
21
  end
@@ -17,8 +17,6 @@ If you are using Asterisk 1.8, you will need to add an additional context with t
17
17
 
18
18
  ## FreeSWITCH
19
19
 
20
- ### With mod_rayo (recommended)
21
-
22
20
  * Ensure that mod_rayo is installed and configured according to its' documentation.
23
21
  * Add an extension to your dialplan like so:
24
22
 
@@ -32,23 +30,6 @@ If you are using Asterisk 1.8, you will need to add an additional context with t
32
30
 
33
31
  * Connect Adhearsion via XMPP using the Rayo protocol, as per the sample config.
34
32
 
35
- ### With Punchblock's FreeSWITCH mode (deprecated)
36
-
37
- * Ensure that mod_event_socket is installed, and configure it in autoload_configs/event_socket.conf.xml to taste
38
- * Add an extension to your dialplan like so:
39
-
40
- ```xml
41
- <extension name='Adhearsion'>
42
- <condition field="destination_number" expression="^10$">
43
- <action application="set" data="hangup_after_bridge=false"/>
44
- <action application="set" data="park_after_bridge=true"/>
45
- <action application='rayo'/>
46
- </condition>
47
- </extension>
48
- ```
49
-
50
- * Connect Adhearsion via EventSocket, as per the sample config.
51
-
52
33
  ## Voxeo PRISM
53
34
 
54
35
  Install the [rayo-server](https://github.com/rayo/rayo-server) app into PRISM 11 and follow the [configuration guide](https://github.com/rayo/rayo-server/wiki/Single-node-and-cluster-configuration-reference).
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ Adhearsion.config do |config|
4
+ <% unless options[:empty] %>
5
+ # Centralized way to specify any Adhearsion platform or plugin configuration
6
+ # - Execute rake config:show to view the active configuration values
7
+ #
8
+ # To update a plugin configuration you can write either:
9
+ #
10
+ # * Option 1
11
+ # Adhearsion.config.<plugin-name> do |config|
12
+ # config.<key> = <value>
13
+ # end
14
+ #
15
+ # * Option 2
16
+ # Adhearsion.config do |config|
17
+ # config.<plugin-name>.<key> = <value>
18
+ # end
19
+ <% end %>
20
+ config.development do |dev|
21
+ dev.platform.logging.level = :debug
22
+ end
23
+
24
+ ##
25
+ # Use with Rayo (eg Voxeo PRISM or FreeSWITCH mod_rayo)
26
+ #
27
+ # config.punchblock.username = "usera@freeswitch.local-dev.mojolingo.com" # Your XMPP JID for use with Rayo
28
+ # config.punchblock.password = "1" # Your XMPP password
29
+
30
+ ##
31
+ # Use with Asterisk
32
+ #
33
+ # config.punchblock.platform = :asterisk # Use Asterisk
34
+ # config.punchblock.username = "manager" # Your AMI username
35
+ # config.punchblock.password = "password" # Your AMI password
36
+ # config.punchblock.host = "asterisk.local-dev.mojolingo.com" # Your AMI host
37
+ end
@@ -2,4 +2,9 @@
2
2
 
3
3
  require 'bundler'
4
4
  Bundler.setup
5
- Bundler.require
5
+
6
+ require 'adhearsion'
7
+
8
+ Bundler.require(:default, Adhearsion.environment)
9
+
10
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../app/')))
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ Adhearsion::Events.draw do
4
+ <% unless options[:empty] %>
5
+ # Register global handlers for events
6
+ #
7
+ # eg. Handling Punchblock events
8
+ # punchblock do |event|
9
+ # ...
10
+ # end
11
+ #
12
+ # eg Handling PeerStatus AMI events
13
+ # ami :name => 'PeerStatus' do |event|
14
+ # ...
15
+ # end
16
+ #
17
+ <% end %>
18
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ <% unless options[:empty] %>
4
+ require 'call_controllers/simon_game'
5
+ <% end %>
6
+
7
+ Adhearsion.router do
8
+ <% if options[:empty] %>
9
+ route 'default' do
10
+
11
+ end
12
+ <% else %>
13
+ #
14
+ # Specify your call routes, directing calls with particular attributes to a controller
15
+ #
16
+
17
+ route 'default', SimonGame
18
+ <% end %>
19
+ end
@@ -15,8 +15,8 @@ module Adhearsion
15
15
  self.destination_root = '.'
16
16
  empty_directory 'lib'
17
17
  empty_directory 'spec'
18
- template 'lib/controller.rb', "lib/#{@controller_name.underscore}.rb"
19
- template 'spec/controller_spec.rb', "spec/#{@controller_name.underscore}_spec.rb"
18
+ template 'lib/controller.rb.erb', "lib/#{@controller_name.underscore}.rb"
19
+ template 'spec/controller_spec.rb.erb', "spec/#{@controller_name.underscore}_spec.rb"
20
20
  end
21
21
 
22
22
  end
@@ -13,25 +13,26 @@ module Adhearsion
13
13
  def create_plugin
14
14
  @plugin_file = @plugin_name.underscore
15
15
  @plugin_name = @plugin_name.camelize
16
- self.destination_root = '.'
16
+ self.destination_root = @plugin_file
17
17
 
18
- empty_directory @plugin_file
19
- empty_directory "#{@plugin_file}/lib"
20
- empty_directory "#{@plugin_file}/lib/#{@plugin_file}"
21
- empty_directory "#{@plugin_file}/spec"
18
+ empty_directory "lib"
19
+ empty_directory "lib/#{@plugin_file}"
20
+ empty_directory "spec"
22
21
 
23
- template 'plugin-template.gemspec.tt', "#{@plugin_file}/#{@plugin_file}.gemspec"
24
- template 'Rakefile.tt', "#{@plugin_file}/Rakefile"
25
- template 'README.md.tt', "#{@plugin_file}/README.md"
26
- template 'Gemfile.tt', "#{@plugin_file}/Gemfile"
22
+ copy_file "gitignore", ".gitignore"
27
23
 
28
- template 'lib/plugin-template.rb.tt', "#{@plugin_file}/lib/#{@plugin_file}.rb"
29
- template 'lib/plugin-template/version.rb.tt', "#{@plugin_file}/lib/#{@plugin_file}/version.rb"
30
- template 'lib/plugin-template/plugin.rb.tt', "#{@plugin_file}/lib/#{@plugin_file}/plugin.rb"
31
- template 'lib/plugin-template/controller_methods.rb.tt', "#{@plugin_file}/lib/#{@plugin_file}/controller_methods.rb"
24
+ template 'plugin-template.gemspec.tt', "#{@plugin_file}.gemspec"
25
+ template 'Rakefile.tt', "Rakefile"
26
+ template 'README.md.tt', "README.md"
27
+ template 'Gemfile.tt', "Gemfile"
32
28
 
33
- template 'spec/spec_helper.rb.tt', "#{@plugin_file}/spec/spec_helper.rb"
34
- template 'spec/plugin-template/controller_methods_spec.rb.tt', "#{@plugin_file}/spec/#{@plugin_file}/controller_methods_spec.rb"
29
+ template 'lib/plugin-template.rb.tt', "lib/#{@plugin_file}.rb"
30
+ template 'lib/plugin-template/version.rb.tt', "lib/#{@plugin_file}/version.rb"
31
+ template 'lib/plugin-template/plugin.rb.tt', "lib/#{@plugin_file}/plugin.rb"
32
+ template 'lib/plugin-template/controller_methods.rb.tt', "lib/#{@plugin_file}/controller_methods.rb"
33
+
34
+ template 'spec/spec_helper.rb.tt', "spec/spec_helper.rb"
35
+ template 'spec/plugin-template/controller_methods_spec.rb.tt', "spec/#{@plugin_file}/controller_methods_spec.rb"
35
36
  end
36
37
 
37
38
  end
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -16,7 +16,7 @@ module <%= @plugin_name %>
16
16
 
17
17
  describe "#greet" do
18
18
  it "greets with the correct parameter" do
19
- subject.expects(:play).once.with("Hello, Luca")
19
+ subject.should_receive(:play).once.with("Hello, Luca")
20
20
  subject.greet "Luca"
21
21
  end
22
22
  end
@@ -34,7 +34,7 @@ module Adhearsion
34
34
  @mode = options[:mode]
35
35
  @pid_file = options[:pid_file].nil? ? ENV['PID_FILE'] : options[:pid_file]
36
36
  @loaded_init_files = options[:loaded_init_files]
37
- Adhearsion.ahn_root = '.'
37
+ Adhearsion.root = '.'
38
38
  end
39
39
 
40
40
  def start
@@ -42,6 +42,8 @@ module Adhearsion
42
42
  resolve_pid_file_path
43
43
  load_lib_folder
44
44
  load_config_file
45
+ load_events_file
46
+ load_routes_file
45
47
  initialize_log_paths
46
48
 
47
49
  if should_daemonize?
@@ -195,6 +197,16 @@ module Adhearsion
195
197
  require "#{Adhearsion.config.root}/config/adhearsion.rb"
196
198
  end
197
199
 
200
+ def load_events_file
201
+ path = "#{Adhearsion.config.root}/config/events.rb"
202
+ require path if File.exists?(path)
203
+ end
204
+
205
+ def load_routes_file
206
+ path = "#{Adhearsion.config.root}/config/routes.rb"
207
+ require path if File.exists?(path)
208
+ end
209
+
198
210
  def init_get_logging_appenders
199
211
  @file_loggers ||= memoize_logging_appenders
200
212
  end
@@ -249,7 +261,7 @@ module Adhearsion
249
261
  end
250
262
 
251
263
  def launch_console
252
- Adhearsion::Process.important_threads << Thread.new do
264
+ Thread.new do
253
265
  catching_standard_errors do
254
266
  Adhearsion::Console.run
255
267
  end
@@ -88,6 +88,7 @@ module Adhearsion
88
88
  'stdout',
89
89
  :layout => ::Logging.layouts.pattern(
90
90
  :pattern => adhearsion_pattern,
91
+ :date_pattern => "%Y-%m-%d %H:%M:%S.%L",
91
92
  :color_scheme => 'bright'
92
93
  ),
93
94
  :auto_flushing => 2,
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Adhearsion
4
4
  class OutboundCall < Call
5
- execute_block_on_receiver :register_handler, :register_tmp_handler, :register_handler_with_priority, :register_event_handler, :on_joined, :on_unjoined, :on_end, :execute_controller, :on_answer, :execute_controller_or_router_on_answer
5
+ execute_block_on_receiver :on_answer, :execute_controller_or_router_on_answer, *execute_block_on_receiver
6
6
 
7
7
  attr_reader :dial_command
8
8
 
@@ -73,7 +73,7 @@ module Adhearsion
73
73
  wait_timeout = 60
74
74
  end
75
75
 
76
- write_and_await_response(Punchblock::Command::Dial.new(options), wait_timeout).tap do |dial_command|
76
+ write_and_await_response(Punchblock::Command::Dial.new(options), wait_timeout, true).tap do |dial_command|
77
77
  @dial_command = dial_command
78
78
  Adhearsion.active_calls << current_actor
79
79
  Adhearsion::Events.trigger_immediately :call_dialed, current_actor
@@ -95,15 +95,11 @@ module Adhearsion
95
95
  def run_router_on_answer
96
96
  register_event_handler Punchblock::Event::Answered do |event|
97
97
  run_router
98
- throw :pass
99
98
  end
100
99
  end
101
100
 
102
101
  def on_answer(&block)
103
- register_event_handler Punchblock::Event::Answered do |event|
104
- block.call event
105
- throw :pass
106
- end
102
+ register_event_handler Punchblock::Event::Answered, &block
107
103
  end
108
104
 
109
105
  def execute_controller_or_router_on_answer(controller, metadata = {}, &controller_block)
@@ -127,7 +127,8 @@ module Adhearsion
127
127
 
128
128
  def dispatch_offer(offer)
129
129
  catching_standard_errors do
130
- call = Adhearsion.active_calls.from_offer offer
130
+ call = Call.new(offer)
131
+ Adhearsion.active_calls << call
131
132
  case Adhearsion::Process.state_name
132
133
  when :booting, :rejecting
133
134
  logger.info "Declining call because the process is not yet running."
@@ -144,7 +145,7 @@ module Adhearsion
144
145
  if call = Adhearsion.active_calls[event.target_call_id]
145
146
  call.async.deliver_message event
146
147
  else
147
- logger.error "Event received for inactive call #{event.target_call_id}: #{event.inspect}"
148
+ logger.warn "Event received for inactive call #{event.target_call_id}: #{event.inspect}"
148
149
  end
149
150
  end
150
151
 
@@ -8,7 +8,7 @@ module Adhearsion
8
8
  end
9
9
 
10
10
  def dispatch(call, callback = nil)
11
- call[:ahn_prevent_hangup] = true
11
+ call.auto_hangup = false
12
12
  super
13
13
  end
14
14
  end
@@ -38,10 +38,11 @@ module Adhearsion
38
38
 
39
39
  call.execute_controller controller, lambda { |call_actor|
40
40
  begin
41
- if call_actor[:ahn_prevent_hangup]
42
- logger.info "Call routing completed, keeping the call alive at controller/router request."
43
- else
41
+ if call_actor.auto_hangup
42
+ logger.info "Call routing completed. Hanging up now..."
44
43
  call_actor.hangup
44
+ else
45
+ logger.info "Call routing completed, keeping the call alive at controller/router request."
45
46
  end
46
47
  rescue Call::Hangup, Call::ExpiredError
47
48
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Adhearsion
4
- VERSION = '2.4.0'
4
+ VERSION = '2.5.0'
5
5
  end