adhearsion 0.7.6 → 0.7.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.version +1 -1
- data/CHANGELOG +43 -25
- data/Rakefile +0 -5
- data/TODO +51 -2
- data/ahn +2 -1
- data/apps/default/Rakefile +16 -7
- data/apps/default/config/adhearsion.yml +22 -1
- data/apps/default/config/helpers/manager_proxy.yml +1 -0
- data/apps/default/config/helpers/micromenus/images/arrow-off.gif +0 -0
- data/apps/default/config/helpers/micromenus/images/arrow-on.gif +0 -0
- data/apps/default/config/helpers/micromenus/images/error.gif +0 -0
- data/apps/default/config/helpers/micromenus/images/folder-off.gif +0 -0
- data/apps/default/config/helpers/micromenus/images/folder-on.gif +0 -0
- data/apps/default/config/helpers/micromenus/images/folder.png +0 -0
- data/apps/default/config/helpers/micromenus/images/ggbridge.jpg +0 -0
- data/apps/default/config/helpers/micromenus/images/green.png +0 -0
- data/apps/default/config/helpers/micromenus/images/microbrowser.bg.gif +0 -0
- data/apps/default/config/helpers/micromenus/images/red.png +0 -0
- data/apps/default/config/helpers/micromenus/images/url-off.gif +0 -0
- data/apps/default/config/helpers/micromenus/images/url-on.gif +0 -0
- data/apps/default/config/helpers/micromenus/images/yellow.png +0 -0
- data/apps/default/config/helpers/micromenus/javascripts/animation.js +1341 -0
- data/apps/default/config/helpers/micromenus/javascripts/carousel.js +1238 -0
- data/apps/default/config/helpers/micromenus/javascripts/columnav.js +306 -0
- data/apps/default/config/helpers/micromenus/javascripts/connection.js +965 -0
- data/apps/default/config/helpers/micromenus/javascripts/container.js +4727 -0
- data/apps/default/config/helpers/micromenus/javascripts/container_core.js +2915 -0
- data/apps/default/config/helpers/micromenus/javascripts/dom.js +892 -0
- data/apps/default/config/helpers/micromenus/javascripts/dragdrop.js +2921 -907
- data/apps/default/config/helpers/micromenus/javascripts/event.js +1771 -0
- data/apps/default/config/helpers/micromenus/javascripts/yahoo.js +433 -0
- data/apps/default/config/helpers/micromenus/stylesheets/carousel.css +78 -0
- data/apps/default/config/helpers/micromenus/stylesheets/columnav.css +135 -0
- data/apps/default/config/helpers/micromenus/stylesheets/microbrowsers.css +42 -0
- data/apps/default/config/helpers/multi_messenger.yml +5 -1
- data/apps/default/config/migration.rb +10 -0
- data/apps/default/extensions.rb +1 -1
- data/apps/default/helpers/factorial.alien.c +3 -3
- data/apps/default/helpers/lookup.rb +2 -1
- data/apps/default/helpers/manager_proxy.rb +67 -15
- data/apps/default/helpers/micromenus.rb +173 -31
- data/apps/default/helpers/multi_messenger.rb +20 -3
- data/lib/adhearsion.rb +218 -88
- data/lib/constants.rb +1 -0
- data/lib/core_extensions.rb +15 -9
- data/lib/phone_number.rb +85 -0
- data/lib/rami.rb +3 -2
- data/lib/servlet_container.rb +47 -24
- data/lib/sexy_migrations.rb +70 -0
- data/test/asterisk_module_test.rb +9 -9
- data/test/specs/numerical_string_spec.rb +53 -0
- metadata +31 -11
- data/apps/default/config/helpers/micromenus/javascripts/builder.js +0 -131
- data/apps/default/config/helpers/micromenus/javascripts/controls.js +0 -834
- data/apps/default/config/helpers/micromenus/javascripts/effects.js +0 -956
- data/apps/default/config/helpers/micromenus/javascripts/prototype.js +0 -2319
- data/apps/default/config/helpers/micromenus/javascripts/scriptaculous.js +0 -51
- data/apps/default/config/helpers/micromenus/javascripts/slider.js +0 -278
- data/apps/default/config/helpers/micromenus/javascripts/unittest.js +0 -557
- data/apps/default/config/helpers/micromenus/stylesheets/firefox.css +0 -10
- data/apps/default/config/helpers/micromenus/stylesheets/firefox.xul.css +0 -44
@@ -7,10 +7,10 @@ require 'xmpp4r-simple'
|
|
7
7
|
class MultiMessenger
|
8
8
|
|
9
9
|
Format = /\A[\w\._%-]+@[\w\.-]+\.[a-zA-Z]{2,4}\z/
|
10
|
-
|
11
|
-
def initialize username, password
|
10
|
+
def initialize username, password, accept_subs=false
|
12
11
|
@username, @password = username, password
|
13
12
|
@connection = Jabber::Simple.new username, password
|
13
|
+
@connection.accept_subscriptions = accept_subs
|
14
14
|
end
|
15
15
|
|
16
16
|
def connected?() @connection.connected? end
|
@@ -28,9 +28,26 @@ config = $HELPERS['multi_messenger']
|
|
28
28
|
|
29
29
|
username = config['username']||''
|
30
30
|
password = config['password']||''
|
31
|
+
accept_subs = config['accept_subscriptions']
|
31
32
|
|
32
33
|
log "MultiMessenger: Connecting to #{username}"
|
33
|
-
jabber = MultiMessenger.new username, password
|
34
|
+
jabber = MultiMessenger.new username, password, accept_subs
|
35
|
+
|
36
|
+
jabber.connection.received_messages do |msg|
|
37
|
+
# Need to do something with each message? Do it here.
|
38
|
+
end
|
39
|
+
|
40
|
+
jabber.connection.presence_updates do |friend, old_presence, new_presence|
|
41
|
+
# Handle presence updates here, optionally
|
42
|
+
end
|
43
|
+
|
44
|
+
jabber.connection.subscription_requests do |friend, presence|
|
45
|
+
# When a subscription request comes in, handle it here.
|
46
|
+
end
|
47
|
+
|
48
|
+
jabber.connection.new_subscriptions do |friend, presence|
|
49
|
+
# Handle each subscription notification
|
50
|
+
end
|
34
51
|
|
35
52
|
InstantMessenger.use_service jabber
|
36
53
|
$HUTDOWN.hook { jabber.connection.disconnect }
|
data/lib/adhearsion.rb
CHANGED
@@ -16,6 +16,7 @@
|
|
16
16
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
17
|
|
18
18
|
require 'core_extensions'
|
19
|
+
require 'phone_number'
|
19
20
|
|
20
21
|
module Asterisk
|
21
22
|
|
@@ -41,18 +42,18 @@ module Asterisk
|
|
41
42
|
# AGI. This code has been kept here in case these bugs are fixed.
|
42
43
|
def old_input digits=nil, user_options=Hash.new('')
|
43
44
|
used_options = {:variable => String.random, :digits => digits}
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
45
|
+
used_options.default = ''
|
46
|
+
used_options.merge! user_options
|
47
|
+
args = []
|
48
|
+
%w(variable soundfile digits option attempts timeout).each do |x|
|
49
|
+
args << used_options[x.to_sym]
|
50
|
+
end
|
51
|
+
log "THESE ARE THE INPUT ARGS: " + args.inspect
|
52
|
+
exec :read, args
|
53
|
+
$OSCAR[:VARS] << args.first
|
54
|
+
x = get_variable(args.first).gsub(/[\(\)]/, "")
|
55
|
+
debug "RETURN: #{x.inspect}"
|
56
|
+
x.simplify
|
56
57
|
end
|
57
58
|
|
58
59
|
# Input is used to receive keypad input from the user, pausing until they
|
@@ -66,6 +67,8 @@ module Asterisk
|
|
66
67
|
#
|
67
68
|
# When called without any arguments (or a first argument of -1), the user is
|
68
69
|
# able to enter digits ad infinitum until they press the pound (#) key.
|
70
|
+
#
|
71
|
+
# Note: input() does NOT catch "#" character! Use wait_for_digit instead.
|
69
72
|
def input digits=nil, hash={}
|
70
73
|
timeout, file = (hash[:timeout] || -1), (hash[:play] || hash[:file] || 'beep')
|
71
74
|
result = rawr "GET DATA #{file} #{timeout} #{digits}"
|
@@ -150,7 +153,7 @@ module Asterisk
|
|
150
153
|
# returns nil. If the asterisk or pound key was pressed, a String is returned of that
|
151
154
|
# response. In all other cases, the Fixnum of the number pressed is returned.
|
152
155
|
def wait_for_digit timeout=-1
|
153
|
-
digit = rawr("WAIT FOR DIGIT #{timeout < 0 ? -1 : timeout
|
156
|
+
digit = rawr("WAIT FOR DIGIT #{timeout < 0 ? -1 : timeout * 1000.0}").match(/=(.*)$/)[1].to_i
|
154
157
|
return nil if digit <= 0 # If there was an error or timeout
|
155
158
|
return digit.chr if (32..45).include? digit
|
156
159
|
digit - ?0
|
@@ -167,12 +170,34 @@ module Asterisk
|
|
167
170
|
end
|
168
171
|
end
|
169
172
|
|
173
|
+
def detach!
|
174
|
+
PBX.io.close
|
175
|
+
end
|
176
|
+
|
170
177
|
# An abstracted remote accessor for retrieving Asterisk variables.
|
171
178
|
def get_variable(key, default=nil)
|
172
179
|
result = rawr "GET VARIABLE #{key}"
|
173
|
-
result[0..12] == "200 result=0" ? default : result[
|
180
|
+
result[0..12] == "200 result=0" ? default : result[14..-2].strip
|
174
181
|
end
|
175
182
|
|
183
|
+
# Plays a tone over the call.
|
184
|
+
#
|
185
|
+
# Usage:
|
186
|
+
# - tone:busy
|
187
|
+
# - tone:dial
|
188
|
+
# - tone:info
|
189
|
+
# - tone:record
|
190
|
+
# - tone "3333/33,0/15000" # Random custom tone
|
191
|
+
def tone type
|
192
|
+
exec 'PlayTones', (case type
|
193
|
+
when :busy then "480+620/500,0/500"
|
194
|
+
when :dial then "440+480/2000,0/4000"
|
195
|
+
when :info then "!950/330,!1400/330,!1800/330,0"
|
196
|
+
when :record then "1400/500,0/15000"
|
197
|
+
else type
|
198
|
+
end)
|
199
|
+
end
|
200
|
+
|
176
201
|
# == Dialing Users
|
177
202
|
#
|
178
203
|
# This method will be used in most dial plans written with Adhearsion.
|
@@ -230,7 +255,18 @@ module Asterisk
|
|
230
255
|
# last_dial_status. Note: last_dial_status returns a Symbol representing
|
231
256
|
# the result of the last call. For more information, see its appropriate
|
232
257
|
# documentation.
|
233
|
-
#
|
258
|
+
#
|
259
|
+
# === Setting CallerID
|
260
|
+
#
|
261
|
+
# To set the callerid number, simply pass either a number or a String of the
|
262
|
+
# digits to dial() as a Symbol key argument.
|
263
|
+
#
|
264
|
+
# dial :crusher, :callerid => 1_555_123_4567
|
265
|
+
# dial :picard, :callerid => 12224561701
|
266
|
+
# dial :laforge, :callerid => '14442223333'
|
267
|
+
#
|
268
|
+
# === Dial options
|
269
|
+
#
|
234
270
|
# Additionally, you can use the :options hash key argument to specify options
|
235
271
|
# which Asterisk's Dial() application normally takes. For example:
|
236
272
|
#
|
@@ -243,7 +279,17 @@ module Asterisk
|
|
243
279
|
# http://www.voip-info.org/wiki-Asterisk+cmd+Dial
|
244
280
|
def dial who, hash={}
|
245
281
|
# if who.is_a_group? TODO: Set the CDR GROUP() value if a Group is dialed.
|
246
|
-
|
282
|
+
|
283
|
+
# TODO Must be provided as a number until the Set(CALLERID(name)=something)
|
284
|
+
# stuff is figured out.
|
285
|
+
cid = hash.delete :callerid
|
286
|
+
if cid
|
287
|
+
cid = cid.to_s
|
288
|
+
cid = "1" << cid if cid.size == 10
|
289
|
+
rawr %(SET CALLERID "#{cid}") if cid
|
290
|
+
end
|
291
|
+
|
292
|
+
exec :dial, PBX.properize(who), *[hash[:for], hash[:options]]
|
247
293
|
end
|
248
294
|
|
249
295
|
# As you might expect, last_call_successful? returns a boolean depending on whether
|
@@ -258,6 +304,11 @@ module Asterisk
|
|
258
304
|
!last_call_successful?
|
259
305
|
end
|
260
306
|
|
307
|
+
# Send a DTMF tone over the line
|
308
|
+
def dtmf digits
|
309
|
+
exec "SendDTMF", digits.to_s
|
310
|
+
end
|
311
|
+
|
261
312
|
# The stream_file() method comes right over from the AGI protocol.
|
262
313
|
# Its use is very similar to the Background() application from
|
263
314
|
# Asterisk's extensions.conf language. A file is played in the
|
@@ -293,8 +344,29 @@ module Asterisk
|
|
293
344
|
# Festival is pretty buggy (and pretty inefficient). In theory,
|
294
345
|
# this should speak out any text supplied to it.
|
295
346
|
def speak text
|
296
|
-
text.gsub!
|
297
|
-
|
347
|
+
text.gsub! "\n",''
|
348
|
+
text.gsub! "\r",''
|
349
|
+
text.strip!
|
350
|
+
exec :Festival, "#{text.inspect}"
|
351
|
+
end
|
352
|
+
|
353
|
+
def build_local first, second=nil
|
354
|
+
num = 1
|
355
|
+
context = nil
|
356
|
+
if first.kind_of? Fixnum
|
357
|
+
num = first
|
358
|
+
context = second if second
|
359
|
+
else
|
360
|
+
context = first
|
361
|
+
num = second if second
|
362
|
+
end
|
363
|
+
returning("Local/#{num}") do |s|
|
364
|
+
s << "@#{context}" if context
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def external_invoke *args
|
369
|
+
dial build_local(*args)
|
298
370
|
end
|
299
371
|
|
300
372
|
# Since voicemail is used so frequently, extra effort has been made to
|
@@ -362,12 +434,40 @@ module Asterisk
|
|
362
434
|
def play *files
|
363
435
|
files.flatten!
|
364
436
|
files.each do |f|
|
365
|
-
if f.
|
437
|
+
if f.kind_of? Time
|
438
|
+
exec :SayUnixTime, f.to_i
|
439
|
+
elsif f.kind_of? Symbol then exec :playback, f
|
440
|
+
elsif f[0] == ?$
|
441
|
+
# Speak a currency. TODO: support currencies other than dollars.
|
442
|
+
full,dollars,decimal,cents = *f.match(/^\$(\d+)(\.(\d{1,2}).*)?$/)
|
443
|
+
if full
|
444
|
+
exec :saynumber, dollars
|
445
|
+
exec :playback, (dollars == '1') ? 'dollar' : 'dollars'
|
446
|
+
if decimal
|
447
|
+
exec :playback, 'and'
|
448
|
+
exec :saynumber, cents
|
449
|
+
exec :playback, (cents == '1') ? 'cent' : 'cents'
|
450
|
+
end
|
451
|
+
else exec :playback, f
|
452
|
+
end
|
453
|
+
elsif f.simplify.kind_of? Numeric then exec :saynumber, f
|
366
454
|
else exec :playback, f
|
367
455
|
end
|
368
456
|
end
|
369
457
|
end
|
370
458
|
|
459
|
+
# Compiles the provided Asterisk dialplan pattern into a Ruby regular
|
460
|
+
# expression. For more usage of Asterisk's pattern syntax, see
|
461
|
+
# http://www.voip-info.org/wiki/view/Asterisk+Dialplan+Patterns
|
462
|
+
def _ pattern
|
463
|
+
# Uncomment the following code fragment for complete compatability.
|
464
|
+
# The fragment handles the seldom-used hyphen number spacer with no
|
465
|
+
# meaning.
|
466
|
+
Regexp.new '^' << pattern.#gsub(/(?!\[[\w+-]+)-(?![\w-]+\])/,'').
|
467
|
+
gsub('X', '[0-9]').gsub('Z', '[1-9]').gsub('N','[2-9]').
|
468
|
+
gsub('.','.+').gsub('!','.*') << '$'
|
469
|
+
end
|
470
|
+
|
371
471
|
# == Dialplan Instruction Caching
|
372
472
|
#
|
373
473
|
# If a cynic ever says Ruby doesn't make an efficient dial plan manager,
|
@@ -548,37 +648,7 @@ module Asterisk
|
|
548
648
|
end
|
549
649
|
|
550
650
|
# Very simply sends the command over the AGI IO socket and forgets about it.
|
551
|
-
def putc(what) PBX.io.print "#{what}" end
|
552
|
-
|
553
|
-
# The magical method that handles how objects passed to dial() are converted to their
|
554
|
-
# corresponding Asterisk-recognizable technology/extension identifier. This likely
|
555
|
-
# wouldn't be used much outside of dial(), but you may find it useful.
|
556
|
-
def properize who
|
557
|
-
# These are the convention methods for Group-like objects
|
558
|
-
group_method = who.is_a_group?
|
559
|
-
|
560
|
-
# If 'who' has any of the possible_methods, replace 'who' with the return value
|
561
|
-
# of that method
|
562
|
-
who = who.send group_method if group_method
|
563
|
-
return nil unless who
|
564
|
-
|
565
|
-
# In case we can't perform collection algorithms on 'who', let's encapsulate it in
|
566
|
-
# an Array
|
567
|
-
who = [who] unless who.kind_of?(Enumerable) && !who.kind_of?(String)
|
568
|
-
|
569
|
-
user_method = who.first.is_a_user?
|
570
|
-
# If the first thing in the Enumerable responds to a User-like convention, then
|
571
|
-
# set 'who' equal to the extension(s) accessor of those objects. We refine the "who"
|
572
|
-
# argument more and more in this way until it's finally in a way Asterisk can read.
|
573
|
-
who.map! { |p| p.send user_method }.compact! if user_method
|
574
|
-
|
575
|
-
# Now replace each item in the Enumerable with its form converted to
|
576
|
-
# extension (assuming it's not already in that format)
|
577
|
-
who.map! do |ext|
|
578
|
-
(ext.kind_of?(String) && ext.index(?/)) ? ext : "SIP/#{ext}"
|
579
|
-
end
|
580
|
-
who * '&' # Finally, join() anything left in the Array with an '&'
|
581
|
-
end
|
651
|
+
def putc(what) PBX.io.print "#{what}" end
|
582
652
|
|
583
653
|
# Returns the status of the last dial(). Possible dial
|
584
654
|
# statuses include :answer, :busy, :noanswer, :cancel,
|
@@ -600,59 +670,119 @@ module Asterisk
|
|
600
670
|
# Direct translation of the Asterisk NoOp() application. Used primarily for
|
601
671
|
# viewing debug information in the Asterisk CLI.
|
602
672
|
def noop(*options) rawr "NOOP #{options}" end
|
603
|
-
end
|
604
|
-
|
605
|
-
# This SIP class abstracts several SIP-related functions. In your dialplan,
|
606
|
-
# if you should want to set a SIP header specifically, simply use the class
|
607
|
-
# []= operator. For example, you may want to do SIP['Alert-Info'] = 'Ring-Answer'
|
608
|
-
# which will affect the next SIP call placed. Additionally, you can use this
|
609
|
-
# class's division operator to naturally represent "technology/channel"
|
610
|
-
# endpoints (e.g. SIP/1550 or SIP/:tweedledum)
|
611
|
-
class SIP
|
612
|
-
|
613
|
-
# This will set the header value specified within the square bracked to the
|
614
|
-
# value given after the equals sign. Note: this can only be called if the
|
615
|
-
# current call's thread is handling an Asterisk call over AGI (i.e. dialplan).
|
616
|
-
def self.[]=(header, value)
|
617
|
-
exec :SipAddHeader, "#{header}: #{value}"
|
618
|
-
end
|
619
673
|
|
620
|
-
# Simple convenience method to make Adhearsion's DSL more Asterisk-like.
|
621
|
-
# Virtually anything can be provided after the "/", as long as its to_s()
|
622
|
-
# method is what you intended to represent.
|
623
|
-
def self./(ext) "SIP/#{ext}" end
|
624
674
|
end
|
625
675
|
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
676
|
+
# # This Endpoint module is only used when using the
|
677
|
+
# # forward-slash operator on the dialplan technology
|
678
|
+
# # classes such as IAX, SIP, Zap, Local, SCCP, etc.
|
679
|
+
# # The String's eigencalss returned from IAX/:foobar
|
680
|
+
# # extends this module.
|
681
|
+
# module Endpoint
|
682
|
+
# def /(x) to_s << "/" << x.to_s end
|
683
|
+
# end
|
684
|
+
#
|
685
|
+
# # Use like IAX/:trunk/12345
|
686
|
+
# class IAX
|
687
|
+
# def self./(x) "IAX2/#{x}".extend Endpoint end
|
688
|
+
# end
|
689
|
+
# # Use like SIP/:trunk/12345
|
690
|
+
# class SIP
|
691
|
+
# def self./(x) "SIP/#{x}".extend Endpoint end
|
692
|
+
# end
|
693
|
+
# # Use like SCCP/:trunk/12345
|
694
|
+
# class SCCP
|
695
|
+
# def self./(x) "SCCP/#{x}".extend Endpoint end
|
696
|
+
# end
|
697
|
+
# # Use like Zap/:channel/12345
|
698
|
+
# class Zap
|
699
|
+
# def self./(x) "ZAP/#{x}".extend Endpoint end
|
700
|
+
# end
|
701
|
+
# # Use like Local/'extension@context'
|
702
|
+
# class Local
|
703
|
+
# def self./(x) "Local/#{x}".extend Endpoint end
|
704
|
+
# end
|
705
|
+
# class GTalk
|
706
|
+
# def self./(x) "gtalk/#{x}".extend Endpoint end
|
707
|
+
# end
|
708
|
+
#
|
709
|
+
# # Use like IAX2/:trunk/12345
|
710
|
+
# class IAX2 < IAX;end
|
711
|
+
# # Use like ZAP/:channel/12345
|
712
|
+
# class ZAP < Zap;end
|
713
|
+
|
714
|
+
# Contributed by Bruce Williams of Five Runs.
|
715
|
+
module DialplanTechnologies
|
716
|
+
module Endpoint
|
717
|
+
def /(x) to_s << "/" << x.to_s end
|
718
|
+
end
|
719
|
+
|
720
|
+
class Base
|
721
|
+
def self./(x) "#{self}/#{x}".extend(Endpoint) end
|
722
|
+
end
|
723
|
+
|
724
|
+
class << self
|
725
|
+
def define(&block)
|
726
|
+
instance_eval(&block)
|
727
|
+
end
|
728
|
+
def add(*technologies)
|
729
|
+
options = technologies.last.is_a?(Hash) ? technologies.pop : {}
|
730
|
+
technologies.each do |name|
|
731
|
+
eval %{class ::#{name} < Base; def self.to_s; "#{options[:as] || name}"; end; end}
|
732
|
+
end
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
631
736
|
end
|
632
737
|
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
738
|
+
DialplanTechnologies.define do
|
739
|
+
add :IAX2, :SIP, :SCCP, :ZAP, :Local
|
740
|
+
add :GTalk, :as => :gtalk
|
741
|
+
add :Zap, :as => :ZAP
|
742
|
+
add :IAX, :as => :IAX2
|
638
743
|
end
|
639
744
|
|
640
|
-
# For users who may try to use the (proper) IAX2 form. See IAX for more info.
|
641
|
-
class IAX2 < IAX; end
|
642
|
-
|
643
|
-
# For users who may try to use the (common) "Zap" form. See ZAP for more info.
|
644
|
-
class Zap < ZAP; end
|
645
745
|
|
646
746
|
# The PBX object is an object manifestation of the PBX with which Adhearsion will be
|
647
747
|
# associated. Helpers often open up this class and add methods to it. Note: when doing
|
648
748
|
# this in your own helpers, all methods will need to be class (a.k.a. static) methods
|
649
749
|
# since no actual instance of this object is passed around.
|
650
750
|
class PBX
|
651
|
-
def method_missing name
|
751
|
+
def self.method_missing name
|
652
752
|
raise NameError, "Method #{name} not found! Are you sure manager_proxy is configured properly?"
|
653
753
|
end
|
754
|
+
|
755
|
+
# The magical method that handles how objects passed to dial() are converted to their
|
756
|
+
# corresponding Asterisk-recognizable technology/extension identifier. This likely
|
757
|
+
# wouldn't be used much outside of dial(), but you may find it useful.
|
758
|
+
def self.properize who
|
759
|
+
|
760
|
+
group_method = who.is_a_group?
|
761
|
+
|
762
|
+
# If 'who' has any of the possible_methods, replace 'who' with the return value
|
763
|
+
# of that method
|
764
|
+
who = who.send group_method if group_method
|
765
|
+
return nil unless who
|
766
|
+
|
767
|
+
# In case we can't perform collection algorithms on 'who', let's encapsulate it in
|
768
|
+
# an Array
|
769
|
+
who = [who] unless who.kind_of?(Enumerable) && !who.kind_of?(String)
|
770
|
+
|
771
|
+
user_method = who.first.is_a_user?
|
772
|
+
# If the first thing in the Enumerable responds to a User-like convention, then
|
773
|
+
# set 'who' equal to the extension(s) accessor of those objects. We refine the "who"
|
774
|
+
# argument more and more in this way until it's finally in a way Asterisk can read.
|
775
|
+
who.map! { |p| p.send user_method }.compact! if user_method
|
776
|
+
|
777
|
+
# Now replace each item in the Enumerable with its form converted to
|
778
|
+
# extension (assuming it's not already in that format)
|
779
|
+
who.map! do |ext|
|
780
|
+
(ext.kind_of?(String) && ext.index(?/)) ? ext : "SIP/#{ext}"
|
781
|
+
end
|
782
|
+
who * '&' # Finally, join() anything left in the Array with an '&'
|
783
|
+
end
|
654
784
|
|
655
|
-
def
|
785
|
+
def self.io() Thread.current[:io] end
|
656
786
|
end
|
657
787
|
|
658
788
|
# The Contexts class is a blank slate in which the extensions.rb file is evaluated.
|
@@ -822,4 +952,4 @@ end
|
|
822
952
|
# is one of the names you're signed into AIM with. Note: this example doesn't use the :through
|
823
953
|
# Hash-key argument because it assumes no other helpers are installed with this same format.
|
824
954
|
# If you had a MSN or Yahoo helper installed too, you'd need to do specify :through because
|
825
|
-
def im(sn, msg, hash={}) InstantMessenger.im(sn,msg,hash) end
|
955
|
+
def im(sn, msg, hash={}) InstantMessenger.im(sn,msg,hash) end
|