punchblock 1.9.4 → 2.0.0.beta1

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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -2
  4. data/CHANGELOG.md +17 -0
  5. data/Gemfile +1 -0
  6. data/Guardfile +4 -0
  7. data/README.markdown +6 -0
  8. data/Rakefile +16 -0
  9. data/benchmarks/ami_event_name_comparison.rb +14 -0
  10. data/benchmarks/channel.rb +27 -0
  11. data/lib/punchblock/client.rb +2 -6
  12. data/lib/punchblock/command/accept.rb +3 -24
  13. data/lib/punchblock/command/answer.rb +3 -24
  14. data/lib/punchblock/command/dial.rb +24 -76
  15. data/lib/punchblock/command/hangup.rb +3 -19
  16. data/lib/punchblock/command/join.rb +21 -70
  17. data/lib/punchblock/command/mute.rb +3 -3
  18. data/lib/punchblock/command/redirect.rb +6 -39
  19. data/lib/punchblock/command/reject.rb +14 -54
  20. data/lib/punchblock/command/unjoin.rb +8 -40
  21. data/lib/punchblock/command/unmute.rb +3 -3
  22. data/lib/punchblock/command_node.rb +0 -17
  23. data/lib/punchblock/component/asterisk/agi/command.rb +20 -127
  24. data/lib/punchblock/component/asterisk/ami/action.rb +30 -117
  25. data/lib/punchblock/component/component_node.rb +1 -1
  26. data/lib/punchblock/component/input.rb +89 -268
  27. data/lib/punchblock/component/output.rb +106 -154
  28. data/lib/punchblock/component/prompt.rb +51 -0
  29. data/lib/punchblock/component/record.rb +41 -130
  30. data/lib/punchblock/component.rb +1 -0
  31. data/lib/punchblock/connection/asterisk.rb +31 -4
  32. data/lib/punchblock/connection/xmpp.rb +6 -14
  33. data/lib/punchblock/core_ext/blather/stanza.rb +1 -1
  34. data/lib/punchblock/event/active_speaker.rb +2 -10
  35. data/lib/punchblock/event/answered.rb +3 -3
  36. data/lib/punchblock/event/asterisk/ami/event.rb +15 -47
  37. data/lib/punchblock/event/complete.rb +26 -48
  38. data/lib/punchblock/event/dtmf.rb +3 -13
  39. data/lib/punchblock/event/end.rb +10 -11
  40. data/lib/punchblock/event/joined.rb +5 -25
  41. data/lib/punchblock/event/offer.rb +4 -25
  42. data/lib/punchblock/event/ringing.rb +3 -3
  43. data/lib/punchblock/event/unjoined.rb +5 -25
  44. data/lib/punchblock/event.rb +0 -10
  45. data/lib/punchblock/has_headers.rb +20 -26
  46. data/lib/punchblock/rayo_node.rb +46 -23
  47. data/lib/punchblock/ref.rb +39 -18
  48. data/lib/punchblock/translator/asterisk/agi_app.rb +15 -0
  49. data/lib/punchblock/translator/asterisk/agi_command.rb +3 -1
  50. data/lib/punchblock/translator/asterisk/ami_error_converter.rb +20 -0
  51. data/lib/punchblock/translator/asterisk/call.rb +60 -39
  52. data/lib/punchblock/translator/asterisk/channel.rb +41 -0
  53. data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +4 -1
  54. data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +4 -4
  55. data/lib/punchblock/translator/asterisk/component/composed_prompt.rb +62 -0
  56. data/lib/punchblock/translator/asterisk/component/input.rb +1 -0
  57. data/lib/punchblock/translator/asterisk/component/mrcp_native_prompt.rb +56 -0
  58. data/lib/punchblock/translator/asterisk/component/mrcp_prompt.rb +53 -0
  59. data/lib/punchblock/translator/asterisk/component/mrcp_recog_prompt.rb +99 -0
  60. data/lib/punchblock/translator/asterisk/component/output.rb +30 -22
  61. data/lib/punchblock/translator/asterisk/component/record.rb +8 -6
  62. data/lib/punchblock/translator/asterisk/component.rb +6 -5
  63. data/lib/punchblock/translator/asterisk/unimrcp_app.rb +26 -0
  64. data/lib/punchblock/translator/asterisk.rb +24 -28
  65. data/lib/punchblock/translator/dtmf_recognizer.rb +39 -20
  66. data/lib/punchblock/translator/freeswitch/call.rb +15 -14
  67. data/lib/punchblock/translator/freeswitch/component/abstract_output.rb +5 -4
  68. data/lib/punchblock/translator/freeswitch/component/flite_output.rb +1 -1
  69. data/lib/punchblock/translator/freeswitch/component/input.rb +5 -0
  70. data/lib/punchblock/translator/freeswitch/component/output.rb +2 -2
  71. data/lib/punchblock/translator/freeswitch/component/record.rb +19 -13
  72. data/lib/punchblock/translator/freeswitch/component/tts_output.rb +2 -2
  73. data/lib/punchblock/translator/freeswitch/component.rb +2 -5
  74. data/lib/punchblock/translator/freeswitch.rb +2 -2
  75. data/lib/punchblock/translator/input_component.rb +33 -13
  76. data/lib/punchblock/uri_list.rb +21 -0
  77. data/lib/punchblock/version.rb +1 -1
  78. data/lib/punchblock.rb +4 -3
  79. data/punchblock.gemspec +7 -3
  80. data/spec/punchblock/client/component_registry_spec.rb +1 -1
  81. data/spec/punchblock/client_spec.rb +10 -26
  82. data/spec/punchblock/command/accept_spec.rb +41 -7
  83. data/spec/punchblock/command/answer_spec.rb +51 -7
  84. data/spec/punchblock/command/dial_spec.rb +56 -14
  85. data/spec/punchblock/command/hangup_spec.rb +41 -7
  86. data/spec/punchblock/command/join_spec.rb +53 -11
  87. data/spec/punchblock/command/mute_spec.rb +19 -4
  88. data/spec/punchblock/command/redirect_spec.rb +40 -10
  89. data/spec/punchblock/command/reject_spec.rb +43 -11
  90. data/spec/punchblock/command/unjoin_spec.rb +40 -9
  91. data/spec/punchblock/command/unmute_spec.rb +19 -4
  92. data/spec/punchblock/command_node_spec.rb +0 -4
  93. data/spec/punchblock/component/asterisk/agi/command_spec.rb +16 -39
  94. data/spec/punchblock/component/asterisk/ami/action_spec.rb +50 -53
  95. data/spec/punchblock/component/component_node_spec.rb +3 -5
  96. data/spec/punchblock/component/input_spec.rb +194 -61
  97. data/spec/punchblock/component/output_spec.rb +194 -62
  98. data/spec/punchblock/component/prompt_spec.rb +132 -0
  99. data/spec/punchblock/component/record_spec.rb +70 -32
  100. data/spec/punchblock/connection/asterisk_spec.rb +17 -3
  101. data/spec/punchblock/connection/freeswitch_spec.rb +4 -4
  102. data/spec/punchblock/connection/xmpp_spec.rb +20 -38
  103. data/spec/punchblock/event/answered_spec.rb +12 -10
  104. data/spec/punchblock/event/asterisk/ami/event_spec.rb +27 -22
  105. data/spec/punchblock/event/complete_spec.rb +15 -19
  106. data/spec/punchblock/event/dtmf_spec.rb +5 -6
  107. data/spec/punchblock/event/end_spec.rb +20 -10
  108. data/spec/punchblock/event/joined_spec.rb +8 -7
  109. data/spec/punchblock/event/offer_spec.rb +41 -12
  110. data/spec/punchblock/event/ringing_spec.rb +12 -10
  111. data/spec/punchblock/event/started_speaking_spec.rb +5 -6
  112. data/spec/punchblock/event/stopped_speaking_spec.rb +5 -6
  113. data/spec/punchblock/event/unjoined_spec.rb +7 -7
  114. data/spec/punchblock/ref_spec.rb +86 -9
  115. data/spec/punchblock/translator/asterisk/call_spec.rb +317 -154
  116. data/spec/punchblock/translator/asterisk/component/asterisk/agi_command_spec.rb +28 -5
  117. data/spec/punchblock/translator/asterisk/component/asterisk/ami_action_spec.rb +15 -13
  118. data/spec/punchblock/translator/asterisk/component/composed_prompt_spec.rb +237 -0
  119. data/spec/punchblock/translator/asterisk/component/input_spec.rb +171 -14
  120. data/spec/punchblock/translator/asterisk/component/mrcp_native_prompt_spec.rb +652 -0
  121. data/spec/punchblock/translator/asterisk/component/mrcp_prompt_spec.rb +646 -0
  122. data/spec/punchblock/translator/asterisk/component/output_spec.rb +127 -77
  123. data/spec/punchblock/translator/asterisk/component/record_spec.rb +17 -8
  124. data/spec/punchblock/translator/asterisk/component/stop_by_redirect_spec.rb +2 -2
  125. data/spec/punchblock/translator/asterisk/component_spec.rb +3 -7
  126. data/spec/punchblock/translator/asterisk_spec.rb +20 -24
  127. data/spec/punchblock/translator/freeswitch/call_spec.rb +103 -99
  128. data/spec/punchblock/translator/freeswitch/component/flite_output_spec.rb +17 -8
  129. data/spec/punchblock/translator/freeswitch/component/input_spec.rb +26 -14
  130. data/spec/punchblock/translator/freeswitch/component/output_spec.rb +30 -52
  131. data/spec/punchblock/translator/freeswitch/component/record_spec.rb +23 -19
  132. data/spec/punchblock/translator/freeswitch/component/tts_output_spec.rb +18 -8
  133. data/spec/punchblock/translator/freeswitch/component_spec.rb +4 -8
  134. data/spec/punchblock/translator/freeswitch_spec.rb +11 -14
  135. data/spec/punchblock/uri_list_spec.rb +49 -0
  136. data/spec/punchblock_spec.rb +11 -1
  137. data/spec/spec_helper.rb +7 -11
  138. data/spec/support/mock_connection_with_event_handler.rb +1 -1
  139. metadata +104 -24
  140. data/lib/punchblock/header.rb +0 -9
  141. data/lib/punchblock/key_value_pair_node.rb +0 -51
  142. data/spec/punchblock/header_spec.rb +0 -11
