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,240 @@
1
+ require File.join(File.dirname(__FILE__), 'config_generator')
2
+
3
+ module Adhearsion
4
+ module VoIP
5
+ module Asterisk
6
+ module ConfigFileGenerators
7
+ class Voicemail < AsteriskConfigGenerator
8
+
9
+ DEFAULT_GENERAL_SECTION = {
10
+ :format => :wav
11
+ }
12
+
13
+ # Don't worry. These will be overridable soon.
14
+ STATIC_ZONEMESSAGES_CONTEXT = %{
15
+ [zonemessages]
16
+ eastern=America/New_York|'vm-received' Q 'digits/at' IMp
17
+ central=America/Chicago|'vm-received' Q 'digits/at' IMp
18
+ central24=America/Chicago|'vm-received' q 'digits/at' H N 'hours'
19
+ military=Zulu|'vm-received' q 'digits/at' H N 'hours' 'phonetic/z_p'
20
+ european=Europe/Copenhagen|'vm-received' a d b 'digits/at' HM
21
+ }.unindent
22
+
23
+ attr_reader :properties, :context_definitions
24
+ def initialize
25
+ @properties = DEFAULT_GENERAL_SECTION.clone
26
+ @mailboxes = {}
27
+ @context_definitions = []
28
+ super
29
+ end
30
+
31
+ def context(name)
32
+ raise ArgumentError, "Name cannot be 'general'!" if name.to_s.downcase == 'general'
33
+ raise ArgumentError, "A name can only be characters, numbers, and underscores!" if name.to_s !~ /^[\w_]+$/
34
+
35
+ returning ContextDefinition.new(name) do |context_definition|
36
+ yield context_definition
37
+ context_definitions << context_definition
38
+ end
39
+ end
40
+
41
+ def greeting_maximum(seconds)
42
+ int "maxgreet" => seconds
43
+ end
44
+
45
+ def execute_on_pin_change(command)
46
+ string "externpass" => command
47
+ end
48
+
49
+ def recordings
50
+ @recordings ||= RecordingDefinition.new
51
+ yield @recordings if block_given?
52
+ @recordings
53
+ end
54
+
55
+ def emails
56
+ @emails ||= EmailDefinition.new
57
+ if block_given?
58
+ yield @emails
59
+ else
60
+ @emails
61
+ end
62
+ end
63
+
64
+ def to_s
65
+ email_properties = @emails ? @emails.properties : {}
66
+ AsteriskConfigGenerator.warning_message +
67
+ "[general]\n" +
68
+ properties.merge(email_properties).map { |(key,value)| "#{key}=#{value}" }.sort.join("\n") + "\n\n" +
69
+ STATIC_ZONEMESSAGES_CONTEXT +
70
+ context_definitions.map(&:to_s).join("\n\n")
71
+ end
72
+
73
+ private
74
+
75
+ class ContextDefinition < AsteriskConfigGenerator
76
+
77
+ attr_reader :mailboxes
78
+ def initialize(name)
79
+ @name = name
80
+ @mailboxes = []
81
+ super()
82
+ end
83
+
84
+ # TODO: This will hold a lot of the methods from the [general] section!
85
+
86
+ def to_s
87
+ (%W[[#@name]] + mailboxes.map(&:to_s)).join "\n"
88
+ end
89
+
90
+ def mailbox(mailbox_number)
91
+ box = MailboxDefinition.new(mailbox_number)
92
+ yield box
93
+ mailboxes << box
94
+ end
95
+
96
+ private
97
+
98
+ def mailbox_entry(options)
99
+ returning MailboxDefinition.new do |mailbox|
100
+ yield mailbox if block_given?
101
+ mailboxes << definition
102
+ end
103
+ end
104
+
105
+ class MailboxDefinition
106
+
107
+ attr_reader :mailbox_number
108
+ def initialize(mailbox_number)
109
+ check_numeric mailbox_number
110
+ @mailbox_number = mailbox_number
111
+ @definition = {}
112
+ super()
113
+ end
114
+
115
+ def pin_number(number)
116
+ check_numeric number
117
+ @definition[:pin_number] = number
118
+ end
119
+
120
+ def name(str)
121
+ @definition[:name] = str
122
+ end
123
+
124
+ def email(str)
125
+ @definition[:email] = str
126
+ end
127
+
128
+ def to_hash
129
+ @definition
130
+ end
131
+
132
+ def to_s
133
+ %(#{mailbox_number} => #{@definition[:pin_number]},#{@definition[:name]},#{@definition[:email]})[/^(.+?),*$/,1]
134
+ end
135
+
136
+ private
137
+
138
+ def check_numeric(number)
139
+ raise ArgumentError, number.inspect + " is not numeric!" unless number.to_s =~ /^\d+$/
140
+ end
141
+
142
+ end
143
+ end
144
+
145
+ class EmailDefinition < AsteriskConfigGenerator
146
+ EMAIL_VARIABLE_CONVENIENCES = {
147
+ :name => '${VM_NAME}',
148
+ :duration => '${VM_DUR}',
149
+ :message_number => '${VM_MSGNUM}',
150
+ :mailbox => '${VM_MAILBOX}',
151
+ :caller_id => '${VM_CALLERID}',
152
+ :date => '${VM_DATE}',
153
+ :caller_id_number => '${VM_CIDNUM}',
154
+ :caller_id_name => '${VM_CIDNAME}'
155
+ }
156
+
157
+ attr_reader :properties
158
+ def initialize
159
+ @properties = {}
160
+ super
161
+ end
162
+
163
+ def [](email_variable)
164
+ if EMAIL_VARIABLE_CONVENIENCES.has_key? email_variable
165
+ EMAIL_VARIABLE_CONVENIENCES[email_variable]
166
+ else
167
+ raise ArgumentError, "Unrecognized variable #{email_variable.inspect}"
168
+ end
169
+ end
170
+
171
+ def disable!
172
+ raise NotImpementedError
173
+ end
174
+
175
+ def from(options)
176
+ name, email = options.values_at :name, :email
177
+ string :serveremail => email
178
+ string :fromstring => name
179
+ end
180
+
181
+ def attach_recordings(true_or_false)
182
+ boolean :attach => true_or_false
183
+ end
184
+
185
+ def attach_recordings?
186
+ properties[:attach] == 'yes'
187
+ end
188
+
189
+ def body(str)
190
+ str = str.gsub("\r", '').gsub("\n", '\n')
191
+ if str.length > 512
192
+ raise ArgumentError, "Asterisk has an email body limit of 512 characters! Your body is too long!\n" +
193
+ ("-" * 10) + "\n" + str
194
+ end
195
+ string :emailbody => str
196
+ end
197
+
198
+ def subject(str)
199
+ string :emailsubject => str
200
+ end
201
+
202
+ def command(cmd)
203
+ string :mailcmd => cmd
204
+ end
205
+
206
+ end
207
+
208
+ class RecordingDefinition < AsteriskConfigGenerator
209
+
210
+ attr_reader :properties
211
+ def initialize
212
+ @properties = {}
213
+ super
214
+ end
215
+
216
+ def format(symbol)
217
+ one_of [:gsm, :wav49, :wav], :format => symbol
218
+ end
219
+
220
+ def allowed_length(seconds)
221
+ case seconds
222
+ when Fixnum
223
+ int :maxmessage => "value"
224
+ when Range
225
+ int :minmessage => seconds.first
226
+ int :maxmessage => seconds.last
227
+ else
228
+ raise ArgumentError, "Argument must be a Fixnum or Range!"
229
+ end
230
+ end
231
+
232
+ def maximum_silence(seconds)
233
+ int :maxsilence => seconds
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,71 @@
1
+ require 'enumerator'
2
+ module Adhearsion
3
+ module VoIP
4
+ module Asterisk
5
+ class ConfigurationManager
6
+
7
+ class << self
8
+ def normalize_configuration(file_contents)
9
+ # cat sip.conf | sed -e 's/\s*;.*$//g' | sed -e '/^;.*$/d' | sed -e '/^\s*$/d'
10
+ file_contents.split(/\n+/).map do |line|
11
+ line.sub(/;.+$/, '').strip
12
+ end.join("\n").squeeze("\n")
13
+ end
14
+ end
15
+
16
+ attr_reader :filename
17
+
18
+ def initialize(filename)
19
+ @filename = filename
20
+ end
21
+
22
+ def sections
23
+ @sections ||= read_configuration
24
+ end
25
+
26
+ def [](section_name)
27
+ result = sections.find { |(name, *rest)| section_name == name }
28
+ result.last if result
29
+ end
30
+
31
+ def delete_section(section_name)
32
+ sections.reject! { |(name, *rest)| section_name == name }
33
+ end
34
+
35
+ def new_section(name, properties={})
36
+ sections << [name, properties]
37
+ end
38
+
39
+ private
40
+
41
+ def read_configuration
42
+ normalized_file = self.class.normalize_configuration execute(read_command)
43
+ normalized_file.split(/^\[([-_\w]+)\]$/)[1..-1].enum_slice(2).map do |(name,properties)|
44
+ [name, hash_from_properties(properties)]
45
+ end
46
+ end
47
+
48
+ def hash_from_properties(properties)
49
+ properties.split(/\n+/).inject({}) do |property_hash,property|
50
+ all, name, value = *property.match(/^\s*([^=]+?)\s*=\s*(.+)\s*$/)
51
+ next property_hash unless name && value
52
+ property_hash[name] = value
53
+ property_hash
54
+ end
55
+ end
56
+
57
+ def execute(command)
58
+ %x[command]
59
+ end
60
+
61
+ def read_command
62
+ "cat #{filename}"
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ # Read a file: cat a file
71
+ # Parse a file: separate into a two dimensional hash