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,373 @@
1
+ module Adhearsion
2
+
3
+ class << self
4
+
5
+ ##
6
+ # Shuts down the framework.
7
+ #
8
+ def self.shutdown!
9
+ ahn_log "Shutting down gracefully at #{Time.now}."
10
+ Events.stop!
11
+ exit
12
+ end
13
+
14
+ end
15
+ class PathString < String
16
+
17
+ class << self
18
+
19
+ ##
20
+ # Will return a PathString for the application root folder to which the specified arbitrarily nested subfolder belongs.
21
+ # It works by traversing parent directories looking for the .ahnrc file. If no .ahnrc is found, nil is returned.
22
+ #
23
+ # @param [String] folder The path to the directory which should be a
24
+ # @return [nil] if the subdirectory does not belong to a parent Adhearsion app directory
25
+ # @return [PathString] if a directory is found
26
+ #
27
+ def from_application_subdirectory(folder)
28
+ folder = File.expand_path folder
29
+ ahn_rc = nil
30
+
31
+ until ahn_rc || folder == "/"
32
+ possible_ahn_rc = File.join(folder, ".ahnrc")
33
+ if File.exists?(possible_ahn_rc)
34
+ ahn_rc = possible_ahn_rc
35
+ else
36
+ folder = File.expand_path(folder + "/..")
37
+ end
38
+ end
39
+ ahn_rc ? new(folder) : nil
40
+ end
41
+ end
42
+
43
+ attr_accessor :component_path, :dialplan_path, :log_path
44
+
45
+ def initialize(path)
46
+ super
47
+ defaults
48
+ end
49
+
50
+ def defaults
51
+ @component_path = build_path_for "components"
52
+ @dialplan_path = dup
53
+ @log_path = build_path_for "logs"
54
+ end
55
+
56
+ def base_path=(value)
57
+ replace(value)
58
+ defaults
59
+ end
60
+
61
+ def using_base_path(temporary_base_path, &block)
62
+ original_path = dup
63
+ self.base_path = temporary_base_path
64
+ block.call
65
+ ensure
66
+ self.base_path = original_path
67
+ end
68
+
69
+ private
70
+ def build_path_for(path)
71
+ File.join(to_s, path)
72
+ end
73
+ end
74
+
75
+ class Initializer
76
+
77
+ class << self
78
+ def get_rules_from(location)
79
+ location = File.join location, ".ahnrc" if File.directory? location
80
+ File.exists?(location) ? YAML.load_file(location) : nil
81
+ end
82
+
83
+ def ahn_root=(path)
84
+ if Object.constants.include?("AHN_ROOT")
85
+ Object.const_get(:AHN_ROOT).base_path = File.expand_path(path)
86
+ else
87
+ Object.const_set(:AHN_ROOT, PathString.new(File.expand_path(path)))
88
+ end
89
+ end
90
+
91
+ def start(*args, &block)
92
+ new(*args, &block).start
93
+ end
94
+
95
+ def start_from_init_file(file, ahn_app_path)
96
+ return if defined?(@@started) && @@started
97
+ start ahn_app_path, :loaded_init_files => file
98
+ end
99
+
100
+ end
101
+
102
+ attr_reader :path, :daemon, :pid_file, :log_file, :ahn_app_log_directory
103
+
104
+ # Creation of pid_files
105
+ #
106
+ # - You may want to have Adhearsion create a process identification
107
+ # file when it boots so that a crash monitoring program such as
108
+ # Monit can reboot if necessary or so the init script can kill it
109
+ # for system shutdowns.
110
+ # - To have Adhearsion create a pid file in the default location (i.e.
111
+ # AHN_INSTALL_DIR/adhearsion.pid), supply :pid_file with 'true'. Otherwise
112
+ # one is not created UNLESS it is running in daemon mode, in which
113
+ # case one is created. You can force Adhearsion to not create one
114
+ # even in daemon mode by supplying "false".
115
+ def initialize(path=nil, options={})
116
+ @@started = true
117
+ @path = path
118
+ @daemon = options[:daemon]
119
+ @pid_file = options[:pid_file].nil? ? ENV['PID_FILE'] : options[:pid_file]
120
+ @loaded_init_files = options[:loaded_init_files]
121
+ end
122
+
123
+ def start
124
+ self.class.ahn_root = path
125
+
126
+ resolve_pid_file_path
127
+ resolve_log_file_path
128
+ switch_to_root_directory
129
+ catch_termination_signal
130
+ bootstrap_rc
131
+ daemonize! if should_daemonize?
132
+ initialize_log_file
133
+ load_all_init_files
134
+ init_components_subsystem
135
+ init_modules
136
+ init_events_subsystem
137
+ create_pid_file if pid_file
138
+ load_components
139
+ init_events_file
140
+
141
+ ahn_log "Adhearsion initialized!"
142
+
143
+ trigger_after_initialized_hooks
144
+ join_important_threads
145
+
146
+ self
147
+ end
148
+
149
+ def default_pid_path
150
+ File.join AHN_ROOT, 'adhearsion.pid'
151
+ end
152
+
153
+ def resolve_pid_file_path
154
+ @pid_file = if pid_file.equal?(true) then default_pid_path
155
+ elsif pid_file then pid_file
156
+ elsif pid_file.equal?(false) then nil
157
+ # FIXME @pid_file = @daemon? Assignment or equality? I'm assuming equality.
158
+ else @pid_file = @daemon ? default_pid_path : nil
159
+ end
160
+ end
161
+
162
+ def resolve_log_file_path
163
+ @ahn_app_log_directory = AHN_ROOT + '/log'
164
+ @log_file = File.expand_path(ahn_app_log_directory + "/adhearsion.log")
165
+ end
166
+
167
+ def switch_to_root_directory
168
+ Dir.chdir AHN_ROOT
169
+ end
170
+
171
+ def catch_termination_signal
172
+ %w'INT TERM'.each do |process_signal|
173
+ trap process_signal do
174
+ ahn_log "Shutting down gracefully at #{Time.now}."
175
+ Events.trigger :shutdown
176
+ exit
177
+ end
178
+ end
179
+ end
180
+
181
+ ##
182
+ # This step in the initialization process loads the .ahnrc in the given app folder. With the information in .ahnrc, we
183
+ # can continue the initialization knowing where certain files are specifically.
184
+ #
185
+ def bootstrap_rc
186
+ rules = self.class.get_rules_from AHN_ROOT
187
+
188
+ AHN_CONFIG.ahnrc = rules
189
+
190
+ # DEPRECATION: Check if the old paths format is being used. If so, abort and notify.
191
+ if rules.has_key?("paths") && rules["paths"].kind_of?(Hash)
192
+ paths = rules["paths"].each_pair do |key,value|
193
+ if value.kind_of?(Hash)
194
+ if value.has_key?("directory") || value.has_key?("pattern")
195
+ puts
196
+ puts *caller
197
+ puts
198
+
199
+ abort <<-WARNING
200
+ Deprecation Warning
201
+ -------------------
202
+ The (hidden) .ahnrc file in this app is of an older format and needs to be fixed.
203
+
204
+ There is a rake task to automatically fix it or you can do it manually. Note: it's
205
+ best if you do it manually so you can retain the YAML comments in your .ahnrc file.
206
+
207
+ The rake task is called "deprecations:fix_ahnrc_path_format".
208
+
209
+ To do it manually, find all entries in the "paths" section of your ".ahnrc" file
210
+ which look like the following:
211
+
212
+ paths:
213
+ key_name_could_be_anything:
214
+ directory: some_folder
215
+ pattern: *.rb
216
+
217
+ Note: the "models" section had this syntax before:
218
+
219
+ models:
220
+ directory: models
221
+ pattern: "*.rb"
222
+
223
+ The NEW syntax is as follows (using models as an example):
224
+
225
+ models: models/*.rb
226
+
227
+ This new format is much cleaner.
228
+
229
+ Adhearsion will abort until you fix this. Sorry for the incovenience.
230
+ WARNING
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ gems = rules['gems']
237
+ if gems.kind_of?(Hash) && gems.any? && respond_to?(:gem)
238
+ gems.each_pair do |gem_name,properties_hash|
239
+ if properties_hash && properties_hash["version"]
240
+ gem gem_name, properties_hash["version"]
241
+ else
242
+ gem gem_name
243
+ end
244
+ if properties_hash
245
+ case properties_hash["require"]
246
+ when Array
247
+ properties_hash["require"].each { |lib| require lib }
248
+ when String
249
+ require properties_hash["require"]
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
255
+
256
+ def load_all_init_files
257
+ init_files_from_rc = AHN_CONFIG.files_from_setting("paths", "init").map { |file| File.expand_path(file) }
258
+ already_loaded_init_files = Array(@loaded_init_files).map { |file| File.expand_path(file) }
259
+ (init_files_from_rc - already_loaded_init_files).each { |init| load init }
260
+ end
261
+
262
+ def init_modules
263
+ require 'adhearsion/initializer/database.rb'
264
+ require 'adhearsion/initializer/asterisk.rb'
265
+ require 'adhearsion/initializer/drb.rb'
266
+ require 'adhearsion/initializer/rails.rb'
267
+ # require 'adhearsion/initializer/freeswitch.rb'
268
+
269
+ DatabaseInitializer.start if AHN_CONFIG.database_enabled?
270
+ AsteriskInitializer.start if AHN_CONFIG.asterisk_enabled?
271
+ DrbInitializer.start if AHN_CONFIG.drb_enabled?
272
+ RailsInitializer.start if AHN_CONFIG.rails_enabled?
273
+ # FreeswitchInitializer.start if AHN_CONFIG.freeswitch_enabled?
274
+ end
275
+
276
+ def init_events_subsystem
277
+ application_events_files = AHN_CONFIG.files_from_setting("paths", "events")
278
+ if application_events_files.any?
279
+ Events.register_callback(:shutdown) do
280
+ ahn_log.events "Performing a graceful stop of events subsystem"
281
+ Events.framework_theatre.graceful_stop!
282
+ end
283
+ Events.framework_theatre.start!
284
+ else
285
+ ahn_log.events.warn 'No entries in the "events" section of .ahnrc. Skipping its initialization.'
286
+ end
287
+ end
288
+
289
+ def init_events_file
290
+ application_events_files = AHN_CONFIG.files_from_setting("paths", "events")
291
+ application_events_files.each do |file|
292
+ Events.framework_theatre.load_events_file file
293
+ end
294
+ end
295
+
296
+ def should_daemonize?
297
+ @daemon || ENV['DAEMON']
298
+ end
299
+
300
+ def daemonize!
301
+ ahn_log "Daemonizing now! Creating #{pid_file}."
302
+ extend Adhearsion::CustomDaemonizer
303
+ daemonize log_file
304
+ end
305
+
306
+ def initialize_log_file
307
+ Dir.mkdir(ahn_app_log_directory) unless File.directory? ahn_app_log_directory
308
+ file_logger = Log4r::FileOutputter.new("Main Adhearsion log file", :filename => log_file, :trunc => false)
309
+
310
+ if should_daemonize?
311
+ Logging::AdhearsionLogger.outputters = file_logger
312
+ else
313
+ Logging::AdhearsionLogger.outputters << file_logger
314
+ end
315
+ Logging::DefaultAdhearsionLogger.redefine_outputters
316
+ end
317
+
318
+ def create_pid_file(file = pid_file)
319
+ if file
320
+ File.open pid_file, 'w' do |file|
321
+ file.puts Process.pid
322
+ end
323
+
324
+ Events.register_callback :shutdown do
325
+ File.delete(pid_file) if File.exists?(pid_file)
326
+ end
327
+ end
328
+ end
329
+
330
+ def init_components_subsystem
331
+ @components_directory = File.expand_path "components"
332
+ if File.directory? @components_directory
333
+ Components.component_manager = Components::ComponentManager.new @components_directory
334
+ Kernel.send(:const_set, :COMPONENTS, Components.component_manager.lazy_config_loader)
335
+ Components.component_manager.globalize_global_scope!
336
+ Components.component_manager.extend_object_with(Theatre::CallbackDefinitionLoader, :events)
337
+ else
338
+ ahn_log.warn "No components directory found. Not initializing any components."
339
+ end
340
+ end
341
+
342
+ def load_components
343
+ if Components.component_manager
344
+ Components.component_manager.load_components
345
+ end
346
+ end
347
+
348
+ def trigger_after_initialized_hooks
349
+ Events.trigger_immediately :after_initialized
350
+ end
351
+
352
+ ##
353
+ # This method will block Thread.main() until calling join() has returned for all Threads in IMPORTANT_THREADS.
354
+ # Note: IMPORTANT_THREADS won't always contain Thread instances. It simply requires the objects respond to join().
355
+ #
356
+ def join_important_threads
357
+ # Note: we're using this ugly accumulator to ensure that all threads have ended since IMPORTANT_THREADS will almost
358
+ # certainly change sizes after this method is called.
359
+ index = 0
360
+ until index == IMPORTANT_THREADS.size
361
+ begin
362
+ IMPORTANT_THREADS[index].join
363
+ rescue => e
364
+ ahn_log.error "Error after join()ing Thread #{thread.inspect}. #{e.message}"
365
+ ensure
366
+ index = index + 1
367
+ end
368
+ end
369
+ end
370
+
371
+ class InitializationFailedError < Exception; end
372
+ end
373
+ end
@@ -0,0 +1,92 @@
1
+ require 'log4r'
2
+
3
+ module Adhearsion
4
+ module Logging
5
+
6
+ @@logging_level_lock = Mutex.new
7
+
8
+ class << self
9
+
10
+ def silence!
11
+ self.logging_level = :fatal
12
+ end
13
+
14
+ def unsilence!
15
+ self.logging_level = :info
16
+ end
17
+
18
+ def logging_level=(new_logging_level)
19
+ new_logging_level = Log4r.const_get(new_logging_level.to_s.upcase)
20
+ @@logging_level_lock.synchronize do
21
+ @@logging_level = new_logging_level
22
+ Log4r::Logger.each_logger do |logger|
23
+ logger.level = new_logging_level
24
+ end
25
+ end
26
+ end
27
+
28
+ def logging_level
29
+ @@logging_level_lock.synchronize do
30
+ return @@logging_level ||= Log4r::INFO
31
+ end
32
+ end
33
+ end
34
+
35
+ class AdhearsionLogger < Log4r::Logger
36
+
37
+ @@outputters = [Log4r::Outputter.stdout]
38
+
39
+ class << self
40
+ def outputters
41
+ @@outputters
42
+ end
43
+
44
+ def outputters=(other)
45
+ @@outputters = other
46
+ end
47
+ end
48
+
49
+ def initialize(*args)
50
+ super
51
+ redefine_outputters
52
+ end
53
+
54
+ def redefine_outputters
55
+ self.outputters = @@outputters
56
+ end
57
+
58
+ def method_missing(logger_name, *args, &block)
59
+ define_logging_method(logger_name, self.class.new(logger_name.to_s))
60
+ send(logger_name, *args, &block)
61
+ end
62
+
63
+ private
64
+
65
+ def define_logging_method(name, logger)
66
+ # Can't use Module#define_method() because blocks in Ruby 1.8.x can't
67
+ # have their own block arguments.
68
+ self.class.class_eval(<<-CODE, __FILE__, __LINE__)
69
+ def #{name}(*args, &block)
70
+ logger = Log4r::Logger['#{name}']
71
+ if args.any? || block_given?
72
+ logger.info(*args, &block)
73
+ else
74
+ logger
75
+ end
76
+ end
77
+ CODE
78
+ end
79
+ end
80
+
81
+ DefaultAdhearsionLogger = AdhearsionLogger.new 'ahn'
82
+
83
+ end
84
+ end
85
+
86
+ def ahn_log(*args)
87
+ if args.any?
88
+ Adhearsion::Logging::DefaultAdhearsionLogger.info(*args)
89
+ else
90
+ Adhearsion::Logging::DefaultAdhearsionLogger
91
+ end
92
+ end
@@ -0,0 +1,5 @@
1
+ task:migrate do
2
+ require 'active_record'
3
+ %w.db/migrate db/ahn..each
4
+ ActiveRecord::Migrator.migrate 'db/migrate', ENV['VERSION'] ? ENV['VERSION'].to_i : nil
5
+ end
@@ -0,0 +1,59 @@
1
+ namespace :deprecations do
2
+ desc <<-DESC
3
+ Older versions of Adhearsion had an .ahnrc "paths" section similar to the following...
4
+
5
+ paths:
6
+ models:
7
+ directory: models
8
+ pattern: *.rb
9
+
10
+ This has been deprecated. The new format is this:
11
+
12
+ paths:
13
+ models: {models,gui/app/models}/*.rb
14
+
15
+ This Rake task will fix your .ahnrc if you have
16
+ DESC
17
+ task :fix_ahnrc_path_format do
18
+ puts "\nThis will remove all comments from your .ahnrc file. A backup will be created as .ahnrc.backup."
19
+ puts "If you wish to do this manually to preserve your comments, simply overwrite .ahnrc with .ahnrc.backup"
20
+ puts "and apply the change manually."
21
+ puts
22
+
23
+ require 'fileutils'
24
+ require 'yaml'
25
+
26
+ ahnrc_file = File.expand_path(".ahnrc")
27
+
28
+ FileUtils.cp ahnrc_file, ahnrc_file + ".backup"
29
+ ahnrc_contents = YAML.load_file ahnrc_file
30
+
31
+ abort '.ahnrc does not have a "paths" section!' unless ahnrc_contents.has_key? "paths"
32
+
33
+ paths = ahnrc_contents["paths"]
34
+ paths.clone.each_pair do |key,value|
35
+ if value.kind_of?(Hash)
36
+ if value.has_key?("directory") || value.has_key?("pattern")
37
+ directory, pattern = value.values_at "directory", "pattern"
38
+ new_path = "#{directory}/#{pattern}"
39
+
40
+ puts "!!! CHANGING KEY #{key.inspect}!"
41
+ puts "!!! NEW: #{new_path.inspect}"
42
+ puts "!!! OLD:\n#{{key => value}.to_yaml.sub("---", "")}\n\n"
43
+
44
+ paths[key] = new_path
45
+ end
46
+ end
47
+ end
48
+
49
+ ahnrc_contents["paths"] = paths
50
+ new_yaml = ahnrc_contents.to_yaml.gsub("--- \n", "")
51
+
52
+ puts "New .ahnrc file:\n" + ("#" * 25) + "\n"
53
+ puts new_yaml
54
+ puts '#' * 25
55
+
56
+ File.open(ahnrc_file, "w") { |file| file.puts new_yaml }
57
+ puts "Wrote to .ahnrc. Done!"
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+ namespace:create do
2
+
3
+ task:war do
4
+ # Hmm, this will is a tough one
5
+ end
6
+
7
+ task:rails_plugin do
8
+
9
+ end
10
+
11
+ task:migration do
12
+ name = ARGV.shift
13
+ end
14
+ end
15
+
16
+ namespace:delete do
17
+ task:migration do
18
+ # Take arg.underscore and remove it
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ task :sanity do
2
+ puts "Performing many checks on your Adhearsion application!"
3
+ # TODO: Anything that should be brought to the user's attention should be placed here!
4
+ end
@@ -0,0 +1,37 @@
1
+ namespace:test do
2
+ desc "Run tests for a component specified by COMPONENT=<component_name>. If no component is specified, tests will be executed for all components"
3
+ task :component do
4
+ component = ENV['COMPONENT']
5
+ components_to_test = component.nil? ? all_component_directories : [full_path_for(component)]
6
+ components_to_test.each do |component_name|
7
+ setup_and_execute(component_name)
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def setup_and_execute(component_path)
14
+ task = create_test_task_for(component_path)
15
+ Rake::Task[task.name].execute
16
+ end
17
+
18
+ def create_test_task_for(component_path)
19
+ Rake::TestTask.new(task_name_for(component_path)) do |t|
20
+ t.libs = ["lib", "test"].map{|subdir| File.join(component_path, subdir)}
21
+ t.test_files = FileList["#{component_path}/test/test_*.rb"]
22
+ t.verbose = true
23
+ end
24
+ end
25
+
26
+ def task_name_for(component_path)
27
+ "test_#{component_path.split(/\//).last}"
28
+ end
29
+
30
+ def all_component_directories
31
+ Dir['components/*']
32
+ end
33
+
34
+ def full_path_for(component)
35
+ component =~ /^components\// ? component : File.join("components", component)
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ require 'rake/testtask'
2
+ require 'adhearsion'
3
+ require 'adhearsion/tasks/database'
4
+ require 'adhearsion/tasks/testing'
5
+ require 'adhearsion/tasks/generating'
6
+ require 'adhearsion/tasks/lint'
7
+ require 'adhearsion/tasks/deprecations'
8
+
9
+ namespace :adhearsion do
10
+ desc "Dump useful information about this application's adhearsion environment"
11
+ task :about do
12
+ puts "Adhearsion version: #{Adhearsion::VERSION::STRING}"
13
+ end
14
+ end
15
+
16
+ task :default => "adhearsion:about"
@@ -0,0 +1,9 @@
1
+ module Adhearsion #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0 unless defined? MAJOR
4
+ MINOR = 7 unless defined? MINOR
5
+ TINY = 999 unless defined? TINY
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.') unless defined? STRING
8
+ end
9
+ end
@@ -0,0 +1,81 @@
1
+ require 'gserver'
2
+ module Adhearsion
3
+ module VoIP
4
+ module Asterisk
5
+ module AGI
6
+ class Server
7
+
8
+ class RubyServer < GServer
9
+
10
+ def initialize(port, host)
11
+ super(port, host, (1.0/0.0)) # (1.0/0.0) == Infinity
12
+ end
13
+
14
+ def serve(io)
15
+ call = Adhearsion.receive_call_from(io)
16
+ Events.trigger_immediately([:asterisk, :before_call], call)
17
+ ahn_log.agi "Handling call with variables #{call.variables.inspect}"
18
+
19
+ return DialPlan::ConfirmationManager.handle(call) if DialPlan::ConfirmationManager.confirmation_call?(call)
20
+
21
+ # This is what happens 99.9% of the time.
22
+
23
+ DialPlan::Manager.handle call
24
+ rescue DialPlan::Manager::NoContextError => e
25
+ ahn_log.agi e.message
26
+ call.hangup!
27
+ rescue FailedExtensionCallException => failed_call
28
+ begin
29
+ ahn_log.agi "Received \"failed\" meta-call with :failed_reason => #{failed_call.call.failed_reason.inspect}. Executing Executing /asterisk/failed_call event callbacks."
30
+ Events.trigger [:asterisk, :failed_call], failed_call.call
31
+ call.hangup!
32
+ rescue => e
33
+ ahn_log.agi.error e
34
+ end
35
+ rescue HungupExtensionCallException => hungup_call
36
+ begin
37
+ ahn_log.agi "Received \"h\" meta-call. Executing /asterisk/call_hangup event callbacks."
38
+ Events.trigger [:asterisk, :call_hangup], hungup_call.call
39
+ call.hangup!
40
+ rescue => e
41
+ ahn_log.agi.error e
42
+ end
43
+ rescue UselessCallException
44
+ ahn_log.agi "Ignoring meta-AGI request"
45
+ call.hangup!
46
+ # TBD: (may have more hooks than what Jay has defined in hooks.rb)
47
+ rescue => e
48
+ ahn_log.agi.error e.inspect
49
+ ahn_log.agi.error e.backtrace.map { |s| " " * 5 + s }.join("\n")
50
+ ensure
51
+ Adhearsion.remove_inactive_call call rescue nil
52
+ end
53
+
54
+ end
55
+
56
+ DEFAULT_OPTIONS = { :server_class => RubyServer, :port => 4573, :host => "0.0.0.0" } unless defined? DEFAULT_OPTIONS
57
+ attr_reader :host, :port, :server_class, :server
58
+
59
+ def initialize(options = {})
60
+ options = DEFAULT_OPTIONS.merge options
61
+ @host, @port, @server_class = options.values_at(:host, :port, :server_class)
62
+ @server = server_class.new(port, host)
63
+ end
64
+
65
+ def start
66
+ server.start
67
+ end
68
+
69
+ def shutdown
70
+ server.stop
71
+ end
72
+
73
+ def join
74
+ server.join
75
+ end
76
+
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end