@@ -5,48 +5,16 @@ module Punchblock
5
5
  class Unjoin < CommandNode
6
6
  register :unjoin, :core
7
7
 
8
- ##
9
- # Create an ujoin command
10
- #
11
- # @param [Hash] options
12
- # @option options [String, Optional] :call_id the call ID to unjoin
13
- # @option options [String, Optional] :mixer_name the mixer name to unjoin
14
- #
15
- # @return [Command::Unjoin] a formatted Rayo unjoin command
16
- #
17
- def self.new(options = {})
18
- super().tap do |new_node|
19
- options.each_pair { |k,v| new_node.send :"#{k}=", v }
20
- end
21
- end
22
-
23
- ##
24
8
  # @return [String] the call ID to unjoin
25
- def call_id
26
- read_attr :'call-id'
27
- end
28
-
29
- ##
30
- # @param [String] other the call ID to unjoin
31
- def call_id=(other)
32
- write_attr :'call-id', other
33
- end
9
+ attribute :call_uri
10
+ alias :call_id= :call_uri=
34
11
 
35
- ##
36
12
  # @return [String] the mixer name to unjoin
37
- def mixer_name
38
- read_attr :'mixer-name'
39
- end
40
-
41
- ##
42
- # @param [String] other the mixer name to unjoin
43
- def mixer_name=(other)
44
- write_attr :'mixer-name', other
45
- end
13
+ attribute :mixer_name
46
14
 
