punchblock 0.5.1 → 0.6.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 (64) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/LICENSE.txt +3 -1
  3. data/bin/punchblock-console +19 -1
  4. data/lib/punchblock.rb +11 -4
  5. data/lib/punchblock/command/reject.rb +6 -2
  6. data/lib/punchblock/component.rb +1 -0
  7. data/lib/punchblock/component/asterisk.rb +10 -0
  8. data/lib/punchblock/component/asterisk/agi.rb +11 -0
  9. data/lib/punchblock/component/asterisk/agi/command.rb +157 -0
  10. data/lib/punchblock/component/asterisk/ami.rb +12 -0
  11. data/lib/punchblock/component/asterisk/ami/action.rb +144 -0
  12. data/lib/punchblock/component/input.rb +2 -2
  13. data/lib/punchblock/connection.rb +1 -0
  14. data/lib/punchblock/connection/asterisk.rb +31 -0
  15. data/lib/punchblock/core_ext/celluloid.rb +11 -0
  16. data/lib/punchblock/event.rb +1 -1
  17. data/lib/punchblock/event/asterisk.rb +9 -0
  18. data/lib/punchblock/event/asterisk/ami.rb +11 -0
  19. data/lib/punchblock/event/asterisk/ami/event.rb +66 -0
  20. data/lib/punchblock/event/complete.rb +20 -0
  21. data/lib/punchblock/event/dtmf.rb +19 -0
  22. data/lib/punchblock/event/end.rb +23 -0
  23. data/lib/punchblock/event/offer.rb +23 -0
  24. data/lib/punchblock/header.rb +4 -44
  25. data/lib/punchblock/key_value_pair_node.rb +50 -0
  26. data/lib/punchblock/rayo_node.rb +1 -1
  27. data/lib/punchblock/ref.rb +6 -0
  28. data/lib/punchblock/translator.rb +7 -0
  29. data/lib/punchblock/translator/asterisk.rb +74 -0
  30. data/lib/punchblock/translator/asterisk/ami_action.rb +86 -0
  31. data/lib/punchblock/translator/asterisk/call.rb +25 -0
  32. data/lib/punchblock/translator/asterisk/component.rb +11 -0
  33. data/lib/punchblock/version.rb +1 -1
  34. data/punchblock.gemspec +3 -1
  35. data/spec/punchblock/command/accept_spec.rb +8 -0
  36. data/spec/punchblock/command/answer_spec.rb +8 -0
  37. data/spec/punchblock/command/dial_spec.rb +22 -2
  38. data/spec/punchblock/command/hangup_spec.rb +8 -0
  39. data/spec/punchblock/command/join_spec.rb +21 -0
  40. data/spec/punchblock/command/mute_spec.rb +8 -0
  41. data/spec/punchblock/command/redirect_spec.rb +21 -0
  42. data/spec/punchblock/command/reject_spec.rb +19 -8
  43. data/spec/punchblock/command/unjoin_spec.rb +17 -0
  44. data/spec/punchblock/command/unmute_spec.rb +8 -0
  45. data/spec/punchblock/component/asterisk/agi/command_spec.rb +102 -0
  46. data/spec/punchblock/component/asterisk/ami/action_spec.rb +118 -0
  47. data/spec/punchblock/component/input_spec.rb +40 -0
  48. data/spec/punchblock/component/output_spec.rb +28 -0
  49. data/spec/punchblock/component/record_spec.rb +27 -0
  50. data/spec/punchblock/connection/asterisk_spec.rb +69 -0
  51. data/spec/punchblock/event/asterisk/ami/event_spec.rb +60 -0
  52. data/spec/punchblock/event/complete_spec.rb +8 -0
  53. data/spec/punchblock/event/dtmf_spec.rb +8 -0
  54. data/spec/punchblock/event/end_spec.rb +8 -0
  55. data/spec/punchblock/event/offer_spec.rb +15 -2
  56. data/spec/punchblock/ref_spec.rb +6 -0
  57. data/spec/punchblock/translator/asterisk/ami_action_spec.rb +149 -0
  58. data/spec/punchblock/translator/asterisk/call_spec.rb +18 -0
  59. data/spec/punchblock/translator/asterisk/component_spec.rb +11 -0
  60. data/spec/punchblock/translator/asterisk_spec.rb +150 -0
  61. data/spec/spec_helper.rb +42 -0
  62. metadata +92 -42
  63. data/lib/punchblock/event/info.rb +0 -15
  64. data/spec/punchblock/event/info_spec.rb +0 -30
