adhearsion 2.6.4 → 3.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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -9
  3. data/CHANGELOG.md +22 -7
  4. data/Gemfile +2 -0
  5. data/README.markdown +4 -5
  6. data/Rakefile +1 -2
  7. data/adhearsion.gemspec +19 -8
  8. data/features/cli_create.feature +19 -3
  9. data/features/step_definitions/cli_steps.rb +0 -11
  10. data/features/support/env.rb +3 -4
  11. data/lib/adhearsion.rb +48 -27
  12. data/lib/adhearsion/call.rb +34 -50
  13. data/lib/adhearsion/call_controller.rb +6 -12
  14. data/lib/adhearsion/call_controller/dial.rb +15 -53
  15. data/lib/adhearsion/call_controller/input.rb +39 -162
  16. data/lib/adhearsion/call_controller/input/ask_grammar_builder.rb +44 -0
  17. data/lib/adhearsion/call_controller/input/menu_builder.rb +136 -0
  18. data/lib/adhearsion/call_controller/input/prompt_builder.rb +78 -0
  19. data/lib/adhearsion/call_controller/input/result.rb +46 -0
  20. data/lib/adhearsion/call_controller/output.rb +48 -67
  21. data/lib/adhearsion/call_controller/output/abstract_player.rb +3 -3
  22. data/lib/adhearsion/call_controller/output/async_player.rb +3 -3
  23. data/lib/adhearsion/call_controller/output/player.rb +1 -1
  24. data/lib/adhearsion/call_controller/record.rb +23 -8
  25. data/lib/adhearsion/calls.rb +1 -1
  26. data/lib/adhearsion/cli_commands/ahn_command.rb +2 -65
  27. data/lib/adhearsion/cli_commands/thor_errors.rb +0 -6
  28. data/lib/adhearsion/configuration.rb +91 -39
  29. data/lib/adhearsion/core_ext/blather/stanza.rb +41 -0
  30. data/lib/adhearsion/core_ext/blather/stanza/presence.rb +13 -0
  31. data/lib/adhearsion/error.rb +5 -0
  32. data/lib/adhearsion/event.rb +21 -0
  33. data/lib/adhearsion/event/active_speaker.rb +11 -0
  34. data/lib/adhearsion/event/answered.rb +11 -0
  35. data/lib/adhearsion/event/asterisk.rb +10 -0
  36. data/lib/adhearsion/event/asterisk/ami.rb +34 -0
  37. data/lib/adhearsion/event/complete.rb +75 -0
  38. data/lib/adhearsion/event/dtmf.rb +11 -0
  39. data/lib/adhearsion/event/end.rb +22 -0
  40. data/lib/adhearsion/event/input_timers_started.rb +9 -0
  41. data/lib/adhearsion/event/joined.rb +17 -0
  42. data/lib/adhearsion/event/offer.rb +14 -0
  43. data/lib/adhearsion/event/ringing.rb +11 -0
  44. data/lib/adhearsion/event/started_speaking.rb +13 -0
  45. data/lib/adhearsion/event/stopped_speaking.rb +13 -0
  46. data/lib/adhearsion/event/unjoined.rb +17 -0
  47. data/lib/adhearsion/events.rb +47 -66
  48. data/lib/adhearsion/foundation.rb +0 -1
  49. data/lib/adhearsion/foundation/object.rb +0 -5
  50. data/lib/adhearsion/generators/app/app_generator.rb +4 -1
  51. data/lib/adhearsion/generators/app/templates/Gemfile.erb +2 -10
  52. data/lib/adhearsion/generators/app/templates/adhearsion.erb +9 -9
  53. data/lib/adhearsion/generators/app/templates/config.ru +7 -0
  54. data/lib/adhearsion/generators/app/templates/en.yml +4 -0
  55. data/lib/adhearsion/generators/app/templates/events.erb +2 -2
  56. data/lib/adhearsion/generators/app/templates/hello_world.wav +0 -0
  57. data/lib/adhearsion/generators/app/templates/simon_game.rb +2 -1
  58. data/lib/adhearsion/generators/app/templates/simon_game_spec.rb +2 -2
  59. data/lib/adhearsion/has_headers.rb +34 -0
  60. data/lib/adhearsion/http_server.rb +37 -0
  61. data/lib/adhearsion/initializer.rb +19 -153
  62. data/lib/adhearsion/logging.rb +6 -25
  63. data/lib/adhearsion/outbound_call.rb +5 -5
  64. data/lib/adhearsion/plugin.rb +1 -0
  65. data/lib/adhearsion/protocol_error.rb +26 -0
  66. data/lib/adhearsion/rayo.rb +30 -0
  67. data/lib/adhearsion/rayo/client.rb +62 -0
  68. data/lib/adhearsion/rayo/client/component_registry.rb +33 -0
  69. data/lib/adhearsion/rayo/command.rb +21 -0
  70. data/lib/adhearsion/rayo/command/accept.rb +16 -0
  71. data/lib/adhearsion/rayo/command/answer.rb +16 -0
  72. data/lib/adhearsion/rayo/command/dial.rb +57 -0
  73. data/lib/adhearsion/rayo/command/hangup.rb +16 -0
  74. data/lib/adhearsion/rayo/command/join.rb +43 -0
  75. data/lib/adhearsion/rayo/command/mute.rb +13 -0
  76. data/lib/adhearsion/rayo/command/redirect.rb +23 -0
  77. data/lib/adhearsion/rayo/command/reject.rb +40 -0
  78. data/lib/adhearsion/rayo/command/unjoin.rb +24 -0
  79. data/lib/adhearsion/rayo/command/unmute.rb +13 -0
  80. data/lib/adhearsion/rayo/command_node.rb +47 -0
  81. data/lib/adhearsion/rayo/component.rb +21 -0
  82. data/lib/adhearsion/rayo/component/asterisk.rb +13 -0
  83. data/lib/adhearsion/rayo/component/asterisk/agi.rb +14 -0
  84. data/lib/adhearsion/rayo/component/asterisk/agi/command.rb +46 -0
  85. data/lib/adhearsion/rayo/component/asterisk/ami.rb +14 -0
  86. data/lib/adhearsion/rayo/component/asterisk/ami/action.rb +61 -0
  87. data/lib/adhearsion/rayo/component/component_node.rb +90 -0
  88. data/lib/adhearsion/rayo/component/input.rb +186 -0
  89. data/lib/adhearsion/rayo/component/output.rb +471 -0
  90. data/lib/adhearsion/rayo/component/prompt.rb +53 -0
  91. data/lib/adhearsion/rayo/component/receive_fax.rb +26 -0
  92. data/lib/adhearsion/rayo/component/record.rb +165 -0
  93. data/lib/adhearsion/rayo/component/send_fax.rb +64 -0
  94. data/lib/adhearsion/rayo/component/stop.rb +11 -0
  95. data/lib/adhearsion/rayo/connection.rb +12 -0
  96. data/lib/adhearsion/rayo/connection/asterisk.rb +74 -0
  97. data/lib/adhearsion/rayo/connection/connected.rb +22 -0
  98. data/lib/adhearsion/rayo/connection/generic_connection.rb +22 -0
  99. data/lib/adhearsion/rayo/connection/xmpp.rb +198 -0
  100. data/lib/adhearsion/rayo/disconnected_error.rb +22 -0
  101. data/lib/adhearsion/{punchblock_plugin → rayo}/initializer.rb +19 -19
  102. data/lib/adhearsion/rayo/rayo_node.rb +127 -0
  103. data/lib/adhearsion/rayo/ref.rb +57 -0
  104. data/lib/adhearsion/statistics.rb +1 -1
  105. data/lib/adhearsion/tasks.rb +1 -2
  106. data/lib/adhearsion/tasks/configuration.rb +1 -1
  107. data/lib/adhearsion/tasks/environment.rb +0 -2
  108. data/lib/adhearsion/tasks/i18n.rb +49 -0
  109. data/lib/adhearsion/translator.rb +11 -0
  110. data/lib/adhearsion/translator/asterisk.rb +234 -0
  111. data/lib/adhearsion/translator/asterisk/agi_app.rb +17 -0
  112. data/lib/adhearsion/translator/asterisk/agi_command.rb +45 -0
  113. data/lib/adhearsion/translator/asterisk/ami_error_converter.rb +20 -0
  114. data/lib/adhearsion/translator/asterisk/call.rb +416 -0
  115. data/lib/adhearsion/translator/asterisk/channel.rb +43 -0
  116. data/lib/adhearsion/translator/asterisk/component.rb +88 -0
  117. data/lib/adhearsion/translator/asterisk/component/asterisk.rb +15 -0
  118. data/lib/adhearsion/translator/asterisk/component/asterisk/agi_command.rb +42 -0
  119. data/lib/adhearsion/translator/asterisk/component/asterisk/ami_action.rb +68 -0
  120. data/lib/adhearsion/translator/asterisk/component/composed_prompt.rb +76 -0
  121. data/lib/adhearsion/translator/asterisk/component/dtmf_recognizer.rb +137 -0
  122. data/lib/adhearsion/translator/asterisk/component/input.rb +34 -0
  123. data/lib/adhearsion/translator/asterisk/component/input_component.rb +90 -0
  124. data/lib/adhearsion/translator/asterisk/component/mrcp_native_prompt.rb +71 -0
  125. data/lib/adhearsion/translator/asterisk/component/mrcp_prompt.rb +55 -0
  126. data/lib/adhearsion/translator/asterisk/component/mrcp_recog_prompt.rb +165 -0
  127. data/lib/adhearsion/translator/asterisk/component/output.rb +233 -0
  128. data/lib/adhearsion/translator/asterisk/component/record.rb +101 -0
  129. data/lib/adhearsion/translator/asterisk/component/stop_by_redirect.rb +30 -0
  130. data/lib/adhearsion/translator/asterisk/unimrcp_app.rb +28 -0
  131. data/lib/adhearsion/uri_list.rb +21 -0
  132. data/lib/adhearsion/version.rb +1 -1
  133. data/spec/adhearsion/call_controller/dial_spec.rb +79 -1420
  134. data/spec/adhearsion/call_controller/input_spec.rb +1141 -237
  135. data/spec/adhearsion/call_controller/output/async_player_spec.rb +10 -10
  136. data/spec/adhearsion/call_controller/output/player_spec.rb +8 -8
  137. data/spec/adhearsion/call_controller/output_spec.rb +162 -215
  138. data/spec/adhearsion/call_controller/record_spec.rb +15 -16
  139. data/spec/adhearsion/call_controller_spec.rb +23 -40
  140. data/spec/adhearsion/call_spec.rb +123 -129
  141. data/spec/adhearsion/calls_spec.rb +3 -3
  142. data/spec/adhearsion/configuration_spec.rb +94 -108
  143. data/spec/adhearsion/event/answered_spec.rb +50 -0
  144. data/spec/adhearsion/event/asterisk/Find Results +402 -0
  145. data/spec/adhearsion/event/asterisk/ami_spec.rb +81 -0
  146. data/spec/adhearsion/event/complete_spec.rb +176 -0
  147. data/spec/adhearsion/event/dtmf_spec.rb +35 -0
  148. data/spec/adhearsion/event/end_spec.rb +85 -0
  149. data/spec/adhearsion/event/input_timers_started_spec.rb +19 -0
  150. data/spec/adhearsion/event/joined_spec.rb +53 -0
  151. data/spec/adhearsion/event/offer_spec.rb +106 -0
  152. data/spec/adhearsion/event/ringing_spec.rb +50 -0
  153. data/spec/adhearsion/event/started_speaking_spec.rb +37 -0
  154. data/spec/adhearsion/event/stopped_speaking_spec.rb +37 -0
  155. data/spec/adhearsion/event/unjoined_spec.rb +48 -0
  156. data/spec/adhearsion/event/untitled +0 -0
  157. data/spec/adhearsion/events_spec.rb +19 -45
  158. data/spec/adhearsion/initializer_spec.rb +12 -184
  159. data/spec/adhearsion/logging_spec.rb +5 -20
  160. data/spec/adhearsion/outbound_call_spec.rb +13 -13
  161. data/spec/adhearsion/plugin_spec.rb +3 -4
  162. data/spec/adhearsion/protocol_error_spec.rb +91 -0
  163. data/spec/adhearsion/rayo/client/component_registry_spec.rb +26 -0
  164. data/spec/adhearsion/rayo/client_spec.rb +134 -0
  165. data/spec/adhearsion/rayo/command/accept_spec.rb +63 -0
  166. data/spec/adhearsion/rayo/command/answer_spec.rb +73 -0
  167. data/spec/adhearsion/rayo/command/dial_spec.rb +156 -0
  168. data/spec/adhearsion/rayo/command/hangup_spec.rb +63 -0
  169. data/spec/adhearsion/rayo/command/join_spec.rb +158 -0
  170. data/spec/adhearsion/rayo/command/mute_spec.rb +32 -0
  171. data/spec/adhearsion/rayo/command/redirect_spec.rb +89 -0
  172. data/spec/adhearsion/rayo/command/reject_spec.rb +117 -0
  173. data/spec/adhearsion/rayo/command/unjoin_spec.rb +82 -0
  174. data/spec/adhearsion/rayo/command/unmute_spec.rb +32 -0
  175. data/spec/adhearsion/rayo/command_node_spec.rb +101 -0
  176. data/spec/adhearsion/rayo/component/asterisk/agi/command_spec.rb +111 -0
  177. data/spec/adhearsion/rayo/component/asterisk/ami/action_spec.rb +173 -0
  178. data/spec/adhearsion/rayo/component/component_node_spec.rb +110 -0
  179. data/spec/adhearsion/rayo/component/input_spec.rb +715 -0
  180. data/spec/adhearsion/rayo/component/output_spec.rb +1030 -0
  181. data/spec/adhearsion/rayo/component/prompt_spec.rb +171 -0
  182. data/spec/adhearsion/rayo/component/receive_fax_spec.rb +136 -0
  183. data/spec/adhearsion/rayo/component/record_spec.rb +497 -0
  184. data/spec/adhearsion/rayo/component/send_fax_spec.rb +144 -0
  185. data/spec/adhearsion/rayo/connection/asterisk_spec.rb +118 -0
  186. data/spec/adhearsion/rayo/connection/xmpp_spec.rb +449 -0
  187. data/spec/adhearsion/rayo/initializer_spec.rb +353 -0
  188. data/spec/adhearsion/rayo/ref_spec.rb +168 -0
  189. data/spec/adhearsion/rayo_spec.rb +7 -0
  190. data/spec/adhearsion/router/route_spec.rb +1 -1
  191. data/spec/adhearsion/statistics_spec.rb +2 -5
  192. data/spec/adhearsion/translator/asterisk/call_spec.rb +2047 -0
  193. data/spec/adhearsion/translator/asterisk/component/asterisk/agi_command_spec.rb +256 -0
  194. data/spec/adhearsion/translator/asterisk/component/asterisk/ami_action_spec.rb +151 -0
  195. data/spec/adhearsion/translator/asterisk/component/composed_prompt_spec.rb +257 -0
  196. data/spec/adhearsion/translator/asterisk/component/input_spec.rb +571 -0
  197. data/spec/adhearsion/translator/asterisk/component/mrcp_native_prompt_spec.rb +774 -0
  198. data/spec/adhearsion/translator/asterisk/component/mrcp_prompt_spec.rb +1244 -0
  199. data/spec/adhearsion/translator/asterisk/component/output_spec.rb +1850 -0
  200. data/spec/adhearsion/translator/asterisk/component/record_spec.rb +426 -0
  201. data/spec/adhearsion/translator/asterisk/component/stop_by_redirect_spec.rb +62 -0
  202. data/spec/adhearsion/translator/asterisk/component_spec.rb +83 -0
  203. data/spec/adhearsion/translator/asterisk_spec.rb +685 -0
  204. data/spec/adhearsion/uri_list_spec.rb +88 -0
  205. data/spec/adhearsion_spec.rb +89 -14
  206. data/spec/fixtures/locale/en.yml +13 -0
  207. data/spec/fixtures/locale/it.yml +13 -0
  208. data/spec/spec_helper.rb +18 -5
  209. data/spec/support/call_controller_test_helpers.rb +3 -2
  210. data/spec/support/initializer_stubs.rb +3 -1
  211. data/spec/support/punchblock_examples.rb +65 -0
  212. data/spec/support/punchblock_mocks.rb +12 -0
  213. metadata +412 -70
  214. data/features/cli_daemon.feature +0 -20
  215. data/features/cli_restart.feature +0 -52
  216. data/features/cli_stop.feature +0 -50
  217. data/lib/adhearsion/call_controller/menu_dsl.rb +0 -21
  218. data/lib/adhearsion/call_controller/menu_dsl/array_match_calculator.rb +0 -26
  219. data/lib/adhearsion/call_controller/menu_dsl/calculated_match.rb +0 -43
  220. data/lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb +0 -45
  221. data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +0 -11
  222. data/lib/adhearsion/call_controller/menu_dsl/match_calculator.rb +0 -40
  223. data/lib/adhearsion/call_controller/menu_dsl/menu.rb +0 -207
  224. data/lib/adhearsion/call_controller/menu_dsl/menu_builder.rb +0 -92
  225. data/lib/adhearsion/call_controller/menu_dsl/range_match_calculator.rb +0 -60
  226. data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +0 -25
  227. data/lib/adhearsion/call_controller/utility.rb +0 -77
  228. data/lib/adhearsion/foundation/custom_daemonizer.rb +0 -52
  229. data/lib/adhearsion/punchblock_plugin.rb +0 -63
  230. data/scripts/cloc-1.64.pl +0 -10483
  231. data/spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb +0 -76
  232. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +0 -60
  233. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +0 -61
  234. data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +0 -39
  235. data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +0 -17
  236. data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +0 -165
  237. data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +0 -420
  238. data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +0 -32
  239. data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +0 -40
  240. data/spec/adhearsion/call_controller/utility_spec.rb +0 -90
  241. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +0 -356
  242. data/spec/adhearsion/punchblock_plugin_spec.rb +0 -59
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adhearsion/rayo/command_node'
4
+ require 'adhearsion/has_headers'
5
+
6
+ module Adhearsion
7
+ module Rayo
8
+ module Command
9
+ class Redirect < CommandNode
10
+ register :redirect, :core
11
+
12
+ include HasHeaders
13
+
14
+ # @return [String] the redirect target
15
+ attribute :to
16
+
17
+ def rayo_attributes
18
+ {'to' => to}
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adhearsion/rayo/command_node'
4
+ require 'adhearsion/has_headers'
5
+
6
+ module Adhearsion
7
+ module Rayo
8
+ module Command
9
+ class Reject < CommandNode
10
+ register :reject, :core
11
+
12
+ include HasHeaders
13
+
14
+ VALID_REASONS = [:busy, :decline, :error].freeze
15
+
16
+ # @return [Symbol] the reason type for rejecting a call. One of :busy, :dclined or :error.
17
+ # @raises ArgumentError if reject_reason is not one of the allowed reasons
18
+ attribute :reason, Symbol
19
+ def reason=(reject_reason)
20
+ if reject_reason && !VALID_REASONS.include?(reject_reason.to_sym)
21
+ raise ArgumentError, "Invalid Reason (#{reject_reason}), use: #{VALID_REASONS*' '}"
22
+ end
23
+ super
24
+ end
25
+
26
+ def inherit(xml_node)
27
+ if first_child = xml_node.at_xpath('*')
28
+ self.reason = first_child.name
29
+ end
30
+ super
31
+ end
32
+
33
+ def rayo_children(root)
34
+ root.send reason if reason
35
+ super
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adhearsion/rayo/command_node'
4
+
5
+ module Adhearsion
6
+ module Rayo
7
+ module Command
8
+ class Unjoin < CommandNode
9
+ register :unjoin, :core
10
+
11
+ # @return [String] the call ID to unjoin
12
+ attribute :call_uri
13
+ alias :call_id= :call_uri=
14
+
15
+ # @return [String] the mixer name to unjoin
16
+ attribute :mixer_name
17
+
18
+ def rayo_attributes
19
+ {'call-uri' => call_uri, 'mixer-name' => mixer_name}
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adhearsion/rayo/command_node'
4
+
5
+ module Adhearsion
6
+ module Rayo
7
+ module Command
8
+ class Unmute < CommandNode
9
+ register :unmute, :core
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ require 'state_machine'
4
+ require 'future-resource'
5
+ require 'adhearsion/rayo/rayo_node'
6
+
7
+ module Adhearsion
8
+ module Rayo
9
+ class CommandNode < RayoNode
10
+
11
+ attribute :request_id, String, default: ->(*) { Adhearsion.new_request_id }
12
+
13
+ def initialize(*args)
14
+ super
15
+ @response = FutureResource.new
16
+ end
17
+
18
+ state_machine :state, :initial => :new do
19
+ event :request do
20
+ transition :new => :requested
21
+ end
22
+
23
+ event :execute do
24
+ transition :requested => :executing
25
+ end
26
+
27
+ event :complete do
28
+ transition :executing => :complete
29
+ end
30
+ end
31
+
32
+ def response(timeout = nil)
33
+ @response.resource timeout
34
+ end
35
+
36
+ def response=(other)
37
+ return if @response.set_yet?
38
+ @response.resource = other
39
+ execute!
40
+ rescue StateMachine::InvalidTransition => e
41
+ e.message << " for command #{self}"
42
+ raise e
43
+ rescue FutureResource::ResourceAlreadySetException
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ module Rayo
5
+ module Component
6
+ InvalidActionError = Class.new StandardError
7
+ end
8
+ end
9
+ end
10
+
11
+ %w{
12
+ asterisk
13
+ component_node
14
+ input
15
+ output
16
+ prompt
17
+ receive_fax
18
+ record
19
+ send_fax
20
+ stop
21
+ }.each { |component| require "adhearsion/rayo/component/#{component}" }
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ module Rayo
5
+ module Component
6
+ module Asterisk
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require 'adhearsion/rayo/component/asterisk/agi'
13
+ require 'adhearsion/rayo/component/asterisk/ami'
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ module Rayo
5
+ module Component
6
+ module Asterisk
7
+ module AGI
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ require 'adhearsion/rayo/component/asterisk/agi/command'
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adhearsion/rayo/component/component_node'
4
+ require 'adhearsion/event/complete'
5
+
6
+ module Adhearsion
7
+ module Rayo
8
+ module Component
9
+ module Asterisk
10
+ module AGI
11
+ class Command < ComponentNode
12
+ register :command, :agi
13
+
14
+ attribute :name
15
+ attribute :params, Array, default: []
16
+
17
+ def inherit(xml_node)
18
+ xml_node.xpath('//ns:param', ns: self.class.registered_ns).to_a.each do |param|
19
+ params << param[:value]
20
+ end
21
+ super
22
+ end
23
+
24
+ class Complete
25
+ class Success < Event::Complete::Reason
26
+ register :success, :agi_complete
27
+
28
+ attribute :code, Integer
29
+ attribute :result, Integer
30
+ attribute :data
31
+
32
+ def inherit(xml_node)
33
+ [:code, :result, :data].each do |attr|
34
+ node = xml_node.at_xpath "ns:#{attr}", ns: self.class.registered_ns
35
+ self.send "#{attr}=", node.text if node
36
+ end
37
+ super
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ module Rayo
5
+ module Component
6
+ module Asterisk
7
+ module AMI
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ require 'adhearsion/rayo/component/asterisk/ami/action'
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ module Rayo
5
+ module Component
6
+ module Asterisk
7
+ module AMI
8
+ class Action < ComponentNode
9
+ register :action, :ami
10
+
11
+ attribute :name
12
+ attribute :params, Hash, default: {}
13
+
14
+ def inherit(xml_node)
15
+ xml_node.xpath('//ns:param', ns: self.class.registered_ns).to_a.each do |param|
16
+ params[param[:name]] = param[:value]
17
+ end
18
+ super
19
+ end
20
+
21
+ def rayo_attributes
22
+ {'name' => name}
23
+ end
24
+
25
+ def rayo_children(root)
26
+ super
27
+ params.each do |name, value|
28
+ root.param name: name, value: value
29
+ end
30
+ end
31
+
32
+ class Complete
33
+ class Success < Event::Complete::Reason
34
+ register :success, :ami_complete
35
+
36
+ attribute :message
37
+ attribute :text_body
38
+ attribute :headers, Hash, default: {}
39
+
40
+ alias :attributes :headers
41
+
42
+ def inherit(xml_node)
43
+ message_node = xml_node.at_xpath 'ns:message', ns: self.class.registered_ns
44
+ self.message = message_node.text if message_node
45
+
46
+ text_body_node = xml_node.at_xpath 'ns:text-body', ns: self.class.registered_ns
47
+ self.text_body = text_body_node.text if text_body_node
48
+
49
+ xml_node.xpath('//ns:attribute', ns: self.class.registered_ns).to_a.each do |attribute|
50
+ headers[attribute[:name]] = attribute[:value]
51
+ end
52
+ super
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,90 @@
1
+ # encoding: utf-8
2
+
3
+ require 'future-resource'
4
+ require 'has_guarded_handlers'
5
+ require 'adhearsion/rayo/command_node'
6
+
7
+ module Adhearsion
8
+ module Rayo
9
+ module Component
10
+ class ComponentNode < CommandNode
11
+ include HasGuardedHandlers
12
+
13
+ def initialize(*args)
14
+ super
15
+ @complete_event_resource = FutureResource.new
16
+ @mutex = Mutex.new
17
+ register_internal_handlers
18
+ end
19
+
20
+ def register_internal_handlers
21
+ register_handler :internal, Event::Complete do |event|
22
+ self.complete_event = event
23
+ throw :pass
24
+ end
25
+ end
26
+
27
+ def add_event(event)
28
+ trigger_handler :internal, event
29
+ end
30
+
31
+ def trigger_event_handler(event)
32
+ trigger_handler :event, event
33
+ end
34
+
35
+ def register_event_handler(*guards, &block)
36
+ register_handler :event, *guards, &block
37
+ end
38
+
39
+ def write_action(action)
40
+ client.execute_command action, :target_call_id => target_call_id, :component_id => component_id
41
+ action
42
+ end
43
+
44
+ def response=(other)
45
+ @mutex.synchronize do
46
+ if other.is_a?(Ref)
47
+ @component_id = other.component_id
48
+ @source_uri = other.uri.to_s
49
+ client.register_component self if client
50
+ end
51
+ super
52
+ end
53
+ end
54
+
55
+ def complete_event(timeout = nil)
56
+ @complete_event_resource.resource timeout
57
+ end
58
+
59
+ def complete_event=(other)
60
+ @mutex.synchronize do
61
+ return if @complete_event_resource.set_yet?
62
+ client.delete_component_registration self if client
63
+ complete!
64
+ @complete_event_resource.resource = other
65
+ end
66
+ rescue StateMachine::InvalidTransition => e
67
+ e.message << " for component #{self}"
68
+ raise e
69
+ end
70
+
71
+ ##
72
+ # Create a Rayo stop message
73
+ #
74
+ # @return [Stop] a Rayo stop message
75
+ #
76
+ def stop_action
77
+ Stop.new :component_id => component_id, :target_call_id => target_call_id
78
+ end
79
+
80
+ ##
81
+ # Sends a Rayo stop message for the current component
82
+ #
83
+ def stop!(options = {})
84
+ raise InvalidActionError, "Cannot stop a #{self.class.name.split("::").last} that is #{state}" unless executing?
85
+ stop_action.tap { |action| write_action action }
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,186 @@
1
+ # encoding: utf-8
2
+
3
+ module Adhearsion
4
+ module Rayo
5
+ module Component
6
+ class Input < ComponentNode
7
+
8
+ include HasHeaders
9
+
10
+ NLSML_NAMESPACE = 'http://www.ietf.org/xml/ns/mrcpv2'
11
+
12
+ register :input, :input
13
+
14
+ # @return [Integer] the amount of time in milliseconds that an input command will wait until considered that a silence becomes a NO-MATCH
15
+ attribute :max_silence, Integer
16
+
17
+ # @return [Float] Confidence with which to consider a response acceptable
18
+ attribute :min_confidence, Float
19
+
20
+ # @return [Symbol] mode by which to accept input. Can be :voice, :dtmf or :any
21
+ attribute :mode, Symbol, default: :dtmf
22
+
23
+ # @return [String] recognizer to use for speech recognition
24
+ attribute :recognizer, String
25
+
26
+ # @return [String] language to use for speech recognition
27
+ attribute :language, String
28
+
29
+ # @return [String] terminator by which to signal the end of input
30
+ attribute :terminator, String
31
+
32
+ # @return [Float] Indicates how sensitive the interpreter should be to loud versus quiet input. Higher values represent greater sensitivity.
33
+ attribute :sensitivity, Float
34
+
35
+ # @return [Integer] Indicates the amount of time (in milliseconds) preceding input which may expire before a timeout is triggered.
36
+ attribute :initial_timeout, Integer
37
+
38
+ # @return [Integer] Indicates (in the case of DTMF input) the amount of time (in milliseconds) between input digits which may expire before a timeout is triggered.
39
+ attribute :inter_digit_timeout, Integer
40
+
41
+ # @return [Integer] Indicates the amount of time during input that recognition will occur before a timeout is triggered.
42
+ attribute :recognition_timeout, Integer
43
+
44
+ attribute :grammars, Array, default: []
45
+ def grammars=(others)
46
+ super others.map { |other| Grammar.new(other) }
47
+ end
48
+
49
+ ##
50
+ # @param [Hash] other
51
+ # @option other [String] :content_type the document content type
52
+ # @option other [String] :value the grammar doucment
53
+ # @option other [String] :url the url from which to fetch the grammar
54
+ #
55
+ def grammar=(other)
56
+ self.grammars = [other].compact
57
+ end
58
+
59
+ def inherit(xml_node)
60
+ grammar_nodes = xml_node.xpath('ns:grammar', ns: self.class.registered_ns)
61
+ self.grammars = grammar_nodes.to_a.map { |grammar_node| Grammar.from_xml(grammar_node)}
62
+ super
63
+ end
64
+
65
+ def rayo_attributes
66
+ {
67
+ 'max-silence' => max_silence,
68
+ 'min-confidence' => min_confidence,
69
+ 'mode' => mode,
70
+ 'recognizer' => recognizer,
71
+ 'language' => language,
72
+ 'terminator' => terminator,
73
+ 'sensitivity' => sensitivity,
74
+ 'initial-timeout' => initial_timeout,
75
+ 'inter-digit-timeout' => inter_digit_timeout,
76
+ 'recognition-timeout' => recognition_timeout
77
+ }
78
+ end
79
+
80
+ def rayo_children(root)
81
+ grammars.each do |grammar|
82
+ grammar.to_rayo(root)
83
+ end
84
+ super
85
+ end
86
+
87
+ class Grammar < RayoNode
88
+ register :grammar, :input
89
+
90
+ GRXML_CONTENT_TYPE = 'application/srgs+xml'
91
+
92
+ attribute :value
93
+ attribute :content_type, String, default: ->(grammar, attribute) { grammar.url ? nil : GRXML_CONTENT_TYPE }
94
+ attribute :url
95
+
96
+ def inherit(xml_node)
97
+ self.value = xml_node.content.strip
98
+ super
99
+ end
100
+
101
+ def rayo_attributes
102
+ {
103
+ 'url' => url,
104
+ 'content-type' => content_type
105
+ }
106
+ end
107
+
108
+ def rayo_children(root)
109
+ root.cdata value if value
110
+ end
111
+
112
+ private
113
+
114
+ def grxml?
115
+ content_type == GRXML_CONTENT_TYPE
116
+ end
117
+ end
118
+
119
+ class Signal < Event::Complete::Reason
120
+ register :signal, :cpa
121
+
122
+ attribute :type, String
123
+ attribute :duration, Integer
124
+ attribute :value, String
125
+ end
126
+
127
+ class Complete
128
+ class Match < Event::Complete::Reason
129
+ register :match, :input_complete
130
+
131
+ attribute :content_type, String, default: 'application/nlsml+xml'
132
+
133
+ attribute :nlsml
134
+ def nlsml=(other)
135
+ doc = case other
136
+ when Nokogiri::XML::Element, Nokogiri::XML::Document
137
+ RubySpeech::NLSML::Document.new(other)
138
+ else
139
+ other
140
+ end
141
+ super doc
142
+ end
143
+
144
+ def mode
145
+ nlsml.best_interpretation[:input][:mode]
146
+ end
147
+
148
+ def confidence
149
+ nlsml.best_interpretation[:confidence]
150
+ end
151
+
152
+ def utterance
153
+ nlsml.best_interpretation[:input][:content]
154
+ end
155
+
156
+ def interpretation
157
+ nlsml.best_interpretation[:instance]
158
+ end
159
+
160
+ def inherit(xml_node)
161
+ self.nlsml = result_node(xml_node)
162
+ super
163
+ end
164
+
165
+ private
166
+
167
+ def result_node(xml)
168
+ directly_nested = xml.at_xpath 'ns:result', ns: NLSML_NAMESPACE
169
+ return directly_nested if directly_nested
170
+ document = Nokogiri::XML.parse xml.text, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS
171
+ document.at_xpath 'ns:result', ns: NLSML_NAMESPACE or raise "Couldn't find the NLSML node"
172
+ end
173
+ end
174
+
175
+ class NoMatch < Event::Complete::Reason
176
+ register :nomatch, :input_complete
177
+ end
178
+
179
+ class NoInput < Event::Complete::Reason
180
+ register :noinput, :input_complete
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end