47
- def inspect_attributes # :nodoc:
48
- [:call_id, :mixer_name] + super
15
+ def rayo_attributes
16
+ {'call-uri' => call_uri, 'mixer-name' => mixer_name}
49
17
  end
50
- end # Unjoin
51
- end # Command
52
- end # Punchblock
18
+ end
19
+ end
20
+ end
@@ -4,6 +4,6 @@ module Punchblock
4
4
  module Command
5
5
  class Unmute < CommandNode
6
6
  register :unmute, :core
7
- end # Mute
8
- end # Command
9
- end # Punchblock
7
+ end
8
+ end
9
+ end
@@ -1,16 +1,8 @@
1
1
  # encoding: utf-8
2
-
3
2
  require 'state_machine'
4
3
 
5
4
  module Punchblock
6
5
  class CommandNode < RayoNode
7
- def self.new(options = {})
8
- super().tap do |new_node|
9
- new_node.target_call_id = options[:target_call_id]
10
- new_node.target_mixer_name = options[:target_mixer_name]
11
- new_node.component_id = options[:component_id]
12
- end
13
- end
14
6
 
15
7
  def initialize(*args)
16
8
  super
@@ -31,11 +23,6 @@ module Punchblock
31
23
  end
32
24
  end
33
25
 
34
- def write_attr(*args)
35
- raise StandardError, "Cannot alter attributes of a requested command" unless new?
36
- super
37
- end
38
-
39
26
  def response(timeout = nil)
40
27
  @response.resource timeout
41
28
  end
@@ -45,9 +32,5 @@ module Punchblock
45
32
  @response.resource = other
46
33
  execute!
47
34
  end
48
-
49
- def inspect_attributes
50
- super + [:state_name]
51
- end
52
35
  end # CommandNode
53
36
  end # Punchblock
@@ -7,142 +7,35 @@ module Punchblock
7
7
  class Command < ComponentNode