@@ -209,7 +209,7 @@ module Punchblock
209
209
  end
210
210
 
211
211
  def inspect_attributes # :nodoc:
212
- [:mode, :terminator, :max_digits, :recognizer, :initial_timeout, :inter_digit_timeout, :term_timeout, :complete_timeout, :incomplete_timeout, :sensitivity, :min_confidence, :choices] + super
212
+ [:mode, :terminator, :max_digits, :recognizer, :initial_timeout, :inter_digit_timeout, :term_timeout, :complete_timeout, :incomplete_timeout, :sensitivity, :min_confidence, :grammar] + super
213
213
  end
214
214
 
215
215
  class Grammar < RayoNode
@@ -316,5 +316,5 @@ module Punchblock
316
316
  end
317
317
  end # Complete
318
318
  end # Input
319
- end # Command
319
+ end # Component
320
320
  end # Punchblock
@@ -2,6 +2,7 @@ module Punchblock
2
2
  module Connection
3
3
  extend ActiveSupport::Autoload
4
4
 
5
+ autoload :Asterisk
5
6
  autoload :Connected
6
7
  autoload :XMPP
7
8
  end
@@ -0,0 +1,31 @@
1
+ require 'ruby_ami'
2
+
3
+ module Punchblock
4
+ module Connection
5
+ class Asterisk
6
+ attr_reader :ami_client, :translator
7
+ attr_accessor :event_handler
8
+
9
+ def initialize(options = {})
10
+ @ami_client = RubyAMI::Client.new options.merge(:event_handler => lambda { |event| translator.handle_ami_event! event })
11
+ @translator = Translator::Asterisk.new @ami_client, self
12
+ end
13
+
14
+ def run
15
+ ami_client.start
16
+ end
17
+
18
+ def stop
19
+ ami_client.stop
20
+ end
21
+
22
+ def write(command, options)
23
+ translator.execute_command! command, options
24
+ end
25
+
26
+ def handle_event(event)
27
+ event_handler.call event
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ module Celluloid
2
+ class Actor
3
+ attr_reader :subject
4
+ end
5
+
6
+ class ActorProxy
7
+ def actor_subject
8
+ @actor.subject
9
+ end
10
+ end
11
+ end
@@ -5,10 +5,10 @@ end
5
5
 
