adhearsion 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/CHANGELOG +11 -2
  2. data/EVENTS +1 -1
  3. data/Rakefile +4 -4
  4. data/adhearsion.gemspec +8 -4
  5. data/app_generators/ahn/USAGE +3 -3
  6. data/app_generators/ahn/ahn_generator.rb +11 -11
  7. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +3 -3
  8. data/app_generators/ahn/templates/components/disabled/restful_rpc/example-client.rb +6 -6
  9. data/app_generators/ahn/templates/components/disabled/restful_rpc/restful_rpc.rb +16 -16
  10. data/app_generators/ahn/templates/components/disabled/restful_rpc/spec/restful_rpc_spec.rb +42 -42
  11. data/app_generators/ahn/templates/components/disabled/sandbox/sandbox.rb +11 -11
  12. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +1 -1
  13. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +6 -6
  14. data/app_generators/ahn/templates/components/simon_game/simon_game.rb +4 -4
  15. data/app_generators/ahn/templates/config/startup.rb +31 -16
  16. data/bin/ahn +3 -3
  17. data/bin/ahnctl +8 -8
  18. data/bin/jahn +3 -3
  19. data/examples/asterisk_manager_interface/standalone.rb +2 -2
  20. data/lib/adhearsion.rb +4 -2
  21. data/lib/adhearsion/cli.rb +31 -31
  22. data/lib/adhearsion/component_manager.rb +39 -39
  23. data/lib/adhearsion/component_manager/component_tester.rb +14 -14
  24. data/lib/adhearsion/component_manager/spec_framework.rb +1 -1
  25. data/lib/adhearsion/events_support.rb +12 -12
  26. data/lib/adhearsion/foundation/blank_slate.rb +1 -1
  27. data/lib/adhearsion/foundation/custom_daemonizer.rb +2 -2
  28. data/lib/adhearsion/foundation/event_socket.rb +26 -26
  29. data/lib/adhearsion/foundation/future_resource.rb +6 -6
  30. data/lib/adhearsion/foundation/metaprogramming.rb +2 -2
  31. data/lib/adhearsion/foundation/numeric.rb +3 -3
  32. data/lib/adhearsion/foundation/relationship_properties.rb +7 -7
  33. data/lib/adhearsion/foundation/string.rb +8 -8
  34. data/lib/adhearsion/foundation/synchronized_hash.rb +8 -8
  35. data/lib/adhearsion/host_definitions.rb +16 -16
  36. data/lib/adhearsion/initializer.rb +74 -65
  37. data/lib/adhearsion/initializer/asterisk.rb +15 -9
  38. data/lib/adhearsion/initializer/configuration.rb +54 -39
  39. data/lib/adhearsion/initializer/database.rb +4 -4
  40. data/lib/adhearsion/initializer/drb.rb +6 -6
  41. data/lib/adhearsion/initializer/freeswitch.rb +1 -1
  42. data/lib/adhearsion/initializer/ldap.rb +51 -0
  43. data/lib/adhearsion/initializer/rails.rb +8 -8
  44. data/lib/adhearsion/logging.rb +16 -16
  45. data/lib/adhearsion/tasks/deprecations.rb +12 -12
  46. data/lib/adhearsion/tasks/generating.rb +2 -2
  47. data/lib/adhearsion/tasks/testing.rb +7 -7
  48. data/lib/adhearsion/version.rb +1 -1
  49. data/lib/adhearsion/voip/asterisk/agi_server.rb +44 -14
  50. data/lib/adhearsion/voip/asterisk/commands.rb +281 -237
  51. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +8 -8
  52. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +14 -14
  53. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +16 -16
  54. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +39 -39
  55. data/lib/adhearsion/voip/asterisk/config_manager.rb +13 -13
  56. data/lib/adhearsion/voip/asterisk/manager_interface.rb +91 -87
  57. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +739 -739
  58. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +60 -60
  59. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +16 -16
  60. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +1 -1
  61. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +13 -13
  62. data/lib/adhearsion/voip/asterisk/super_manager.rb +3 -3
  63. data/lib/adhearsion/voip/call.rb +101 -64
  64. data/lib/adhearsion/voip/call_routing.rb +9 -9
  65. data/lib/adhearsion/voip/constants.rb +7 -7
  66. data/lib/adhearsion/voip/conveniences.rb +1 -1
  67. data/lib/adhearsion/voip/dial_plan.rb +42 -40
  68. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +27 -27
  69. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +1 -1
  70. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +6 -6
  71. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +17 -17
  72. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +7 -7
  73. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +2 -2
  74. data/lib/adhearsion/voip/dsl/numerical_string.rb +3 -3
  75. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +7 -7
  76. data/lib/adhearsion/voip/freeswitch/event_handler.rb +1 -1
  77. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +20 -20
  78. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +5 -5
  79. data/lib/adhearsion/voip/freeswitch/oes_server.rb +33 -33
  80. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +1 -1
  81. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +2 -2
  82. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +9 -9
  83. data/lib/theatre.rb +18 -18
  84. data/lib/theatre/callback_definition_loader.rb +17 -17
  85. data/lib/theatre/guid.rb +6 -6
  86. data/lib/theatre/invocation.rb +19 -19
  87. data/lib/theatre/namespace_manager.rb +28 -28
  88. metadata +55 -14