8
8
  register :command, :agi
9
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 [Array[String]] array of values of params
26
- #
27
- def params_array
28
- params.map(&:value)
29
- end
30
-
31
- ##
32
- # @return [Array[Param]] params
33
- #
34
- def params
35
- find('//ns:param', :ns => self.class.registered_ns).map do |i|
36
- Param.new i
37
- end
38
- end
39
-
40
- ##
41
- # @param [Hash, Array] params A hash of key-value param pairs, or an array of Param objects
42
- #
43
- def params=(params)
44
- find('//ns:param', :ns => self.class.registered_ns).each(&:remove)
45
- [params].flatten.each { |i| self << Param.new(i) } if params.is_a? Array
46
- end
47
-
48
- def inspect_attributes # :nodoc:
49
- [:name, :params_array] + super
50
- end
51
-
52
- class Param < RayoNode
53
- ##
54
- # @param [String] name
55
- # @param [String] value
56
- #
57
- def self.new(value)
58
- super(:param).tap do |new_node|
59
- case value
60
- when Nokogiri::XML::Node
61
- new_node.inherit value
62
- else
63
- new_node.value = value
64
- end
65
- end
66
- end
67
-
68
- # The Header's value
69
- # @return [String]
70
- def value
71
- read_attr :value
72
- end
73
-
74
- # Set the Header's value
75
- # @param [String] value the new value for the param
76
- def value=(value)
77
- write_attr :value, value
78
- end
10
+ attribute :name
11
+ attribute :params, Array, default: []
79
12
 
80
- def inspect_attributes # :nodoc:
81
- [:value] + super
13
+ def inherit(xml_node)
14
+ xml_node.xpath('//ns:param', ns: self.class.registered_ns).to_a.each do |param|
15
+ params << param[:value]
82
16
  end
17
+ super
83
18
  end
84
19
 
85
20
  class Complete
86
21
  class Success < Event::Complete::Reason
87
22
  register :success, :agi_complete
88
23
 
89
- def node_with_name(name)
90
- n = if self.class.registered_ns
91
- find_first "ns:#{name}", :ns => self.class.registered_ns
92
- else
93
- find_first name
94
- end
24
+ attribute :code, Integer
25
+ attribute :result, Integer
26
+ attribute :data
95
27
 
96
- unless n
97
- self << (n = RayoNode.new(name, self.document))
98
- n.namespace = self.class.registered_ns
28
+ def inherit(xml_node)
29
+ [:code, :result, :data].each do |attr|
30
+ node = xml_node.at_xpath "ns:#{attr}", ns: self.class.registered_ns
31
+ self.send "#{attr}=", node.text if node
99
32
  end
100
- n
101
- end
102
-
103
- def code_node
104
- node_with_name 'code'
105
- end
106
-
107
- def result_node
108
- node_with_name 'result'
109
- end
110
-
111
- def data_node
112
- node_with_name 'data'
113
- end
114
-
115
- def code
116
- code_node.text.to_i
117
- end
118
-
119
- def code=(other)
120
- code_node.content = other
121
- end
122
-
123
- def result
124
- result_node.text.to_i
125
- end
126
-
127
- def result=(other)
128
- result_node.content = other
129
- end
130
-
131
- def data
132
- data_node.text
133
- end
134
-
135
- def data=(other)
136
- data_node.content = other
137
- end
138
-
139
- def inspect_attributes
140
- [:code, :result, :data]
33
+ super
141
34
  end
142
35
  end
143
- end # Complete
144
- end # Command
145
- end # AGI
146
- end # Asterisk
147
- end # Component
148
- end # Punchblock
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,7 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'punchblock/key_value_pair_node'
4
-
5
3
  module Punchblock
6
4
  module Component
7
5
  module Asterisk
@@ -9,138 +7,53 @@ module Punchblock
9
7
  class Action < ComponentNode
10
8
  register :action, :ami
11
9
 
12
- def self.new(options = {})
13
- super().tap do |new_node|
14
- options.each_pair { |k,v| new_node.send :"#{k}=", v }
15
- end
16
- end
17
-
18
- def name
19
- read_attr :name
20
- end
21
-
22
- def name=(other)
23
- write_attr :name, other
24
- end
10
+ attribute :name
11
+ attribute :params, Hash, default: {}
25
12
 
26
- ##
27
- # @return [Hash] hash of key-value pairs of params
28
- #
29
- def params_hash
30
- params.inject({}) do |hash, param|
31
- hash[param.name.downcase.gsub('-', '_').to_sym] = param.value
32
- hash
13
+ def inherit(xml_node)
14
+ xml_node.xpath('//ns:param', ns: self.class.registered_ns).to_a.each do |param|
15
+ params[param[:name]] = param[:value]
33
16
  end
