;--------------------------------------------------------------------------------; ; Do NOT edit this file as it is auto-generated by FreePBX. All modifications to ; ; this file must be done via the web gui. There are alternative files to make ; ; custom modifications, details at: http://freepbx.org/configuration_files ; ;--------------------------------------------------------------------------------; ; ; This file is part of FreePBX. ; ; FreePBX is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 2 of the License, or ; (at your option) any later version. ; ; FreePBX is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with FreePBX. If not, see . ; ; Copyright (C) 2004 Coalescent Systems Inc (Canada) ; Copyright (C) 2006 Why Pay More 4 Less Pty Ltd (Australia) ; Copyright (C) 2007 Astrogen LLC (USA) ; dialparties.agi (http://www.sprackett.com/asterisk/) ; Asterisk::AGI (http://asterisk.gnuinter.net/) ; gsm (http://www.ibiblio.org/pub/Linux/utils/compress/!INDEX.short.html) ; loligo sounds (http://www.loligo.com/asterisk/sounds/) ; mpg123 (http://voip-info.org/wiki-Asterisk+config+musiconhold.conf) ;************************** -WARNING- **************************************** ; * ; This include file is to be used with extreme caution. In almost all cases * ; any custom dialplan SHOULD be put in extensions_custom.conf which will * ; not hurt a FreePBX generated dialplan. In some very rare and custom * ; situations users may have a need to override what FreePBX automatically * ; generates. If so anything in this file will do that. If you come up with a * ; situation where you need to modify the existing dialplan or macro, please * ; put it here and also notify the FreePBX development team so they can take it * ; into account in the future. * ; * #include extensions_override_freepbx.conf ; * ;************************** -WARNING- **************************************** ; include extension contexts generated from AMP #include extensions_additional.conf ; Customizations to this dialplan should be made in extensions_custom.conf ; See extensions_custom.conf.sample for an example. ; If you need to use [macro-dialout-trunk-predial-hook], [ext-did-custom], or ; [from-internal-custom] for example, place these in this file or they will get overwritten. ; #include extensions_custom.conf [from-digital] include => from-pstn [from-analog] include => from-dahdi [from-trunk] ; just an alias since VoIP shouldn't be called PSTN include => from-pstn [from-pstn] include => from-pstn-custom ; create this context in extensions_custom.conf to include customizations include => ext-did include => ext-did-post-custom include => from-did-direct ; MODIFICATION (PL) for findmefollow if enabled, should be before ext-local include => ext-did-catchall ; THIS MUST COME AFTER ext-did ;------------------------------------------------------------------------------- ; from-pstn-e164-us: ; ; The context is designed for providers who send calls in e164 format and is ; biased towards NPA calls, callerid and dialing rules. It will do the following: ; ; DIDs in an NPA e164 format of +1NXXNXXXXXX will be converted to 10 digit DIDs ; ; DIDs in any other format will be delivered as they are, including e164 non NPA ; DIDs which means they will need the full format including the + in the inbound ; route. ; ; CallerID(number) presented in e164 NPA format will be trimmed to a 10 digit CID ; ; CallerID(number) presented in e164 non-NPA (country code other than 1) will be ; reformated from: + to 011 ; [from-pstn-e164-us] exten => _+1NXXNXXXXXX/_+1NXXNXXXXXX,1,Set(CALLERID(number)=${CALLERID(number):2}) exten => _+1NXXNXXXXXX/_NXXNXXXXXX,2,Goto(from-pstn,${EXTEN:2},1) exten => _+1NXXNXXXXXX/_+X.,1,Set(CALLERID(number)=011${CALLERID(number):1}) exten => _+1NXXNXXXXXX/_011X.,n,Goto(from-pstn,${EXTEN:2},1) exten => _+1NXXNXXXXXX,1,Goto(from-pstn,${EXTEN:2},1) exten => _[0-9+]./_+1NXXNXXXXXX,1,Set(CALLERID(number)=${CALLERID(number):2}) exten => _[0-9+]./_NXXNXXXXXX,n,Goto(from-pstn,${EXTEN},1) exten => _[0-9+]./_+X.,1,Set(CALLERID(number)=011${CALLERID(number):1}) exten => _[0-9+]./_011X.,n,Goto(from-pstn,${EXTEN},1) exten => _[0-9+].,1,Goto(from-pstn,${EXTEN},1) exten => s/_+1NXXNXXXXXX,1,Set(CALLERID(number)=${CALLERID(number):2}) exten => s/_NXXNXXXXXX,n,Goto(from-pstn,${EXTEN},1) exten => s/_+X.,1,Set(CALLERID(number)=011${CALLERID(number):1}) exten => s/_011X.,n,Goto(from-pstn,${EXTEN},1) exten => s,1,Goto(from-pstn,${EXTEN},1) ;------------------------------------------------------------------------------- ;------------------------------------------------------------------------------- ; from-pstn-to-did ; ; The context is designed for providers who send the DID in the TO: SIP header ; only. The format of this header is: ; ; To: ; ; So the DID must be extracted between the sip: and the @, which this does ; [from-pstn-toheader] exten => _.,1,Goto(from-pstn,${CUT(CUT(SIP_HEADER(To),@,1),:,2)},1) ;------------------------------------------------------------------------------- ; MODIFICATION (PL) ; ; Required to assure that direct dids go to personal ring group before local extension. ; This could be auto-generated however I it is preferred to be put here and hard coded ; so that it can be modified if ext-local should take precedence in certain situations. ; will have to decide what to do later. ; [from-did-direct] include => ext-findmefollow include => ext-local ; ############################################################################ ; Macros [macro] ; ############################################################################ ; Rings one or more extensions. Handles things like call forwarding and DND ; We don't call dial directly for anything internal anymore. ; ARGS: $TIMER, $OPTIONS, $EXT1, $EXT2, $EXT3, ... ; Use a Macro call such as the following: ; Macro(dial,$DIAL_TIMER,$DIAL_OPTIONS,$EXT1,$EXT2,$EXT3,...) [macro-dial] exten => s,1,GotoIf($["${MOHCLASS}" = ""]?dial) exten => s,n,SetMusicOnHold(${MOHCLASS}) exten => s,n(dial),AGI(dialparties.agi) exten => s,n,NoOp(Returned from dialparties with no extensions to call and DIALSTATUS: ${DIALSTATUS}) exten => s,n+2(normdial),Dial(${ds}) ; dialparties will set the priority to 10 if $ds is not null exten => s,n,Set(DIALSTATUS=${IF($["${DIALSTATUS_CW}"!="" ]?${DIALSTATUS_CW}:${DIALSTATUS})}) exten => s,n,GosubIf($["${SCREEN}" != "" | "${DIALSTATUS}" = "ANSWER"]?${DIALSTATUS},1) exten => s,20(huntdial),NoOp(Returned from dialparties with hunt groups to dial ) exten => s,n,Set(HuntLoop=0) exten => s,n(a22),GotoIf($[${HuntMembers} >= 1]?a30) ; if this is from rg-group, don't strip prefix exten => s,n,NoOp(Returning there are no members left in the hunt group to ring) ; dialparties.agi has setup the dialstring for each hunt member in a variable labeled HuntMember0, HuntMember1 etc for each iteration ; and The total number in HuntMembers. So for each iteration, we will update the CALLTRACE Data. ; exten => s,n+2(a30),Set(HuntMember=HuntMember${HuntLoop}) exten => s,n,GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $[$["${RingGroupMethod}" = "hunt" ] | $["${RingGroupMethod}" = "firstavailable"] | $["${RingGroupMethod}" = "firstnotonphone"]]]?a32:a35) exten => s,n(a32),Set(CT_EXTEN=${CUT(FILTERED_DIAL,,$[${HuntLoop} + 1])}) exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT}) exten => s,n,Goto(s,a42) ;Set Call Trace for each hunt member we are going to call "Memory groups have multiple members to set CALL TRACE For" hence the loop ; exten => s,n(a35),GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "memoryhunt" ]]?a36:a50) exten => s,n(a36),Set(CTLoop=0) exten => s,n(a37),GotoIf($[${CTLoop} > ${HuntLoop}]?a42) ; if this is from rg-group, don't strip prefix exten => s,n,Set(CT_EXTEN=${CUT(FILTERED_DIAL,,$[${CTLoop} + 1])}) exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT}) exten => s,n,Set(CTLoop=$[1 + ${CTLoop}]) exten => s,n,Goto(s,a37) exten => s,n(a42),Dial(${${HuntMember}}${ds}) exten => s,n,GotoIf($["${DIALSTATUS}" = "ANSWER"]?ANSWER,1) exten => s,n,Set(HuntLoop=$[1 + ${HuntLoop}]) exten => s,n,GotoIf($[$[$["foo${RingGroupMethod}" != "foofirstavailable"] & $["foo${RingGroupMethod}" != "foofirstnotonphone"]] | $["foo${DialStatus}" = "fooBUSY"]]?a46) exten => s,n,Set(HuntMembers=0) exten => s,n(a46),Set(HuntMembers=$[${HuntMembers} - 1]) exten => s,n,Goto(s,a22) exten => s,n(a50),DBdel(CALLTRACE/${CT_EXTEN}) exten => s,n,Goto(s,a42) ; For call screening exten => NOANSWER,1,Macro(vm,${SCREEN_EXTEN},BUSY,${IVR_RETVM}) exten => NOANSWER,n,GotoIf($["${IVR_RETVM}" != "RETURN" | "${IVR_CONTEXT}" = ""]?bye) exten => NOANSWER,n,Return exten => NOANSWER,n(bye),Macro(hangupcall) exten => TORTURE,1,Goto(app-blackhole,musiconhold,1) exten => TORTURE,n,Macro(hangupcall) exten => DONTCALL,1,Answer exten => DONTCALL,n,Wait(1) exten => DONTCALL,n,Zapateller() exten => DONTCALL,n,Playback(ss-noservice) exten => DONTCALL,n,Macro(hangupcall) exten => ANSWER,1,Noop(Call successfully answered - Hanging up now) exten => ANSWER,n,Macro(hangupcall,) ; make sure hungup calls go here so that proper cleanup occurs from call confirmed calls and the like ; exten => h,1,Macro(hangupcall) ; get the voicemail context for the user in ARG1 [macro-get-vmcontext] exten => s,1,Set(VMCONTEXT=${DB(AMPUSER/${ARG1}/voicemail)}) exten => s,2,GotoIf($["foo${VMCONTEXT}" = "foo"]?200:300) exten => s,200,Set(VMCONTEXT=default) exten => s,300,NoOp() ; For some reason, if I don't run setCIDname, CALLERID(name) will be blank in my AGI ; ARGS: none [macro-fixcid] exten => s,1,Set(CALLERID(name)=${CALLERID(name)}) ; Ring groups of phones ; ARGS: comma separated extension list ; 1 - Ring Group Strategy ; 2 - ringtimer ; 3 - prefix ; 4 - extension list [macro-rg-group] exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from ringgroup exten => s,2,GotoIf($["${CALLERID(name):0:${LEN(${RGPREFIX})}}" != "${RGPREFIX}"]?4:3) ; check for old prefix exten => s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ; strip off old prefix exten => s,4,Set(RGPREFIX=${ARG3}) ; set new prefix exten => s,5,Set(CALLERID(name)=${RGPREFIX}${CALLERID(name)}) ; add prefix to callerid name exten => s,6,Set(RecordMethod=Group) ; set new prefix exten => s,7,Macro(record-enable,${MACRO_EXTEN},${RecordMethod}) exten => s,8,Set(RingGroupMethod=${ARG1}) ; exten => s,9,Macro(dial,${ARG2},${DIAL_OPTIONS},${ARG4}) exten => s,10,Set(RingGroupMethod='') ; ; ; Outgoing channel(s) are busy ... inform the client ; but use noanswer features like ringgroups don't break by being answered ; just to play the message. ; [macro-outisbusy] exten => s,1,Progress exten => s,n,Playback(all-circuits-busy-now,noanswer) exten => s,n,Playback(pls-try-call-later,noanswer) exten => s,n,Macro(hangupcall) ; dialout and strip the prefix [macro-dialout] exten => s,1,Macro(user-callerid,SKIPTTL) exten => s,2,GotoIf($["${ECID${CALLERID(number)}}" = ""]?5) ;check for CID override for exten exten => s,3,Set(CALLERID(all)=${ECID${CALLERID(number)}}) exten => s,4,Goto(7) exten => s,5,GotoIf($["${OUTCID_${ARG1}}" = ""]?7) ;check for CID override for trunk exten => s,6,Set(CALLERID(all)=${OUTCID_${ARG1}}) exten => s,7,Set(length=${LEN(${DIAL_OUT_${ARG1}})}) exten => s,8,Dial(${OUT_${ARG1}}/${ARG2:${length}}) exten => s,9,Playtones(congestion) exten => s,10,Congestion(5) exten => s,109,Macro(outisbusy) ; dialout using default OUT trunk - no prefix [macro-dialout-default] exten => s,1,Macro(user-callerid,SKIPTTL) exten => s,2,Macro(record-enable,${CALLERID(number)},OUT) exten => s,3,Macro(outbound-callerid,${ARG1}) exten => s,4,Dial(${OUT}/${ARG1}) exten => s,5,Playtones(congestion) exten => s,6,Congestion(5) exten => s,105,Macro(outisbusy) [macro-dialout-trunk-predial-hook] ; this macro intentionally left blank so it may be safely overwritten for any custom ; requirements that an installation may have. ; ; MACRO RETURN CODE: ${PREDIAL_HOOK_RET} ; if set to "BYPASS" then this trunk will be skipped ; exten => s,1,MacroExit() [macro-user-logon] ; check device type ; exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)}) exten => s,n,Answer() exten => s,n,Wait(1) exten => s,n,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1) ; get user's extension ; exten => s,n,Set(AMPUSER=${ARG1}) exten => s,n,GotoIf($["${AMPUSER}" != ""]?gotpass) exten => s,n(playagain),Read(AMPUSER,please-enter-your-extension-then-press-pound,,,4) ; get user's password and authenticate ; exten => s,n,GotoIf($["${AMPUSER}" = ""]?s-MAXATTEMPTS,1) exten => s,n(gotpass),GotoIf($["${DB_EXISTS(AMPUSER/${AMPUSER}/password)}" = "0"]?s-NOUSER,1) exten => s,n,Set(AMPUSERPASS=${DB_RESULT}) exten => s,n,GotoIf($[${LEN(${AMPUSERPASS})} = 0]?s-NOPASSWORD,1) ; do not continue if the user has already logged onto this device ; exten => s,n,Set(DEVICEUSER=${DB(DEVICE/${CALLERID(number)}/user)}) exten => s,n,GotoIf($["${DEVICEUSER}" = "${AMPUSER}"]?s-ALREADYLOGGEDON,1) exten => s,n,Authenticate(${AMPUSERPASS}) exten => s,n,AGI(user_login_out.agi,login,${CALLERID(number)},${AMPUSER}) exten => s,n,Playback(vm-goodbye) exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged into) exten => s-FIXED,n,Playback(ha/phone) exten => s-FIXED,n,SayDigits(${CALLERID(number)}) exten => s-FIXED,n,Playback(is-curntly-unavail&vm-goodbye) exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into exten => s-ALREADYLOGGEDON,1,NoOp(This device has already been logged into by this user) exten => s-ALREADYLOGGEDON,n,Playback(vm-goodbye) exten => s-ALREADYLOGGEDON,n,Hangup ;TODO should play msg indicated device is already logged into exten => s-NOPASSWORD,1,NoOp(This extension does not exist or no password is set) exten => s-NOPASSWORD,n,Playback(pbx-invalid) exten => s-NOPASSWORD,n,Goto(s,playagain) exten => s-MAXATTEMPTS,1,NoOp(Too many login attempts) exten => s-MAXATTEMPTS,n,Playback(vm-goodbye) exten => s-MAXATTEMPTS,n,Hangup exten => s-NOUSER,1,NoOp(Invalid extension ${AMPUSER} entered) exten => s-NOUSER,n,Playback(pbx-invalid) exten => s-NOUSER,n,Goto(s,playagain) [macro-user-logoff] ; check device type ; exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)}) exten => s,n,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1) exten => s,n,AGI(user_login_out.agi,logout,${CALLERID(number)}) exten => s,n(done),Playback(vm-goodbye) exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged out of) exten => s-FIXED,n,Playback(an-error-has-occured&vm-goodbye) exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into ; Privacy Manager Macro makes sure that any calls that don't pass the privacy manager are presented ; with congestion since there have been observed cases of the call continuing if not stopped with a ; congestion, and this provides a slightly more friendly 'sorry' message in case the user is ; legitimately trying to be cooperative. ; ; Note: the following options are configurable in privacy.conf: ; ; maxretries = 3 ; default value, number of retries before failing ; minlength = 10 ; default value, number of digits to be accepted as valid CID ; [macro-privacy-mgr] exten => s,1,Set(KEEPCID=${CALLERID(num)}) exten => s,n,GotoIf($["foo${CALLERID(num):0:1}"="foo+"]?CIDTEST2:CIDTEST1) exten => s,n(CIDTEST1),Set(TESTCID=${MATH(1+${CALLERID(num)})}) exten => s,n,Goto(TESTRESULT) exten => s,n(CIDTEST2),Set(TESTCID=${MATH(1+${CALLERID(num):1})}) exten => s,n(TESTRESULT),GotoIf($["foo${TESTCID}"="foo"]?CLEARCID:PRIVMGR) exten => s,n(CLEARCID),Set(CALLERID(num)=) exten => s,n(PRIVMGR),PrivacyManager(${ARG1},${ARG2}) exten => s,n,GotoIf($["${PRIVACYMGRSTATUS}"="FAILED"]?fail) exten => s,n,GosubIf($["${CALLED_BLACKLIST}" = "1"]?app-blacklist-check,s,1) exten => s,n,SetCallerPres(allowed_passed_screen); stop gap until app_privacy.c clears unavailable bit exten => s,PRIVMGR+101(fail),Noop(STATUS: ${PRIVACYMGRSTATUS} CID: ${CALLERID(num)} ${CALLERID(name)} CALLPRES: ${CALLLINGPRES}) exten => s,n,Playback(sorry-youre-having-problems) exten => s,n,Playback(goodbye) exten => s,n,Playtones(congestion) exten => s,n,Congestion(5) exten => h,1,Hangup ; Text-To-Speech related macros ; These all follow common actions. First try to playback a file "tts/custom-md5" ; where "md5" is the md5() of whatever is going to be played. If that doesn't exist, ; try to playback using macro-tts-sayXXXXX (where XXXXX is text/digits/etc, same as ; the macro below). If that macro exits with MACRO_OFFSET=100, then it's done, ; otherwise, fallback to the default asterisk method. ; ; say text is purely for text-to-speech, there is no fallback [macro-saytext] exten => s,1,Noop(Trying custom SayText playback for "${ARG1}") exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) ; call tts-saytext. This should set MACRO_OFFSET=101 if it was successful exten => s,n(tts),Macro(tts-saytext,${ARG1},${ARG2},${ARG3}) exten => s,n,Noop(No text-to-speech handler for SayText, cannot say "${ARG1}") exten => s,n,Goto(done) exten => s,tts+101,Noop(tts handled saytext) ; say name is for saying names typically, but fallsback to using SayAlpha ; (saying the word letter-by-letter) [macro-sayname] exten => s,1,Noop(Trying custom SayName playback for "${ARG1}") exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) ; call tts-sayalpha. This should set MACRO_OFFSET=101 if it was successful exten => s,n(tts),Macro(tts-sayalpha,${ARG1},${ARG2},${ARG3}) exten => s,n,SayAlpha(${ARG1}) exten => s,n,Goto(done) exten => s,tts+101,Noop(tts handled sayname) ; Say number is for saying numbers (eg "one thousand forty six") [macro-saynumber] exten => s,1,Noop(Trying custom SayNumber playback for "${ARG1}") exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) ; call tts-saynumber. This should set MACRO_OFFSET=101 if it was successful exten => s,n(tts),Macro(tts-saynumber,${ARG1},${ARG2},${ARG3}) exten => s,n,SayNumber(${ARG1}) exten => s,n,Goto(done) exten => s,tts+101,Noop(tts handled saynumber) ; Say digits is for saying digits one-by-one (eg, "one zero four six") [macro-saydigits] exten => s,1,Noop(Trying custom SayDigits playback for "${ARG1}") exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) ; call tts-saydigits. This should set MACRO_OFFSET=101 if it was successful exten => s,n(tts),Macro(tts-saydigits,${ARG1},${ARG2},${ARG3}) exten => s,n,SayDigits(${ARG1}) exten => s,n,Goto(done) ; ; ############################################################################ ; Inbound Contexts [from] ; ############################################################################ [from-sip-external] ; Yes. This is _really_ meant to be _. - I know asterisk whines about it, but ; I do know what I'm doing. This is correct. exten => _.,1,NoOp(Received incoming SIP connection from unknown peer to ${EXTEN}) exten => _.,n,Set(DID=${IF($["${EXTEN:1:2}"=""]?s:${EXTEN})}) exten => _.,n,Goto(s,1) exten => s,1,GotoIf($["${ALLOW_SIP_ANON}"="yes"]?checklang:noanonymous) exten => s,n(checklang),GotoIf($["${SIPLANG}"!=""]?setlanguage:from-trunk,${DID},1) exten => s,n(setlanguage),Set(CHANNEL(language)=${SIPLANG}) exten => s,n,Goto(from-trunk,${DID},1) exten => s,n(noanonymous),Set(TIMEOUT(absolute)=15) exten => s,n,Answer exten => s,n,Wait(2) exten => s,n,Playback(ss-noservice) exten => s,n,Playtones(congestion) exten => s,n,Congestion(5) exten => h,1,Hangup exten => i,1,Hangup exten => t,1,Hangup [from-internal-xfer] ; applications are now mostly all found in from-internal-additional in _custom.conf include => from-internal-custom include => parkedcalls ; MODIFIED (PL) ; ; Currently the include for findmefollow is being auto-generated before ext-local which is the desired behavior. ; However, I haven't been able to do anything that I know of to force this. We need to determine if it should ; be hardcoded into here to make sure it doesn't change with some configuration. For now I will leave it out ; until we can discuss this. ; include => ext-local-confirm include => findmefollow-ringallv2 include => from-internal-additional ; This causes grief with '#' transfers, commenting out for the moment. ; include => bad-number exten => s,1,Macro(hangupcall) exten => h,1,Macro(hangupcall) [from-internal] include => from-internal-xfer include => bad-number ;------------------------------------------------------------------------ ; [macro-setmusic] ;------------------------------------------------------------------------ ; CONTEXT: macro-setmusic ; PURPOSE: to turn off moh on routes where it is not desired ; ;------------------------------------------------------------------------ [macro-setmusic] exten => s,1,NoOp(Setting Outbound Route MoH To: ${ARG1}) exten => s,2,Set(CHANNEL(musicclass)=${ARG1}) ; this won't work in 1.2 anymore, could fix in auto-generate if we wanted... ;------------------------------------------------------------------------ ; ########################################## ; ## Ring Groups with Confirmation macros ## ; ########################################## ; Used by followme and ringgroups ;------------------------------------------------------------------------ ; [macro-dial-confirm] ;------------------------------------------------------------------------ ; This has now been incorporated into dialparties. It still only works with ringall ; and ringall-prim strategies. Have not investigated why it doesn't work with ; hunt and memory hunt. ; ;------------------------------------------------------------------------ [macro-dial-confirm] ; This was written to make it easy to use macro-dial-confirm instead of macro-dial in generated dialplans. ; This takes the same parameters, with an additional parameter of the ring group Number ; ARG1 is the timeout ; ARG2 is the DIAL_OPTIONS ; ARG3 is a list of xtns to call - 203-222-240-123123123#-211 ; ARG4 is the ring group number ; This sets a unique value to indicate that the channel is ringing. This is used for warning slow ; users that the call has already been picked up. ; exten => s,1,Set(DB(RG/${ARG4}/${CHANNEL})=RINGING) ; We need to keep that channel variable, because it'll change when we do this dial, so set it to ; fallthrough to every sibling. ; exten => s,n,Set(__UNIQCHAN=${CHANNEL}) ; The calling ringgroup should have set RingGroupMethod appropriately. We need to set two ; additional parameters: ; ; USE_CONFIRMATION, RINGGROUP_INDEX ; ; These are passed to inform dialparties to place external calls through the [grps] context ; exten => s,n,Set(USE_CONFIRMATION=TRUE) exten => s,n,Set(RINGGROUP_INDEX=${ARG4}) exten => s,n,Set(ARG4=) ; otherwise it gets passed to dialparties.agi which processes it (prob bug) exten => s,n,Macro(dial,${ARG1},${ARG2},${ARG3}) ; delete the variable, if we are here, we are done trying to dial and it may have been left around ; exten => s,n,Noop(DELETE KEY: RG/${RINGGROUP_INDEX}/${CHANNEL}: ${DB_DELETE(RG/${RINGGROUP_INDEX}/${CHANNEL})}) exten => s,n,Set(USE_CONFIRMATION=) exten => s,n,Set(RINGGROUP_INDEX=) ;------------------------------------------------------------------------ ;------------------------------------------------------------------------ ; [ext-local-confirm] ;------------------------------------------------------------------------ ; If call confirm is being used in a ringgroup, then calls that do not require confirmation are sent ; to this extension instead of straight to the device. ; ; The sole purpose of sending them here is to make sure we run Macro(auto-confirm) if this ; extension answers the line. This takes care of clearing the database key that is used to inform ; other potential late comers that the extension has been answered by someone else. ; ; ALERT_INFO is deprecated in Asterisk 1.4 but still used throughout the FreePBX dialplan and ; usually set by dialparties.agi. This allows inheritance. Since no dialparties.agi here, set the ; header if it is set. ; ;------------------------------------------------------------------------ [ext-local-confirm] exten => _LC-.,1,Noop(IN ext-local-confirm with - RT: ${RT}, RG_IDX: ${RG_IDX}) exten => _LC-.,n,GotoIf($["x${ALERT_INFO}"="x"]?godial) exten => _LC-.,n,SIPAddHeader(Alert-Info: ${ALERT_INFO}) exten => _LC-.,n(godial),dial(${DB(DEVICE/${EXTEN:3}/dial)},${RT},M(auto-confirm^${RG_IDX})${DIAL_OPTIONS}) ;------------------------------------------------------------------------ ; [findmefollow-ringallv2] ;------------------------------------------------------------------------ ; This context, to be included in from-internal, implements the PreRing part of findmefollow ; as well as the GroupRing part. It also communicates between the two so that if DND is set ; on the primary extension, and mastermode is enabled, then the other extensions will not ring ; ;------------------------------------------------------------------------ [findmefollow-ringallv2] exten => _FMPR-.,1,Noop(In FMPR ${FMGRP} with ${EXTEN:5}) exten => _FMPR-.,n,Set(RingGroupMethod=) exten => _FMPR-.,n,Set(USE_CONFIRMATION=) exten => _FMPR-.,n,Set(RINGGROUP_INDEX=) exten => _FMPR-.,n,Macro(simple-dial,${EXTEN:5},${FMREALPRERING}) exten => _FMPR-.,n,GotoIf($["${DIALSTATUS}" != "BUSY"]?nodnd) exten => _FMPR-.,n,Set(DB(FM/DND/${FMGRP}/${FMUNIQUE})=DND) exten => _FMPR-.,n(nodnd),Noop(Ending FMPR ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS}) exten => _FMPR-.,n,Hangup() exten => _FMGL-.,1,Noop(In FMGL ${FMGRP} with ${EXTEN:5}) exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) exten => _FMGL-.,n,Wait(1) exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) exten => _FMGL-.,n,Wait(1) exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) exten => _FMGL-.,n,Wait(${FMPRERING}) exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) exten => _FMGL-.,n,DBDel(FM/DND/${FMGRP}/${FMUNIQUE}) exten => _FMGL-.,n(dodial),Macro(dial,${FMGRPTIME},${DIAL_OPTIONS},${EXTEN:5}) exten => _FMGL-.,n,Noop(Ending FMGL ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS}) exten => _FMGL-.,n,Hangup() exten => _FMGL-.,n+10(dodnd),DBDel(FM/DND/${FMGRP}/${FMUNIQUE}) exten => _FMGL-.,n,GotoIf($["${FMPRIME}" = "FALSE"]?dodial) exten => _FMGL-.,n,Noop(Got DND in FMGL ${FMGRP} with ${EXTEN:5} in ${RingGroupMethod} mode, aborting) exten => _FMGL-.,n,Hangup() ;------------------------------------------------------------------------ ; [block-cf] ;------------------------------------------------------------------------ ; This context is set as a target with FORWARD_CONTEXT when Call Forwarding is set to be ; ignored in a ringgroup or other features that may take advantage of this. Server side ; CF is done in dialparties.agi but if a client device forwards a call, it will be caught ; and blocked here. ;------------------------------------------------------------------------ [block-cf] exten => _X.,1,Noop(Blocking callforward to ${EXTEN} because CF is blocked) exten => _X.,n,Hangup() ;------------------------------------------------------------------------ ;this is where parked calls go if they time-out. Should probably re-ring [default] include => ext-local exten => s,1,Playback(vm-goodbye) exten => s,2,Macro(hangupcall) #include extension_a2billing_additionals.conf