punchblock 1.9.4 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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