6
6
  %w{
7
7
  answered
8
+ asterisk
8
9
  complete
9
10
  dtmf
10
11
  end
11
- info
12
12
  joined
13
13
  offer
14
14
  ringing
@@ -0,0 +1,9 @@
1
+ module Punchblock
2
+ class Event
3
+ module Asterisk
4
+ extend ActiveSupport::Autoload
5
+
6
+ autoload :AMI
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Punchblock
2
+ class Event
3
+ module Asterisk
4
+ module AMI
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Event
8
+ end
9
+ end
10
+ end # Command
11
+ end # Punchblock
@@ -0,0 +1,66 @@
1
+ require 'punchblock/key_value_pair_node'
2
+
3
+ module Punchblock
4
+ class Event
5
+ module Asterisk
6
+ module AMI
7
+ class Event < Punchblock::Event
8
+ register :event, :ami
9
+
10
+ def self.new(options = {})
11
+ super().tap do |new_node|
12
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
13
+ end
14
+ end
15
+
16
+ def name
17
+ read_attr :name
18
+ end
19
+
20
+ def name=(other)
21
+ write_attr :name, other
22
+ end
23
+
24
+ ##
25
+ # @return [Hash] hash of key-value pairs of attributes
26
+ #
27
+ def attributes_hash
28
+ attributes.inject({}) do |hash, attribute|
29
+ hash[attribute.name] = attribute.value
30
+ hash
31
+ end
32
+ end
33
+
34
+ ##
35
+ # @return [Array[Attribute]] attributes
36
+ #
37
+ def attributes
38
+ find('//ns:attribute', :ns => self.class.registered_ns).map do |i|
39
+ Attribute.new i
40
+ end
41
+ end
42
+
43
+ ##
44
+ # @param [Hash, Array] attributes A hash of key-value attribute pairs, or an array of Attribute objects
45
+ #
46
+ def attributes=(attributes)
47
+ find('//ns:attribute', :ns => self.class.registered_ns).each &:remove
48
+ if attributes.is_a? Hash
49
+ attributes.each_pair { |k,v| self << Attribute.new(k, v) }
50
+ elsif attributes.is_a? Array
51
+ [attributes].flatten.each { |i| self << Attribute.new(i) }
52
+ end
53
+ end
54
+
55
+ def inspect_attributes # :nodoc:
56
+ [:name, :attributes_hash] + super
57
+ end
58
+
59
+ class Attribute < RayoNode
60
+ include KeyValuePairNode
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end # Command
66
+ end # Punchblock
@@ -17,6 +17,11 @@ module Punchblock
17
17
  end
18
18
  end
19
19
 
20
+ def reason=(other)
21
+ children.map &:remove
22
+ self << other
23
+ end
24
+
20
25
  def recording
21
26
  element = find_first('//ns:recording', :ns => RAYO_NAMESPACES[:record_complete])
22
27
  if element
@@ -32,6 +37,17 @@ module Punchblock
32
37
  end
33
38
 
34
39
  class Reason < RayoNode
40
+ def self.new(options = {})
41
+ super().tap do |new_node|
42
+ case options
43
+ when Nokogiri::XML::Node
44
+ new_node.inherit options
45
+ when Hash
46
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
47
+ end
48
+ end
49
+ end
50
+
35
51
  def name
36
52
  super.to_sym
37
53
  end
@@ -56,6 +72,10 @@ module Punchblock
56
72
  text.strip
57
73
  end
58
74
 
75
+ def details=(other)
76
+ self << other
77
+ end
78
+
59
79
  def inspect_attributes # :nodoc:
60
80
  [:details] + super
61
81
  end
@@ -3,6 +3,25 @@ module Punchblock
3
3
  class DTMF < Event
4
4
  register :dtmf, :core
5
5
 
6
+ ##
7
+ # Create a DTMF event
8
+ #
9
+ # @param [Hash] options
10
+ # @option options [String, Optional] :signal the DTMF signal received
11
+ #
12
+ # @return [Event::DTMF] a formatted Rayo DTMF event
13
+ #
14
+ def self.new(options = {})
15
+ super().tap do |new_node|
16
+ case options
17
+ when Nokogiri::XML::Node
18
+ new_node.inherit options
19
+ when Hash
20
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
21
+ end
22
+ end
23
+ end
24
+
6
25
  def signal
7
26
  read_attr :signal
8
27
  end
@@ -3,10 +3,33 @@ module Punchblock
3
3
  class End < Event
4
4
  register :end, :core
5
5
 
6
+ ##
7
+ # Create an End event
8
+ #
9
+ # @param [Hash] options
10
+ # @option options [String, Optional] :reason the end reason
11
+ #
12
+ # @return [Event::End] a formatted Rayo end event
13
+ #
14
+ def self.new(options = {})
15
+ super().tap do |new_node|
16
+ case options
17
+ when Nokogiri::XML::Node
18
+ new_node.inherit options
19
+ when Hash
20
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
21
+ end
22
+ end
23
+ end
24
+
6
25
  def reason
7
26
  children.select { |c| c.is_a? Nokogiri::XML::Element }.first.name.to_sym
8
27
  end
9
28
 
29
+ def reason=(other)
30
+ self << Nokogiri::XML::Element.new(other.to_s, self.document)
31
+ end
32
+
10
33
  def inspect_attributes # :nodoc:
11
34
  [:reason] + super
12
35
  end
@@ -5,6 +5,29 @@ module Punchblock
5
5
 
6
6
  include HasHeaders
7
7
 
8
+ ##
9
+ # Create an Offer event
10
+ #
11
+ # @param [Hash] options
12
+ # @option options [String, Optional] :to the call targed
13
+ # @option options [String, Optional] :from the caller ID
14
+ # @option options [Array[Header], Hash, Optional] :headers SIP headers to attach to
15
+ # the call. Can be either a hash of key-value pairs, or an array of
16
+ # Header objects.
17
+ #
18
+ # @return [Event::Offer] a formatted Rayo offer event
19
+ #
20
+ def self.new(options = {})
21
+ super().tap do |new_node|
22
+ case options
23
+ when Nokogiri::XML::Node
24
+ new_node.inherit options
25
+ when Hash
26
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
27
+ end
28
+ end
29
+ end
30
+
8
31
  def to
9
32
  read_attr :to
10
33
  end
@@ -1,47 +1,7 @@
1
+ require 'punchblock/key_value_pair_node'
2
+
1
3
  module Punchblock
2
4
  class Header < RayoNode
3
- ##
4
- # @param [String] name
5
- # @param [String] value
6
- #
7
- def self.new(name, value = '')
8
- super(:header).tap do |new_node|
9
- case name
10
- when Nokogiri::XML::Node
11
- new_node.inherit name
12
- else
13
- new_node.name = name
14
- new_node.value = value
15
- end
16
- end
17
- end
18
-
19
- # The Header's name
20
- # @return [Symbol]
21
- def name
22
- read_attr(:name).gsub('-', '_').to_sym
23
- end
24
-
25
- # Set the Header's name
26
- # @param [Symbol] name the new name for the header
27
- def name=(name)
28
- write_attr :name, name.to_s.gsub('_', '-')
29
- end
30
-
31
- # The Header's value
32
- # @return [String]
33
- def value
34
- read_attr :value
35
- end
36
-
37
- # Set the Header's value
38
- # @param [String] value the new value for the header
39
- def value=(value)
40
- write_attr :value, value
41
- end
42
-
43
- def inspect_attributes # :nodoc:
44
- [:name, :value] + super
45
- end
46
- end
5
+ include KeyValuePairNode
6
+ end # Header
47
7
  end # Punchblock
@@ -0,0 +1,50 @@
1
+ module KeyValuePairNode
2
+ def self.included(klass)
3
+ klass.class_exec do
4
+ ##
5
+ # @param [String] name
6
+ # @param [String] value
7
+ #
8
+ def self.new(name, value = '')
9
+ super(self.name.split('::').last.downcase.to_sym).tap do |new_node|
10
+ case name
11
+ when Nokogiri::XML::Node
12
+ new_node.inherit name
13
+ else
14
+ new_node.name = name
15
+ new_node.value = value
16
+ end
17
+ new_node.name = new_node.name.downcase
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # The Header's name
24
+ # @return [Symbol]
25
+ def name
26
+ read_attr(:name).gsub('-', '_').to_sym
27
+ end
28
+
29
+ # Set the Header's name
30
+ # @param [Symbol] name the new name for the param
31
+ def name=(name)
32
+ write_attr :name, name.to_s.gsub('_', '-')
33
+ end
34
+
35
+ # The Header's value
36
+ # @return [String]
37
+ def value
38
+ read_attr :value
39
+ end
40
+
41
+ # Set the Header's value
42
+ # @param [String] value the new value for the param
43
+ def value=(value)
44
+ write_attr :value, value
45
+ end
46
+
47
+ def inspect_attributes # :nodoc:
48
+ [:name, :value] + super
49
+ end
50
+ end
@@ -67,7 +67,7 @@ module Punchblock
67
67
  end
68
68
 
69
69
  def inspect
70
- "#<#{self.class} #{inspect_attributes.map { |c| "#{c}=#{self.__send__(c).inspect}" rescue nil }.compact * ', '}>"
70
+ "#<#{self.class} #{inspect_attributes.map { |c| "#{c}=#{self.__send__(c).inspect rescue nil}" }.compact * ', '}>"
71
71
  end
72
72
 
73
73
  def eql?(o, *fields)
@@ -5,6 +5,12 @@ module Punchblock
5
5
  class Ref < RayoNode
6
6
  register :ref, :core
7
7
 
8
+ def self.new(options = {})
9
+ super().tap do |new_node|
10
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
11
+ end
12
+ end
13
+
8
14
  ##
9
15
  # @return [String] the command ID
10
16
  #
@@ -0,0 +1,7 @@
1
+ module Punchblock
2
+ module Translator
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Asterisk
6
+ end
7
+ end