jicksta-adhearsion 0.7.999

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 (107) hide show
  1. data/CHANGELOG +6 -0
  2. data/EVENTS +11 -0
  3. data/LICENSE +456 -0
  4. data/README.txt +5 -0
  5. data/Rakefile +120 -0
  6. data/adhearsion.gemspec +146 -0
  7. data/app_generators/ahn/USAGE +5 -0
  8. data/app_generators/ahn/ahn_generator.rb +87 -0
  9. data/app_generators/ahn/templates/.ahnrc +34 -0
  10. data/app_generators/ahn/templates/README +8 -0
  11. data/app_generators/ahn/templates/Rakefile +23 -0
  12. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
  13. data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
  14. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
  15. data/app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml +12 -0
  16. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
  17. data/app_generators/ahn/templates/components/restful_rpc/README.markdown +11 -0
  18. data/app_generators/ahn/templates/components/restful_rpc/config.yml +34 -0
  19. data/app_generators/ahn/templates/components/restful_rpc/example-client.rb +48 -0
  20. data/app_generators/ahn/templates/components/restful_rpc/restful_rpc.rb +87 -0
  21. data/app_generators/ahn/templates/components/simon_game/simon_game.rb +56 -0
  22. data/app_generators/ahn/templates/config/startup.rb +53 -0
  23. data/app_generators/ahn/templates/dialplan.rb +3 -0
  24. data/app_generators/ahn/templates/events.rb +32 -0
  25. data/bin/ahn +28 -0
  26. data/bin/ahnctl +68 -0
  27. data/bin/jahn +42 -0
  28. data/examples/asterisk_manager_interface/standalone.rb +51 -0
  29. data/lib/adhearsion/cli.rb +223 -0
  30. data/lib/adhearsion/component_manager/spec_framework.rb +24 -0
  31. data/lib/adhearsion/component_manager.rb +208 -0
  32. data/lib/adhearsion/events_support.rb +84 -0
  33. data/lib/adhearsion/foundation/all.rb +9 -0
  34. data/lib/adhearsion/foundation/blank_slate.rb +5 -0
  35. data/lib/adhearsion/foundation/custom_daemonizer.rb +45 -0
  36. data/lib/adhearsion/foundation/event_socket.rb +203 -0
  37. data/lib/adhearsion/foundation/future_resource.rb +36 -0
  38. data/lib/adhearsion/foundation/global.rb +1 -0
  39. data/lib/adhearsion/foundation/metaprogramming.rb +17 -0
  40. data/lib/adhearsion/foundation/numeric.rb +13 -0
  41. data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
  42. data/lib/adhearsion/foundation/relationship_properties.rb +42 -0
  43. data/lib/adhearsion/foundation/string.rb +26 -0
  44. data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
  45. data/lib/adhearsion/foundation/thread_safety.rb +7 -0
  46. data/lib/adhearsion/host_definitions.rb +67 -0
  47. data/lib/adhearsion/initializer/asterisk.rb +81 -0
  48. data/lib/adhearsion/initializer/configuration.rb +254 -0
  49. data/lib/adhearsion/initializer/database.rb +49 -0
  50. data/lib/adhearsion/initializer/drb.rb +31 -0
  51. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  52. data/lib/adhearsion/initializer/rails.rb +40 -0
  53. data/lib/adhearsion/initializer.rb +373 -0
  54. data/lib/adhearsion/logging.rb +92 -0
  55. data/lib/adhearsion/tasks/database.rb +5 -0
  56. data/lib/adhearsion/tasks/deprecations.rb +59 -0
  57. data/lib/adhearsion/tasks/generating.rb +20 -0
  58. data/lib/adhearsion/tasks/lint.rb +4 -0
  59. data/lib/adhearsion/tasks/testing.rb +37 -0
  60. data/lib/adhearsion/tasks.rb +16 -0
  61. data/lib/adhearsion/version.rb +9 -0
  62. data/lib/adhearsion/voip/asterisk/agi_server.rb +81 -0
  63. data/lib/adhearsion/voip/asterisk/commands.rb +1284 -0
  64. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  65. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  66. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  67. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  68. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  69. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1754 -0
  70. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +286 -0
  71. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
  72. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
  73. data/lib/adhearsion/voip/asterisk/manager_interface.rb +562 -0
  74. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  75. data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
  76. data/lib/adhearsion/voip/asterisk.rb +4 -0
  77. data/lib/adhearsion/voip/call.rb +440 -0
  78. data/lib/adhearsion/voip/call_routing.rb +64 -0
  79. data/lib/adhearsion/voip/commands.rb +9 -0
  80. data/lib/adhearsion/voip/constants.rb +39 -0
  81. data/lib/adhearsion/voip/conveniences.rb +18 -0
  82. data/lib/adhearsion/voip/dial_plan.rb +218 -0
  83. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  84. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  85. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  86. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  87. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +71 -0
  88. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  89. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  90. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  91. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  92. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  93. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  94. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  95. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  96. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  97. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  98. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  99. data/lib/adhearsion.rb +37 -0
  100. data/lib/theatre/README.markdown +64 -0
  101. data/lib/theatre/callback_definition_loader.rb +84 -0
  102. data/lib/theatre/guid.rb +23 -0
  103. data/lib/theatre/invocation.rb +121 -0
  104. data/lib/theatre/namespace_manager.rb +153 -0
  105. data/lib/theatre/version.rb +2 -0
  106. data/lib/theatre.rb +151 -0
  107. metadata +177 -0