@@ -12,7 +12,7 @@ module Adhearsion
12
12
  @agent_section = {}
13
13
  @agent_section_special = {} # Uses => separator
14
14
  @agent_definitions = []
15
-
15
+
16
16
  super
17
17
  end
18
18
 
@@ -26,7 +26,7 @@ module Adhearsion
26
26
  end
27
27
  end
28
28
  alias conf to_s # Allows "agents.conf" if agents.kind_of?(Agents)
29
-
29
+
30
30
  def agent(id, properties)
31
31
  agent_definitions << {:id => id}.merge(properties)
32
32
  end
@@ -36,7 +36,7 @@ module Adhearsion
36
36
  def groups(*args)
37
37
  agent_section[:group] = args.join(",")
38
38
  end
39
-
39
+
40
40
  # Define whether callbacklogins should be stored in astdb for
41
41
  # persistence. Persistent logins will be reloaded after
42
42
  # Asterisk restarts.
@@ -49,7 +49,7 @@ module Adhearsion
49
49
  def allow_multiple_logins_per_extension(yes_or_no)
50
50
  general_section[:multiplelogin] = boolean_to_yes_no yes_or_no
51
51
  end
52
-
52
+
53
53
  # Define maxlogintries to allow agent to try max logins before
54
54
  # failed. Default to 3
55
55
  def max_login_tries(number_of_tries)
@@ -97,7 +97,7 @@ module Adhearsion
97
97
  end
98
98
 
99
99
  # TODO: I'm not exactly sure what this even does....
100
-
100
+
101
101
  # Define the default good bye sound file for agents
102
102
  # default to vm-goodbye
103
103
  def play_on_agent_goodbye(sound_file_name)
@@ -119,16 +119,16 @@ module Adhearsion
119
119
  def record_agent_calls(yes_or_no)
120
120
  agent_section[:recordagentcalls] = boolean_to_yes_no yes_or_no
121
121
  end
122
-
122
+
123
123
  def recording_format(symbol)
124
124
  raise ArgumentError, "Unrecognized format #{symbol}" unless [:wav, :wav49, :gsm].include? symbol
125
125
  agent_section[:recordformat] = symbol
126
126
  end
127
-
127
+
128
128
  def recording_prefix(string)
129
129
  agent_section[:urlprefix] = string
130
130
  end
131
-
131
+
132
132
  def save_recordings_in(path_to_directory)
133
133
  agent_section[:savecallsin] = path_to_directory
134
134
  end
@@ -2,12 +2,12 @@ module Adhearsion
2
2
  module VoIP
3
3
  module Asterisk
4
4
  module ConfigFileGenerators
5
- class AsteriskConfigGenerator
6
-
5
+ class AsteriskConfigGenerator
6
+
7
7
  SECTION_TITLE = /(\[[\w_-]+\])/
8
-
8
+
9
9
  class << self
10
-
10
+
11
11
  # Converts a config file into a Hash of contexts mapping to two dimensional array of pairs
12
12
  def create_sanitary_hash_from(config_file_content)
