I use your dialplan version 2 and config MY problem is with the Google Voice number every time I dial with GV the call is not made and always I got a **Error: Can't convert VSP into Fixnum. dont know what is wrong
here my code
Code: Select all
# Copyright 2010 Mike Telis
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
require 'mikesgem'
# ************* C O N F I G U R A T I O N S E C T I O N *************** #
Area = '33' # my area code, this will be added to 7-digit dialouts
Tz = -6 # my time zone (GMT format, e.g. Eastern = -5, Central = -6)
# Speed dial entries. Format: "key" => "number"
Speeddial = {
'0' => '22210910', # Home
'21' => '*#2 (646) 657-8199', # New York Voice Mail, dial my NY GV using Santa Monica GV acnt
'27' => 'grrivado@sipsorcery.com', # a grace via sipsorcery account
'277' => '10312255', # Grace
'411' => '(800) 466-4411', # Google's Directory Assistance, GOOG-411
'303' => '303@sip.blueface.ie', # Blueface speaking clock (Ireland time)
'266' => '4153767253@podlinez.net', # CNN Headlines (266 = "CNN")
'677' => '8186882773@podlinez.net', # NPR's most e-mailed stories (677 ="NPR")
'742' => '6506441934@podlinez.net', # Prairie Home Companion's, or PHC's
# News from Lake Wobegon (742 = "PHC")
'932' => '7755333366', # Columbus OH-based national weather (932 = "WEA[ther]")
}
# CNAM table: number in ENUM format => caller's name
CNAM = {
'(212) 555-1212' => 'Dear mom',
'(215) 333-2211' => 'Bratty kid',
}
# Uncomment next line and insert your White Pages API key, if you have it
# WP_key = '427961d1960ac97d0799e6562bbc3bd9dsewe' # White Pages API key
# Uncomment line below to enable misdialing safeguards
# EnableSafeguards = 1
# Excluded Prefixes. Provides a safeguard against accidentally calling premium numbers
ExcludedPrefixes = [
' 1 (900 | 809)', # USA Premium
' 1 \d\d\d 555 1212', # USA Directory assistance
' 52 (900 | 809)', # Mexico Premium
]
# Yet another safeguard, list of blessed country codes
Allowed_Country = %w{
1 52 54
}
# My own ENUM database
MyENUM = {
'+1 (408) 334-1234' => 'brother@local', # Brother George
}
# Enum database list
EnumDB = [
MyENUM, # look in MyENUM first
'e164.org',
'e164.info',
'e164.arpa',
'e164.televolution.net',
'enum.org',
]
# Serviced domains, must be in lowercase!
Domains = ['sipsorcery.com','sip.sipsorcery.com','sip1.sipsorcery.com','sip2.sipsorcery.com','69.59.142.213']
Host = 'sipsorcery.com' # Replaces "host" on incoming calls
# Google Voice accounts
Myacnt1 = { :usr => '*******', :pwd => '********' }
Myacnt2 = { :usr => '*****', :pwd => '******' }
NYCaccount = [
Myacnt1 + { :cb => '(305) 760-XXXX' },
Myacnt1 + { :cb => 'nil' },
]
SMaccount = [
Myacnt2 + { :cb => '(305) 760-XXXX' },
Myacnt2 + { :cb => ' nil ' },
]
# SIP accounts
Nextel = VSP.new '#0', ' ${EXTEN}@Nextel', 'nextel default route'
RealEstate = VSP.new '#2', ' ${EXTEN}@RealEstate', 'realestate route'
VoipBuster = VSP.new '#3', '0052 ${EXTEN}@VoipBuster', 'Voipbuster Nacional route'
Home = VSP.new '#4', ' ${EXTEN}@Home', 'Casa route'
DFine = VSP.new '#5', ' ${EXTEN}@DFine', 'DFine route'
Mont = VSP.new '#8', ' ${EXTEN}@Mont', 'Mont route'
VoipBuster2 = VSP.new '#9', '00 ${EXTEN}@VoipBuster', 'Voipbuster Internacional Route'
Voxalot = VSP.new '#6', ' ${EXTEN}@Voxalot', 'Voxalot Internacional Route'
INUM = VSP.new nil, '011${EXTEN}@Gizmo', 'Gizmo'
NewYork = GV.new '*#1', nil, 'GV-646', :account => NYCaccount, :repeat => 3
Smonica = GV.new '*#2', nil, 'GV-424', :account => SMaccount, :repeat => 2
Dallas = GV.new '*#3', nil, 'GV-214', :usr => '*****', :pwd => '*****',
:cb => '(305) 760-XXXX', :repeat => 2
Provider '**', 'DisableSafeGuards' # Disable safeguards prefix is **
# ******************** s e l e c t V S P *******************************
def selectVSP # VoIP provider selection
case @num
when /^\*/ # For *500, *600 and other Voxalot services
route_to Voxalot, "Voxalot Services", nil
when /^883/ # iNUM
route_to INUM, "iNUM", nil # disable ENUM
when /(^1([2-9]\d\d)[2-9]\d{6})/ # North America
@num = $1 # Truncate to 11 digits
case $2 # check area code
when "800", "866", "877", "888" # toll free numbers...
route_to NewYork, "USA toll-free", nil # call from GV/New York, disable ENUM search
when "424" # Santa Monica CA patch, I have GV number there
route_to Smonica, "Santa Monica"
when "312", "773", "872" # Chicago, I have GV number there
route_to Chicago, "Chicago"
else
route_to NewYork # all other destinations within US & Canada
end
route_to Ribbit, nil, nil # If GV call failed, try one more time with Ribbit
else
rejectCall(603,"Number's too short, check & dial again") if @num.length < 1
route_to Nextel
end
end
# ------------ O P T I O N A L C O N F I G U R A T I O N --------------- #
# ******************** i n c o m i n g C a l l *************************
def incomingCall
sys.SetFromHeader(formatNum(@cname || @cid,true), nil, Host) # Set FromName & FromHost for sys.Dial
# Forward call to the bindings (ATA / softphone)
# Change FromURI when forwarding to @local, or else Bria won't find contact in its phonebook!
callswitch("#{@user}@local[fu=#{@cid}]",45) unless (90..745) === @t.hour*100 + @t.min # reject incoming calls from 1:30a to 7:45a
@code, @reason = 480, "#{@user} is asleep" unless @code # if nothing else, must be the night hour
@code = 486 if @trunk =~ /IPCOMM/i ## *** temporary fix for IPCOMMS ***
end
# ************************** t o E N U M *******************************
def to_ENUM num
num.gsub!(/[^0-9*+]/,'') # Delete all fancy chars (only digits, '+' and '*' allowed)
# Check if the number begins with one of international prefixes:
# '+' - international format
# 00 - European style international prefix (00)
# 011 - US style international prefix (011)
num =~ /^(\+|00|011)/ and return $' # if yes, remove prefix and return
case num # Special cases
when /^[2-9]\d{6}$/ # Local call, 7-digit number
'1' + Area + num # prefix it with country and area code
when /^[01]?([2-9]\d{9})/ # US number with or without "1" country code
'1' + $1 # add country code and truncate number to 10-digit
when /^\*/ # Voxalot voicemail, echotest & other special numbers
num # ... as is
when /^\d{8}$/ # Llamadas Locales en Guadalajara
num # ... as is
else
rejectCall(603,"Wrong number: '#{num}', check & dial again")
end
end
# ****** E N D O F C O N F I G U R A T I O N S E C T I O N ******** #
# ************************** C A L L S W I T C H **********************
def callswitch(num,*args)
@timeout = args[0]
num.gsub!(/%(..)/) {$1.hex.chr} # Convert %hh into ASCII
@num = Speeddial[num] || num # If there is speed dial entry for it...
if @num =~ /@/ # If we already have URI, just dial and return
sys.Log("URI dialing: #@num")
dial(@num,*args)
else # Not URI
rexp = VSP.tab.keys.sort {|a,b| b.length <=> a.length}.map {|x| Regexp.escape(x)}.join('|')
if @num =~ /^(#{rexp})/ # If number starts with VSP selection prefix
@num = $'; @forcedRoute = VSP.tab[$1]
@noSafeGuards = (@forcedRoute.fmt =~ /Disable\s*Safe\s*Guards/i)
end
@num = to_ENUM(@num) # Convert to ENUM
rejectCall(503,"Number's empty") if @num.empty?
sys.Log("Number in ENUM format: #{@num}")
if @forcedRoute && !@noSafeGuards
route_to @forcedRoute, "Forced routing!", false # if forced with prefix, skip ENUM, safeguards & VSP selection
else
checkNum if defined?(EnableSafeguards) && !@noSafeGuards
selectVSP # Pick appropriate provider for the call
end
end # URI
end
# *************************** R O U T E _ T O ****************************
def route_to vsp, dest=nil, enum = EnumDB
enum.to_a.each do |db| # if enum enabled, look in all enum databases
if uri = (db.class == Hash)? db[@num] : sys.ENUMLookup("#{@num}.#{db}")
sys.Log("ENUM entry found: '#{uri}' in #{db.class == Hash ? 'local' : db} database")
dial(uri); break
end
end # ENUM not found or failed, call via regular VSP
return unless vsp # No VSP - do nothing
uri = vsp.fmt.gsub(/\s+/,'').gsub(/\$\{EXTEN(:([^:}]+)(:([^}]+))?)?\}/) {@num[$2.to_i,$4? $4.to_i : 100]}
dest &&= " (#{dest})"; with = vsp.name; with &&= " with #{with}"
sys.Log("Calling #{formatNum(@num)}#{dest}#{with}")
if vsp.is_gv?
vsp.repeat.times do |i|
@code, @reason = 200, "OK" # assume OK
sys.GoogleVoiceCall *vsp.getparams(uri, i + (vsp.rand ? @t.to_i : 0))
sys.Log("Google Voice Call failed!")
@code, @reason = 603, 'Service Unavailable'
end
else
vsp.repeat.times do
dial(uri, @timeout || vsp.tmo || 300) # Dial, global time-out overrides account
end
end
end
# ******************************* D I A L ********************************
def dial *args
@code, @reason = nil
sys.Dial *args # dial URI
status() # We shouldn't be here! Get error code...
sys.Log("Call failed: code #{@code}, #{@reason}")
end
# ***************************** S T A T U S ******************************
def status
begin
@code, @reason = 487, 'Cancelled by Sipsorcery'
sys.LastDialled.each do |ptr|
if ptr
ptr = ptr.TransactionFinalResponse
@code = ptr.StatusCode; @reason = ptr.ReasonPhrase; break if @code == 200
# sys.Log("#{ptr.ToString()}")
end
end
rescue
end
end
# ************************ r e j e c t C a l l ***************************
def rejectCall code, reason
@code = code; @reason = reason
sys.Respond code, reason
end
# **************************** C H E C K N U M **************************
def checkNum
return if @num.match(/^\D/) # skip if number doesn't begin with a digit
# Reject calls to not blessed countries and premium numbers
# (unless VSP was forced using #n dial prefix)
rejectCall(503,"Calls to code #{formatNum(@num).split(' ')[0]} not allowed") \
unless @num.match "^(#{Allowed_Country.join('|')})"
rejectCall(503,"Calls to '#{formatNum($&)}' not allowed") if @num.match \
'^(' + ExcludedPrefixes.map { |x| "(:?#{x.gsub(/\s*/,'')})" }.join('|') + ')'
end
# ********************** k e y s t o E N U M *************************
def keys_to_ENUM (table)
Hash[*table.keys.map! {|key| to_ENUM(key.dup)}.zip(table.values).flatten]
end
# ************************** g e t T I M E *******************************
def getTime
Time.now + ((Tz-6)*60*60) # Get current time and adjust to local. SS Server is in GMT-6
end
# ******************************* M A I N ********************************
begin
sys.Log("** Call from #{req.Header.From} to #{req.URI.User} **")
sys.ExtendScriptTimeout(15) # preventing long running dialscript time-out
@t = getTime()
sys.Log(@t.strftime('Local time: %c'))
EnumDB.map! {|x| x.class == Hash ? keys_to_ENUM(x) : x } # rebuild local ENUM table
if sys.In # If incoming call...
@cid = req.Header.from.FromURI.User.to_s # Get caller ID
# Prepend 10-digit numbers with "1" (US country code) and remove int'l prefix (if present)
@cid = ('1' + @cid) if @cid =~ /^[2-9]\d\d[2-9]\d{6}$/
@cid.sub!(/^(\+|00|011)/,'') # Remove international prefixes, if any
prs = req.URI.User.split('.') # parse User into chunks
@trunk = prs[-2] # get trunk name
@user = prs[-1] # called user name
# Check CNAM first. If not found and US number, try to lookup caller's name in Whitepages
if !(@cname = keys_to_ENUM(CNAM)[@cid]) && @cid =~ /^1([2-9]\d\d[2-9]\d{6})$/ && defined?(WP_key)
url = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'http%3A%2F%2Fapi.whitepages.com%2Freverse_phone%2F1.0%2F%3Fphone%3D#{$1}%3Bapi_key%3D#{WP_key}'%20and%20itemPath%3D'wp.listings.listing'&format=json"
if js = sys.WebGet(url,4).to_s
@cname, dname, city, state = %w(businessname displayname city state).map {|x| js =~ /"#{x}":"([^"]+)"/; $1}
@cname ||= dname; @cname ||= "#{city}, #{state}" if city && state
end
end
sys.Log("Caller's number: '#{@cid}'"); sys.Log("Caller's name: '#{@cname}'") if @cname
incomingCall() # forward incoming call
else # Outbound call ...
# check if it's URI or phone number.
# If destination's host is in our domain, it's a phone call
num = req.URI.User.to_s; reqHost = req.URI.Host.to_s # Get User and Host
host = reqHost.downcase.split(':')[0] # Convert to lowercase and delete optional ":port"
num << '@' << reqHost unless Domains.include?(host) # URI dialing unless host is in our domain list
callswitch(num)
end
sys.Respond(@code,@reason) # Forward error code to ATA
rescue
# Gives a lot more details at what went wrong (borrowed from Myatus' dialplan)
sys.Log("** Error: " + $!) unless $!.to_s =~ /Thread was being aborted./
end
when /(^1([2-9]\d\d)[2-9]\d{6})/ # North America
@num = $1 # Truncate to 11 digits
but in mexico is this way format 52 (xx) xxxxxxxx (country 52 + 2 digit area (xx) + 8 digits Phone xxxxxxxx and need to truncate to 8 digits since the area I dial has is own local phone
thanks for all. and help