punchblock 1.8.2 → 1.9.0

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +8 -0
  4. data/lib/punchblock/component/asterisk/agi/command.rb +0 -11
  5. data/lib/punchblock/connection/asterisk.rb +3 -3
  6. data/lib/punchblock/translator/asterisk/agi_command.rb +40 -0
  7. data/lib/punchblock/translator/asterisk/call.rb +56 -47
  8. data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +13 -37
  9. data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +24 -41
  10. data/lib/punchblock/translator/asterisk/component/input.rb +2 -1
  11. data/lib/punchblock/translator/asterisk/component/output.rb +16 -21
  12. data/lib/punchblock/translator/asterisk/component/record.rb +11 -19
  13. data/lib/punchblock/translator/asterisk/component.rb +12 -9
  14. data/lib/punchblock/translator/asterisk.rb +16 -22
  15. data/lib/punchblock/translator/dtmf_recognizer.rb +4 -4
  16. data/lib/punchblock/translator/freeswitch/component/input.rb +2 -1
  17. data/lib/punchblock/translator/input_component.rb +2 -2
  18. data/lib/punchblock/version.rb +1 -1
  19. data/punchblock.gemspec +1 -1
  20. data/spec/punchblock/connection/asterisk_spec.rb +8 -7
  21. data/spec/punchblock/translator/asterisk/call_spec.rb +262 -229
  22. data/spec/punchblock/translator/asterisk/component/asterisk/agi_command_spec.rb +57 -29
  23. data/spec/punchblock/translator/asterisk/component/asterisk/ami_action_spec.rb +40 -46
  24. data/spec/punchblock/translator/asterisk/component/input_spec.rb +7 -7
  25. data/spec/punchblock/translator/asterisk/component/output_spec.rb +84 -53
  26. data/spec/punchblock/translator/asterisk/component/record_spec.rb +55 -83
  27. data/spec/punchblock/translator/asterisk/component/stop_by_redirect_spec.rb +5 -1
  28. data/spec/punchblock/translator/asterisk/component_spec.rb +2 -10
  29. data/spec/punchblock/translator/asterisk_spec.rb +73 -100
  30. metadata +5 -10
@@ -17,7 +17,6 @@ module Punchblock
17
17
  include DeadActorSafety
18
18
 
19
19
  attr_reader :id, :call, :call_id
20
- attr_accessor :internal
21
20
 
22
21
  def initialize(component_node, call = nil)
23
22
  @component_node, @call = component_node, call
@@ -34,7 +33,7 @@ module Punchblock
34
33
  command.response = ProtocolError.new.setup 'command-not-acceptable', "Did not understand command for component #{id}", call_id, id
35
34
  end
36
35
 
37
- def send_complete_event(reason, recording = nil)
36
+ def send_complete_event(reason, recording = nil, should_terminate = true)
38
37
  return if @complete
39
38
  @complete = true
40
39
  event = Punchblock::Event::Complete.new.tap do |c|
@@ -42,17 +41,13 @@ module Punchblock
42
41
  c << recording if recording
43
42
  end
44
43
  send_event event
45
- terminate
44
+ terminate if should_terminate
46
45
  end
47
46
 
48
47
  def send_event(event)
49
48
  event.component_id = id
50
49
  event.target_call_id = call_id
51
- if internal
52
- @component_node.add_event event
53
- else
54
- safe_from_dead_actors { translator.handle_pb_event event }
55
- end
50
+ safe_from_dead_actors { translator.handle_pb_event event }
56
51
  end
57
52
 
58
53
  def logger_id
@@ -66,7 +61,11 @@ module Punchblock
66
61
  private
67
62
 
68
63
  def translator
69
- call.translator
64
+ @translator ||= call.translator
65
+ end
66
+
67
+ def ami_client
68
+ translator.ami_client
70
69
  end
71
70
 
72
71
  def set_node_response(value)
@@ -80,6 +79,10 @@ module Punchblock
80
79
  def with_error(name, text)
81
80
  set_node_response ProtocolError.new.setup(name, text)
82
81
  end
82
+
83
+ def complete_with_error(error)
84
+ send_complete_event Punchblock::Event::Complete::Error.new(details: error)
85
+ end
83
86
  end
84
87
  end
85
88
  end