13
13
  almost_sanitized = Hash[*config_file_content.
@@ -20,24 +20,24 @@ module Adhearsion
20
20
  map { |token| token =~ /^#{SECTION_TITLE}$/ ? token : token.split(/\n+/).sort }
21
21
  ]
22
22
  end
23
-
23
+
24
24
  def warning_message
25
25
  %{;; THIS FILE WAS GENERATED BY ADHEARSION ON #{Time.now.ctime}!\n} +
26
26
  %{;; ANY CHANGES MADE BELOW WILL BE BLOWN AWAY WHEN THE FILE IS REGENERATED!\n\n}
27
27
  end
28
-
28
+
29
29
  end
30
-
30
+
31
31
  def initialize
32
32
  yield self if block_given?
33
33
  end
34
-
34
+
35
35
  def to_sanitary_hash
36
36
  self.class.create_sanitary_hash_from to_s
37
37
  end
38
-
38
+
39
39
  protected
40
-
40
+
41
41
  def boolean(options)
42
42
  cache = options.delete(:with) || properties
43
43
  options.each_pair do |key, value|
@@ -72,7 +72,7 @@ module Adhearsion
72
72
  cache[key] = [true, false].include?(value) ? boolean_to_yes_no(value) : value
73
73
  end
74
74
  end
75
-
75
+
76
76
  def one_of_and_translate(criteria, options)
77
77
  cache = options.delete(:with) || properties
78
78
  options.each_pair do |key, value|
@@ -84,12 +84,12 @@ module Adhearsion
84
84
  cache[key] = criteria[value]
85
85
  end
86
86
  end
87
-
87
+
88
88
  private
89
-
89
+
90
90
  def boolean_to_yes_no(boolean)
91
91
  unless boolean.equal?(boolean) || boolean.equal?(boolean)
92
- raise "#{boolean.inspect} is not true/false!"
92
+ raise "#{boolean.inspect} is not true/false!"
93
93
  end
94
94
  boolean ? 'yes' : 'no'
95
95
  end
@@ -4,7 +4,7 @@ module Adhearsion
4
4
  module VoIP
5
5
  module Asterisk
6
6
  module ConfigFileGenerators
7
-
7
+
8
8
  # This will generate a queues.conf file. If there is no documentation on what a method
9
9
  # actually does, take a look at the documentation for its original key/value pair in
10
10
  # an unedited queues.conf file. WARNING! Don't get too embedded with these method names.
@@ -22,7 +22,7 @@ module Adhearsion
22
22
  @queue_definitions = []
23
23
  super
24
24
  end
25
-
25
+
26
26
  def queue(name)
27
27
  new_queue = QueueDefinition.new name
28
28
  yield new_queue if block_given?
@@ -36,17 +36,17 @@ module Adhearsion
36
36
  queue_definitions.map(&:to_s).join("\n\n")
37
37
  end
38
38
  alias conf to_s
39
-
39
+
40
40
  def persistent_members(yes_no)
41
41
  boolean :persistentmembers => yes_no, :with => general_section
42
42
  end
43
-
43
+
44
44
  def monitor_type(symbol)
45
45
  criteria = {:monitor => "Monitor", :mix_monitor => "MixMonitor"}
46
46
  one_of_and_translate criteria, 'monitor-type' => symbol, :with => general_section
47
47
  end
48
-
49
-
48
+
49
+
50
50
  class QueueDefinition < AsteriskConfigGenerator
51
51
 
52
52
  DEFAULT_QUEUE_PROPERTIES = {
@@ -57,7 +57,7 @@ module Adhearsion
57
57
  }
58
58
 
59
59
  SUPPORTED_RING_STRATEGIES = [:ringall, :roundrobin, :leastrecent, :fewestcalls, :random, :rrmemory]
60
-
60
+
61
61
  DEFAULT_SOUND_FILES = {
62
62
  'queue-youarenext' => 'queue-youarenext',
63
63
  'queue-thereare' => 'queue-thereare',
@@ -91,7 +91,7 @@ module Adhearsion
91
91
  @properties = DEFAULT_QUEUE_PROPERTIES.clone
92
92
  @sound_files = DEFAULT_SOUND_FILES.clone
93
93
  end
94
-
94
+
95
95
  def to_s
96
96
  "[#{name}]\n" +
97
97
  properties.merge(@sound_files).map { |key, value| "#{key}=#{value}" }.sort.join("\n") + "\n\n" +
@@ -144,7 +144,7 @@ module Adhearsion
144
144
  int :wrapuptime => seconds
145
145
  end
146
146
 
147
-
147
+
148
148
  def autopause(yes_no)
149
149
  boolean :autopause => yes_no
150
150
  end
@@ -159,7 +159,7 @@ module Adhearsion
159
159
 
160
160
  def periodically_announce(sound_file, options={})
161
161
  frequency = options.delete(:every) || 1.minute
162
-
162
+
163
163
  string 'periodic-announce' => sound_file
164
164
  int 'periodic-announce-frequency' => frequency
165
165
  end
@@ -175,7 +175,7 @@ module Adhearsion
175
175
  def monitor_format(symbol)
176
176
  one_of [:wav, :gsm, :wav49], 'monitor-format' => symbol
177
177
  end
178
-
178
+
179
179
  def monitor_type(symbol)
180
180
  criteria = {:monitor => "Monitor", :mix_monitor => "MixMonitor"}
181
181
  one_of_and_translate criteria, 'monitor-type' => symbol
@@ -186,7 +186,7 @@ module Adhearsion
186
186
  def join_empty(yes_no_or_strict)
187
187
  one_of [true, false, :strict], :joinempty => yes_no_or_strict
188
188
  end
189
-
189
+
190
190
  def leave_when_empty(yes_no)
191
191
  boolean :leavewhenempty => yes_no
192
192
  end
@@ -194,7 +194,7 @@ module Adhearsion
194
194
  def report_hold_time(yes_no)
195
195
  boolean :reportholdtime => yes_no
196
196
  end
197
-
197
+
198
198
  def ring_in_use(yes_no)
199
199
  boolean :ringinuse => yes_no
200
200
  end
@@ -204,11 +204,11 @@ module Adhearsion
204
204
  def delay_connection_by(seconds)
205
205
  int :memberdelay => seconds
206
206
  end
207
-
207
+
208
208
  def timeout_restart(yes_no)
209
209
  boolean :timeoutrestart => yes_no
210
210
  end
211
-
211
+
212
212
  # Give a Hash argument here to override the default sound files for this queue.
213
213
  #
214
214
  # Usage:
@@ -236,7 +236,7 @@ module Adhearsion
236
236
  @sound_files[SOUND_FILE_SYMBOL_INTERPRETATIONS[key]] = value
237
237
  end
238
238
  end
239
-
239
+
240
240
  def member(driver)
241
241
  members << (driver.kind_of?(String) && driver =~ %r'/' ? driver : "Agent/#{driver}")
242
242
  end
@@ -5,11 +5,11 @@ module Adhearsion
5
5
  module Asterisk
6
6
  module ConfigFileGenerators
7
7
  class Voicemail < AsteriskConfigGenerator
8
-
8
+
9
9
  DEFAULT_GENERAL_SECTION = {
10
10
  :format => :wav
11
11
  }
12
-
12
+
13
13
  # Don't worry. These will be overridable soon.
14
14
  STATIC_ZONEMESSAGES_CONTEXT = %{
15
15
  [zonemessages]
@@ -19,7 +19,7 @@ module Adhearsion
19
19
  military=Zulu|'vm-received' q 'digits/at' H N 'hours' 'phonetic/z_p'
20
20
  european=Europe/Copenhagen|'vm-received' a d b 'digits/at' HM
21
21
  }.unindent
22
-
22
+
23
23
  attr_reader :properties, :context_definitions
24
24
  def initialize
25
25
  @properties = DEFAULT_GENERAL_SECTION.clone
@@ -27,31 +27,31 @@ module Adhearsion
27
27
  @context_definitions = []
28
28
  super
29
29
  end
30
-
30
+
31
31
  def context(name)
32
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
-
33
+ raise ArgumentError, "A name can only be characters, numbers, and underscores!" if name.to_s !~ /^[\w_]+$/
34
+
35
35
  returning ContextDefinition.new(name) do |context_definition|
36
36
  yield context_definition
37
37
  context_definitions << context_definition
38
38
  end
39
39
  end
40
-
40
+
41
41
  def greeting_maximum(seconds)
42
42
  int "maxgreet" => seconds
43
43
  end
44
-
44
+
45
45
  def execute_on_pin_change(command)
46
- string "externpass" => command
46
+ string "externpass" => command
47
47
  end
48
-
48
+
49
49
  def recordings
50
50
  @recordings ||= RecordingDefinition.new
51
51
  yield @recordings if block_given?
52
52
  @recordings
53
53
  end
54
-
54
+
55
55
  def emails
56
56
  @emails ||= EmailDefinition.new
57
57
  if block_given?
@@ -60,7 +60,7 @@ module Adhearsion
60
60
  @emails
61
61
  end
62
62
  end
63
-
63
+
64
64
  def to_s
65
65
  email_properties = @emails ? @emails.properties : {}
66
66
  AsteriskConfigGenerator.warning_message +
@@ -69,39 +69,39 @@ module Adhearsion
69
69
  STATIC_ZONEMESSAGES_CONTEXT +
70
70
  context_definitions.map(&:to_s).join("\n\n")
71
71
  end
72
-
72
+
73
73
  private
74
-
74
+
75
75
  class ContextDefinition < AsteriskConfigGenerator
76
-
76
+
77
77
  attr_reader :mailboxes
78
78
  def initialize(name)
79
79
  @name = name
80
80
  @mailboxes = []
81
81
  super()
82
82
  end
83
-
83
+
84
84
  # TODO: This will hold a lot of the methods from the [general] section!
85
-
85
+
86
86
  def to_s
87
87
  (%W[[#@name]] + mailboxes.map(&:to_s)).join "\n"
88
88
  end
89
-
89
+
90
90
  def mailbox(mailbox_number)
91
91
  box = MailboxDefinition.new(mailbox_number)
92
92
  yield box
93
93
  mailboxes << box
94
94
  end
95
-
95
+
96
96
  private
97
-
97
+
98
98
  def mailbox_entry(options)
99
99
  returning MailboxDefinition.new do |mailbox|
100
100
  yield mailbox if block_given?
101
101
  mailboxes << definition
102
102
  end
103
103
  end
104
-
104
+
105
105
  class MailboxDefinition
106
106
 
107
107
  attr_reader :mailbox_number
@@ -128,20 +128,20 @@ module Adhearsion
128
128
  def to_hash
129
129
  @definition
130
130
  end
131
-
131
+
132
132
  def to_s
133
133
  %(#{mailbox_number} => #{@definition[:pin_number]},#{@definition[:name]},#{@definition[:email]})[/^(.+?),*$/,1]
134
134
  end
135
135
 
136
136
  private
137
-
137
+
138
138
  def check_numeric(number)
139
139
  raise ArgumentError, number.inspect + " is not numeric!" unless number.to_s =~ /^\d+$/
140
140
  end
141
141
 
142
142
  end
143
143
  end
144
-
144
+
145
145
  class EmailDefinition < AsteriskConfigGenerator
146
146
  EMAIL_VARIABLE_CONVENIENCES = {
147
147
  :name => '${VM_NAME}',
@@ -153,13 +153,13 @@ module Adhearsion
153
153
  :caller_id_number => '${VM_CIDNUM}',
154
154
  :caller_id_name => '${VM_CIDNAME}'
155
155
  }
156
-
156
+
157
157
  attr_reader :properties
158
158
  def initialize
159
159
  @properties = {}
160
160
  super
161
161
  end
162
-
162
+
163
163
  def [](email_variable)
164
164
  if EMAIL_VARIABLE_CONVENIENCES.has_key? email_variable
165
165
  EMAIL_VARIABLE_CONVENIENCES[email_variable]
@@ -167,25 +167,25 @@ module Adhearsion
167
167
  raise ArgumentError, "Unrecognized variable #{email_variable.inspect}"
168
168
  end
169
169
  end
170
-
170
+
171
171
  def disable!
172
172
  raise NotImpementedError
173
173
  end
174
-
174
+
175
175
  def from(options)
176
176
  name, email = options.values_at :name, :email
177
177
  string :serveremail => email
178
178
  string :fromstring => name
179
179
  end
180
-
180
+
181
181
  def attach_recordings(true_or_false)
182
182
  boolean :attach => true_or_false
183
183
  end
184
-
184
+
185
185
  def attach_recordings?
186
186
  properties[:attach] == 'yes'
187
187
  end
188
-
188
+
189
189
  def body(str)
190
190
  str = str.gsub("\r", '').gsub("\n", '\n')
191
191
  if str.length > 512
@@ -194,29 +194,29 @@ module Adhearsion
194
194
  end
195
195
  string :emailbody => str
196
196
  end
197
-
197
+
198
198
  def subject(str)
199
199
  string :emailsubject => str
200
200
  end
201
-
201
+
202
202
  def command(cmd)
203
203
  string :mailcmd => cmd
204
204
  end
205
-
205
+
206
206
  end
207
-
207
+
208
208
  class RecordingDefinition < AsteriskConfigGenerator
209
-
209
+
210
210
  attr_reader :properties
211
211
  def initialize
212
212
  @properties = {}
213
213
  super
214
214
  end
215
-
215
+
216
216
  def format(symbol)
217
217
  one_of [:gsm, :wav49, :wav], :format => symbol
218
218
  end
219
-
219
+
220
220
  def allowed_length(seconds)
221
221
  case seconds
222
222
  when Fixnum
@@ -228,7 +228,7 @@ module Adhearsion
228
228
  raise ArgumentError, "Argument must be a Fixnum or Range!"
229
229
  end
230
230
  end
231
-
231
+
232
232
  def maximum_silence(seconds)
233
233
  int :maxsilence => seconds
234
234
  end