; FreePBX ; Copyright (C) 2004 Coalescent Systems Inc (Canada) ; Copyright (C) 2006 Why Pay More 4 Less Pty Ltd (Australia) ; Released under the GNU GPL Licence version 2. ; 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 freepbx generated dialplan. In some very rare and custom situation * ; users have a need to override what freepbx generates. Anything in this file * ; will do such. * ; * #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 #include extensions_custom.conf [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-catchall ; THIS MUST COME AFTER ext-did include => from-did-direct ; MODIFICATOIN (PL) for findmefollow if enabled, should be bofore ext-local exten => fax,1,Goto(ext-fax,in_fax,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 prefered 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,2,SetMusicOnHold(${MOHCLASS}) exten => s,3(dial),AGI(dialparties.agi) exten => s,4,NoOp(Returned from dialparties with no extensions to call and DIALSTATUS: ${DIALSTATUS}) exten => s,10,Dial(${ds}) ; dialparties will set the priority to 10 if $ds is not null exten => s,11,Set(DIALSTATUS=${IF($["${DIALSTATUS_CW}"!="" ]?${DIALSTATUS_CW}:${DIALSTATUS})}) exten => s,20,NoOp(Returned from dialparties with hunt groups to dial ) exten => s,21,Set(HuntLoop=0) exten => s,22,GotoIf($[${HuntMembers} >= 1]?30 ) ; if this is from rg-group, don't strip prefix exten => s,23,NoOp(Returning there are no members left in the hunt group to ring) exten => s,30,Set(HuntMember=HuntMember${HuntLoop}) exten => s,31,GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "hunt" ]]?32:35 ) ; Set CAll Trace for Hunt member we are going to call exten => s,32,Set(CT_EXTEN=${CUT(ARG3,,$[${HuntLoop} + 1])}) exten => s,33,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT}) exten => s,34,Goto(s,42) exten => s,35,GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "memoryhunt" ]]?36:50 ) ;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,36,Set(CTLoop=0) exten => s,37,GotoIf($[${CTLoop} > ${HuntLoop}]?42 ) ; if this is from rg-group, don't strip prefix exten => s,38,Set(CT_EXTEN=${CUT(ARG3,,$[${CTLoop} + 1])}) exten => s,39,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT}) exten => s,40,Set(CTLoop=$[1 + ${CTLoop}]) exten => s,41,Goto(s,37) exten => s,42,Dial(${${HuntMember}}${ds} ) ; dialparties will set the priority to 20 if $ds is not null and its a hunt group exten => s,43,Set(HuntLoop=$[1 + ${HuntLoop}]) exten => s,44,GotoIf($[$[$["foo${RingGroupMethod}" != "foofirstavailable"] & $["foo${RingGroupMethod}" != "foofirstnotonphone"]] | $["foo${DialStatus}" = "fooBUSY"]]?46) exten => s,45,Set(HuntMembers=0) exten => s,46,Set(HuntMembers=$[${HuntMembers} - 1]) exten => s,47,Goto(s,22) exten => s,50,DBdel(CALLTRACE/${CT_EXTEN}) exten => s,51,Goto(s,42) ; make sure hungup calls go here so that proper cleanup occurs from call confirmed calls and the like ; exten => h,1,Macro(hangupcall) ; Ring an extension, if the extension is busy or there is no answer send it ; to voicemail ; ARGS: $VMBOX, $EXT [macro-exten-vm] exten => s,1,Macro(user-callerid) exten => s,n,Set(FROMCONTEXT=exten-vm) exten => s,n,Set(VMBOX=${ARG1}) exten => s,n,Set(EXTTOCALL=${ARG2}) exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})}) exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})}) exten => s,n,Set(RT=${IF($[$["${VMBOX}"!="novm"] | $["foo${CFUEXT}"!="foo"]]?${RINGTIMER}:"")}) exten => s,n,Macro(record-enable,${EXTTOCALL},IN) exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL}) exten => s,n,Set(SV_DIALSTATUS=${DIALSTATUS}) exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"="NOANSWER"] & $["foo${CFUEXT}"!="foo"]]?docfu,1) ; check for CFU in use on no answer exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"="BUSY"] & $["foo${CFBEXT}"!="foo"]]?docfb,1) ; check for CFB in use on busy exten => s,n,Set(DIALSTATUS=${SV_DIALSTATUS}) exten => s,n,NoOp(Voicemail is '${VMBOX}') exten => s,n,GotoIf($["${VMBOX}" = "novm"]?s-${DIALSTATUS},1) ; no voicemail in use for this extension exten => s,n,NoOp(Sending to Voicemail box ${EXTTOCALL}) exten => s,n,Macro(vm,${VMBOX},${DIALSTATUS}) ; Try the Call Forward on No Answer / Unavailable number exten => docfu,1,Set(RTCFU=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")}) exten => docfu,n,Dial(Local/${CFUEXT}@from-internal/n,${RTCFU},${DIAL_OPTIONS}) exten => docfu,n,Return ; Try the Call Forward on Busy number exten => docfb,1,Set(RTCFB=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")}) exten => docfb,n,Dial(Local/${CFBEXT}@from-internal/n,${RTCFB},${DIAL_OPTIONS}) exten => docfb,n,Return ; Extensions with no Voicemail box reporting BUSY come here exten => s-BUSY,1,NoOp(Extension is reporting BUSY and not passing to Voicemail) exten => s-BUSY,n,Playtones(busy) exten => s-BUSY,n,Busy(20) ; Anything but BUSY comes here exten => _s-.,1,Playtones(congestion) exten => _s-.,n,Congestion(10) ;------------------------------------------------------------------------ ; [macro-vm] ;------------------------------------------------------------------------ ; CONTEXT: macro-vm ; PURPOSE: call voicemail system and extend with personal ivr ; ; Under normal use, this macro will call the voicemail system with the extension and ; desired greeting mode of busy, unavailable or as specified with direct voicemail ; calls (usually unavailable) when entered from destinations. ; ; The voicemail system's two greetings have been 'hijacked' as follows to extend the ; system by giving the option of a private 'ivr' for each voicemail user. The following ; applies to both the busy and unavailable modes of voicemail and can be applied to one ; or both, and differently. ; ; Global Defaults: ; ; The following are default values, used in both busy and unavail modes if no specific ; values are specified. ; ; VMX_REPEAT ; The number of times to repeat the users message if no option is pressed. ; VMX_TIMEOUT ; The timeout to wait after playing message before repeating or giving up. ; VMX_LOOPS ; The number of times it should replay the message and check for an option when ; an invalid option is pressed. ; ; VMX_OPTS_DOVM ; Default voicemail option to use if vm is chosen as an option. No options will ; cause Allison's generic message, 's' will go straight to beep. ; VMX_OPTS_TIMEOUT ; Default voicemail option to use if it times out with no options. No options will ; cause Allison's generic message, 's' will go straight to beep. ; IF THE USER PRESSES # - it will look like a timeout as well since no option will ; be presented. If the user wishes to enable a mode where a caller can press # ; during their message and it goes straight to voicemail with only a 'beep' then ; this should be set to 's'. ; VMX_OPTS_LOOPS ; Default voicemail option to use if to many wrong options occur. No options will ; cause Allison's generic message, 's' will go straight to beep. ; ; VMX_CONTEXT ; Default context for user destinations if not supplied in the user's settings ; VMX_PRI ; Default priority for user destinations if not supplied in the user's settings ; ; VMX_TIMEDEST_CONTEXT ; Default context for timeout destination if not supplied in the user's settings ; VMX_TIMEDEST_EXT ; Default extension for timeout destination if not supplied in the user's settings ; VMX_TIMEDEST_PRI ; Default priority for timeout destination if not supplied in the user's settings ; ; VMX_LOOPDEST_CONTEXT ; Default context for loops destination if not supplied in the user's settings ; VMX_LOOPDEST_EXT ; Default extension for loops destination if not supplied in the user's settings ; VMX_LOOPDEST_PRI ; Default priority for loops destination if not supplied in the user's settings ; ; ; The AMPUSER database variable has been extended with a 'vmx' tree (vm-extension). A ; duplicate set is included for both unavail and busy. You could choose for to have an ; ivr when unavail is taken, but not with busy - or a different once with busy. ; The full list is below, each specific entry is futher described: ; ; state: Whether teh current mode is enabled or disabled. Anything but 'enabled' is ; treated as disabled. ; repeat: This is the number of times that the users message should be played after the ; timeout if the user has not entered anything. It is just a variable to the ; Read() function which will do the repeating. ; timeout: This is how long to wait after the message has been read for a response from ; the user. A caller can enter a digit any time during the playback. ; loops: This is the number of loops that the system will allow a caller to retry if ; they enter a bad menu choice, before going to the loop failover destination ; vmxopts: This is the vm options to send to the voicemail command used when a specific ; voicemail destination is chosen (inidcated by 'dovm' in the ext field). This is ; typically either set to 's' or left blank. When set to 's' there will be no ; message played when entering the voicemail, just a beep. When blank, you will ; have Allison's generic message played. It is not typical to play the greetings ; since they have been 'hijacked' for these IVR's and from a caller's perspecitive ; this system appears interconnected with the voicemail so instructions can be ; left there. ; timedest: The three variables: ext, context and pri are the goto destination if the caller ; enters no options and it timesout. None have to be set and a system default ; will be used. If just ext is set, then defaults will be used for context and ; pri, etc. ; loopdest: This is identical to timedest but used if the caller exceeds the maximum invalid ; menu choices. ; [0-9*]: The user can specify up to 11 ivr options, all as single digits from 0-9 or *. The ; # key can not be used since it is used as a terminator key for the Read command ; and will never be returned. A minimum of the ext must be specified for each valid ; option and as above, the context and priority can also be specified if the default ; is not to be used. ; Option '0' takes on a special meaning. Since a user is able to break out of the ; voicemail command once entering it with a 0, if specified, the 0 destination will ; be used. ; Option '*' can also be used to breakout. It is undecided at this point whether ; providing that option will be used as well. (probably should). ; ; ; /AMPUSER//vmx/[busy|unavail]/state: enabled|disabled ; /AMPUSER//vmx/[busy|unavail]/repeat: n (times to repeat message) ; /AMPUSER//vmx/[busy|unavail]/timeout: n (timeout to wait for digit) ; /AMPUSER//vmx/[busy|unavail]/loops: n (loop returies for invalid entries) ; /AMPUSER//vmx/[busy|unavail]/vmxopts/dovm: vmoptions (if ext is dovm) ; /AMPUSER//vmx/[busy|unavail]/vmxopts/timeout: vmoptions (if timeout) ; /AMPUSER//vmx/[busy|unavail]/vmxopts/loops: vmoptions (if loops) ; /AMPUSER//vmx/[busy|unavail]/timedest/ext: extension (if timeout) ; /AMPUSER//vmx/[busy|unavail]/timedest/context: context (if timeout) ; /AMPUSER//vmx/[busy|unavail]/timedest/pri: priority (if timeout) ; /AMPUSER//vmx/[busy|unavail]/loopdest/ext: extension (if too many failures) ; /AMPUSER//vmx/[busy|unavail]/loopdest/context: context (if too many failures) ; /AMPUSER//vmx/[busy|unavail]/loopdest/pri: priority (if too many failures) ; /AMPUSER//vmx/[busy|unavail]/[0-9*]/ext: extension (dovm for vm access) ; /AMPUSER//vmx/[busy|unavail]/[0-9*]/context: context ; /AMPUSER//vmx/[busy|unavail]/[0-9*]/pri: priority ;------------------------------------------------------------------------ [macro-vm] ; ARG1 - extension ; ARG2 - DIRECTDIAL/BUSY exten => s,1,Macro(user-callerid,SKIPTTL) exten => s,n,Set(VMGAIN=${IF($["foo${VM_GAIN}"!="foo"]?"g(${VM_GAIN})":"")}) ; ; If BLKVM_OVERRIDE is set, then someone told us to block calls from going to ; voicemail. This variable is reset by the answering channel so subsequent ; transfers will properly function. ; exten => s,n,GotoIf($["foo${DB(${BLKVM_OVERRIDE})}" != "fooTRUE"]?vmx,1) ; ; we didn't branch so block this from voicemail ; exten => s,n,Noop(CAME FROM: ${NODEST} - Blocking VM cause of key: ${DB(BLKVM_OVERRIDE)}) ; If vmx not enabled for the current mode,then jump to normal voicemail behavior ; also - if not message (no-msg) is requested, straight to voicemail ; exten => vmx,1,GotoIf($["${ARG2}"="NOMESSAGE"]?s-${ARG2},1) exten => vmx,n,Set(MODE=${IF($["${ARG2}"="BUSY"]?busy:unavail)}) exten => vmx,n,GotoIf($["${ARG2}" != "DIRECTDIAL"]?notdirect) exten => vmx,n,Set(MODE=${IF($["${REGEX("[b]" ${VM_DDTYPE})}" = "1"]?busy:${MODE})}) exten => vmx,n(notdirect),Noop(Checking if ext ${ARG1} is enabled: ${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}) exten => vmx,n,GotoIf($["${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}" != "enabled"]?s-${ARG2},1) ; If the required voicemail file does not exist, then abort and go to normal voicemail behavior ; ; TODO: there have been errors using System() with jump to 101 where asterisk works fine at the begining and ; then starts to jump to 101 even on success. This new mode is being tried with the SYSTEM Status which ; returns SUCCESS when the command returned succcessfully with a 0 app return code. ; exten => vmx,n,Macro(get-vmcontext,${ARG1}) ;exten => vmx,n,TrySystem(/bin/ls ${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}.[wW][aA][vV]) exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}) exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" != "SUCCESS"]?nofile) ; Get the repeat, timeout and loop times to use if they are overriden form the global settings ; exten => vmx,n,Set(LOOPCOUNT=0) exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/repeat)}" = "0"]?vmxtime) exten => vmx,n,Set(VMX_REPEAT=${DB_RESULT}) exten => vmx,n(vmxtime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timeout)}" = "0"]?vmxloops) exten => vmx,n,Set(VMX_TIMEOUT=${DB_RESULT}) exten => vmx,n(vmxloops),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loops)}" = "0"]?vmxanswer) exten => vmx,n,Set(VMX_LOOPS=${DB_RESULT}) exten => vmx,n(vmxanswer),Answer() ; Now play the users voicemail recording as the basis for their ivr, the Read command will repeat as needed and if it timesout ; then we go to the timeout. Otherwise handle invalid options by looping until the limit until a valid option is played. ; exten => vmx,n(loopstart),Read(ACTION,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE},1,skip,${VMX_REPEAT},${VMX_TIMEOUT}) exten => vmx,n,GotoIf($["${EXISTS(${ACTION})}" = "1"]?checkopt) ; If we are here we timed out, go to the required destination ; exten => vmx,n(noopt),Noop(Timeout: going to timeout dest) exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_TIMEOUT}) exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/timeout)}" = "0"]?chktime) exten => vmx,n,Set(VMX_OPTS=${DB_RESULT}) exten => vmx,n(chktime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/ext)}" = "0"]?dotime) exten => vmx,n,Set(VMX_TIMEDEST_EXT=${DB_RESULT}) exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/context)}" = "0"]?timepri) exten => vmx,n,Set(VMX_TIMEDEST_CONTEXT=${DB_RESULT}) exten => vmx,n(timepri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/pri)}" = "0"]?dotime) exten => vmx,n,Set(VMX_TIMEDEST_PRI=${DB_RESULT}) exten => vmx,n(dotime),Goto(${VMX_TIMEDEST_CONTEXT},${VMX_TIMEDEST_EXT},${VMX_TIMEDEST_PRI}) ; We got an option, check if the option is defined, or one of the system defaults ; exten => vmx,n(checkopt),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/ext)}" = "1"]?doopt) exten => vmx,n,GotoIf($["${ACTION}" = "0"]?o,1) exten => vmx,n,GotoIf($["${ACTION}" = "*"]?adef,1) ; Got invalid option loop until the max ; exten => vmx,n,Set(LOOPCOUNT=$[${LOOPCOUNT} + 1]) exten => vmx,n,GotoIf($[${LOOPCOUNT} > ${VMX_LOOPS}]?toomany) exten => vmx,n,Playback(pm-invalid-option&please-try-again) exten => vmx,n,Goto(loopstart) ; tomany: to many invalid options, go to the specified destination ; exten => vmx,n(toomany),Noop(Too Many invalid entries, got to invalid dest) exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_LOOPS}) exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/loops)}" = "0"]?chkloop) exten => vmx,n,Set(VMX_OPTS=${DB_RESULT}) exten => vmx,n(chkloop),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/ext)}" = "0"]?doloop) exten => vmx,n,Set(VMX_LOOPDEST_EXT=${DB_RESULT}) exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/context)}" = "0"]?looppri) exten => vmx,n,Set(VMX_LOOPDEST_CONTEXT=${DB_RESULT}) ;TODO make configurable per above exten => vmx,n(looppri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/pri)}" = "0"]?doloop) exten => vmx,n,Set(VMX_LOOPDEST_PRI=${DB_RESULT}) ;TODO make configurable per above exten => vmx,n(doloop),Goto(${VMX_LOOPDEST_CONTEXT},${VMX_LOOPDEST_EXT},${VMX_LOOPDEST_PRI}) ; doopt: execute the valid option that was chosen ; exten => vmx,n(doopt),Noop(Got a valid option: ${DB_RESULT}) exten => vmx,n,Set(VMX_EXT=${DB_RESULT}) ; ; Special case, if this option was to go to voicemail, set options and go ; exten => vmx,n,GotoIf($["${VMX_EXT}" != "dovm"]?getdest) exten => vmx,n(vmxopts),Set(VMX_OPTS=${VMX_OPTS_DOVM}) exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/dovm)}" = "0"]?vmxdovm) exten => vmx,n(vmxopts),Set(VMX_OPTS=${DB_RESULT}) exten => vmx,n(vmxdovm),goto(dovm,1) ; ; General case, setup the goto destination and go there (no error checking, its up to the GUI's to assure ; reasonable values ; exten => vmx,n(getdest),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/context)}" = "0"]?vmxpri) exten => vmx,n,Set(VMX_CONTEXT=${DB_RESULT}) exten => vmx,n(vmxpri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/pri)}" = "0"]?vmxgoto) exten => vmx,n,Set(VMX_PRI=${DB_RESULT}) exten => vmx,n(vmxgoto),Goto(${VMX_CONTEXT},${VMX_EXT},${VMX_PRI}) ; If the required voicemail file is not present, then revert to normal voicemail ; behavior treating as if it was not set ; exten => vmx,n(nofile),Noop(File for mode: ${MODE} does not exist, SYSTEMSTATUS: ${SYSTEMSTATUS}, going to normal voicemail) exten => vmx,n,Goto(s-${ARG2},1) ; Drop into voicemail either as a direct destination (in which case VMX_OPTS might be set to something) or ; if the user timed out or broke out of the loop then VMX_OPTS is always cleared such that an Allison ; message is played and the caller know's what is going on. ; exten => dovm,1,Noop(VMX Timeout - go to voicemail) exten => dovm,n,Voicemail(${ARG1}@${VMCONTEXT},${VMX_OPTS}${VMGAIN}) ; no flags, so allison plays please leave ... exten => dovm,n,Goto(exit-${VMSTATUS},1) exten => s-BUSY,1,NoOp(BUSY voicemail) exten => s-BUSY,n,Macro(get-vmcontext,${ARG1}) exten => s-BUSY,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}b${VMGAIN}) ; Voicemail Busy message exten => s-BUSY,n,Goto(exit-${VMSTATUS},1) exten => s-NOMESSAGE,1,NoOp(NOMESSAGE (beeb only) voicemail) exten => s-NOMESSAGE,n,Macro(get-vmcontext,${ARG1}) exten => s-NOMESSAGE,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VMGAIN}) ; Voicemail Busy message exten => s-NOMESSAGE,n,Goto(exit-${VMSTATUS},1) exten => s-DIRECTDIAL,1,NoOp(DIRECTDIAL voicemail) exten => s-DIRECTDIAL,n,Macro(get-vmcontext,${ARG1}) exten => s-DIRECTDIAL,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VM_DDTYPE}${VMGAIN}) exten => s-DIRECTDIAL,n,Goto(exit-${VMSTATUS},1) exten => _s-.,1,Macro(get-vmcontext,${ARG1}) exten => _s-.,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}u${VMGAIN}) ; Voicemail Unavailable message exten => _s-.,n,Goto(exit-${VMSTATUS},1) ; If the user has a 0 option defined, use that for operator zero-out from within voicemail ; as well to keep it consistant with the menu structure ; exten => o,1,Background(one-moment-please) ; 0 during vm message will hangup exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/ext)}" = "0"]?doopdef) exten => o,n,Set(VMX_OPDEST_EXT=${DB_RESULT}) exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/context)}" = "1"]?opcontext) exten => o,n,Set(DB_RESULT=${VMX_CONTEXT}) exten => o,n(opcontext),Set(VMX_OPDEST_CONTEXT=${DB_RESULT}) exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/pri)}" = "1"]?oppri) exten => o,n,Set(DB_RESULT=${VMX_PRI}) exten => o,n(oppri),Set(VMX_OPDEST_PRI=${DB_RESULT}) exten => o,n,Goto(${VMX_OPDEST_CONTEXT},${VMX_OPDEST_EXT},${VMX_OPDEST_PRIORITY}) exten => o,n(doopdef),GotoIf($["x${OPERATOR_XTN}"="x"]?nooper:from-internal,${OPERATOR_XTN},1) exten => o,n(nooper),GotoIf($["x${FROM_DID}"="x"]?nodid) exten => o,n,Dial(Local/${FROM_DID)@from-pstn) exten => o,n,Macro(hangup) exten => o,n(nodid),Dial(Local/s@from-pstn) exten => o,n,Macro(hangup) ; If the user has a * option defined, use that for the * out from within voicemail ; as well to keep it consistant with the menu structure ; exten => a,1,Macro(get-vmcontext,${ARG1}) exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/ext)}" = "0"]?adef,1) exten => a,n,Set(VMX_ADEST_EXT=${DB_RESULT}) exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/context)}" = "1"]?acontext) exten => a,n,Set(DB_RESULT=${VMX_CONTEXT}) exten => a,n(acontext),Set(VMX_ADEST_CONTEXT=${DB_RESULT}) exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/pri)}" = "1"]?apri) exten => a,n,Set(DB_RESULT=${VMX_PRI}) exten => a,n(apri),Set(VMX_ADEST_PRI=${DB_RESULT}) exten => a,n,Goto(${VMX_ADEST_CONTEXT},${VMX_ADEST_EXT},${VMX_ADEST_PRI}) exten => adef,1,VoiceMailMain(${ARG1}@${VMCONTEXT}) exten => adef,n,Hangup exten => exit-FAILED,1,Playback(im-sorry&an-error-has-occured) exten => exit-FAILED,n,Hangup() exten => exit-SUCCESS,1,Playback(goodbye) exten => exit-SUCCESS,n,Hangup() exten => exit-USEREXIT,1,Playback(goodbye) exten => exit-USEREXIT,n,Hangup() exten => t,1,Hangup() ;------------------------------------------------------------------------ ;------------------------------------------------------------------------ ; [macro-simple-dial] ;------------------------------------------------------------------------ ; This macro was derived from macro-exten-vm, which is what is normally used to ; ring an extension. It has been simplified and designed to never go to voicemail ; and always return regardless of the DIALSTATUS for any incomplete call. ; ; It's current primary purpose is to allow findmefollow ring an extension prior ; to trying the follow-me ringgroup that is provided. ; ; Ring an extension, if the extension is busy or there is no answer, return ; ARGS: $EXTENSION, $RINGTIME ;------------------------------------------------------------------------ [macro-simple-dial] exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from follow-me ; FROMCONTEXT was in the original macro-exten-vm where this macro was derived from. A ; search through all the modules does not come up with any place using this ; variable, but it is left here as a reminder in case there is functionality ; that eventually behaves in a certain way as a result of this variable being set ; and this macro has to masquerade as exten-vm. ; exten => s,n,Set(EXTTOCALL=${ARG1}) exten => s,n,Set(RT=${ARG2}) exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})}) exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})}) exten => s,n,Macro(record-enable,${EXTTOCALL},IN) exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL}) exten => s,n,Set(PR_DIALSTATUS=${DIALSTATUS}) ; if we return, thus no answer, and they have a CFU setting, then we try that next ; exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"="NOANSWER"] & $["foo${CFUEXT}"!="foo"]]?docfu,1) ; check for CFU in use on no answer exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"="BUSY"] & $["foo${CFBEXT}"!="foo"]]?docfb,1) ; check for CFB in use on busy exten => s,n,Set(DIALSTATUS=${PR_DIALSTATUS}) ; Nothing yet, then go to the end (which will just return, but in case we decide to do something with certain ; return situations, this is left in. ; exten => s,n,Goto(s-${DIALSTATUS},1) ; Try the Call Forward on No Answer / Unavailable number. ; We want to try CFU if set, but we want the same ring timer as was set to our call (or do we want the ; system ringtimer? - probably not). Then if no answer there (assuming it doesn't drop into their vm or ; something we return, which will have the net effect of returning to the followme setup.) ; ; want to avoid going to other follow-me settings here. So check if the CFUEXT is a user and if it is ; then direct it straight to ext-local (to avoid getting intercepted by findmefollow) otherwise send it ; to from-internal since it may be an outside line. ; exten => docfu,1,GotoIf( $[ "foo${DB(AMPUSER/${CFUEXT}/device)}" = "foo" ]?chlocal) exten => docfu,n,Dial(Local/${CFUEXT}@ext-local,${RT},${DIAL_OPTIONS}) exten => docfu,n,Return exten => docfu,n(chlocal),Dial(Local/${CFUEXT}@from-internal/n,${RT},${DIAL_OPTIONS}) exten => docfu,n,Return ; Try the Call Forward on Busy number exten => docfb,1,GotoIf( $[ "foo${DB(AMPUSER/${CFBEXT}/device)}" = "foo" ]?chlocal) exten => docfb,n,Dial(Local/${CFBEXT}@ext-local,${RT},${DIAL_OPTIONS}) exten => docfb,n,Return exten => docfb,n(chlocal),Dial(Local/${CFBEXT}@from-internal/n,${RT},${DIAL_OPTIONS}) exten => docfb,n,Return ; In all cases of no connection, come here and simply return, since the calling dialplan will ; decide what to do next exten => _s-.,1,NoOp(Extension is reporting ${EXTEN}) ;------------------------------------------------------------------------ ; 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,Playback(all-circuits-busy-now,noanswer) exten => s,n,Playback(pls-try-call-later,noanswer) exten => s,n,Macro(hangupcall) ; What to do on hangup. [macro-hangupcall] exten => s,1,ResetCDR(w) exten => s,n,NoCDR() ; Cleanup any remaining RG flag ; exten => s,n,GotoIf($[ "x${USE_CONFIRMATION}" = "x" | "x${RINGGROUP_INDEX}" = "x" | "${CHANNEL}" != "${UNIQCHAN}"]?skiprg) exten => s,n,Noop(Cleaning Up Confirmation Flag: RG/${RINGGROUP_INDEX}/${CHANNEL}) exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL}) ; Cleanup any remaining BLKVM flag ; exten => s,n(skiprg),GotoIf($[ "x${BLKVM_BASE}" = "x" | "BLKVM/${BLKVM_BASE}/${CHANNEL}" != "${BLKVM_OVERRIDE}" ]?skipblkvm) exten => s,n,Noop(Cleaning Up Block VM Flag: ${BLKVM_OVERRIDE}) exten => s,n,DBDel(${BLKVM_OVERRIDE}) ; Cleanup any remaining FollowMe DND flags ; exten => s,n(skipblkvm),GotoIf($[ "x${FMGRP}" = "x" | "x${FMUNIQUE}" = "x" | "${CHANNEL}" != "${FMUNIQUE}" ]?theend) exten => s,n,DBDel(FM/DND/${FMGRP}/${CHANNEL}) exten => s,n(theend),Hangup [macro-faxreceive] exten => s,1,Set(FAXFILE=${ASTSPOOLDIR}/fax/${UNIQUEID}.tif) exten => s,2,Set(EMAILADDR=${FAX_RX_EMAIL}) exten => s,3,rxfax(${FAXFILE}) exten => s,103,Set(EMAILADDR=${FAX_RX_EMAIL}) exten => s,104,Goto(3) ; 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 intentially left blank so it may be safely overwritten for any custom ; requirements that an installatin may have. ; ; MACRO RETURN CODE: ${PREDIAL_HOOK_RET} ; if set to "BYPASS" then this trunk will be skipped ; ; dialout using a trunk, using pattern matching (don't strip any prefix) ; arg1 = trunk number, arg2 = number, arg3 = route password ; ; MODIFIED (PL) ; ; Modified both Dial() commands to include the new TRUNK_OPTIONS from the general ; screen of AMP ; [macro-dialout-trunk] exten => s,1,Set(DIAL_TRUNK=${ARG1}) exten => s,n,Set(DIAL_NUMBER=${ARG2}) exten => s,n,Set(ROUTE_PASSWD=${ARG3}) exten => s,n,GotoIf($["${ROUTE_PASSWD}" = ""]?noauth) ; arg3 is pattern password exten => s,n(auth),Authenticate(${ROUTE_PASSWD}) exten => s,n(noauth),GotoIf($["x${OUTDISABLE_${ARG1}}" = "xon"]?disabletrunk,1) ; If NODEST is set, clear it. No point in remembering since dialout-trunk will just end in the ; bit bucket. But if answered by an outside line with transfer capability, we want NODEST to be ; clear so a subsequent transfer to an internal extension works and goes to voicmail or other ; destinations. ; exten => s,n,Set(_NODEST=) exten => s,n,Set(DIAL_TRUNK_OPTIONS=${DIAL_OPTIONS}) // will be reset to TRUNK_OPTIONS if not intra-company exten => s,n,Set(GROUP()=OUT_${DIAL_TRUNK}) exten => s,n,Macro(user-callerid,SKIPTTL) exten => s,n,Macro(record-enable,${CALLERID(number)},OUT) exten => s,n,GotoIf($["${INTRACOMPANYROUTE}" = "YES"]?skipoutcid) ;Set to YES if treated like internal exten => s,n,Set(DIAL_TRUNK_OPTIONS=${TRUNK_OPTIONS}) exten => s,n,Macro(outbound-callerid,${DIAL_TRUNK}) exten => s,n(skipoutcid),GotoIf($["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]?nomax) exten => s,n(checkmax),GotoIf($[ ${GROUP_COUNT()} > ${OUTMAXCHANS_${DIAL_TRUNK}} ]?chanfull) exten => s,n(nomax),AGI(fixlocalprefix) ; this sets DIAL_NUMBER to the proper dial string for this trunk exten => s,n,Set(OUTNUM=${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER}) ; OUTNUM is the final dial number exten => s,n,Set(custom=${CUT(OUT_${DIAL_TRUNK},:,1)}) ; Custom trunks are prefixed with "AMP:" ; Back to normal processing, whether intracompany or not. ; But add the macro-setmusic if we don't want music on this outbound call ; exten => s,n,GotoIf($[$["${MOHCLASS}" = "default"] | $["foo${MOHCLASS}" = "foo"]]?gocall) ; Set to YES if we should pump silence exten => s,n,Set(DIAL_TRUNK_OPTIONS=M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}) ; set MoH or off ; This macro call will always be blank and is provided as a hook for customization required prior to making a call ; such as adding SIP header information or other requirements. All the channel variables from above are present ; exten => s,n,Macro(dialout-trunk-predial-hook) exten => s,n,GotoIf($["${PREDIAL_HOOK_RET}" = "BYPASS"]?bypass,1) exten => s,n(gocall),GotoIf($["${custom}" = "AMP"]?customtrunk) exten => s,n,Dial(${OUT_${DIAL_TRUNK}}/${OUTNUM},300,${DIAL_TRUNK_OPTIONS}) ; Regular Trunk Dial exten => s,n,Goto(s-${DIALSTATUS},1) exten => s,n(customtrunk),Set(pre_num=${CUT(OUT_${DIAL_TRUNK},$,1)}) exten => s,n,Set(the_num=${CUT(OUT_${DIAL_TRUNK},$,2)}) ; this is where we expect to find string OUTNUM exten => s,n,Set(post_num=${CUT(OUT_${DIAL_TRUNK},$,3)}) exten => s,n,GotoIf($["${the_num}" = "OUTNUM"]?outnum:skipoutnum) ; if we didn't find "OUTNUM", then skip to Dial exten => s,n(outnum),Set(the_num=${OUTNUM}) ; replace "OUTNUM" with the actual number to dial exten => s,n(skipoutnum),Dial(${pre_num:4}${the_num}${post_num},300,${DIAL_TRUNK_OPTIONS}) exten => s,n,Goto(s-${DIALSTATUS},1) exten => s,n(chanfull),Noop(max channels used up) exten => s-BUSY,1,NoOp(Dial failed due to trunk reporting BUSY - giving up) exten => s-BUSY,2,Busy(20) exten => s-NOANSWER,1,NoOp(Dial failed due to trunk reporting NOANSWER - giving up) exten => s-NOANSWER,2,Playtones(congestion) exten => s-NOANSWER,3,Congestion(20) exten => s-CANCEL,1,NoOp(Dial failed due to trunk reporting CANCEL - giving up) exten => s-CANCEL,2,Playtones(congestion) exten => s-CANCEL,3,Congestion(20) exten => _s-.,1,GotoIf($["x${OUTFAIL_${ARG1}}" = "x"]?noreport) exten => _s-.,n,AGI(${OUTFAIL_${ARG1}}) exten => _s-.,n(noreport),Noop(TRUNK Dial failed due to ${DIALSTATUS} - failing through to other trunks) exten => disabletrunk,1,Noop(TRUNK: ${OUT_${DIAL_TRUNK}} DISABLED - falling through to next trunk) exten => bypass,1,Noop(TRUNK: ${OUT_${DIAL_TRUNK}} BYPASSING because dialout-trunk-predial-hook) exten => h,1,Macro(hangupcall) ; Adds a dynamic agent/member to a Queue ; Prompts for call-back number - in not entered, uses CIDNum [macro-agent-add] exten => s,1,Wait(1) exten => s,2,Macro(user-callerid,SKIPTTL) exten => s,3,Read(CALLBACKNUM,agent-user) ; get callback number from user exten => s,4,GotoIf($["${CALLBACKNUM}" = ""]?5:7) ; if user just pressed # or timed out, use cidnum exten => s,5,Set(CALLBACKNUM=${CALLERID(number)}) exten => s,6,GotoIf($["${CALLBACKNUM}" = ""]?2) ; if still no number, start over exten => s,7,GotoIf($["${ARG2}" = ""]?9:8) ; arg2 is queue password exten => s,8,Authenticate(${ARG2}) exten => s,9,AddQueueMember(${ARG1},Local/${CALLBACKNUM}@from-internal/n) ; using chan_local allows us to have agents over trunks exten => s,10,UserEvent(Agentlogin,Agent: ${CALLBACKNUM}) exten => s,11,Wait(1) exten => s,12,Playback(agent-loginok) exten => s,13,Hangup() ; Removes a dynamic agent/member from a Queue ; Prompts for call-back number - in not entered, uses CIDNum [macro-agent-del] exten => s,1,Wait(1) exten => s,2,Macro(user-callerid,SKIPTTL) exten => s,3,Read(CALLBACKNUM,agent-user) ; get callback number from user exten => s,4,GotoIf($["${CALLBACKNUM}" = ""]?5:7) ; if user just pressed # or timed out, use cidnum exten => s,5,Set(CALLBACKNUM=${CALLERID(number)}) exten => s,6,GotoIf($["${CALLBACKNUM}" = ""]?2) ; if still no number, start over exten => s,7,RemoveQueueMember(${ARG1},Local/${CALLBACKNUM}@from-internal/n) exten => s,8,UserEvent(RefreshQueue) exten => s,9,Wait(1) exten => s,10,Playback(agent-loggedoff) exten => s,11,Hangup() ; arg1 = trunk number, arg2 = number [macro-dialout-enum] ; Re-written to use enumlookup.agi exten => s,1,GotoIf($["${ARG3}" != ""]?PASSWD:NOPASSWD); arg3 is pattern password exten => s,n(PASSWD),Authenticate(${ARG3}) exten => s,n(NOPASSWD),Macro(user-callerid,SKIPTTL) exten => s,n,Macro(record-enable,${CALLERID(number)},OUT) exten => s,n,Macro(outbound-callerid,${ARG1}) exten => s,n,Set(GROUP()=OUT_${ARG1}) exten => s,n,GotoIf($["${OUTMAXCHANS_${ARG1}}foo" = "foo"]?nomax) exten => s,n,GotoIf($[ ${GROUP_COUNT()} > ${OUTMAXCHANS_${ARG1}} ]?nochans) exten => s,n(nomax),Set(DIAL_NUMBER=${ARG2}) exten => s,n,Set(DIAL_TRUNK=${ARG1}) exten => s,n,AGI(fixlocalprefix) ; this sets DIAL_NUMBER to the proper dial string for this trunk ; Replacement for asterisk's ENUMLOOKUP function exten => s,n,AGI(enumlookup.agi) ; Now we have the variable DIALARR set to a list of URI's that can be called, in order of priority ; Loop through them trying them in order. exten => s,n(dialloop),GotoIf($["foo${DIALARR}"="foo"]?end) exten => s,n,Set(TRYDIAL=${CUT(DIALARR,%,1)}) exten => s,n,Set(DIALARR=${CUT(DIALARR,%,2-)}) exten => s,n,Dial(${TRYDIAL}) exten => s,n,NoOp(Dial exited in macro-enum-dialout with ${DIALSTATUS}) ; Now, if we're still here, that means the Dial failed for some reason. ; If it's CONGESTION or CHANUNAVAIL we want to try again on a different ; different channel. If there's no more left, the dialloop tag will exit. exten => s,n,GotoIf($[ $[ "${DIALSTATUS}" = "CHANUNAVAIL" ] | $[ "${DIALSTATUS}" = "CONGESTION" ] ]?dialloop) ; If we're here, then it's BUSY or NOANSWER or something and well, deal with it. exten => s,n(dialfailed),Goto(s-${DIALSTATUS},1) ; Here are the exit points for the macro. exten => s,n(nochans),NoOp(max channels used up) exten => s,n(end),NoOp(Exiting macro-dialout-enum) exten => s-BUSY,1,NoOp(Trunk is reporting BUSY) exten => s-BUSY,2,Busy(20) exten => _s-.,1,NoOp(Dial failed due to ${DIALSTATUS}) [macro-record-enable] exten => s,1,GotoIf($[${LEN(${BLINDTRANSFER})} > 0]?2:4) exten => s,2,ResetCDR(w) exten => s,3,StopMonitor() exten => s,4,AGI(recordingcheck,${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)},${UNIQUEID}) exten => s,5,Noop(No recording needed) exten => s,999,MixMonitor(${CALLFILENAME}.wav) ;exten => s,3,BackGround(for-quality-purposes) ;exten => s,4,BackGround(this-call-may-be) ;exten => s,5,BackGround(recorded) ; This macro is for dev purposes and just dumps channel/app variables. Useful when designing new contexts. [macro-dumpvars] exten => s,1,Noop(ACCOUNTCODE=${ACCOUNTCODE}) exten => s,2,Noop(ANSWEREDTIME=${ANSWEREDTIME}) exten => s,3,Noop(BLINDTRANSFER=${BLINDTRANSFER}) exten => s,4,Noop(CALLERID=${CALLERID(all)}) exten => s,5,Noop(CALLERID(name)=${CALLERID(name)}) exten => s,6,Noop(CALLERID(number)=${CALLERID(number)}) exten => s,7,Noop(CALLINGPRES=${CALLINGPRES}) exten => s,8,Noop(CHANNEL=${CHANNEL}) exten => s,9,Noop(CONTEXT=${CONTEXT}) exten => s,10,Noop(DATETIME=${DATETIME}) exten => s,11,Noop(DIALEDPEERNAME=${DIALEDPEERNAME}) exten => s,12,Noop(DIALEDPEERNUMBER=${DIALEDPEERNUMBER}) exten => s,13,Noop(DIALEDTIME=${DIALEDTIME}) exten => s,14,Noop(DIALSTATUS=${DIALSTATUS}) exten => s,15,Noop(DNID=${DNID}) exten => s,16,Noop(EPOCH=${EPOCH}) exten => s,17,Noop(EXTEN=${EXTEN}) exten => s,18,Noop(HANGUPCAUSE=${HANGUPCAUSE}) exten => s,19,Noop(INVALID_EXTEN=${INVALID_EXTEN}) exten => s,20,Noop(LANGUAGE=${LANGUAGE}) exten => s,21,Noop(MEETMESECS=${MEETMESECS}) exten => s,22,Noop(PRIORITY=${PRIORITY}) exten => s,23,Noop(RDNIS=${RDNIS}) exten => s,24,Noop(SIPDOMAIN=${SIPDOMAIN}) exten => s,25,Noop(SIP_CODEC=${SIP_CODEC}) exten => s,26,Noop(SIPCALLID=${SIPCALLID}) exten => s,27,Noop(SIPUSERAGENT=${SIPUSERAGENT}) exten => s,29,Noop(TXTCIDNAME=${TXTCIDNAME}) exten => s,30,Noop(UNIQUEID=${UNIQUEID}) exten => s,31,Noop(TOUCH_MONITOR=${TOUCH_MONITOR}) exten => s,32,Noop(MACRO_CONTEXT=${MACRO_CONTEXT}) exten => s,33,Noop(MACRO_EXTEN=${MACRO_EXTEN}) exten => s,34,Noop(MACRO_PRIORITY=${MACRO_PRIORITY}) [macro-user-logon] ; check device type exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)}) exten => s,2,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1) ; get user's extension exten => s,3,Set(AMPUSER=${ARG1}) exten => s,4,GotoIf($["${AMPUSER}" = ""]?5:9) exten => s,5,Playback(please-enter-your) exten => s,6,Playback(extension) exten => s,7,Read(AMPUSER,then-press-pound) ; get user's password and authenticate exten => s,8,Wait(1) exten => s,9,Set(AMPUSERPASS=${DB(AMPUSER/${AMPUSER}/password)}) exten => s,10,GotoIf($[${LEN(${AMPUSERPASS})} = 0]?s-NOPASSWORD,1) ; do not continue if the user has already logged onto this device exten => s,11,Set(DEVICEUSER=${DB(DEVICE/${CALLERID(number)}/user)}) exten => s,12,GotoIf($["${DEVICEUSER}" = "${AMPUSER}"]?s-ALREADYLOGGEDON,1) exten => s,13,Authenticate(${AMPUSERPASS}) ; devices can only be mapped to one user - loggoff anyone else who is here exten => s,14,Macro(user-logoff) ; map user to device exten => s,15,Set(AMPUSERDEVICES=${DB(AMPUSER/${AMPUSER}/device)}) exten => s,16,GotoIf($[${LEN(${AMPUSERDEVICES})} = 0]?18) exten => s,17,Set(AMPUSERDEVICES=${AMPUSERDEVICES}&) exten => s,18,Set(AMPUSERDEVICES=${AMPUSERDEVICES}${CALLERID(number)}) exten => s,19,Set(DB(AMPUSER/${AMPUSER}/device)=${AMPUSERDEVICES}) ; map device to user exten => s,20,Set(DB(DEVICE/${CALLERID(number)}/user)=${AMPUSER}) ; create symlink from dummy device mailbox to user's mailbox exten => s,21,System(/bin/ln -s ${ASTSPOOLDIR}/voicemail/default/${AMPUSER}/ ${ASTSPOOLDIR}/voicemail/device/${CALLERID(number)}) exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged into) exten => s-FIXED,2,Playback(ha/phone) exten => s-FIXED,3,SayDigits(${CALLERID(number)}) exten => s-FIXED,4,Playback(is-curntly-unavail) exten => s-FIXED,5,Playback(vm-goodbye) exten => s-FIXED,6,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,2,Playback(vm-goodbye) exten => s-ALREADYLOGGEDON,3,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,2,Playback(an-error-has-occured) exten => s-NOPASSWORD,3,Playback(vm-goodbye) exten => s-NOPASSWORD,4,Hangup ;TODO should play msg indicated device is already logged into [macro-user-logoff] ; check device type exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)}) exten => s,2,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1) ; remove entry from user's DEVICE key ; delete the symlink to user's voicemail box exten => s,3,System(rm -f ${ASTSPOOLDIR}/voicemail/device/${CALLERID(number)}) exten => s,4,Set(DEVAMPUSER=${DB(DEVICE/${CALLERID(number)}/user)}) exten => s,5,Set(AMPUSERDEVICES=${DB(AMPUSER/${DEVAMPUSER}/device)}) exten => s,6,AGI(list-item-remove.php,${AMPUSERDEVICES},${CALLERID(number)},AMPUSERDEVICES,&) ; reset user -> device mapping ; users can log onto multiple devices, need to just remove device from value exten => s,7,Set(DB(AMPUSER/${DEVAMPUSER}/device)=${AMPUSERDEVICES}) ; reset device -> user mapping exten => s,8,Set(DB(DEVICE/${CALLERID(number)}/user)=none) exten => s,9,Playback(vm-goodbye) exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged out of) exten => s-FIXED,2,Playback(an-error-has-occured) exten => s-FIXED,3,Playback(vm-goodbye) exten => s-FIXED,4,Hangup ;TODO should play msg indicated device cannot be logged into [macro-systemrecording] exten => s,1,Goto(${ARG1},1) exten => dorecord,1,Record(/tmp/${AMPUSER}-ivrrecording:wav) exten => dorecord,n,Wait(1) exten => dorecord,n,Goto(confmenu,1) exten => docheck,1,Playback(/tmp/${AMPUSER}-ivrrecording) exten => docheck,n,Wait(1) exten => docheck,n,Goto(confmenu,1) exten => confmenu,1,Background(to-listen-to-it&press-1&to-rerecord-it&press-star,m,${LANGUAGE},macro-systemrecording) exten => confmenu,n,Read(RECRESULT,,1,,,4) exten => confmenu,n,GotoIf($["x${RECRESULT}"="x*"]?dorecord,1) exten => confmenu,n,GotoIf($["x${RECRESULT}"="x1"]?docheck,1) exten => confmenu,n,Goto(1) exten => 1,1,Goto(docheck,1) exten => *,1,Goto(dorecord,1) exten => t,1,Playback(goodbye) exten => t,n,Hangup exten => i,1,Playback(pm-invalid-option) exten => i,n,Goto(confmenu,1) exten => h,1,Hangup ; ; ############################################################################ ; CallerID Handling ; ############################################################################ ;sets the callerid of the device to that of the logged in user ; ; ${AMPUSER} is set upon return to the real user despite any aliasing that may ; have been set as a result of the AMPUSER//cidnum field. This is used by ; features like DND, CF, etc. to set the proper structure on aliased instructions ; [macro-user-callerid] exten => s,1,Noop(user-callerid: ${CALLERID(name)} ${CALLERID(number)}) ; make sure AMPUSER is set if it doesn't get set below ; exten => s,n,Set(AMPUSER=${IF($["foo${AMPUSER}" = "foo"]?${CALLERID(number)}:${AMPUSER})}) exten => s,n,GotoIf($["${CHANNEL:0:5}" = "Local"]?report) exten => s,n,GotoIf($["${REALCALLERIDNUM:1:2}" != ""]?start) exten => s,n,Set(REALCALLERIDNUM=${CALLERID(number)}) exten => s,n(start),NoOp(REALCALLERIDNUM is ${REALCALLERIDNUM}) exten => s,n,Set(AMPUSER=${DB(DEVICE/${REALCALLERIDNUM}/user)}) exten => s,n,Set(AMPUSERCIDNAME=${DB(AMPUSER/${AMPUSER}/cidname)}) exten => s,n,GotoIf($["x${AMPUSERCIDNAME:1:2}" = "x"]?report) ; user may masquerade as a different user internally, so set the internal cid as indicated ; but keep the REALCALLERID which is used to determine their true identify and lookup info ; during outbound calls. ; exten => s,n,Set(AMPUSERCID=${IF($["${DB_EXISTS(AMPUSER/${AMPUSER}/cidnum)}" = "1"]?${DB_RESULT}:${AMPUSER})}) exten => s,n,Set(CALLERID(all)="${AMPUSERCIDNAME}" <${AMPUSERCID}>) exten => s,n,Set(REALCALLERIDNUM=${DB(DEVICE/${REALCALLERIDNUM}/user)}) exten => s,n(report),Noop(TTL: ${TTL} ARG1: ${ARG1}) exten => s,n,GotoIf($[ "${ARG1}" = "SKIPTTL" ]?continue) exten => s,n(report2),Set(__TTL=${IF($["foo${TTL}" = "foo"]?64:$[ ${TTL} - 1 ])}) exten => s,n,GotoIf($[ ${TTL} > 0 ]?continue) exten => s,n,Wait(${RINGTIMER}) ; wait for a while, to give it a chance to be picked up by voicemail exten => s,n,Answer() exten => s,n,Wait(2) exten => s,n,Playback(im-sorry&an-error-has-occured&with&call-forwarding) exten => s,n,Macro(hangupcall) exten => s,n,Congestion() exten => s,n(continue),NoOp(Using CallerID ${CALLERID(all)}) exten => h,1,Macro(hangupcall) ; overrides callerid out trunks ; arg1 is trunk ; macro-user-callerid should be called _before_ using this macro [macro-outbound-callerid] ; Keep the original CallerID number, for failover to the next trunk. exten => s,1,GotoIf($["${REALCALLERIDNUM:1:2}" != ""]?start) exten => s,n,Set(REALCALLERIDNUM=${CALLERID(number)}) exten => s,n(start),NoOp(REALCALLERIDNUM is ${REALCALLERIDNUM}) ; If this came through a ringgroup or CF, then we want to retain original CID unless ; OUTKEEPCID_${trunknum} is set. ; exten => s,n,GotoIf($["${KEEPCID}" != "TRUE"]?normcid) ;Set to TRUE if coming from ringgroups, CF, etc. exten => s,n,GotoIf($["x${OUTKEEPCID_${ARG1}}" = "xon"]?normcid) exten => s,n,GotoIf($["foo${REALCALLERIDNUM}" = "foo"]?normcid) ;if not set to anything, go through normal processing exten => s,n,Set(USEROUTCID=${REALCALLERIDNUM}) ; We now have to make sure the CID is valid. If we find an AMPUSER with the same CID, we assume it is an internal ; call (would be quite a conincidence if not) and go through the normal processing to get that CID. If a device ; is set for this CID, then it must be internal ; exten => s,n,GotoIf($["foo${DB(AMPUSER/${REALCALLERIDNUM}/device)}" = "foo"]?bypass:normcid) exten => s,n(normcid),Set(USEROUTCID=${DB(AMPUSER/${REALCALLERIDNUM}/outboundcid)}) exten => s,n(bypass),Set(EMERGENCYCID=${DB(DEVICE/${REALCALLERIDNUM}/emergency_cid)}) exten => s,n,Set(TRUNKOUTCID=${OUTCID_${ARG1}}) exten => s,n,GotoIf($["${EMERGENCYROUTE:1:2}" = ""]?trunkcid) ; check EMERGENCY ROUTE exten => s,n,GotoIf($["${EMERGENCYCID:1:2}" = ""]?trunkcid) ; empty EMERGENCY CID, so default back to trunk exten => s,n,Set(CALLERID(all)=${EMERGENCYCID}) ; emergency cid for device exten => s,n,Goto(report) exten => s,n(trunkcid),GotoIf($["${TRUNKOUTCID:1:2}" = ""]?usercid) ;check for CID override for trunk (global var) exten => s,n,Set(CALLERID(all)=${TRUNKOUTCID}) exten => s,n(usercid),GotoIf($["${USEROUTCID:1:2}" = ""]?report) ; check CID override for extension exten => s,n,Set(CALLERID(all)=${USEROUTCID}) exten => s,n,GotoIf($["x${CALLERID(name)}"!="xhidden"]?report:hidecid) ; check CID blocking for extension exten => s,n(hidecid),SetCallerPres(prohib_passed_screen) ; Only works with ISDN (T1/E1/BRI) exten => s,n(report),NoOp(CallerID set to ${CALLERID(all)}) ; 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 ; legitamately 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() exten => s,n,GotoIf($["${PRIVACYMGRSTATUS}"="FAILED"]?fail) exten => s,n,SetCallerPres(allowed_passed_screen); stop gap until app_privacy.c clears unavailble 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) ; 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, ; therwise, 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] ;give external sip users congestion and hangup ; Yes. This is _really_ meant to be _. - I know asterisk whinges 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"]?from-trunk,${DID},1) exten => s,n,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,NoOp(Hangup) exten => i,1,NoOp(Invalid) exten => t,1,NoOp(Timeout) [from-internal-xfer] ; applications are now mostly all found in from-internal-additional in _custom.conf include => parkedcalls include => from-internal-custom ;allow phones to dial other extensions include => ext-fax ;allow phones to access generated contexts ; ; 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 => ramal-fax include => logar_agents include => teste-pausa include => from-internal-xfer include => bad-number [from-zaptel] exten => _X.,1,Set(DID=${EXTEN}) exten => _X.,n,Goto(s,1) exten => s,1,NoOp(Entering from-zaptel with DID == ${DID}) ; Some trunks _require_ a RINGING be sent before an Answer. exten => s,n,Ringing() ; If ($did == "") { $did = "s"; } exten => s,n,Set(DID=${IF($["${DID}"= ""]?s:${DID})}) exten => s,n,NoOp(DID is now ${DID}) exten => s,n,GotoIf($["${CHANNEL:0:3}"="Zap"]?zapok:notzap) exten => s,n(notzap),Goto(from-pstn,${DID},1) ; If there's no ext-did,s,1, that means there's not a no did/no cid route. Hangup. exten => s,n,Macro(hangup) exten => s,n(zapok),NoOp(Is a Zaptel Channel) exten => s,n,Set(CHAN=${CHANNEL:4}) exten => s,n,Set(CHAN=${CUT(CHAN,-,1)}) exten => s,n,Macro(from-zaptel-${CHAN},${DID},1) ; If nothing there, then treat it as a DID exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN}) exten => s,n,Goto(from-pstn,${DID},1) exten => fax,1,Goto(ext-fax,in_fax,1) ;------------------------------------------------------------------------ ; [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,SetMusicOnHold(${ARG1}) ;------------------------------------------------------------------------ ; ########################################## ; ## 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 paramaters, with an additional paramater 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 ; ; Thse 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,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL}) exten => s,n,Set(USE_CONFIRMATION=) exten => s,n,Set(RINGGROUP_INDEX=) ;------------------------------------------------------------------------ ;------------------------------------------------------------------------ ; [macro-auto-confirm] ;------------------------------------------------------------------------ ; This macro is called from ext-local-confirm to auto-confirm a call so that other extensions ; are aware that the call has been answered. ; ;------------------------------------------------------------------------ [macro-auto-confirm] exten => s,1,Set(__MACRO_RESULT=) exten => s,n,DBDel(${BLKVM_OVERRIDE}) exten => s,n,DBDel(RG/${ARG1}/${UNIQCHAN}) ;------------------------------------------------------------------------ ; [macro-auto-blkvm] ;------------------------------------------------------------------------ ; This macro is called for any extension dialed form a queue, ringgroup ; or followme, so that the answering extension can clear the voicemail block ; override allow subsequent transfers to properly operate. ; ;------------------------------------------------------------------------ [macro-auto-blkvm] exten => s,1,Set(__MACRO_RESULT=) exten => s,n,DBDel(${BLKVM_OVERRIDE}) ;------------------------------------------------------------------------ ; [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 ineritance. 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}) ;------------------------------------------------------------------------ ; [macro-confirm] ;------------------------------------------------------------------------ ; CONTEXT: macro-confirm ; PURPOSE: added default message if none supplied ; ; Follom-Me and Ringgroups provide an option to supply a message to be ; played as part of the confirmation. These changes have added a default ; message if none is supplied. ; ;------------------------------------------------------------------------ [macro-confirm] exten => s,1,Set(LOOPCOUNT=0) exten => s,n,Noop(CALLCONFIRMCID: ${CALLCONFIRMCID}) ; We set ABORT rather than CONTINUE, as we want the server to forget about this channel ; if it's declined, hung up, or timed out. We don't want it to continue on to the next ; step in the dialplan, which could be anything! exten => s,n,Set(__MACRO_RESULT=ABORT) ; ARG1 is the announcement to play to tell the user that they've got a call they need ; to confirm. Something along the lines of 'You have an incoming call. Press 1 to accept, 9 to reject' exten => s,n,Set(MSG1=${IF($["foo${ARG1}" != "foo"]?${ARG1}:"incoming-call-1-accept-2-decline")}) exten => s,n(start),Read(INPUT,${MSG1},1,,1,5) ; So. We've now read something, or nothing. We should check to make sure that the call hasn't ; already been answered by someone else. If it has, send this call to toolate exten => s,n,GotoIf(${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}?check:toolate) ; We passed that test, so it means the call hasn't been answered. Has this user pushed 1? If so, ; then go to OK. exten => s,n(check),GotoIf($["${INPUT}"="1"]?ok) ; If they've pushed 9, then they definately don't want the call. Just pretend there was no response ; and go to noanswer (or 2 since that will be default for asterisk) exten => s,n,GotoIf($["${INPUT}"="9"]?noanswer) exten => s,n,GotoIf($["${INPUT}"="2"]?noanswer) exten => s,n,GotoIf($["${INPUT}"="3"]?playcid) ; Increment LOOPCOUNT, and check to make sure we haven't played it 5 times by now. We assume that ; the person is able to push '1' in a reasonably short time. exten => s,n,Set(LOOPCOUNT=$[ ${LOOPCOUNT} + 1 ]) exten => s,n,GotoIf($[ ${LOOPCOUNT} < 5 ]?start) ; If we're here, that means we've played it MORE than 5 times. Set __MACRO_RESULT=ABORT, well, just ; coz, and goto fin, which is the last line, meaning it returns to the previous Dial, and pretends as ; if nothing has happened. exten => s,n(noanswer),Set(__MACRO_RESULT=ABORT) exten => s,n,Goto(fin) ; Test play callerid ; exten => s,n(playcid),Noop(Playing CID: ${CALLCONFIRMCID}) exten => s,n,SayDigits(${CALLCONFIRMCID}) exten => s,n,Goto(start) ; If we're here, it's because the call was already accepted by someone else. exten => s,n(toolate),Set(MSG2=${IF($["foo${ARG2}" != "foo"]?${ARG2}:"incoming-call-no-longer-avail")}) exten => s,n,Playback(${MSG2}) exten => s,n,Goto(noanswer) ; If we made it here, it's because the call _WAS_ accepted, AND it's still ringing. We delete the ; database entry (so that the DB_EXISTS line above will trigger a 'toolate' jump), and set the ; MACRO_RESULT variable to NOTHING. This is the magic string that joins both legs of the call together exten => s,n(ok),DBDel(RG/${ARG3}/${UNIQCHAN}) exten => s,n,DBDel(${BLKVM_OVERRIDE}) exten => s,n,Set(__MACRO_RESULT=) ; The end. exten => s,n(fin),NoOp(Finished) exten => h,1,Noop(Hangup Extension in macro-confirm) exten => h,n,Macro(hangupcall) ;------------------------------------------------------------------------ ;------------------------------------------------------------------------ ; [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() ;------------------------------------------------------------------------ ; ############################################################################ ; Extension Contexts [ext] ; ############################################################################ [ext-fax] exten => s,1,Answer exten => s,2,Goto(in_fax,1) exten => in_fax,1,StopPlayTones exten => in_fax,2,GotoIf($["${FAX_RX}" = "system"]?3:analog_fax,1) exten => in_fax,3,Macro(faxreceive) exten => in_fax,4,Hangup exten => analog_fax,1,GotoIf($["${FAX_RX}" = "disabled"]?4:2) ;if fax is disabled, just hang up exten => analog_fax,2,Set(DIAL=${DB(DEVICE/${FAX_RX}/dial)}); exten => analog_fax,3,Dial(${DIAL},20,d) exten => analog_fax,4,Hangup ;exten => out_fax,1,wait(7) exten => out_fax,1,txfax(${TXFAX_NAME},caller) exten => out_fax,2,Hangup exten => h,1,system(/var/lib/asterisk/bin/fax-process.pl --to ${EMAILADDR} --from ${FAX_RX_FROM} --subject "Fax from ${URIENCODE(${CALLERID(number)})} ${URIENCODE(${CALLERID(name)})}" --attachment fax_${URIENCODE(${CALLERID(number)})}.pdf --type application/pdf --file ${FAXFILE}); exten => h,2,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) [from-locais] include => ramal-fax include => from-internal exten => _0XXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0XXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0XXX,3,Dial(Zap/g1/${EXTEN:1},30,Ttr) exten => _0XXX,4,Congestion() ;exten => _0XXX,1,Dial(Zap/g1/${EXTEN:1},30,Ttr) ;exten => _0XXX,2,Congestion() exten => _00800X.,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _00800X.,2,Monitor(wav49,${CALLFILENAME},m) exten => _00800X.,3,Dial(Zap/g1/${EXTEN:1},30,Ttr) exten => _00800X.,4,Congestion() ;exten => _00800X.,1,Dial(Zap/g1/${EXTEN:1},30,Ttr) ;exten => _00800X.,2,Congestion() ;exten => _00500X.,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) ;exten => _00500X.,2,Monitor(wav49,${CALLFILENAME},m) ;exten => _00500X.,3,Dial(Zap/g1/${EXTEN:1},30,Ttr) ;exten => _00500X.,4,Congestion() ;exten => _00500X.,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) ;exten => _00500X.,2,Monitor(wav49,${CALLFILENAME},m) exten => _00500X.,1,Dial(Zap/g1/${EXTEN:1},30,Ttr) exten => _00500X.,2,Congestion() exten => _0[2-6]XXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0[2-6]XXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0[2-6]XXXXXX,3,Dial(Zap/g1/${EXTEN:1},30,Ttr); exten => _0[2-6]XXXXXX,4,Congestion(); ;exten => _0[2-6]XXXXXX,1,Dial(Zap/g1/${EXTEN:1},30,Ttr); ;exten => _0[2-6]XXXXXX,2,Congestion(); exten => _0[2-6]XXXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0[2-6]XXXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0[2-6]XXXXXXX,3,Dial(Zap/g1/${EXTEN:1},30,Ttr); exten => _0[2-6]XXXXXXX,4,Congestion(); ;exten => _0[2-6]XXXXXXX,1,Dial(Zap/g1/${EXTEN:1},30,Ttr); ;exten => _0[2-6]XXXXXXX,2,Congestion(); [from-celular] include => ramal-fax include => from-locais include => from-DDD exten => _0[7-9]XXXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0[7-9]XXXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0[7-9]XXXXXXX,3,Dial(Sip/${EXTEN}@2000,50,Ttr);Dial(Zap/g0/${EXTEN:1},30,Ttr); exten => _0[7-9]XXXXXXX,4,Congestion(); ;exten => _0[7-9]XXXXXXX,1,Dial(Sip/${EXTEN}@2000,50,Ttr);Dial(Zap/g0/${EXTEN:1},30,Ttr); ;exten => _0[7-9]XXXXXXX,2,Congestion(); exten => _0XXX[7-9]XXXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0XXX[7-9]XXXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0XXX[7-9]XXXXXXX,3,Dial(Sip/${EXTEN}@2000,50,Ttr);Dial(Zap/g0/${EXTEN:1},30,Ttr); exten => _0XXX[7-9]XXXXXXX,4,Congestion(); ;exten => _0XXX[7-9]XXXXXXX,1,Dial(Sip/${EXTEN}@2000,50,Ttr);Dial(Zap/g0/${EXTEN:1},30,Ttr); ;exten => _0XXX[7-9]XXXXXXX,2,Congestion(); exten => _0XXXXX[7-9]XXXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0XXXXX[7-9]XXXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0XXXXX[7-9]XXXXXXX,3,Dial(Sip/${EXTEN}@2000,50,Ttr);Dial(Zap/g0/${EXTEN:1},30,Ttr); exten => _0XXXXX[7-9]XXXXXXX,4,Congestion(); ;exten => _0XXXXX[7-9]XXXXXXX,1,Dial(Sip/${EXTEN}@2000,50,Ttr);Dial(Zap/g0/${EXTEN:1},30,Ttr); ;exten => _0XXXXX[7-9]XXXXXXX,2,Congestion(); [from-DDD] include => ramal-fax include => from-celular exten => _0XXX[2-6]XXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0XXX[2-6]XXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0XXX[2-6]XXXXXX,3,Dial(Zap/g1/025${EXTEN:2},30,Ttr); exten => _0XXX[2-6]XXXXXX,4,Congestion(); ;exten => _0XXX[2-6]XXXXXX,1,Dial(Zap/g1/025${EXTEN:2},30,Ttr); ;exten => _0XXX[2-6]XXXXXX,2,Congestion(); exten => _0XXX[2-6]XXXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0XXX[2-6]XXXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0XXX[2-6]XXXXXXX,3,Dial(Zap/g1/025${EXTEN:2},30,Ttr); exten => _0XXX[2-6]XXXXXXX,4,Congestion(); ;exten => _0XXX[2-6]XXXXXXX,1,Dial(Zap/g1/025${EXTEN:2},30,Ttr); ;exten => _0XXX[2-6]XXXXXXX,2,Congestion(); exten => _0XXXXX[2-6]XXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0XXXXX[2-6]XXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0XXXXX[2-6]XXXXXX,3,Dial(Zap/g1/025${EXTEN:4},30,Ttr); exten => _0XXXXX[2-6]XXXXXX,4,Congestion(); ;exten => _0XXXXX[2-6]XXXXXX,1,Dial(Zap/g1/025${EXTEN:4},30,Ttr); ;exten => _0XXXXX[2-6]XXXXXX,2,Congestion(); exten => _0XXXXX[2-6]XXXXXXX,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0XXXXX[2-6]XXXXXXX,2,Monitor(wav49,${CALLFILENAME},m) exten => _0XXXXX[2-6]XXXXXXX,3,Dial(Zap/g1/025${EXTEN:4},30,Ttr); exten => _0XXXXX[2-6]XXXXXXX,4,Congestion(); ;exten => _0XXXXX[2-6]XXXXXXX,1,Dial(Zap/g1/025${EXTEN:4},30,Ttr); ;exten => _0XXXXX[2-6]XXXXXXX,2,Congestion(); [from-DDI] include => ramal-fax include => from-DDD exten => _0X.,1,SetVar(CALLFILENAME=${EXTEN:1}-${TIMESTAMP}) exten => _0X.,2,Monitor(wav49,${CALLFILENAME},m) exten => _0X.,3,Dial(Zap/g1/${EXTEN:1},30,Ttr); exten => _0X.,4,Congestion(); ;exten => _0X.,1,Dial(Zap/g1/${EXTEN:1},30,Ttr); ;exten => _0X.,2,Congestion(); [from-diretoria] include => ramal-fax include => espiao include => from-DDD [entrada-e1] exten => 3711,1,Goto(ext-fax,s,1) exten => 3700,1,Goto(entrada-acs,s,1) exten => 3777,1,Answer() exten => 3777,2,Goto(entrada-callcenter,s,1) ;;;;;;;;;;;DDR;;;;;;;;;;;;;;;;;;;; exten => 3702,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3702,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3703,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3703,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3704,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3704,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3705,1,Dial(Sip/707,30,Ttr) exten => 707,2,Dial(Sip/707,50,Ttr) exten => 707,3,Congestion() exten => 3706,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3706,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3707,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3707,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3708,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3708,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3709,1,Dial(Sip/${EXTEN:1},20,Ttr) exten => 3709,2,Dial(Sip/714,15,Ttr) exten => 3709,3,Dial(Sip/715,15,Ttr) exten => 3709,4,Dial(Sip/716,15,Ttr) exten => 3709,5,Dial(Sip/718,15,Ttr) exten => 3709,6,Dial(Sip/700,15,Ttr) exten => 700,7,Congestion() exten => 3710,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3710,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3714,1,Dial(Sip/${EXTEN:1},20,Ttr) exten => 3714,2,Dial(Sip/709,15,Ttr) exten => 3714,3,Dial(Sip/715,15,Ttr) exten => 3714,4,Dial(Sip/716,15,Ttr) exten => 3714,5,Dial(Sip/718,15,Ttr) exten => 3714,6,Dial(Sip/700,15,Ttr) exten => 700,7,Congestion() exten => 3715,1,Dial(Sip/${EXTEN:1},20,Ttr) exten => 3715,2,Dial(Sip/709,15,Ttr) exten => 3715,3,Dial(Sip/714,15,Ttr) exten => 3715,4,Dial(Sip/716,15,Ttr) exten => 3715,5,Dial(Sip/718,15,Ttr) exten => 3715,6,Dial(Sip/700,15,Ttr) exten => 700,7,Congestion() exten => 3716,1,Dial(Sip/${EXTEN:1},20,Ttr) exten => 3716,2,Dial(Sip/709,15,Ttr) exten => 3716,3,Dial(Sip/714,15,Ttr) exten => 3716,4,Dial(Sip/715,15,Ttr) exten => 3716,5,Dial(Sip/718,15,Ttr) exten => 3716,6,Dial(Sip/700,15,Ttr) exten => 700,7,Congestion() exten => 3718,1,Dial(Sip/${EXTEN:1},20,Ttr) exten => 3718,2,Dial(Sip/709,15,Ttr) exten => 3718,3,Dial(Sip/714,15,Ttr) exten => 3718,4,Dial(Sip/715,15,Ttr) exten => 3718,5,Dial(Sip/716,15,Ttr) exten => 3718,6,Dial(Sip/700,15,Ttr) exten => 700,7,Congestion() exten => 3719,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3719,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3720,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3720,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3721,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3721,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3723,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3723,2,Dial(Sip/724,10,Ttr) exten => 3723,3,Dial(Sip/728,10,Ttr) exten => 3723,4,Dial(Sip/738,10,Ttr) exten => 3723,5,Dial(Sip/700,10,Ttr) exten => 700,6,Congestion() exten => 3724,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3724,2,Dial(Sip/723,10,Ttr) exten => 3724,3,Dial(Sip/728,10,Ttr) exten => 3724,4,Dial(Sip/738,10,Ttr) exten => 3724,5,Dial(Sip/700,10,Ttr) exten => 700,6,Congestion() exten => 3727,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3727,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3728,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3728,2,Dial(Sip/723,10,Ttr) exten => 3728,3,Dial(Sip/724,10,Ttr) exten => 3728,4,Dial(Sip/738,10,Ttr) exten => 3728,5,Dial(Sip/700,10,Ttr) exten => 700,6,Congestion() exten => 3729,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3729,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3730,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3730,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3731,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3731,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3738,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3738,2,Dial(Sip/723,10,Ttr) exten => 3738,3,Dial(Sip/724,10,Ttr) exten => 3738,4,Dial(Sip/728,10,Ttr) exten => 3738,5,Dial(Sip/700,10,Ttr) exten => 700,6,Congestion() exten => 3742,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3742,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3745,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3745,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3753,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3753,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3755,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3755,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3756,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3756,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3757,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3757,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3760,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3760,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3761,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3761,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3762,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3762,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3763,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3763,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3764,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3764,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3765,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3765,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3766,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3766,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3767,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3767,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3768,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3768,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3769,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3769,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3770,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3770,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() exten => 3790,1,Dial(Sip/${EXTEN:1},30,Ttr) exten => 3790,2,Dial(Sip/700,50,Ttr) exten => 700,3,Congestion() [logar_agents] exten => 200,1,AgentCallbackLogin(${CALLERIDNUM}|s|${CALLERIDNUM}@from-internal) exten => 300,1,AgentCallbackLogin(${CALLERIDNUM}||); exten => 350,1,AgentCallbackLogin(200||); exten => h,1,Hangup exten => t,1,Hangup [ramal-fax] exten => _711,1,Goto(ext-fax,s,1) [entrada-acs] exten => s,1,answer exten => s,2,Set(TIMEOUT(digit)=10) exten => s,3,Set(TIMEOUT(response)=10) exten => s,4,BackGround(custom/saudacao_novo2) exten => 711,1,Goto(ext-fax,s,1) exten => _XXX,1,Dial(Sip/${EXTEN},40,Ttr) exten => _XXX,2,Congestion() exten => t,1,Dial(Sip/700,30,Ttr) exten => t,2,Congestion() exten => i,1,Dial(Sip/700,30,Ttr) exten => h,1,Hangup() [entrada-callcenter] ;feriado ;exten => s,1,answer ;exten => s,2,Set(TIMEOUT(digit)=4) ;exten => s,3,Set(TIMEOUT(response)=4) ;exten => s,4,wait(1) ;exten => s,5,Background(entrada_callcenter) ;exten => 1,1,Goto(ext-fax,s,1) ;exten => t,1,Dial(Sip/714,30,Ttr) ;exten => t,2,Congestion() ;exten => i,1,Dial(Sip/714,30,Ttr) ;exten => h,1,Hangup() exten => s,1,answer exten => s,2,Set(TIMEOUT(digit)=4) exten => s,3,Set(TIMEOUT(response)=4) exten => s,4,wait(1) exten => s,5,Background(entrada_callcenter) exten => 1,1,Goto(ext-fax,s,1) exten => t,1,queue(200|tT|||2300) [teste-pausa] exten => _*1111XXX,1,PauseQueueMember(|Agent/${EXTEN:5}) exten => _*1113XXX,1,PauseQueueMember(|Agent/${EXTEN:5}) exten => _*1112XXX,1,UnPauseQueueMember(|Agent/${EXTEN:5}) [ramais-internos] exten => _7XX,1,Dial(Sip/${EXTEN},40,Ttr) exten => _7XX,2,Hangup() [entrada-fxo] exten => s,1,Answer() exten => s,2,Dial(Sip/700,40,Ttr) exten => s,3,Hangup() exten => 2000,1,Answer() exten => 2000,2,Dial(Sip/700,40,Ttr) exten => 2000,3,Hangup() [novo-fone] exten => _X.,1,answer() exten => _X.,2,BackGround(mensagen) exten => _X.,3,Hangup() [espiao] exten => _8XXX,1,ChanSpy(Sip/${EXTEN:1})