17
+ super
34
18
  end
35
19
 
36
- ##
37
- # @return [Array[Param]] params
38
- #
39
- def params
40
- find('//ns:param', :ns => self.class.registered_ns).map do |i|
41
- Param.new i
42
- end
20
+ def rayo_attributes
21
+ {'name' => name}
43
22
  end
44
23
 
45
- ##
46
- # @param [Hash, Array] params A hash of key-value param pairs, or an array of Param objects
47
- #
48
- def params=(params)
49
- find('//ns:param', :ns => self.class.registered_ns).each(&:remove)
50
- if params.is_a? Hash
51
- params.each_pair { |k,v| self << Param.new(k, v) }
52
- elsif params.is_a? Array
53
- [params].flatten.each { |i| self << Param.new(i) }
24
+ def rayo_children(root)
25
+ super
26
+ params.each do |name, value|
27
+ root.param name: name, value: value
54
28
  end
55
29
  end
56
30
 
57
- def inspect_attributes # :nodoc:
58
- [:name, :params] + super
59
- end
60
-
61
- class Param < RayoNode
62
- include KeyValuePairNode
63
- end
64
-
65
31
  class Complete
66
32
  class Success < Event::Complete::Reason
67
33
  register :success, :ami_complete
68
34
 
69
- def self.new(options = {})
70
- super().tap do |new_node|
71
- case options
72
- when Nokogiri::XML::Node
73
- new_node.inherit options
74
- else
75
- options.each_pair { |k,v| new_node.send :"#{k}=", v }
76
- end
77
- end
78
- end
35
+ attribute :message
36
+ attribute :text_body
37
+ attribute :headers, Hash, default: {}
79
38
 
80
- def message_node
81
- mn = if self.class.registered_ns
82
- find_first 'ns:message', :ns => self.class.registered_ns
83
- else
84
- find_first 'message'
85
- end
39
+ alias :attributes :headers
86
40
 
87
- unless mn
88
- self << (mn = RayoNode.new('message', self.document))
89
- mn.namespace = self.class.registered_ns
90
- end
91
- mn
92
- end
93
-
94
- def message
95
- message_node.text
96
- end
97
-
98
- def message=(other)
99
- message_node.content = other
100
- end
41
+ def inherit(xml_node)
42
+ message_node = xml_node.at_xpath 'ns:message', ns: self.class.registered_ns
43
+ self.message = message_node.text if message_node
101
44
 
102
- ##
103
- # @return [Hash] hash of key-value pairs of attributes
104
- #
105
- def attributes_hash
106
- attributes.inject({}) do |hash, attribute|
107
- hash[attribute.name.downcase.gsub('-', '_').to_sym] = attribute.value
108
- hash
109
- end
110
- end
45
+ text_body_node = xml_node.at_xpath 'ns:text-body', ns: self.class.registered_ns
46
+ self.text_body = text_body_node.text if text_body_node
111
47
 
112
- ##
113
- # @return [Array[Attribute]] attributes
114
- #
115
- def attributes
116
- find('//ns:attribute', :ns => self.class.registered_ns).map do |i|
117
- Attribute.new i
48
+ xml_node.xpath('//ns:attribute', ns: self.class.registered_ns).to_a.each do |attribute|
49
+ headers[attribute[:name]] = attribute[:value]
118
50
  end
119
- end
120
-
121
- ##
122
- # @param [Hash, Array] attributes A hash of key-value attribute pairs, or an array of Attribute objects
123
- #
124
- def attributes=(attributes)
125
- find('//ns:attribute', :ns => self.class.registered_ns).each(&:remove)
126
- if attributes.is_a? Hash
127
- attributes.each_pair { |k,v| self << Attribute.new(k, v) }
128
- elsif attributes.is_a? Array
129
- [attributes].flatten.each { |i| self << Attribute.new(i) }
130
- end
131
- end
132
-
133
- def inspect_attributes
134
- [:message, :attributes_hash]
51
+ super
135
52
  end
136
53
  end
137
-
138
- class Attribute < RayoNode
139
- include KeyValuePairNode
140
- end
141
- end # Complete
142
- end # Action
143
- end # AMI
144
- end # Asterisk
145
- end # Component
146
- end # Punchblock
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -37,7 +37,7 @@ module Punchblock
37
37
 
38
38
  def response=(other)
39
39
  if other.is_a?(Ref)
40
- @component_id = other.id
40
+ @component_id = other.component_id
41
41
  client.register_component self if client
42
42
  end
43
43
  super