@@ -0,0 +1,146 @@
1
+ ADHEARSION_FILES = %w{
2
+ adhearsion.gemspec
3
+ app_generators/ahn/ahn_generator.rb
4
+ app_generators/ahn/templates/.ahnrc
5
+ app_generators/ahn/templates/components/ami_remote/ami_remote.rb
6
+ app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE
7
+ app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml
8
+ app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown
9
+ app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb
10
+ app_generators/ahn/templates/components/restful_rpc/config.yml
11
+ app_generators/ahn/templates/components/restful_rpc/example-client.rb
12
+ app_generators/ahn/templates/components/restful_rpc/README.markdown
13
+ app_generators/ahn/templates/components/restful_rpc/restful_rpc.rb
14
+ app_generators/ahn/templates/components/simon_game/simon_game.rb
15
+ app_generators/ahn/templates/config/startup.rb
16
+ app_generators/ahn/templates/dialplan.rb
17
+ app_generators/ahn/templates/events.rb
18
+ app_generators/ahn/templates/Rakefile
19
+ app_generators/ahn/templates/README
20
+ app_generators/ahn/USAGE
21
+ bin/ahn
22
+ bin/ahnctl
23
+ bin/jahn
24
+ CHANGELOG
25
+ EVENTS
26
+ examples/asterisk_manager_interface/standalone.rb
27
+ lib/adhearsion.rb
28
+ lib/adhearsion/cli.rb
29
+ lib/adhearsion/component_manager.rb
30
+ lib/adhearsion/component_manager/spec_framework.rb
31
+ lib/adhearsion/events_support.rb
32
+ lib/adhearsion/foundation/all.rb
33
+ lib/adhearsion/foundation/blank_slate.rb
34
+ lib/adhearsion/foundation/custom_daemonizer.rb
35
+ lib/adhearsion/foundation/event_socket.rb
36
+ lib/adhearsion/foundation/future_resource.rb
37
+ lib/adhearsion/foundation/global.rb
38
+ lib/adhearsion/foundation/metaprogramming.rb
39
+ lib/adhearsion/foundation/numeric.rb
40
+ lib/adhearsion/foundation/pseudo_guid.rb
41
+ lib/adhearsion/foundation/relationship_properties.rb
42
+ lib/adhearsion/foundation/string.rb
43
+ lib/adhearsion/foundation/synchronized_hash.rb
44
+ lib/adhearsion/foundation/thread_safety.rb
45
+ lib/adhearsion/host_definitions.rb
46
+ lib/adhearsion/initializer.rb
47
+ lib/adhearsion/initializer/asterisk.rb
48
+ lib/adhearsion/initializer/configuration.rb
49
+ lib/adhearsion/initializer/database.rb
50
+ lib/adhearsion/initializer/drb.rb
51
+ lib/adhearsion/initializer/freeswitch.rb
52
+ lib/adhearsion/initializer/rails.rb
53
+ lib/adhearsion/logging.rb
54
+ lib/adhearsion/tasks.rb
55
+ lib/adhearsion/tasks/database.rb
56
+ lib/adhearsion/tasks/deprecations.rb
57
+ lib/adhearsion/tasks/generating.rb
58
+ lib/adhearsion/tasks/lint.rb
59
+ lib/adhearsion/tasks/testing.rb
60
+ lib/adhearsion/version.rb
61
+ lib/adhearsion/voip/asterisk.rb
62
+ lib/adhearsion/voip/asterisk/agi_server.rb
63
+ lib/adhearsion/voip/asterisk/commands.rb
64
+ lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb
65
+ lib/adhearsion/voip/asterisk/config_generators/config_generator.rb
66
+ lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb
67
+ lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb
68
+ lib/adhearsion/voip/asterisk/config_manager.rb
69
+ lib/adhearsion/voip/asterisk/manager_interface.rb
70
+ lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb
71
+ lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb
72
+ lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb
73
+ lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl
74
+ lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb
75
+ lib/adhearsion/voip/asterisk/super_manager.rb
76
+ lib/adhearsion/voip/call.rb
77
+ lib/adhearsion/voip/call_routing.rb
78
+ lib/adhearsion/voip/commands.rb
79
+ lib/adhearsion/voip/constants.rb
80
+ lib/adhearsion/voip/conveniences.rb
81
+ lib/adhearsion/voip/dial_plan.rb
82
+ lib/adhearsion/voip/dsl/dialing_dsl.rb
83
+ lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb
84
+ lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb
85
+ lib/adhearsion/voip/dsl/dialplan/dispatcher.rb
86
+ lib/adhearsion/voip/dsl/dialplan/parser.rb
87
+ lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb
88
+ lib/adhearsion/voip/dsl/numerical_string.rb
89
+ lib/adhearsion/voip/freeswitch/basic_connection_manager.rb
90
+ lib/adhearsion/voip/freeswitch/event_handler.rb
91
+ lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb
92
+ lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb
93
+ lib/adhearsion/voip/freeswitch/oes_server.rb
94
+ lib/adhearsion/voip/menu_state_machine/calculated_match.rb
95
+ lib/adhearsion/voip/menu_state_machine/matchers.rb
96
+ lib/adhearsion/voip/menu_state_machine/menu_builder.rb
97
+ lib/adhearsion/voip/menu_state_machine/menu_class.rb
98
+ lib/theatre.rb
99
+ lib/theatre/callback_definition_loader.rb
100
+ lib/theatre/guid.rb
101
+ lib/theatre/invocation.rb
102
+ lib/theatre/namespace_manager.rb
103
+ lib/theatre/README.markdown
104
+ lib/theatre/version.rb
105
+ LICENSE
106
+ Rakefile
107
+ README.txt
108
+ }
109
+
110
+ Gem::Specification.new do |s|
111
+ s.name = "adhearsion"
112
+ s.version = "0.7.999"
113
+
114
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
115
+ s.authors = ["Jay Phillips"]
116
+
117
+ s.date = "2008-08-21"
118
+ s.description = "Adhearsion is an open-source telephony development framework"
119
+ s.email = "Jay -at- Codemecca.com"
120
+ s.executables = ["ahn", "ahnctl", "jahn"]
121
+
122
+ s.files = ADHEARSION_FILES
123
+
124
+ s.has_rdoc = false
125
+ s.homepage = "http://adhearsion.com"
126
+ s.require_paths = ["lib"]
127
+ s.rubyforge_project = "adhearsion"
128
+ s.rubygems_version = "1.2.0"
129
+ s.summary = "Adhearsion, open-source telephony development framework"
130
+
131
+ if s.respond_to? :specification_version then
132
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
133
+ s.specification_version = 2
134
+
135
+ if current_version >= 3 then
136
+ s.add_runtime_dependency("rubigen", [">= 1.0.6"])
137
+ s.add_runtime_dependency("log4r", [">= 1.0.5"])
138
+ else
139
+ s.add_dependency("rubigen", [">= 1.0.6"])
140
+ s.add_dependency("log4r", [">= 1.0.5"])
141
+ end
142
+ else
143
+ s.add_dependency("rubigen", [">= 1.0.6"])
144
+ s.add_dependency("log4r", [">= 1.0.5"])
145
+ end
146
+ end
@@ -0,0 +1,5 @@
1
+ Description:
2
+
3
+
4
+ Usage:
5
+
@@ -0,0 +1,87 @@
1
+ class AhnGenerator < RubiGen::Base
2
+
3
+ DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
4
+ Config::CONFIG['ruby_install_name'])
5
+
6
+ default_options :author => nil
7
+
8
+ attr_reader :name, :component
9
+
10
+ def initialize(runtime_args, runtime_options = {})
11
+ super
12
+ usage if args.empty?
13
+ @destination_root = File.expand_path(args.shift)
14
+ @name = base_name
15
+ @component = 'simon_game'
16
+ extract_options
17
+ end
18
+
19
+ def manifest
20
+ record do |m|
21
+ # Ensure appropriate folder(s) exists
22
+ m.directory ''
23
+ BASEDIRS.each { |path| m.directory path }
24
+
25
+ m.file *[".ahnrc"]*2
26
+
27
+ m.file *["components/simon_game/simon_game.rb"]*2
28
+ m.file *["components/ami_remote/ami_remote.rb"]*2
29
+
30
+ m.file *["components/disabled/stomp_gateway/stomp_gateway.rb"]*2
31
+ m.file *["components/disabled/stomp_gateway/config.yml"]*2
32
+ m.file *["components/disabled/stomp_gateway/README.markdown"]*2
33
+
34
+ m.file *["components/restful_rpc/restful_rpc.rb"]*2
35
+ m.file *["components/restful_rpc/config.yml"]*2
36
+ m.file *["components/restful_rpc/README.markdown"]*2
37
+ m.file *["components/restful_rpc/example-client.rb"]*2
38
+ m.file *["components/restful_rpc/spec/restful_rpc_spec.rb"]*2
39
+
40
+ m.file *["config/startup.rb"]*2
41
+ m.file *["dialplan.rb"]*2
42
+ m.file *["events.rb"]*2
43
+ m.file *["README"]*2
44
+ m.file *["Rakefile"]*2
45
+
46
+ # m.dependency "install_rubigen_scripts", [destination_root, 'ahn', 'adhearsion', 'test_spec'],
47
+ # :shebang => options[:shebang], :collision => :force
48
+ end
49
+ end
50
+
51
+ protected
52
+ def banner
53
+ <<-EOS
54
+ Creates a ...
55
+
56
+ USAGE: #{spec.name} name"
57
+ EOS
58
+ end
59
+
60
+ def add_options!(opts)
61
+ opts.separator ''
62
+ opts.separator 'Options:'
63
+ # For each option below, place the default
64
+ # at the top of the file next to "default_options"
65
+ # opts.on("-a", "--author=\"Your Name\"", String,
66
+ # "Some comment about this option",
67
+ # "Default: none") { |options[:author]| }
68
+ opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
69
+ end
70
+
71
+ def extract_options
72
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
73
+ # Templates can access these value via the attr_reader-generated methods, but not the
74
+ # raw instance variable value.
75
+ # @author = options[:author]
76
+ end
77
+
78
+ # Installation skeleton. Intermediate directories are automatically
79
+ # created so don't sweat their absence here.
80
+ BASEDIRS = %w(
81
+ components/simon_game
82
+ components/disabled/stomp_gateway
83
+ components/ami_remote
84
+ components/restful_rpc/spec
85
+ config
86
+ )
87
+ end
@@ -0,0 +1,34 @@
1
+ # Adhearsion Runtime Configuration.
2
+
3
+ # You can use the "gems" section to force Adhearsion to load a particular version of a gem.
4
+ # This is useful when a component require()s a gem, but you don't want it to use the latest one installed on the system.
5
+ # For example, if a component require()s activerecord, sucking in the latest on the system, and then you enable a Rails app
6
+ # which wants a particular version of activerecord, RubyGems will raise an error saying "you cannot activate two versions of
7
+ # the same gem". Note: specifying the version, source and require names is optional, but you must include a : after the gem name to make it a YAML key/value pair (with a nil value).
8
+ gems:
9
+ # twitter:
10
+ # hpricot:
11
+ # rack:
12
+ # # require() one library when initializing:
13
+ # require: rack
14
+ # memcache-client:
15
+ # version >= 1.5.2
16
+ # require:
17
+ # # require() an Array of libraries when initializing:
18
+ # - memcache
19
+ # - memcache_util
20
+ # activerecord:
21
+ # version: >= 2.1.0
22
+ # aasm:
23
+ # source: http://gems.github.com
24
+
25
+ paths:
26
+
27
+ # All paths are relative to this file's directory
28
+ init: config/startup.rb
29
+
30
+ dialplan: dialplan.rb
31
+
32
+ events: events.rb
33
+
34
+ models: models/*.rb
@@ -0,0 +1,8 @@
1
+ Start your new app with "ahn start /path/to/your/app"
2
+
3
+ If you wish to use Adhearsion to control Asterisk's dialplan,
4
+ change the contexts you wish to be affected in your
5
+ /etc/asterisk/extensions.conf file to the following:
6
+
7
+ [your_context_name]
8
+ exten => _X.,1,AGI(agi://1.2.3.4) ; This IP here
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+
3
+ begin
4
+ require 'adhearsion'
5
+ require 'adhearsion/tasks'
6
+ rescue LoadError
7
+ STDERR.puts "\nCannot load Adhearsion! Not all Rake tasks will be loaded!\n\n"
8
+ end
9
+
10
+ desc "Writes a .gitignore file that ignores certain SCM annoyances such as log files"
11
+ task :gitignore do
12
+ ignore_file = "#{Dir.pwd}/.gitignore"
13
+ if File.exists? ignore_file
14
+ STDERR.puts "File #{ignore_file} already exists!"
15
+ else
16
+ File.open ignore_file, 'w' do |file|
17
+ # Add other files to the Array below
18
+ %w[ log ].each do |pattern|
19
+ file.puts pattern
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ methods_for :rpc do
2
+
3
+ # Simply create proxy methods for the high-level AMI methods
4
+
5
+ [:send_action, :introduce, :originate, :call_into_context, :call_and_exec].each do |method_name|
6
+ define_method(method_name) do |*args|
7
+ if VoIP::Asterisk.manager_interface
8
+ VoIP::Asterisk.manager_interface.send(method_name, *args)
9
+ else
10
+ ahn_log.ami_remote.error "AMI has not been enabled in startup.rb!"
11
+ end
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,7 @@
1
+ Type "ahn enable component COMPONENT_NAME_FROM_DISABLED_FOLDER
2
+
3
+ For example:
4
+
5
+ ~/Desktop $ ahn create myapp
6
+ ~/Desktop $ cd myapp
7
+ ~/Desktop/myapp $ ahn enable component stomp_gateway
@@ -0,0 +1,47 @@
1
+ What is Stomp?
2
+ ==============
3
+
4
+ Stomp is a very simple message-queue protocol with which two separate systems can communicate. Because the protocol is so simple, there are many Stomp server implementations from which you can choose. Some of these include
5
+
6
+ - ActiveMQ (http://activemq.com)
7
+ - Ruby "stompserver" gem (gem install stompserver)
8
+ - RabbitMQ (http://rabbitmq.com)
9
+
10
+ If you wish to get up and running with a development environment, the Ruby stompserver gem is a fantastic starting point. For a critical production system, ActiveMQ should probably be used but it bears the cumbersome paradigm of many "enterprisey" Java applications.
11
+
12
+ How does it work?
13
+ =================
14
+
15
+ Stomp is used when certain processes have defined responsibilities. For example, your Adhearsion application's responsibility is to communicate with your Asterisk machine. Other processes (e.g. a Rails web application) will probably need to instruct Adhearsion to do something. Instructions may include
16
+
17
+ - Start a new call between two given phone numbers
18
+ - Have a particular call do something based on a new event
19
+ - Hangup a call
20
+
21
+ Below is a diagram which should give you a better idea of how it works.
22
+
23
+ Process Process Process (e.g. Rails)
24
+ \ | /
25
+ \ | /
26
+ Stomp Server (e.g. ActiveMQ)
27
+ |
28
+ |
29
+ Process (e.g. Adhearsion)
30
+
31
+ Note: Adhearsion could also be the sender of messages through the Stomp server which are consumed by a number of handlers.
32
+
33
+ Setting up a Ruby Stomp server
34
+ ==============================
35
+
36
+ Install the pure-Ruby Stomp server by doing "gem install stompserver". This will add the "stompserver" command to your system. When running it without any parameters, it starts without requiring authentication. If you're wanting to get a quick experiment running, I recommend simply doing that.
37
+
38
+ Open the config.yml file in the stomp_gateway component folder. Comment out the four settings at the top of the file named "user", "pass", "host" and "port" by prepending a "#" to their line. This will cause the component to choose defaults for those properties. The component's defaults will match the expected credentials for the experimental stompserver you're already running on your computer.
39
+
40
+ You also need specify a subscription name in
41
+
42
+ events.stomp.start_call.each do |event|
43
+ # The "event" variable holds a Stomp::Message object.
44
+ name = event.headers
45
+ end
46
+
47
+ You a
@@ -0,0 +1,12 @@
1
+ # Comment out any of these properties to use a default.
2
+
3
+ user: stomp_user
4
+ pass: secret_password
5
+ host: localhost
6
+ port: 61613
7
+
8
+ ### Add your list of subscriptions below that this gateway should proxy to events.rb
9
+
10
+ # subscriptions:
11
+ # - start_call
12
+ # - hangup_call
@@ -0,0 +1,34 @@
1
+ require 'stomp'
2
+
3
+ # TODO: Recover from a disconnect!
4
+
5
+ initialization do
6
+ user = COMPONENTS.stomp_gateway[:user] || ""
7
+ pass = COMPONENTS.stomp_gateway[:pass] || ""
8
+ host = COMPONENTS.stomp_gateway[:host] || "localhost"
9
+ port = COMPONENTS.stomp_gateway[:port] || 61613
10
+
11
+ ::StompGatewayConnection = Stomp::Client.open(user, pass, host, port)
12
+
13
+ subscriptions = COMPONENTS.stomp_gateway["subscriptions"]
14
+
15
+ ahn_log.stomp_gateway "Connection established. Subscriptions: #{subscriptions.inspect}"
16
+
17
+ Events.register_namespace_name "/stomp"
18
+
19
+ subscriptions.each do |subscription|
20
+ Events.register_namespace_name "/stomp/#{subscription}"
21
+ ::StompGatewayConnection.subscribe subscription do |event|
22
+ Adhearsion::Events.trigger ["stomp", subscription], event
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ methods_for :global do
29
+ def send_stomp(destination, message, headers={})
30
+ ::StompGatewayConnection.send(destination, message, headers)
31
+ end
32
+ end
33
+
34
+ # In the future, I may add a methods_for(:events) method which allows synchronous messaging.
@@ -0,0 +1,11 @@
1
+ Adhearsion RESTful RPC Component
2
+ ================================
3
+
4
+ This is a component for people want to integrate their telephony systems with non-Ruby systems. When enabled, this component
5
+ will start up a HTTP server within the Adhearsion process and accept POST requests to invoke Ruby methods shared in the
6
+ `methods_for(:rpc)` context.
7
+
8
+ Protocol Notes
9
+ --------------
10
+
11
+ When POSTing your data to.
@@ -0,0 +1,34 @@
1
+ # Use path_nesting to specify an arbitrarily nested. Could be used for additional security or in HTTP reverse proxy server.
2
+ path_nesting: /
3
+
4
+ port: 5000
5
+
6
+ # The "handler" option here can be any valid Rack::Handler constant name.
7
+ # Other options: WEBrick, EventedMongrel.
8
+ # If you don't know the differences between these, "Mongrel" is definitely a good choice.
9
+ handler: Mongrel
10
+
11
+ # In a production system, you should make this "false" since
12
+ show_exceptions: true
13
+
14
+ # The "authentication" config option can either be "false" or key/value pairs representing allowed usernames and passwords.
15
+
16
+ #authentication: false
17
+ authentication:
18
+ jicksta: roflcopterz
19
+ foo: bar6213671682
20
+
21
+ access: everyone # When allowing "everyone" access, no IPs are blocked.
22
+ #access: whitelist # When using a whitelist, the "whitelist" data below will be used.
23
+ #access: blacklist # When using a blacklist, the "blacklist" data below will be used.
24
+
25
+ # This is a list of IPs which are exclusively allowed to call this web service.
26
+ # Note: whitelists are far more secure than blacklists.
27
+ whitelist:
28
+ - 127.0.0.1
29
+ - 192.168.*.*
30
+
31
+ # This is a list of the IPs which are explicitly NOT allowed to call this web service. This will only be used if "access" is
32
+ # set to "blacklist" above.
33
+ blacklist:
34
+ - 100.200.100.200
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rest_client'
3
+ require 'json'
4
+
5
+ # You must have the "rest-client" and "json" gems installed for this file to work.
6
+
7
+ class RESTfulAdhearsion
8
+
9
+ DEFAULT_OPTIONS = {
10
+ # Note: :user and :password are non-existent by default
11
+ :host => "localhost",
12
+ :port => "5000",
13
+ :path_nesting => "/"
14
+ }
15
+
16
+ def initialize(options={})
17
+ @options = DEFAULT_OPTIONS.merge options
18
+
19
+ @path_nesting = @options.delete :path_nesting
20
+ @host = @options.delete :host
21
+ @port = @options.delete :port
22
+
23
+ @url_beginning = "http://#{@host}:#{@port}#{@path_nesting}"
24
+ end
25
+
26
+ def method_missing(method_name, *args)
27
+ JSON.parse RestClient::Resource.new(@url_beginning + method_name.to_s, @options).post(args.to_json)
28
+ end
29
+
30
+ end
31
+
32
+ Adhearsion = RESTfulAdhearsion.new :host => "localhost", :port => 5000, :user => "jicksta", :password => "roflcopterz"
33
+
34
+ # ### Sample component code. Try doing "ahn create component testing123" and pasting this code in.
35
+ #
36
+ # methods_for :rpc do
37
+ # def i_like_hashes(options={})
38
+ # options.has_key?(:foo)
39
+ # end
40
+ # def i_like_arrays(*args)
41
+ # args.reverse
42
+ # end
43
+ # end
44
+
45
+ # Note: everything returned will be wrapped in an Array
46
+
47
+ p Adhearsion.i_like_hashes(:foo => "bar")
48
+ p Adhearsion.i_like_arrays(1,2,3,4,5)
@@ -0,0 +1,87 @@
1
+ require 'rack'
2
+ require 'json'
3
+
4
+ # Don't you love regular expressions? Matches only 0-255 octets. Recognizes "*" as an octet wildcard.
5
+ VALID_IP_ADDRESS = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|\*)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|\*)$/
6
+
7
+ def ip_allowed?(ip)
8
+ raise ArgumentError, "#{ip.inspect} is not a valid IP address!" unless ip.kind_of?(String) && ip =~ VALID_IP_ADDRESS
9
+
10
+ octets = ip.split "."
11
+
12
+ case COMPONENTS.restful_rpc["access"]
13
+ when "everyone"
14
+ true
15
+ when "whitelist"
16
+ whitelist = COMPONENTS.restful_rpc["whitelist"]
17
+ !! whitelist.find do |pattern|
18
+ pattern_octets = pattern.split "."
19
+ # Traverse both arrays in parallel
20
+ octets.zip(pattern_octets).map do |octet, octet_pattern|
21
+ octet_pattern == "*" ? true : (octet == octet_pattern)
22
+ end == [true, true, true, true]
23
+ end
24
+ when "blacklist"
25
+ blacklist = COMPONENTS.restful_rpc["blacklist"]
26
+ ! blacklist.find do |pattern|
27
+ pattern_octets = pattern.split "."
28
+ # Traverse both arrays in parallel
29
+ octets.zip(pattern_octets).map do |octet, octet_pattern|
30
+ octet_pattern == "*" ? true : (octet == octet_pattern)
31
+ end == [true, true, true, true]
32
+ end
33
+ else
34
+ raise Adhearsion::Components::ConfigurationError, 'Unrecognized "access" configuration value!'
35
+ end
36
+ end
37
+
38
+ RESTFUL_API_HANDLER = lambda do |env|
39
+ json = env["rack.input"].read
40
+
41
+ # Return "Bad Request" HTTP error if the client forgot
42
+ return [400, {}, "You must POST a valid JSON object!"] if json.blank?
43
+
44
+ json = JSON.parse json
45
+
46
+ nesting = COMPONENTS.restful_rpc["path_nesting"]
47
+ path = env["PATH_INFO"]
48
+
49
+ return [404, {}, "This resource does not respond to #{path.inspect}"] unless path[0...nesting.size] == nesting
50
+
51
+ path = path[nesting.size..-1]
52
+
53
+ return [404, {"Content-Type" => "application/json"}, "You cannot nest method names!"] if path.include?("/")
54
+
55
+ rpc_object = Adhearsion::Components.component_manager.extend_object_with(Object.new, :rpc)
56
+
57
+ # TODO: set the content-type and other HTTP headers
58
+ response_object = Array rpc_object.send(path, *json)
59
+ [200, {"Content-Type" => "application/json"}, response_object.to_json]
60
+
61
+ end
62
+
63
+ initialization do
64
+ config = COMPONENTS.restful_rpc
65
+
66
+ api = RESTFUL_API_HANDLER
67
+
68
+ port = config["port"] || 5000
69
+ authentication = config["authentication"]
70
+ show_exceptions = config["show_exceptions"]
71
+ handler = Rack::Handler.const_get(config["handler"] || "Mongrel")
72
+
73
+ if authentication
74
+ api = Rack::Auth::Basic.new(api) do |username, password|
75
+ authentication[username] == password
76
+ end
77
+ api.realm = "Adhearsion API"
78
+ end
79
+
80
+ if show_exceptions
81
+ api = Rack::ShowStatus.new(Rack::ShowExceptions.new(api))
82
+ end
83
+
84
+ Thread.new do
85
+ handler.run api, :Port => port
86
+ end
87
+ end
@@ -0,0 +1,56 @@
1
+ methods_for :dialplan do
2
+ def simon_game
3
+ SimonGame.new(self).start
4
+ end
5
+ end
6
+
7
+ class SimonGame
8
+
9
+ def initialize(call)
10
+ @call = call
11
+ reset
12
+ end
13
+
14
+ def start
15
+ loop do
16
+ say_number
17
+ collect_attempt
18
+ verify_attempt
19
+ end
20
+ end
21
+
22
+ def random_number
23
+ rand(10).to_s
24
+ end
25
+
26
+ def update_number
27
+ @number << random_number
28
+ end
29
+
30
+ def say_number
31
+ update_number
32
+ @call.say_digits @number
33
+ end
34
+
35
+ def collect_attempt
36
+ @attempt = @call.input @number.length
37
+ end
38
+
39
+ def verify_attempt
40
+ if attempt_correct?
41
+ @call.play 'good'
42
+ else
43
+ @call.play %W[#{@number.length-1} times wrong-try-again-smarty]
44
+ reset
45
+ end
46
+ end
47
+
48
+ def attempt_correct?
49
+ @attempt == @number
50
+ end
51
+
52
+ def reset
53
+ @attempt, @number = '', ''
54
+ end
55
+
56
+ end