@@ -10,6 +10,7 @@ module Punchblock
10
10
 
11
11
  extend ActiveSupport::Autoload
12
12
 
13
+ autoload :AGICommand
13
14
  autoload :Call
14
15
  autoload :Component
15
16
 
@@ -65,12 +66,8 @@ module Punchblock
65
66
  return unless event.is_a? RubyAMI::Event
66
67
 
67
68
  if event.name.downcase == "fullybooted"
68
- @fully_booted_count += 1
69
- if @fully_booted_count >= 2
70
- handle_pb_event Connection::Connected.new
71
- @fully_booted_count = 0
72
- run_at_fully_booted
73
- end
69
+ handle_pb_event Connection::Connected.new
70
+ run_at_fully_booted
74
71
  return
75
72
  end
76
73
 
@@ -122,11 +119,11 @@ module Punchblock
122
119
  def execute_global_command(command)
123
120
  case command
124
121
  when Punchblock::Component::Asterisk::AMI::Action
125
- component = Component::Asterisk::AMIAction.new command, current_actor
122
+ component = Component::Asterisk::AMIAction.new command, current_actor, ami_client
126
123
  register_component component
127
124
  component.async.execute
128
125
  when Punchblock::Command::Dial
129
- call = Call.new_link command.to, current_actor
126
+ call = Call.new_link command.to, current_actor, ami_client, connection
130
127
  register_call call
131
128
  call.async.dial command
132
129
  else
@@ -134,21 +131,14 @@ module Punchblock
134
131
  end
135
132
  end
136
133
 
137
- def send_ami_action(name, headers = {}, &block)
138
- ami_client.send_action name, headers, &block
139
- end
140
-
141
134
  def run_at_fully_booted
142
- send_ami_action('Command', {
143
- 'Command' => "dialplan add extension #{REDIRECT_EXTENSION},#{REDIRECT_PRIORITY},AGI,agi:async into #{REDIRECT_CONTEXT}"
144
- })
145
- send_ami_action('Command', {
146
- 'Command' => "dialplan show #{REDIRECT_CONTEXT}"
147
- }) do |result|
148
- if result.text_body =~ /failed/
149
- pb_logger.error "Punchblock failed to add the #{REDIRECT_EXTENSION} extension to the #{REDIRECT_CONTEXT} context. Please add a [#{REDIRECT_CONTEXT}] entry to your dialplan."
150
- end
135
+ send_ami_action 'Command', 'Command' => "dialplan add extension #{REDIRECT_EXTENSION},#{REDIRECT_PRIORITY},AGI,agi:async into #{REDIRECT_CONTEXT}"
136
+
137
+ result = send_ami_action 'Command', 'Command' => "dialplan show #{REDIRECT_CONTEXT}"
138
+ if result.text_body =~ /failed/
139
+ pb_logger.error "Punchblock failed to add the #{REDIRECT_EXTENSION} extension to the #{REDIRECT_CONTEXT} context. Please add a [#{REDIRECT_CONTEXT}] entry to your dialplan."
151
140
  end
141
+
152
142
  check_recording_directory
153
143
  end
154
144
 
@@ -168,6 +158,10 @@ module Punchblock
168
158
 
169
159
  private
170
160
 
161
+ def send_ami_action(name, headers = {})
162
+ ami_client.send_action name, headers
163
+ end
164
+
171
165
  def handle_varset_ami_event(event)
172
166
  return unless event.name == 'VarSet' && event['Variable'] == 'punchblock_call_id' && (call = call_with_id event['Value'])
173
167
 
@@ -213,7 +207,7 @@ module Punchblock
213
207
 
214
208
  return if env[:agi_extension] == 'h' || env[:agi_type] == 'Kill'
215
209
 
216
- call = Call.new event['Channel'], current_actor, env
210
+ call = Call.new event['Channel'], current_actor, ami_client, connection, env
217
211
  link call
218
212
  register_call call
219
213
  call.async.send_offer
@@ -3,10 +3,6 @@
3
3
  module Punchblock
4
4
  module Translator
5
5
  class DTMFRecognizer
6
- include Celluloid
7
-
8
- finalizer :finalize
9
-
10
6
  def initialize(responder, grammar, initial_timeout = nil, inter_digit_timeout = nil)
11
7
  @responder = responder
