sant0sk1-adhearsion 0.7.999

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/LICENSE +456 -0
  2. data/README.txt +5 -0
  3. data/Rakefile +75 -0
  4. data/adhearsion.gemspec +136 -0
  5. data/app_generators/ahn/USAGE +5 -0
  6. data/app_generators/ahn/ahn_generator.rb +77 -0
  7. data/app_generators/ahn/templates/.ahnrc +36 -0
  8. data/app_generators/ahn/templates/README +8 -0
  9. data/app_generators/ahn/templates/Rakefile +18 -0
  10. data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
  11. data/app_generators/ahn/templates/components/simon_game/lib/simon_game.rb +61 -0
  12. data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +14 -0
  13. data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +31 -0
  14. data/app_generators/ahn/templates/config/startup.rb +53 -0
  15. data/app_generators/ahn/templates/dialplan.rb +4 -0
  16. data/bin/ahn +28 -0
  17. data/bin/ahnctl +68 -0
  18. data/bin/jahn +32 -0
  19. data/lib/adhearsion.rb +32 -0
  20. data/lib/adhearsion/blank_slate.rb +5 -0
  21. data/lib/adhearsion/cli.rb +106 -0
  22. data/lib/adhearsion/component_manager.rb +277 -0
  23. data/lib/adhearsion/core_extensions/all.rb +9 -0
  24. data/lib/adhearsion/core_extensions/array.rb +0 -0
  25. data/lib/adhearsion/core_extensions/custom_daemonizer.rb +45 -0
  26. data/lib/adhearsion/core_extensions/global.rb +1 -0
  27. data/lib/adhearsion/core_extensions/hash.rb +0 -0
  28. data/lib/adhearsion/core_extensions/metaprogramming.rb +17 -0
  29. data/lib/adhearsion/core_extensions/numeric.rb +4 -0
  30. data/lib/adhearsion/core_extensions/proc.rb +0 -0
  31. data/lib/adhearsion/core_extensions/publishable.rb +73 -0
  32. data/lib/adhearsion/core_extensions/relationship_properties.rb +40 -0
  33. data/lib/adhearsion/core_extensions/string.rb +26 -0
  34. data/lib/adhearsion/core_extensions/thread.rb +13 -0
  35. data/lib/adhearsion/core_extensions/thread_safety.rb +7 -0
  36. data/lib/adhearsion/core_extensions/time.rb +0 -0
  37. data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
  38. data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
  39. data/lib/adhearsion/distributed/gateways/rest_gateway.rb +9 -0
  40. data/lib/adhearsion/distributed/gateways/soap_gateway.rb +9 -0
  41. data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +9 -0
  42. data/lib/adhearsion/distributed/peer_finder.rb +0 -0
  43. data/lib/adhearsion/distributed/remote_cli.rb +0 -0
  44. data/lib/adhearsion/events_support.rb +26 -0
  45. data/lib/adhearsion/hooks.rb +57 -0
  46. data/lib/adhearsion/host_definitions.rb +63 -0
  47. data/lib/adhearsion/initializer.rb +246 -0
  48. data/lib/adhearsion/initializer/asterisk.rb +59 -0
  49. data/lib/adhearsion/initializer/configuration.rb +236 -0
  50. data/lib/adhearsion/initializer/database.rb +49 -0
  51. data/lib/adhearsion/initializer/drb.rb +25 -0
  52. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  53. data/lib/adhearsion/initializer/rails.rb +40 -0
  54. data/lib/adhearsion/logging.rb +92 -0
  55. data/lib/adhearsion/tasks.rb +15 -0
  56. data/lib/adhearsion/tasks/database.rb +5 -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/version.rb +9 -0
  61. data/lib/adhearsion/voip/asterisk.rb +10 -0
  62. data/lib/adhearsion/voip/asterisk/agi_server.rb +81 -0
  63. data/lib/adhearsion/voip/asterisk/ami.rb +147 -0
  64. data/lib/adhearsion/voip/asterisk/ami/actions.rb +238 -0
  65. data/lib/adhearsion/voip/asterisk/ami/machine.rb +871 -0
  66. data/lib/adhearsion/voip/asterisk/ami/machine.rl +109 -0
  67. data/lib/adhearsion/voip/asterisk/ami/parser.rb +262 -0
  68. data/lib/adhearsion/voip/asterisk/commands.rb +1284 -0
  69. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  70. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  71. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  72. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  73. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  74. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  75. data/lib/adhearsion/voip/call.rb +436 -0
  76. data/lib/adhearsion/voip/call_routing.rb +64 -0
  77. data/lib/adhearsion/voip/commands.rb +9 -0
  78. data/lib/adhearsion/voip/constants.rb +39 -0
  79. data/lib/adhearsion/voip/conveniences.rb +18 -0
  80. data/lib/adhearsion/voip/dial_plan.rb +207 -0
  81. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  82. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  83. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  84. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  85. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +71 -0
  86. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  87. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  88. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  89. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  90. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  91. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  92. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  93. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  94. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  95. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  96. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  97. metadata +167 -0
