adhearsion-asterisk 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,462 +1,10 @@
1
+ require 'adhearsion/asterisk/call_controller_methods'
2
+
1
3
  module Adhearsion
2
4
  module Asterisk
3
- PLAYBACK_SUCCESS = 'SUCCESS' unless defined? PLAYBACK_SUCCESS
4
-
5
-
6
5
  class Plugin < Adhearsion::Plugin
7
- DYNAMIC_FEATURE_EXTENSIONS = {
8
- :attended_transfer => lambda do |options|
9
- variable "TRANSFER_CONTEXT" => options[:context] if options && options.has_key?(:context)
10
- extend_dynamic_features_with "atxfer"
11
- end,
12
- :blind_transfer => lambda do |options|
13
- variable "TRANSFER_CONTEXT" => options[:context] if options && options.has_key?(:context)
14
- extend_dynamic_features_with 'blindxfer'
15
- end
16
- } unless defined? DYNAMIC_FEATURE_EXTENSIONS
17
-
18
- dialplan :agi do |name, *params|
19
- component = Punchblock::Component::Asterisk::AGI::Command.new :name => name, :params => params
20
- execute_component_and_await_completion component
21
- complete_reason = component.complete_event.reason
22
- [:code, :result, :data].map { |p| complete_reason.send p }
23
- end
24
-
25
- #
26
- # This asterisk dialplan command allows you to instruct Asterisk to start applications
27
- # which are typically run from extensions.conf and do not have AGI command equivalents.
28
- #
29
- # For example, if there are specific asterisk modules you have loaded that will not be
30
- # available through the standard commands provided through FAGI - then you can use EXEC.
31
- #
32
- # @example Using execute in this way will add a header to an existing SIP call.
33
- # execute 'SIPAddHeader', "Call-Info: answer-after=0"
34
- #
35
- # @see http://www.voip-info.org/wiki/view/Asterisk+-+documentation+of+application+commands Asterisk Dialplan Commands
36
- #
37
- dialplan :execute do |name, *params|
38
- agi "EXEC #{name}", *params
39
- end
40
-
41
- #
42
- # Sends a message to the console via the verbose message system.
43
- #
44
- # @param [String] message
45
- # @param [Integer] level
46
- #
47
- # @return the result of the command
48
- #
49
- # @example Use this command to inform someone watching the Asterisk console
50
- # of actions happening within Adhearsion.
51
- # verbose 'Processing call with Adhearsion' 3
52
- #
53
- # @see http://www.voip-info.org/wiki/view/verbose
54
- #
55
- dialplan :verbose do |message, level = nil|
56
- agi 'VERBOSE', message, level
57
- end
58
-
59
- # A high-level way of enabling features you create/uncomment from features.conf.
60
- #
61
- # Certain Symbol features you enable (as defined in DYNAMIC_FEATURE_EXTENSIONS) have optional
62
- # arguments that you can also specify here. The usage examples show how to do this.
63
- #
64
- # Usage examples:
65
- #
66
- # enable_feature :attended_transfer # Enables "atxfer"
67
- #
68
- # enable_feature :attended_transfer, :context => "my_dial" # Enables "atxfer" and then
69
- # # sets "TRANSFER_CONTEXT" to :context's value
70
- #
71
- # enable_feature :blind_transfer, :context => 'my_dial' # Enables 'blindxfer' and sets TRANSFER_CONTEXT
72
- #
73
- # enable_feature "foobar" # Enables "foobar"
74
- #
75
- # enable_feature("dup"); enable_feature("dup") # Enables "dup" only once.
76
- #
77
- # dialplan :voicemail do |*args|
78
- # options_hash = args.last.kind_of?(Hash) ? args.pop : {}
79
- # mailbox_number = args.shift
80
- # greeting_option = options_hash.delete :greeting
81
- #
82
- dialplan :enable_feature do |*args|
83
- feature_name, optional_options = args.flatten
84
-
85
- if DYNAMIC_FEATURE_EXTENSIONS.has_key? feature_name
86
- instance_exec(optional_options, &DYNAMIC_FEATURE_EXTENSIONS[feature_name])
87
- else
88
- unless optional_options.nil? or optional_options.empty?
89
- raise ArgumentError, "You cannot supply optional options when the feature name is " +
90
- "not internally recognized!"
91
- end
92
- extend_dynamic_features_with feature_name
93
- end
94
- end
95
-
96
- # Disables a feature name specified in features.conf. If you're disabling it, it was probably
97
- # set by enable_feature().
98
- #
99
- # @param [String] feature_name
100
- dialplan :disable_feature do |feature_name|
101
- enabled_features_variable = variable 'DYNAMIC_FEATURES'
102
- enabled_features = enabled_features_variable.split('#')
103
- if enabled_features.include? feature_name
104
- enabled_features.delete feature_name
105
- variable 'DYNAMIC_FEATURES' => enabled_features.join('#')
106
- end
107
- end
108
-
109
- # helper method that should probably should private...
110
- dialplan :extend_dynamic_features_with do |feature_name|
111
- current_variable = variable("DYNAMIC_FEATURES") || ''
112
- enabled_features = current_variable.split '#'
113
- unless enabled_features.include? feature_name
114
- enabled_features << feature_name
115
- variable "DYNAMIC_FEATURES" => enabled_features.join('#')
116
- end
117
- end
118
-
119
- #
120
- # Issue this command to access a channel variable that exists in the asterisk dialplan (i.e. extensions.conf)
121
- # Use get_variable to pass information from other modules or high level configurations from the asterisk dialplan
122
- # to the adhearsion dialplan.
123
- #
124
- # @param [String] variable_name
125
- #
126
- # @see: http://www.voip-info.org/wiki/view/get+variable Asterisk Get Variable
127
- #
128
- dialplan :get_variable do |variable_name|
129
- code, result, data = agi "GET VARIABLE", variable_name
130
- data
131
- end
132
-
133
- #
134
- # Pass information back to the asterisk dial plan.
135
- #
136
- # Keep in mind that the variables are not global variables. These variables only exist for the channel
137
- # related to the call that is being serviced by the particular instance of your adhearsion application.
138
- # You will not be able to pass information back to the asterisk dialplan for other instances of your adhearsion
139
- # application to share. Once the channel is "hungup" then the variables are cleared and their information is gone.
140
- #
141
- # @param [String] variable_name
142
- # @param [String] value
143
- #
144
- # @see http://www.voip-info.org/wiki/view/set+variable Asterisk Set Variable
145
- #
146
- dialplan :set_variable do |variable_name, value|
147
- agi "SET VARIABLE", variable_name, value
148
- end
149
-
150
- #
151
- # Issue the command to add a custom SIP header to the current call channel
152
- # example use: sip_add_header("x-ahn-test", "rubyrox")
153
- #
154
- # @param[String] the name of the SIP header
155
- # @param[String] the value of the SIP header
156
- #
157
- # @return [String] the Asterisk response
158
- #
159
- # @see http://www.voip-info.org/wiki/index.php?page=Asterisk+cmd+SIPAddHeader Asterisk SIPAddHeader
160
- #
161
- dialplan :sip_add_header do |header, value|
162
- execute "SIPAddHeader", "#{header}: #{value}"
163
- end
164
-
165
- #
166
- # Issue the command to fetch a SIP header from the current call channel
167
- # example use: sip_get_header("x-ahn-test")
168
- #
169
- # @param[String] the name of the SIP header to get
170
- #
171
- # @return [String] the Asterisk response
172
- #
173
- # @see http://www.voip-info.org/wiki/index.php?page=Asterisk+cmd+SIPGetHeader Asterisk SIPGetHeader
174
- #
175
- dialplan :sip_get_header do |header|
176
- get_variable "SIP_HEADER(#{header})"
177
- end
178
-
179
- #
180
- # Allows you to either set or get a channel variable from Asterisk.
181
- # The method takes a hash key/value pair if you would like to set a variable
182
- # Or a single string with the variable to get from Asterisk
183
- #
184
- dialplan :variable do |*args|
185
- if args.last.kind_of? Hash
186
- assignments = args.pop
187
- raise ArgumentError, "Can't mix variable setting and fetching!" if args.any?
188
- assignments.each_pair do |key, value|
189
- set_variable key, value
190
- end
191
- else
192
- if args.size == 1
193
- get_variable args.first
194
- else
195
- args.map { |var| get_variable var }
196
- end
197
- end
198
- end
199
-
200
- #
201
- # Used to join a particular conference with the MeetMe application. To use MeetMe, be sure you
202
- # have a proper timing device configured on your Asterisk box. MeetMe is Asterisk's built-in
203
- # conferencing program.
204
- #
205
- # @param [String] conference_id
206
- # @param [Hash] options
207
- #
208
- # @see http://www.voip-info.org/wiki-Asterisk+cmd+MeetMe Asterisk Meetme Application Information
209
- #
210
- dialplan :meetme do |conference_id, options = {}|
211
- conference_id = conference_id.to_s.scan(/\w/).join
212
- command_flags = options[:options].to_s # This is a passthrough string straight to Asterisk
213
- pin = options[:pin]
214
- raise ArgumentError, "A conference PIN number must be numerical!" if pin && pin.to_s !~ /^\d+$/
215
-
216
- # To disable dynamic conference creation set :use_static_conf => true
217
- use_static_conf = options.has_key?(:use_static_conf) ? options[:use_static_conf] : false
218
-
219
- # The 'd' option of MeetMe creates conferences dynamically.
220
- command_flags += 'd' unless command_flags.include?('d') || use_static_conf
221
-
222
- execute "MeetMe", conference_id, command_flags, options[:pin]
223
- end
224
-
225
- #
226
- # Send a caller to a voicemail box to leave a message.
227
- #
228
- # The method takes the mailbox_number of the user to leave a message for and a
229
- # greeting_option that will determine which message gets played to the caller.
230
- #
231
- # @see http://www.voip-info.org/tiki-index.php?page=Asterisk+cmd+VoiceMail Asterisk Voicemail
232
- #
233
- dialplan :voicemail do |*args|
234
- options_hash = args.last.kind_of?(Hash) ? args.pop : {}
235
- mailbox_number = args.shift
236
- greeting_option = options_hash.delete :greeting
237
- skip_option = options_hash.delete :skip
238
- raise ArgumentError, 'You supplied too many arguments!' if mailbox_number && options_hash.any?
239
-
240
- greeting_option = case greeting_option
241
- when :busy then 'b'
242
- when :unavailable then 'u'
243
- when nil then nil
244
- else raise ArgumentError, "Unrecognized greeting #{greeting_option}"
245
- end
246
- skip_option &&= 's'
247
- options = "#{greeting_option}#{skip_option}"
248
-
249
- raise ArgumentError, "Mailbox cannot be blank!" if !mailbox_number.nil? && mailbox_number.blank?
250
- number_with_context = if mailbox_number then mailbox_number else
251
- raise ArgumentError, "You must supply ONE context name!" unless options_hash.size == 1
252
- context_name, mailboxes = options_hash.to_a.first
253
- Array(mailboxes).map do |mailbox|
254
- raise ArgumentError, "Mailbox numbers must be numerical!" unless mailbox.to_s =~ /^\d+$/
255
- [mailbox, context_name].join '@'
256
- end.join '&'
257
- end
258
-
259
- execute 'voicemail', number_with_context, options
260
- case variable('VMSTATUS')
261
- when 'SUCCESS' then true
262
- when 'USEREXIT' then false
263
- else nil
264
- end
265
- end
266
-
267
- #
268
- # The voicemail_main method puts a caller into the voicemail system to fetch their voicemail
269
- # or set options for their voicemail box.
270
- #
271
- # @param [Hash] options
272
- #
273
- # @see http://www.voip-info.org/wiki-Asterisk+cmd+VoiceMailMain Asterisk VoiceMailMain Command
274
- #
275
- dialplan :voicemail_main do |options = {}|
276
- mailbox, context, folder = options.values_at :mailbox, :context, :folder
277
- authenticate = options.has_key?(:authenticate) ? options[:authenticate] : true
278
-
279
- folder = if folder
280
- if folder.to_s =~ /^[\w_]+$/
281
- "a(#{folder})"
282
- else
283
- raise ArgumentError, "Voicemail folder must be alphanumerical/underscore characters only!"
284
- end
285
- elsif folder == ''
286
- raise ArgumentError, "Folder name cannot be an empty String!"
287
- else
288
- nil
289
- end
290
-
291
- real_mailbox = ""
292
- real_mailbox << "#{mailbox}" unless mailbox.blank?
293
- real_mailbox << "@#{context}" unless context.blank?
294
-
295
- real_options = ""
296
- real_options << "s" if !authenticate
297
- real_options << folder unless folder.blank?
298
-
299
- command_args = [real_mailbox]
300
- command_args << real_options unless real_options.blank?
301
- command_args.clear if command_args == [""]
302
-
303
- execute 'VoiceMailMain', *command_args
304
- end
305
-
306
- #
307
- # Place a call in a queue to be answered by a registered agent. You must then call #join!
308
- #
309
- # @param [String] queue_name the queue name to place the caller in
310
- # @return [Adhearsion::Asterisk::QueueProxy] a queue proxy object
311
- #
312
- # @see http://www.voip-info.org/wiki-Asterisk+cmd+Queue Full information on the Asterisk Queue
313
- # @see Adhearsion::Asterisk":QueueProxy#join! for further details
314
- #
315
- dialplan :queue do |queue_name|
316
- queue_name = queue_name.to_s
317
-
318
- @queue_proxy_hash_lock ||= Mutex.new
319
- @queue_proxy_hash_lock.synchronize do
320
- @queue_proxy_hash ||= {}
321
- if @queue_proxy_hash.has_key? queue_name
322
- return @queue_proxy_hash[queue_name]
323
- else
324
- proxy = @queue_proxy_hash[queue_name] = QueueProxy.new(queue_name, self)
325
- return proxy
326
- end
327
- end
328
- end
329
-
330
- # Plays the specified sound file names. This method will handle Time/DateTime objects (e.g. Time.now),
331
- # Fixnums (e.g. 1000), Strings which are valid Fixnums (e.g "123"), and direct sound files. When playing
332
- # numbers, Adhearsion assumes you're saying the number, not the digits. For example, play("100")
333
- # is pronounced as "one hundred" instead of "one zero zero". To specify how the Date/Time objects are said
334
- # pass in as an array with the first parameter as the Date/Time/DateTime object along with a hash with the
335
- # additional options. See play_time for more information.
336
- #
337
- # Note: it is not necessary to supply a sound file extension; Asterisk will try to find a sound
338
- # file encoded using the current channel's codec, if one exists. If not, it will transcode from
339
- # the default codec (GSM). Asterisk stores its sound files in /var/lib/asterisk/sounds.
340
- #
341
- # @example Play file hello-world.???
342
- # play 'hello-world'
343
- # @example Speak current time
344
- # play Time.now
345
- # @example Speak today's date
346
- # play Date.today
347
- # @example Speak today's date in a specific format
348
- # play [Date.today, {:format => 'BdY'}]
349
- # @example Play sound file, speak number, play two more sound files
350
- # play %w"a-connect-charge-of 22 cents-per-minute will-apply"
351
- # @example Play two sound files
352
- # play "you-sound-cute", "what-are-you-wearing"
353
- #
354
- # @return [Boolean] true is returned if everything was successful. Otherwise, false indicates that
355
- # some sound file(s) could not be played.
356
- dialplan :play do |*arguments|
357
- begin
358
- play! arguments
359
- rescue Adhearsion::PlaybackError => e
360
- return false
361
- end
362
- true
363
- end
364
-
365
- # Same as {#play}, but immediately raises an exception if a sound file cannot be played.
366
- #
367
- # @return [true]
368
- # @raise [Adhearsion::VoIP::PlaybackError] If a sound file cannot be played
369
- dialplan :play! do |*arguments|
370
- result = true
371
- unless play_time(arguments)
372
- arguments.flatten.each do |argument|
373
- result &= play_numeric(argument) || play_soundfile(argument)
374
- end
375
- end
376
- raise Adhearsion::PlaybackError if !result
377
- end
378
-
379
- # Plays the given Date, Time, or Integer (seconds since epoch)
380
- # using the given timezone and format.
381
- #
382
- # @param [Date|Time|DateTime] Time to be said.
383
- # @param [Hash] Additional options to specify how exactly to say time specified.
384
- #
385
- # +:timezone+ - Sends a timezone to asterisk. See /usr/share/zoneinfo for a list. Defaults to the machine timezone.
386
- # +:format+ - This is the format the time is to be said in. Defaults to "ABdY 'digits/at' IMp"
387
- #
388
- # @see http://www.voip-info.org/wiki/view/Asterisk+cmd+SayUnixTime
389
- dialplan :play_time do |*args|
390
- argument, options = args.flatten
391
- options ||= {}
392
-
393
- return false unless options.is_a? Hash
394
-
395
- timezone = options.delete(:timezone) || ''
396
- format = options.delete(:format) || ''
397
- epoch = case argument
398
- when Time || DateTime
399
- argument.to_i
400
- when Date
401
- format = 'BdY' unless format.present?
402
- argument.to_time.to_i
403
- end
404
-
405
- return false if epoch.nil?
406
-
407
- execute "SayUnixTime", epoch, timezone, format
408
- end
409
-
410
- #Executes SayNumber with the passed argument.
411
- #
412
- # @param [Numeric|String] Numeric argument, or a string contanining numbers.
413
- # @return [Boolean] Returns false if the argument could not be played.
414
- dialplan :play_numeric do |argument|
415
- if argument.kind_of?(Numeric) || argument =~ /^\d+$/
416
- execute "SayNumber", argument
417
- end
418
- end
419
-
420
- # Instruct Asterisk to play a sound file to the channel.
421
- #
422
- # @param [String] File name to play in the Asterisk convention, without extension.
423
- # @return [Boolean] Returns false if the argument could not be played.
424
- dialplan :play_soundfile do |argument|
425
- execute "Playback", argument
426
- get_variable('PLAYBACKSTATUS') == PLAYBACK_SUCCESS
427
- end
428
-
429
- #
430
- # Plays a single output, not only files, accepting interruption by one of the digits specified
431
- # Currently still stops execution, will be fixed soon in Punchblock
432
- #
433
- # @param [Object] String or Hash specifying output and options
434
- # @param [String] String with the digits that are allowed to interrupt output
435
- # @return [String|nil] The pressed digit, or nil if nothing was pressed
436
- #
437
- dialplan :stream_file do |argument, digits = '0123456789#*'|
438
- begin
439
- output_component = ::Punchblock::Component::Asterisk::AGI::Command.new :name => "STREAM FILE",
440
- :params => [
441
- argument,
442
- digits
443
- ]
444
- execute_component_and_await_completion output_component
445
-
446
- reason = output_component.complete_event.reason
447
-
448
- case reason.result
449
- when 0
450
- raise Adhearsion::PlaybackError if reason.data == "endpos=0"
451
- nil
452
- when -1
453
- raise Adhearsion::PlaybackError
454
- else
455
- [reason.result].pack 'U*'
456
- end
457
- rescue StandardError => e
458
- raise Adhearsion::PlaybackError, "Output failed for argument #{argument.inspect}"
459
- end
6
+ init do
7
+ ::Adhearsion::CallController.mixin ::Adhearsion::Asterisk::CallControllerMethods
460
8
  end
461
9
 
462
10
  end#class