12
8
  self.grammar = grammar
@@ -45,6 +41,10 @@ module Punchblock
45
41
  @grammar.normalize_whitespace
46
42
  end
47
43
 
44
+ def after(*args, &block)
45
+ @responder.after *args, &block
46
+ end
47
+
48
48
  def initial_timeout=(other)
49
49
  raise OptionError, 'An initial timeout value that is negative (and not -1) is invalid.' if other < -1
50
50
  @initial_timeout = other
@@ -11,9 +11,10 @@ module Punchblock
11
11
  private
12
12
 
13
13
  def register_dtmf_event_handler
14
+ component = current_actor
14
15
  call.register_handler :es, :event_name => 'DTMF' do |event|
15
16
  safe_from_dead_actors do
16
- @recognizer << event[:dtmf_digit]
17
+ component.process_dtmf event[:dtmf_digit]
17
18
  end
18
19
  end
19
20
  end
@@ -6,8 +6,7 @@ module Punchblock
6
6
  def execute
7
7
  validate
8
8
 
9
- component = current_actor
10
- @recognizer = DTMFRecognizer.new current_actor,
9
+ @recognizer = DTMFRecognizer.new self,
11
10
  @component_node.grammar.value,
12
11
  (@component_node.initial_timeout || -1),
13
12
  (@component_node.inter_digit_timeout || -1)
@@ -54,6 +53,7 @@ module Punchblock
54
53
 
55
54
  def complete(reason)
56
55
  unregister_dtmf_event_handler
56
+ @recognizer.finalize if @recognizer
57
57
  send_complete_event reason
58
58
  end
59
59
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Punchblock
4
- VERSION = "1.8.2"
4
+ VERSION = "1.9.0"
5
5
  end
data/punchblock.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
30
30
  s.add_runtime_dependency %q<future-resource>, ["~> 1.0"]
31
31
  s.add_runtime_dependency %q<has-guarded-handlers>, ["~> 1.5"]
32
32
  s.add_runtime_dependency %q<celluloid>, ["~> 0.13"]
33
- s.add_runtime_dependency %q<ruby_ami>, ["~> 1.2", ">= 1.2.1"]
33
+ s.add_runtime_dependency %q<ruby_ami>, ["~> 2.0"]
34
34
  s.add_runtime_dependency %q<ruby_fs>, ["~> 1.0"]
35
35
  s.add_runtime_dependency %q<ruby_speech>, ["~> 1.0"]
36
36
 
@@ -25,7 +25,7 @@ module Punchblock
25
25
  subject.event_handler = mock_event_handler
26
26
  end
27
27
 
28
- its(:ami_client) { should be_a RubyAMI::Client }
28
+ its(:ami_client) { should be_a RubyAMI::Stream }
29
29
 
30
30
  it 'should set the connection on the translator' do
31
31
  subject.translator.connection.should be subject
@@ -36,15 +36,15 @@ module Punchblock
36
36
  end
37
37
 
38
38
  describe '#run' do
39
- it 'starts the RubyAMI::Client' do
40
- subject.ami_client.should_receive(:start).once
39
+ it 'starts the RubyAMI::Stream' do
40
+ subject.ami_client.should_receive(:run).once
41
41
  lambda { subject.run }.should raise_error DisconnectedError
42
42
  end
43
43
  end
44
44
 
45
45
  describe '#stop' do
46
- it 'stops the RubyAMI::Client' do
47
- subject.ami_client.should_receive(:stop).once
46
+ it 'stops the RubyAMI::Stream' do
47
+ subject.ami_client.should_receive(:terminate).once
48
48
  subject.stop
49
49
  end
50
50
 
@@ -55,9 +55,10 @@ module Punchblock
55
55
  end
56
56
 
57
57
  it 'sends events from RubyAMI to the translator' do
58
- event = mock 'RubyAMI::Event'
58
+ event = RubyAMI::Event.new 'FullyBooted'
59
59
  subject.translator.async.should_receive(:handle_ami_event).once.with event
60
- subject.ami_client.handle_event event
60
+ subject.translator.async.should_receive(:handle_ami_event).once.with RubyAMI::Stream::Disconnected.new
61
+ subject.ami_client.message_received event
61
62
  end
62
63
 
63
64
  describe '#write' do