@@ -0,0 +1,9 @@
1
+ require 'English'
2
+ require 'tmpdir'
3
+ require 'tempfile'
4
+ require 'active_support'
5
+
6
+ # Require all other files here.
7
+ Dir.glob File.join(File.dirname(__FILE__), "*rb") do |file|
8
+ require file
9
+ end
File without changes
@@ -0,0 +1,45 @@
1
+ # This is largely based on the Daemonize library by Travis Whitton and
2
+ # Judson Lester. http://grub.ath.cx/daemonize. I cleaned it up a bit to
3
+ # meet Adhearsion's quality standards.
4
+ module Adhearsion
5
+ module CustomDaemonizer
6
+
7
+ # Try to fork if at all possible retrying every 5 sec if the
8
+ # maximum process limit for the system has been reached
9
+ def safefork
10
+ begin
11
+ pid = fork
12
+ return pid if pid
13
+ rescue Errno::EWOULDBLOCK
14
+ sleep 5
15
+ retry
16
+ end
17
+ end
18
+
19
+ # This method causes the current running process to become a daemon
20
+ def daemonize(log_file='/dev/null')
21
+ oldmode = 0
22
+ srand # Split rand streams between spawning and daemonized process
23
+ safefork and exit # Fork and exit from the parent
24
+
25
+ # Detach from the controlling terminal
26
+ unless sess_id = Process.setsid
27
+ raise 'Cannot detach from controlled terminal'
28
+ end
29
+
30
+ # Prevent the possibility of acquiring a controlling terminal
31
+ if oldmode.zero?
32
+ trap 'SIGHUP', 'IGNORE'
33
+ exit if pid = safefork
34
+ end
35
+
36
+ Dir.chdir "/" # Release old working directory
37
+ File.umask 0000 # Ensure sensible umask
38
+
39
+ STDIN.reopen "/dev/null"
40
+ STDOUT.reopen '/dev/null', "a"
41
+ STDERR.reopen log_file
42
+ return oldmode ? sess_id : 0
43
+ end
44
+ end
45
+ end
@@ -0,0 +1 @@
1
+ Infinity = 1.0/0.0
File without changes
@@ -0,0 +1,17 @@
1
+ class Object
2
+ def metaclass
3
+ class << self
4
+ self
5
+ end
6
+ end
7
+
8
+ def meta_eval(&block)
9
+ metaclass.instance_eval &block
10
+ end
11
+
12
+ def meta_def(name, &block)
13
+ meta_eval do
14
+ define_method name, &block
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,4 @@
1
+ class Numeric
2
+ def digit() self end
3
+ def digits() self end
4
+ end
File without changes
@@ -0,0 +1,73 @@
1
+ module Adhearsion
2
+ class DrbDoor
3
+
4
+ include Singleton
5
+
6
+ def add(interface, name, meth)
7
+ @interfaces ||= {}
8
+ @interfaces[interface] ||= returning(Object.new) { |obj| obj.metaclass.send(:attr_accessor, :__methods) }
9
+ obj = @interfaces[interface]
10
+ obj.__methods ||= {}
11
+ obj.__methods[name] = meth
12
+ obj.instance_eval(<<-STR, __FILE__, __LINE__)
13
+ def #{name}(*args, &block)
14
+ begin
15
+ __methods["#{name}"].call(*args, &block)
16
+ rescue => exception
17
+ raise RuntimeError, exception.message, exception.backtrace
18
+ end
19
+ end
20
+ STR
21
+ end
22
+
23
+ def method_missing(name, *args, &block)
24
+ return Module.const_get(name) if name.to_s =~ /^[A-Z]/
25
+ super unless @interfaces && @interfaces.has_key?(name.to_s)
26
+ @interfaces[name.to_s]
27
+ end
28
+ end
29
+
30
+ module Publishable
31
+ def self.included(base)
32
+ base.send(:alias_method_chain, :initialize, :publishable)
33
+ base.extend(ClassMethods)
34
+ end
35
+
36
+ def initialize_with_publishable(*args, &block)
37
+ initialize_without_publishable(*args, &block)
38
+ self.class.published_instance_methods.each do |(sym, interface)|
39
+ DrbDoor.instance.add(interface, sym.to_s, self.method(sym))
40
+ end
41
+ end
42
+
43
+ module ClassMethods
44
+ attr_reader :interface
45
+ attr_reader :published_instance_methods
46
+
47
+ def publish(options={}, &block)
48
+ @interface = options.delete(:through).to_s || self.to_s
49
+ begin
50
+ @capture = true
51
+ yield
52
+ ensure
53
+ @capture = false
54
+ end
55
+ end
56
+
57
+ def method_added(sym)
58
+ return if not @capture
59
+ if sym.to_s !~ /method_added/
60
+ @published_instance_methods ||= []
61
+ @published_instance_methods << [sym, @interface]
62
+ end
63
+ end
64
+
65
+ def singleton_method_added(sym)
66
+ return if not @capture
67
+ if sym.to_s !~ /method_added/
68
+ DrbDoor.instance.add(@interface, sym.to_s, method(sym.to_s))
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,40 @@
1
+ class Module
2
+
3
+ # In OOP, relationships between classes should be treated as *properties* of those classes. Often, in a complex OO
4
+ # architecture, you'll end up with many relationships that intermingle in monolithic ways, blunting the effectiveness of
5
+ # subclassing.
6
+ #
7
+ # For example, say you have an Automobile class which, in its constructor, instantiates a new Battery class and performs
8
+ # some operations on it such as calling an install() method. Let's also assume the Automobile class exposes a repair()
9
+ # method which uses a class-level method of Battery to diagnose your own instance of Battery. If the result of the
10
+ # diagnosis shows that the Battery is bad, the Automobile will instantiate a new Battery object and replace the old battery
11
+ # with the new one.
12
+ #
13
+ # Now, what if you wish to create a new Automobile derived from existing technology: a HybridAutomobile subclass. For this
14
+ # particular HybridAutomobile class, let's simply say the only difference between it and its parent is which kind of
15
+ # Battery it uses -- it requires its own special subclass of Battery. With Automobile's current implementation, its
16
+ # references to which Battery it instantiates and uses are embedded in the immutable method defintions. This
17
+ # HybridAutomobile needs to override which Battery its superclass' methods use and nothing else.
18
+ #
19
+ # For this reason, the Battery class which Automobile uses is semantically a property which others may want to override.
20
+ # In OOP theory, we define overridable properties in the form of methods and override those methods in the subclasses.
21
+ #
22
+ # This method exposes one method which creates human-readable semantics to defining these relationships as properties. It's
23
+ # used as follows:
24
+ #
25
+ # class Automobile
26
+ # relationship :battery => Battery
27
+ # relationship :chassis => Chassis
28
+ # # Other properties and instance methods here....
29
+ # end
30
+ #
31
+ # class HybridAutomobile < Automobile
32
+ # relationship :battery => HybridBattery
33
+ # end
34
+ def relationships(relationship_mapping)
35
+ relationship_mapping.each_pair do |class_name, class_object|
36
+ define_method(class_name) { class_object }
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,26 @@
1
+ class String
2
+
3
+ def unindent
4
+ gsub(/^\s*/,'')
5
+ end
6
+
7
+ def unindent!
8
+ gsub!(/^\s*/,'')
9
+ end
10
+
11
+ def self.random_char
12
+ case random_digit = rand(62)
13
+ when 0...10 : random_digit.to_s
14
+ when 10...36 : (random_digit + 55).chr
15
+ when 36...62 : (random_digit + 61).chr
16
+ end
17
+ end
18
+
19
+ def self.random(length_of_string=8)
20
+ Array.new(length_of_string) { random_char }.join
21
+ end
22
+
23
+ def nameify() downcase.gsub(/[^\w]/, '') end
24
+ def nameify!() replace nameify end
25
+
26
+ end
@@ -0,0 +1,13 @@
1
+ class Thread
2
+ class << self
3
+
4
+ # Syntactically sugar Thread.current since it's used so much.
5
+ #
6
+ # Allows:
7
+ # Thread.me.extend DSL::Dialplan::ThreadMixin
8
+ # Thread.my.call.io = io
9
+
10
+ alias me current
11
+ alias my current
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ require 'thread'
2
+ class Object
3
+ def synchronize(&block)
4
+ @mutex ||= Mutex.new
5
+ @mutex.synchronize &block
6
+ end
7
+ end
File without changes
@@ -0,0 +1,9 @@
1
+ module Adhearsion
2
+ module Distributed
3
+ module Gateway
4
+ module REST
5
+
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Adhearsion
2
+ module Distributed
3
+ module Gateway
4
+ module SOAP
5
+
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Adhearsion
2
+ module Distributed
3
+ module Gateway
4
+ module XMLRPC
5
+
6
+ end
7
+ end
8
+ end
9
+ end
File without changes
File without changes
@@ -0,0 +1,26 @@
1
+ # gem 'theatre', '>= 0.8.0'
2
+ # require 'theatre'
3
+
4
+ module Adhearsion
5
+ module Events
6
+
7
+ class << self
8
+
9
+ def framework_theatre
10
+ defined?(@@framework_theatre) ? @@framework_theatre : reinitialize_theatre!
11
+ end
12
+
13
+ def reinitialize_theatre!
14
+ @@framework_theatre.gracefully_stop! if defined? @@framework_theatre
15
+ rescue
16
+ # Recover and reinitalize
17
+ ensure
18
+ # TODO: Extract number of threads to use from AHN_CONFIG
19
+ @@framework_theatre = Theatre::Theatre.new
20
+ return @@framework_theatre
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,57 @@
1
+ module Adhearsion
2
+
3
+
4
+ module Hooks
5
+
6
+ class GenericHook
7
+
8
+ def initialize
9
+ @hooks = []
10
+ end
11
+
12
+ def create_hook(&block)
13
+ @hooks.synchronize do
14
+ @hooks << block
15
+ end
16
+ end
17
+
18
+ # TODO: This is hardly thread safe!
19
+ def trigger_hooks
20
+ @hooks.each &:call
21
+ end
22
+
23
+ end
24
+
25
+ class HookWithArguments < GenericHook
26
+ def trigger_hooks(*args)
27
+ @hooks.each { |hook| hook.call(*args) }
28
+ end
29
+ end
30
+
31
+ ThreadsJoinedAfterInitialized = GenericHook.new
32
+
33
+ OnFailedCall = HookWithArguments.new
34
+ OnHungupCall = HookWithArguments.new
35
+ AfterInitialized = GenericHook.new
36
+ BeforeCall = GenericHook.new
37
+ AfterCall = GenericHook.new
38
+ TearDown = GenericHook.new
39
+
40
+ class << TearDown
41
+ def aliases
42
+ [:before_shutdown]
43
+ end
44
+
45
+ def catch_termination_signals
46
+ %w'INT TERM'.each do |sig|
47
+ trap sig do
48
+ ahn_log "Shutting down gracefully at #{Time.now}."
49
+ Adhearsion::Hooks::TearDown.trigger_hooks
50
+ exit
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,63 @@
1
+ require 'yaml'
2
+
3
+ module Adhearsion
4
+ class HostDefinition
5
+
6
+ SUPPORTED_KEYS = [:host, :username, :password, :key, :name]
7
+
8
+ cattr_reader :definitions
9
+ @@definitions ||= []
10
+
11
+ class << self
12
+ def import_from_data_structure(local_definitions)
13
+ case local_definitions
14
+ when Array
15
+ local_definitions.each do |definition|
16
+ raise HostDefinitionException, "Unrecognized definition: #{definition}" unless definition.is_a?(Hash)
17
+ end
18
+ local_definitions.map { |definition| new definition }
19
+ when Hash
20
+ local_definitions.map do |(name,definition)|
21
+ new definition.merge(:name => name)
22
+ end
23
+ else
24
+ raise HostDefinitionException, "Unrecognized definition #{local_definitions}"
25
+ end
26
+ end
27
+
28
+ def import_from_yaml(yaml_string)
29
+ import_from_data_structure YAML.load(yaml_string)
30
+ end
31
+
32
+ def import_from_yaml_file(file)
33
+ import_from_yaml YAML.load_file(file)
34
+ end
35
+
36
+ def clear_definitions!
37
+ definitions.clear
38
+ end
39
+ end
40
+
41
+ attr_reader :name, :host, :username, :password, :key
42
+ def initialize(hash)
43
+ @host, @username, @password, @key, @name = hash.values_at(*SUPPORTED_KEYS)
44
+ @name ||= new_guid
45
+
46
+ unrecognized_keys = hash.keys - SUPPORTED_KEYS
47
+ raise HostDefinitionException, "Unrecognized key(s): #{unrecognized_keys.map(&:inspect).to_sentence}" if unrecognized_keys.any?
48
+ raise HostDefinitionException, "You must supply a password or key!" if username && !(password || key)
49
+ raise HostDefinitionException, "You must supply a username!" unless username
50
+ raise HostDefinitionException, 'You cannot supply both a password and key!' if password && key
51
+ raise HostDefinitionException, 'You must supply a host!' unless host
52
+
53
+ self.class.definitions << self
54
+ end
55
+
56
+ class HostDefinitionException < Exception
57
+
58
+ end
59
+
60
+ end
61
+
62
+
63
+ end