| 1 |
; do not edit this file, this is an auto-generated file by freepbx |
|---|
| 2 |
; all modifications must be done from the web gui |
|---|
| 3 |
|
|---|
| 4 |
; FreePBX |
|---|
| 5 |
; Copyright (C) 2004 Coalescent Systems Inc (Canada) |
|---|
| 6 |
; Copyright (C) 2006 Why Pay More 4 Less Pty Ltd (Australia) |
|---|
| 7 |
; Copyright (C) 2007 Astrogen LLC (USA) |
|---|
| 8 |
; Released under the GNU GPL Licence version 2. |
|---|
| 9 |
|
|---|
| 10 |
; dialparties.agi (http://www.sprackett.com/asterisk/) |
|---|
| 11 |
; Asterisk::AGI (http://asterisk.gnuinter.net/) |
|---|
| 12 |
; gsm (http://www.ibiblio.org/pub/Linux/utils/compress/!INDEX.short.html) |
|---|
| 13 |
; loligo sounds (http://www.loligo.com/asterisk/sounds/) |
|---|
| 14 |
; mpg123 (http://voip-info.org/wiki-Asterisk+config+musiconhold.conf) |
|---|
| 15 |
|
|---|
| 16 |
;************************** -WARNING- **************************************** |
|---|
| 17 |
; * |
|---|
| 18 |
; This include file is to be used with extreme caution. In almost all cases * |
|---|
| 19 |
; any custom dialplan SHOULD be put in extensions_custom.conf which will * |
|---|
| 20 |
; not hurt freepbx generated dialplan. In some very rare and custom situation * |
|---|
| 21 |
; users have a need to override what freepbx generates. Anything in this file * |
|---|
| 22 |
; will do such. * |
|---|
| 23 |
; * |
|---|
| 24 |
#include extensions_override_freepbx.conf |
|---|
| 25 |
; * |
|---|
| 26 |
;************************** -WARNING- **************************************** |
|---|
| 27 |
|
|---|
| 28 |
; include extension contexts generated from AMP |
|---|
| 29 |
#include extensions_additional.conf |
|---|
| 30 |
|
|---|
| 31 |
; Customizations to this dialplan should be made in extensions_custom.conf |
|---|
| 32 |
; See extensions_custom.conf.sample for an example |
|---|
| 33 |
#include extensions_custom.conf |
|---|
| 34 |
|
|---|
| 35 |
[from-trunk] ; just an alias since VoIP shouldn't be called PSTN |
|---|
| 36 |
include => from-pstn |
|---|
| 37 |
|
|---|
| 38 |
[from-pstn] |
|---|
| 39 |
include => from-pstn-custom ; create this context in extensions_custom.conf to include customizations |
|---|
| 40 |
include => ext-did |
|---|
| 41 |
include => from-did-direct ; MODIFICATOIN (PL) for findmefollow if enabled, should be bofore ext-local |
|---|
| 42 |
include => ext-did-catchall ; THIS MUST COME AFTER ext-did |
|---|
| 43 |
exten => fax,1,Goto(ext-fax,in_fax,1) |
|---|
| 44 |
|
|---|
| 45 |
; MODIFICATION (PL) |
|---|
| 46 |
; |
|---|
| 47 |
; Required to assure that direct dids go to personal ring group before local extension. |
|---|
| 48 |
; This could be auto-generated however I it is prefered to be put here and hard coded |
|---|
| 49 |
; so that it can be modified if ext-local should take precedence in certain situations. |
|---|
| 50 |
; will have to decide what to do later. |
|---|
| 51 |
; |
|---|
| 52 |
[from-did-direct] |
|---|
| 53 |
include => ext-findmefollow |
|---|
| 54 |
include => ext-local |
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 |
; ############################################################################ |
|---|
| 59 |
; Macros [macro] |
|---|
| 60 |
; ############################################################################ |
|---|
| 61 |
|
|---|
| 62 |
; Rings one or more extensions. Handles things like call forwarding and DND |
|---|
| 63 |
; We don't call dial directly for anything internal anymore. |
|---|
| 64 |
; ARGS: $TIMER, $OPTIONS, $EXT1, $EXT2, $EXT3, ... |
|---|
| 65 |
; Use a Macro call such as the following: |
|---|
| 66 |
; Macro(dial,$DIAL_TIMER,$DIAL_OPTIONS,$EXT1,$EXT2,$EXT3,...) |
|---|
| 67 |
[macro-dial] |
|---|
| 68 |
exten => s,1,GotoIf($["${MOHCLASS}" = ""]?dial) |
|---|
| 69 |
exten => s,n,SetMusicOnHold(${MOHCLASS}) |
|---|
| 70 |
exten => s,n(dial),AGI(dialparties.agi) |
|---|
| 71 |
exten => s,n,NoOp(Returned from dialparties with no extensions to call and DIALSTATUS: ${DIALSTATUS}) |
|---|
| 72 |
|
|---|
| 73 |
exten => s,n+2(normdial),Dial(${ds}) ; dialparties will set the priority to 10 if $ds is not null |
|---|
| 74 |
exten => s,n,Set(DIALSTATUS=${IF($["${DIALSTATUS_CW}"!="" ]?${DIALSTATUS_CW}:${DIALSTATUS})}) |
|---|
| 75 |
|
|---|
| 76 |
exten => s,20(huntdial),NoOp(Returned from dialparties with hunt groups to dial ) |
|---|
| 77 |
exten => s,n,Set(HuntLoop=0) |
|---|
| 78 |
exten => s,n(a22),GotoIf($[${HuntMembers} >= 1]?a30) ; if this is from rg-group, don't strip prefix |
|---|
| 79 |
exten => s,n,NoOp(Returning there are no members left in the hunt group to ring) |
|---|
| 80 |
|
|---|
| 81 |
; dialparties.agi has setup the dialstring for each hunt member in a variable labeled HuntMember0, HuntMember1 etc for each iteration |
|---|
| 82 |
; and The total number in HuntMembers. So for each iteration, we will update the CALLTRACE Data. |
|---|
| 83 |
; |
|---|
| 84 |
exten => s,n+2(a30),Set(HuntMember=HuntMember${HuntLoop}) |
|---|
| 85 |
exten => s,n,GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "hunt" ]]?a32:a35) |
|---|
| 86 |
exten => s,n(a32),Set(CT_EXTEN=${CUT(FILTERED_DIAL,,$[${HuntLoop} + 1])}) |
|---|
| 87 |
exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT}) |
|---|
| 88 |
exten => s,n,Goto(s,a42) |
|---|
| 89 |
|
|---|
| 90 |
;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 |
|---|
| 91 |
; |
|---|
| 92 |
exten => s,n(a35),GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "memoryhunt" ]]?a36:a50) |
|---|
| 93 |
exten => s,n(a36),Set(CTLoop=0) |
|---|
| 94 |
exten => s,n(a37),GotoIf($[${CTLoop} > ${HuntLoop}]?a42) ; if this is from rg-group, don't strip prefix |
|---|
| 95 |
exten => s,n,Set(CT_EXTEN=${CUT(FILTERED_DIAL,,$[${CTLoop} + 1])}) |
|---|
| 96 |
exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT}) |
|---|
| 97 |
exten => s,n,Set(CTLoop=$[1 + ${CTLoop}]) |
|---|
| 98 |
exten => s,n,Goto(s,a37) |
|---|
| 99 |
|
|---|
| 100 |
exten => s,n(a42),Dial(${${HuntMember}}${ds}) |
|---|
| 101 |
exten => s,n,Set(HuntLoop=$[1 + ${HuntLoop}]) |
|---|
| 102 |
exten => s,n,GotoIf($[$[$["foo${RingGroupMethod}" != "foofirstavailable"] & $["foo${RingGroupMethod}" != "foofirstnotonphone"]] | $["foo${DialStatus}" = "fooBUSY"]]?a46) |
|---|
| 103 |
exten => s,n,Set(HuntMembers=0) |
|---|
| 104 |
exten => s,n(a46),Set(HuntMembers=$[${HuntMembers} - 1]) |
|---|
| 105 |
exten => s,n,Goto(s,a22) |
|---|
| 106 |
|
|---|
| 107 |
exten => s,n(a50),DBdel(CALLTRACE/${CT_EXTEN}) |
|---|
| 108 |
exten => s,n,Goto(s,a42) |
|---|
| 109 |
|
|---|
| 110 |
; make sure hungup calls go here so that proper cleanup occurs from call confirmed calls and the like |
|---|
| 111 |
; |
|---|
| 112 |
exten => h,1,Macro(hangupcall) |
|---|
| 113 |
|
|---|
| 114 |
; Ring an extension, if the extension is busy or there is no answer send it |
|---|
| 115 |
; to voicemail |
|---|
| 116 |
; ARGS: $VMBOX, $EXT |
|---|
| 117 |
[macro-exten-vm] |
|---|
| 118 |
exten => s,1,Macro(user-callerid) |
|---|
| 119 |
|
|---|
| 120 |
exten => s,n,Set(FROMCONTEXT=exten-vm) |
|---|
| 121 |
exten => s,n,Set(VMBOX=${ARG1}) |
|---|
| 122 |
exten => s,n,Set(EXTTOCALL=${ARG2}) |
|---|
| 123 |
exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})}) |
|---|
| 124 |
exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})}) |
|---|
| 125 |
exten => s,n,Set(RT=${IF($[$["${VMBOX}"!="novm"] | $["foo${CFUEXT}"!="foo"]]?${RINGTIMER}:"")}) |
|---|
| 126 |
exten => s,n,Macro(record-enable,${EXTTOCALL},IN) |
|---|
| 127 |
|
|---|
| 128 |
exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL}) |
|---|
| 129 |
exten => s,n,Set(SV_DIALSTATUS=${DIALSTATUS}) |
|---|
| 130 |
exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"="NOANSWER"] & $["foo${CFUEXT}"!="foo"]]?docfu,1) ; check for CFU in use on no answer |
|---|
| 131 |
exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"="BUSY"] & $["foo${CFBEXT}"!="foo"]]?docfb,1) ; check for CFB in use on busy |
|---|
| 132 |
exten => s,n,Set(DIALSTATUS=${SV_DIALSTATUS}) |
|---|
| 133 |
exten => s,n,NoOp(Voicemail is '${VMBOX}') |
|---|
| 134 |
exten => s,n,GotoIf($["${VMBOX}" = "novm"]?s-${DIALSTATUS},1) ; no voicemail in use for this extension |
|---|
| 135 |
exten => s,n,NoOp(Sending to Voicemail box ${EXTTOCALL}) |
|---|
| 136 |
exten => s,n,Macro(vm,${VMBOX},${DIALSTATUS}) |
|---|
| 137 |
|
|---|
| 138 |
; Try the Call Forward on No Answer / Unavailable number |
|---|
| 139 |
exten => docfu,1,Set(RTCFU=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")}) |
|---|
| 140 |
exten => docfu,n,Dial(Local/${CFUEXT}@from-internal/n,${RTCFU},${DIAL_OPTIONS}) |
|---|
| 141 |
exten => docfu,n,Return |
|---|
| 142 |
|
|---|
| 143 |
; Try the Call Forward on Busy number |
|---|
| 144 |
exten => docfb,1,Set(RTCFB=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")}) |
|---|
| 145 |
exten => docfb,n,Dial(Local/${CFBEXT}@from-internal/n,${RTCFB},${DIAL_OPTIONS}) |
|---|
| 146 |
exten => docfb,n,Return |
|---|
| 147 |
|
|---|
| 148 |
; Extensions with no Voicemail box reporting BUSY come here |
|---|
| 149 |
exten => s-BUSY,1,NoOp(Extension is reporting BUSY and not passing to Voicemail) |
|---|
| 150 |
exten => s-BUSY,n,Playtones(busy) |
|---|
| 151 |
exten => s-BUSY,n,Busy(20) |
|---|
| 152 |
|
|---|
| 153 |
; Anything but BUSY comes here |
|---|
| 154 |
exten => _s-.,1,Playtones(congestion) |
|---|
| 155 |
exten => _s-.,n,Congestion(10) |
|---|
| 156 |
|
|---|
| 157 |
;------------------------------------------------------------------------ |
|---|
| 158 |
; [macro-vm] |
|---|
| 159 |
;------------------------------------------------------------------------ |
|---|
| 160 |
; CONTEXT: macro-vm |
|---|
| 161 |
; PURPOSE: call voicemail system and extend with personal ivr |
|---|
| 162 |
; |
|---|
| 163 |
; Under normal use, this macro will call the voicemail system with the extension and |
|---|
| 164 |
; desired greeting mode of busy, unavailable or as specified with direct voicemail |
|---|
| 165 |
; calls (usually unavailable) when entered from destinations. |
|---|
| 166 |
; |
|---|
| 167 |
; The voicemail system's two greetings have been 'hijacked' as follows to extend the |
|---|
| 168 |
; system by giving the option of a private 'ivr' for each voicemail user. The following |
|---|
| 169 |
; applies to both the busy and unavailable modes of voicemail and can be applied to one |
|---|
| 170 |
; or both, and differently. |
|---|
| 171 |
; |
|---|
| 172 |
; Global Defaults: |
|---|
| 173 |
; |
|---|
| 174 |
; The following are default values, used in both busy and unavail modes if no specific |
|---|
| 175 |
; values are specified. |
|---|
| 176 |
; |
|---|
| 177 |
; VMX_REPEAT |
|---|
| 178 |
; The number of times to repeat the users message if no option is pressed. |
|---|
| 179 |
; VMX_TIMEOUT |
|---|
| 180 |
; The timeout to wait after playing message before repeating or giving up. |
|---|
| 181 |
; VMX_LOOPS |
|---|
| 182 |
; The number of times it should replay the message and check for an option when |
|---|
| 183 |
; an invalid option is pressed. |
|---|
| 184 |
; |
|---|
| 185 |
; VMX_OPTS_DOVM |
|---|
| 186 |
; Default voicemail option to use if vm is chosen as an option. No options will |
|---|
| 187 |
; cause Allison's generic message, 's' will go straight to beep. |
|---|
| 188 |
; VMX_OPTS_TIMEOUT |
|---|
| 189 |
; Default voicemail option to use if it times out with no options. No options will |
|---|
| 190 |
; cause Allison's generic message, 's' will go straight to beep. |
|---|
| 191 |
; IF THE USER PRESSES # - it will look like a timeout as well since no option will |
|---|
| 192 |
; be presented. If the user wishes to enable a mode where a caller can press # |
|---|
| 193 |
; during their message and it goes straight to voicemail with only a 'beep' then |
|---|
| 194 |
; this should be set to 's'. |
|---|
| 195 |
; VMX_OPTS_LOOPS |
|---|
| 196 |
; Default voicemail option to use if to many wrong options occur. No options will |
|---|
| 197 |
; cause Allison's generic message, 's' will go straight to beep. |
|---|
| 198 |
; |
|---|
| 199 |
; VMX_CONTEXT |
|---|
| 200 |
; Default context for user destinations if not supplied in the user's settings |
|---|
| 201 |
; VMX_PRI |
|---|
| 202 |
; Default priority for user destinations if not supplied in the user's settings |
|---|
| 203 |
; |
|---|
| 204 |
; VMX_TIMEDEST_CONTEXT |
|---|
| 205 |
; Default context for timeout destination if not supplied in the user's settings |
|---|
| 206 |
; VMX_TIMEDEST_EXT |
|---|
| 207 |
; Default extension for timeout destination if not supplied in the user's settings |
|---|
| 208 |
; VMX_TIMEDEST_PRI |
|---|
| 209 |
; Default priority for timeout destination if not supplied in the user's settings |
|---|
| 210 |
; |
|---|
| 211 |
; VMX_LOOPDEST_CONTEXT |
|---|
| 212 |
; Default context for loops destination if not supplied in the user's settings |
|---|
| 213 |
; VMX_LOOPDEST_EXT |
|---|
| 214 |
; Default extension for loops destination if not supplied in the user's settings |
|---|
| 215 |
; VMX_LOOPDEST_PRI |
|---|
| 216 |
; Default priority for loops destination if not supplied in the user's settings |
|---|
| 217 |
; |
|---|
| 218 |
; |
|---|
| 219 |
; The AMPUSER database variable has been extended with a 'vmx' tree (vm-extension). A |
|---|
| 220 |
; duplicate set is included for both unavail and busy. You could choose for to have an |
|---|
| 221 |
; ivr when unavail is taken, but not with busy - or a different once with busy. |
|---|
| 222 |
; The full list is below, each specific entry is futher described: |
|---|
| 223 |
; |
|---|
| 224 |
; state: Whether teh current mode is enabled or disabled. Anything but 'enabled' is |
|---|
| 225 |
; treated as disabled. |
|---|
| 226 |
; repeat: This is the number of times that the users message should be played after the |
|---|
| 227 |
; timeout if the user has not entered anything. It is just a variable to the |
|---|
| 228 |
; Read() function which will do the repeating. |
|---|
| 229 |
; timeout: This is how long to wait after the message has been read for a response from |
|---|
| 230 |
; the user. A caller can enter a digit any time during the playback. |
|---|
| 231 |
; loops: This is the number of loops that the system will allow a caller to retry if |
|---|
| 232 |
; they enter a bad menu choice, before going to the loop failover destination |
|---|
| 233 |
; vmxopts: This is the vm options to send to the voicemail command used when a specific |
|---|
| 234 |
; voicemail destination is chosen (inidcated by 'dovm' in the ext field). This is |
|---|
| 235 |
; typically either set to 's' or left blank. When set to 's' there will be no |
|---|
| 236 |
; message played when entering the voicemail, just a beep. When blank, you will |
|---|
| 237 |
; have Allison's generic message played. It is not typical to play the greetings |
|---|
| 238 |
; since they have been 'hijacked' for these IVR's and from a caller's perspecitive |
|---|
| 239 |
; this system appears interconnected with the voicemail so instructions can be |
|---|
| 240 |
; left there. |
|---|
| 241 |
; timedest: The three variables: ext, context and pri are the goto destination if the caller |
|---|
| 242 |
; enters no options and it timesout. None have to be set and a system default |
|---|
| 243 |
; will be used. If just ext is set, then defaults will be used for context and |
|---|
| 244 |
; pri, etc. |
|---|
| 245 |
; loopdest: This is identical to timedest but used if the caller exceeds the maximum invalid |
|---|
| 246 |
; menu choices. |
|---|
| 247 |
; [0-9*]: The user can specify up to 11 ivr options, all as single digits from 0-9 or *. The |
|---|
| 248 |
; # key can not be used since it is used as a terminator key for the Read command |
|---|
| 249 |
; and will never be returned. A minimum of the ext must be specified for each valid |
|---|
| 250 |
; option and as above, the context and priority can also be specified if the default |
|---|
| 251 |
; is not to be used. |
|---|
| 252 |
; Option '0' takes on a special meaning. Since a user is able to break out of the |
|---|
| 253 |
; voicemail command once entering it with a 0, if specified, the 0 destination will |
|---|
| 254 |
; be used. |
|---|
| 255 |
; Option '*' can also be used to breakout. It is undecided at this point whether |
|---|
| 256 |
; providing that option will be used as well. (probably should). |
|---|
| 257 |
; |
|---|
| 258 |
; |
|---|
| 259 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/state: enabled|disabled |
|---|
| 260 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/repeat: n (times to repeat message) |
|---|
| 261 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/timeout: n (timeout to wait for digit) |
|---|
| 262 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/loops: n (loop returies for invalid entries) |
|---|
| 263 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/dovm: vmoptions (if ext is dovm) |
|---|
| 264 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/timeout: vmoptions (if timeout) |
|---|
| 265 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/loops: vmoptions (if loops) |
|---|
| 266 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/ext: extension (if timeout) |
|---|
| 267 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/context: context (if timeout) |
|---|
| 268 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/pri: priority (if timeout) |
|---|
| 269 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/ext: extension (if too many failures) |
|---|
| 270 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/context: context (if too many failures) |
|---|
| 271 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/pri: priority (if too many failures) |
|---|
| 272 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/ext: extension (dovm for vm access) |
|---|
| 273 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/context: context |
|---|
| 274 |
; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/pri: priority |
|---|
| 275 |
;------------------------------------------------------------------------ |
|---|
| 276 |
[macro-vm] |
|---|
| 277 |
; ARG1 - extension |
|---|
| 278 |
; ARG2 - DIRECTDIAL/BUSY |
|---|
| 279 |
; ARG3 - RETURN makes macro return, otherwise hangup |
|---|
| 280 |
exten => s,1,Macro(user-callerid,SKIPTTL) |
|---|
| 281 |
exten => s,n,Set(VMGAIN=${IF($["foo${VM_GAIN}"!="foo"]?"g(${VM_GAIN})":"")}) |
|---|
| 282 |
; |
|---|
| 283 |
; If BLKVM_OVERRIDE is set, then someone told us to block calls from going to |
|---|
| 284 |
; voicemail. This variable is reset by the answering channel so subsequent |
|---|
| 285 |
; transfers will properly function. |
|---|
| 286 |
; |
|---|
| 287 |
exten => s,n,GotoIf($["foo${DB(${BLKVM_OVERRIDE})}" != "fooTRUE"]?vmx,1) |
|---|
| 288 |
; |
|---|
| 289 |
; we didn't branch so block this from voicemail |
|---|
| 290 |
; |
|---|
| 291 |
exten => s,n,Noop(CAME FROM: ${NODEST} - Blocking VM cause of key: ${DB(BLKVM_OVERRIDE)}) |
|---|
| 292 |
|
|---|
| 293 |
|
|---|
| 294 |
; If vmx not enabled for the current mode,then jump to normal voicemail behavior |
|---|
| 295 |
; also - if not message (no-msg) is requested, straight to voicemail |
|---|
| 296 |
; |
|---|
| 297 |
exten => vmx,1,GotoIf($["${ARG2}"="NOMESSAGE"]?s-${ARG2},1) |
|---|
| 298 |
exten => vmx,n,Set(MODE=${IF($["${ARG2}"="BUSY"]?busy:unavail)}) |
|---|
| 299 |
exten => vmx,n,GotoIf($["${ARG2}" != "DIRECTDIAL"]?notdirect) |
|---|
| 300 |
exten => vmx,n,Set(MODE=${IF($["${REGEX("[b]" ${VM_DDTYPE})}" = "1"]?busy:${MODE})}) |
|---|
| 301 |
exten => vmx,n(notdirect),Noop(Checking if ext ${ARG1} is enabled: ${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}) |
|---|
| 302 |
exten => vmx,n,GotoIf($["${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}" != "enabled"]?s-${ARG2},1) |
|---|
| 303 |
|
|---|
| 304 |
; If the required voicemail file does not exist, then abort and go to normal voicemail behavior |
|---|
| 305 |
; |
|---|
| 306 |
; TODO: there have been errors using System() with jump to 101 where asterisk works fine at the begining and |
|---|
| 307 |
; then starts to jump to 101 even on success. This new mode is being tried with the SYSTEM Status which |
|---|
| 308 |
; returns SUCCESS when the command returned succcessfully with a 0 app return code. |
|---|
| 309 |
; |
|---|
| 310 |
exten => vmx,n,Macro(get-vmcontext,${ARG1}) |
|---|
| 311 |
;exten => vmx,n,TrySystem(/bin/ls ${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}.[wW][aA][vV]) |
|---|
| 312 |
exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/temp) |
|---|
| 313 |
exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" = "SUCCESS"]?tmpgreet) |
|---|
| 314 |
exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}) |
|---|
| 315 |
exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" != "SUCCESS"]?nofile) |
|---|
| 316 |
|
|---|
| 317 |
; Get the repeat, timeout and loop times to use if they are overriden form the global settings |
|---|
| 318 |
; |
|---|
| 319 |
exten => vmx,n,Set(LOOPCOUNT=0) |
|---|
| 320 |
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/repeat)}" = "0"]?vmxtime) |
|---|
| 321 |
exten => vmx,n,Set(VMX_REPEAT=${DB_RESULT}) |
|---|
| 322 |
exten => vmx,n(vmxtime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timeout)}" = "0"]?vmxloops) |
|---|
| 323 |
exten => vmx,n,Set(VMX_TIMEOUT=${DB_RESULT}) |
|---|
| 324 |
exten => vmx,n(vmxloops),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loops)}" = "0"]?vmxanswer) |
|---|
| 325 |
exten => vmx,n,Set(VMX_LOOPS=${DB_RESULT}) |
|---|
| 326 |
exten => vmx,n(vmxanswer),Answer() |
|---|
| 327 |
|
|---|
| 328 |
; Now play the users voicemail recording as the basis for their ivr, the Read command will repeat as needed and if it timesout |
|---|
| 329 |
; then we go to the timeout. Otherwise handle invalid options by looping until the limit until a valid option is played. |
|---|
| 330 |
; |
|---|
| 331 |
exten => vmx,n(loopstart),Read(ACTION,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE},1,skip,${VMX_REPEAT},${VMX_TIMEOUT}) |
|---|
| 332 |
exten => vmx,n,GotoIf($["${EXISTS(${ACTION})}" = "1"]?checkopt) |
|---|
| 333 |
|
|---|
| 334 |
; If we are here we timed out, go to the required destination |
|---|
| 335 |
; |
|---|
| 336 |
exten => vmx,n(noopt),Noop(Timeout: going to timeout dest) |
|---|
| 337 |
exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_TIMEOUT}) |
|---|
| 338 |
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/timeout)}" = "0"]?chktime) |
|---|
| 339 |
exten => vmx,n,Set(VMX_OPTS=${DB_RESULT}) |
|---|
| 340 |
exten => vmx,n(chktime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/ext)}" = "0"]?dotime) |
|---|
| 341 |
exten => vmx,n,Set(VMX_TIMEDEST_EXT=${DB_RESULT}) |
|---|
| 342 |
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/context)}" = "0"]?timepri) |
|---|
| 343 |
exten => vmx,n,Set(VMX_TIMEDEST_CONTEXT=${DB_RESULT}) |
|---|
| 344 |
exten => vmx,n(timepri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/pri)}" = "0"]?dotime) |
|---|
| 345 |
exten => vmx,n,Set(VMX_TIMEDEST_PRI=${DB_RESULT}) |
|---|
| 346 |
exten => vmx,n(dotime),Goto(${VMX_TIMEDEST_CONTEXT},${VMX_TIMEDEST_EXT},${VMX_TIMEDEST_PRI}) |
|---|
| 347 |
|
|---|
| 348 |
; We got an option, check if the option is defined, or one of the system defaults |
|---|
| 349 |
; |
|---|
| 350 |
exten => vmx,n(checkopt),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/ext)}" = "1"]?doopt) |
|---|
| 351 |
exten => vmx,n,GotoIf($["${ACTION}" = "0"]?o,1) |
|---|
| 352 |
exten => vmx,n,GotoIf($["${ACTION}" = "*"]?adef,1) |
|---|
| 353 |
|
|---|
| 354 |
; Got invalid option loop until the max |
|---|
| 355 |
; |
|---|
| 356 |
exten => vmx,n,Set(LOOPCOUNT=$[${LOOPCOUNT} + 1]) |
|---|
| 357 |
exten => vmx,n,GotoIf($[${LOOPCOUNT} > ${VMX_LOOPS}]?toomany) |
|---|
| 358 |
exten => vmx,n,Playback(pm-invalid-option&please-try-again) |
|---|
| 359 |
exten => vmx,n,Goto(loopstart) |
|---|
| 360 |
|
|---|
| 361 |
; tomany: to many invalid options, go to the specified destination |
|---|
| 362 |
; |
|---|
| 363 |
exten => vmx,n(toomany),Noop(Too Many invalid entries, got to invalid dest) |
|---|
| 364 |
exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_LOOPS}) |
|---|
| 365 |
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/loops)}" = "0"]?chkloop) |
|---|
| 366 |
exten => vmx,n,Set(VMX_OPTS=${DB_RESULT}) |
|---|
| 367 |
exten => vmx,n(chkloop),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/ext)}" = "0"]?doloop) |
|---|
| 368 |
exten => vmx,n,Set(VMX_LOOPDEST_EXT=${DB_RESULT}) |
|---|
| 369 |
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/context)}" = "0"]?looppri) |
|---|
| 370 |
exten => vmx,n,Set(VMX_LOOPDEST_CONTEXT=${DB_RESULT}) ;TODO make configurable per above |
|---|
| 371 |
exten => vmx,n(looppri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/pri)}" = "0"]?doloop) |
|---|
| 372 |
exten => vmx,n,Set(VMX_LOOPDEST_PRI=${DB_RESULT}) ;TODO make configurable per above |
|---|
| 373 |
exten => vmx,n(doloop),Goto(${VMX_LOOPDEST_CONTEXT},${VMX_LOOPDEST_EXT},${VMX_LOOPDEST_PRI}) |
|---|
| 374 |
|
|---|
| 375 |
; doopt: execute the valid option that was chosen |
|---|
| 376 |
; |
|---|
| 377 |
exten => vmx,n(doopt),Noop(Got a valid option: ${DB_RESULT}) |
|---|
| 378 |
exten => vmx,n,Set(VMX_EXT=${DB_RESULT}) |
|---|
| 379 |
; |
|---|
| 380 |
; Special case, if this option was to go to voicemail, set options and go |
|---|
| 381 |
; |
|---|
| 382 |
exten => vmx,n,GotoIf($["${VMX_EXT}" != "dovm"]?getdest) |
|---|
| 383 |
exten => vmx,n(vmxopts),Set(VMX_OPTS=${VMX_OPTS_DOVM}) |
|---|
| 384 |
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/dovm)}" = "0"]?vmxdovm) |
|---|
| 385 |
exten => vmx,n(vmxopts),Set(VMX_OPTS=${DB_RESULT}) |
|---|
| 386 |
exten => vmx,n(vmxdovm),goto(dovm,1) |
|---|
| 387 |
; |
|---|
| 388 |
; General case, setup the goto destination and go there (no error checking, its up to the GUI's to assure |
|---|
| 389 |
; reasonable values |
|---|
| 390 |
; |
|---|
| 391 |
exten => vmx,n(getdest),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/context)}" = "0"]?vmxpri) |
|---|
| 392 |
exten => vmx,n,Set(VMX_CONTEXT=${DB_RESULT}) |
|---|
| 393 |
exten => vmx,n(vmxpri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/pri)}" = "0"]?vmxgoto) |
|---|
| 394 |
exten => vmx,n,Set(VMX_PRI=${DB_RESULT}) |
|---|
| 395 |
exten => vmx,n(vmxgoto),Goto(${VMX_CONTEXT},${VMX_EXT},${VMX_PRI}) |
|---|
| 396 |
|
|---|
| 397 |
; If the required voicemail file is not present, then revert to normal voicemail |
|---|
| 398 |
; behavior treating as if it was not set |
|---|
| 399 |
; |
|---|
| 400 |
exten => vmx,n(nofile),Noop(File for mode: ${MODE} does not exist, SYSTEMSTATUS: ${SYSTEMSTATUS}, going to normal voicemail) |
|---|
| 401 |
exten => vmx,n,Goto(s-${ARG2},1) |
|---|
| 402 |
exten => vmx,n(tmpgreet),Noop(Temporary Greeting Detected, going to normal voicemail) |
|---|
| 403 |
exten => vmx,n,Goto(s-${ARG2},1) |
|---|
| 404 |
|
|---|
| 405 |
; Drop into voicemail either as a direct destination (in which case VMX_OPTS might be set to something) or |
|---|
| 406 |
; if the user timed out or broke out of the loop then VMX_OPTS is always cleared such that an Allison |
|---|
| 407 |
; message is played and the caller know's what is going on. |
|---|
| 408 |
; |
|---|
| 409 |
exten => dovm,1,Noop(VMX Timeout - go to voicemail) |
|---|
| 410 |
exten => dovm,n,Voicemail(${ARG1}@${VMCONTEXT},${VMX_OPTS}${VMGAIN}) ; no flags, so allison plays please leave ... |
|---|
| 411 |
exten => dovm,n,Goto(exit-${VMSTATUS},1) |
|---|
| 412 |
|
|---|
| 413 |
exten => s-BUSY,1,NoOp(BUSY voicemail) |
|---|
| 414 |
exten => s-BUSY,n,Macro(get-vmcontext,${ARG1}) |
|---|
| 415 |
exten => s-BUSY,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}b${VMGAIN}) ; Voicemail Busy message |
|---|
| 416 |
exten => s-BUSY,n,Goto(exit-${VMSTATUS},1) |
|---|
| 417 |
|
|---|
| 418 |
exten => s-NOMESSAGE,1,NoOp(NOMESSAGE (beeb only) voicemail) |
|---|
| 419 |
exten => s-NOMESSAGE,n,Macro(get-vmcontext,${ARG1}) |
|---|
| 420 |
exten => s-NOMESSAGE,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VMGAIN}) ; Voicemail Busy message |
|---|
| 421 |
exten => s-NOMESSAGE,n,Goto(exit-${VMSTATUS},1) |
|---|
| 422 |
|
|---|
| 423 |
exten => s-DIRECTDIAL,1,NoOp(DIRECTDIAL voicemail) |
|---|
| 424 |
exten => s-DIRECTDIAL,n,Macro(get-vmcontext,${ARG1}) |
|---|
| 425 |
exten => s-DIRECTDIAL,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VM_DDTYPE}${VMGAIN}) |
|---|
| 426 |
exten => s-DIRECTDIAL,n,Goto(exit-${VMSTATUS},1) |
|---|
| 427 |
|
|---|
| 428 |
exten => _s-.,1,Macro(get-vmcontext,${ARG1}) |
|---|
| 429 |
exten => _s-.,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}u${VMGAIN}) ; Voicemail Unavailable message |
|---|
| 430 |
exten => _s-.,n,Goto(exit-${VMSTATUS},1) |
|---|
| 431 |
|
|---|
| 432 |
; If the user has a 0 option defined, use that for operator zero-out from within voicemail |
|---|
| 433 |
; as well to keep it consistant with the menu structure |
|---|
| 434 |
; |
|---|
| 435 |
exten => o,1,Background(one-moment-please) ; 0 during vm message will hangup |
|---|
| 436 |
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/ext)}" = "0"]?doopdef) |
|---|
| 437 |
|
|---|
| 438 |
exten => o,n,Set(VMX_OPDEST_EXT=${DB_RESULT}) |
|---|
| 439 |
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/context)}" = "1"]?opcontext) |
|---|
| 440 |
exten => o,n,Set(DB_RESULT=${VMX_CONTEXT}) |
|---|
| 441 |
exten => o,n(opcontext),Set(VMX_OPDEST_CONTEXT=${DB_RESULT}) |
|---|
| 442 |
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/pri)}" = "1"]?oppri) |
|---|
| 443 |
exten => o,n,Set(DB_RESULT=${VMX_PRI}) |
|---|
| 444 |
exten => o,n(oppri),Set(VMX_OPDEST_PRI=${DB_RESULT}) |
|---|
| 445 |
|
|---|
| 446 |
exten => o,n,Goto(${VMX_OPDEST_CONTEXT},${VMX_OPDEST_EXT},${VMX_OPDEST_PRI}) |
|---|
| 447 |
exten => o,n(doopdef),GotoIf($["x${OPERATOR_XTN}"="x"]?nooper:from-internal,${OPERATOR_XTN},1) |
|---|
| 448 |
exten => o,n(nooper),GotoIf($["x${FROM_DID}"="x"]?nodid) |
|---|
| 449 |
exten => o,n,Dial(Local/${FROM_DID)@from-pstn) |
|---|
| 450 |
exten => o,n,Macro(hangup) |
|---|
| 451 |
exten => o,n(nodid),Dial(Local/s@from-pstn) |
|---|
| 452 |
exten => o,n,Macro(hangup) |
|---|
| 453 |
|
|---|
| 454 |
; If the user has a * option defined, use that for the * out from within voicemail |
|---|
| 455 |
; as well to keep it consistant with the menu structure |
|---|
| 456 |
; |
|---|
| 457 |
exten => a,1,Macro(get-vmcontext,${ARG1}) |
|---|
| 458 |
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/ext)}" = "0"]?adef,1) |
|---|
| 459 |
|
|---|
| 460 |
exten => a,n,Set(VMX_ADEST_EXT=${DB_RESULT}) |
|---|
| 461 |
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/context)}" = "1"]?acontext) |
|---|
| 462 |
exten => a,n,Set(DB_RESULT=${VMX_CONTEXT}) |
|---|
| 463 |
exten => a,n(acontext),Set(VMX_ADEST_CONTEXT=${DB_RESULT}) |
|---|
| 464 |
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/pri)}" = "1"]?apri) |
|---|
| 465 |
exten => a,n,Set(DB_RESULT=${VMX_PRI}) |
|---|
| 466 |
exten => a,n(apri),Set(VMX_ADEST_PRI=${DB_RESULT}) |
|---|
| 467 |
exten => a,n,Goto(${VMX_ADEST_CONTEXT},${VMX_ADEST_EXT},${VMX_ADEST_PRI}) |
|---|
| 468 |
|
|---|
| 469 |
exten => adef,1,VoiceMailMain(${ARG1}@${VMCONTEXT}) |
|---|
| 470 |
exten => adef,n,Hangup |
|---|
| 471 |
|
|---|
| 472 |
exten => exit-FAILED,1,Playback(im-sorry&an-error-has-occured) |
|---|
| 473 |
exten => exit-FAILED,n,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1) |
|---|
| 474 |
exten => exit-FAILED,n,Hangup() |
|---|
| 475 |
|
|---|
| 476 |
exten => exit-SUCCESS,1,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1) |
|---|
| 477 |
exten => exit-SUCCESS,n,Playback(goodbye) |
|---|
| 478 |
exten => exit-SUCCESS,n,Hangup() |
|---|
| 479 |
|
|---|
| 480 |
exten => exit-USEREXIT,1,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1) |
|---|
| 481 |
exten => exit-USEREXIT,n,Playback(goodbye) |
|---|
| 482 |
exten => exit-USEREXIT,n,Hangup() |
|---|
| 483 |
|
|---|
| 484 |
exten => exit-RETURN,1,Noop(Returning From Voicemail because macro) |
|---|
| 485 |
|
|---|
| 486 |
exten => t,1,Hangup() |
|---|
| 487 |
;------------------------------------------------------------------------ |
|---|
| 488 |
|
|---|
| 489 |
;------------------------------------------------------------------------ |
|---|
| 490 |
; [macro-simple-dial] |
|---|
| 491 |
;------------------------------------------------------------------------ |
|---|
| 492 |
; This macro was derived from macro-exten-vm, which is what is normally used to |
|---|
| 493 |
; ring an extension. It has been simplified and designed to never go to voicemail |
|---|
| 494 |
; and always return regardless of the DIALSTATUS for any incomplete call. |
|---|
| 495 |
; |
|---|
| 496 |
; It's current primary purpose is to allow findmefollow ring an extension prior |
|---|
| 497 |
; to trying the follow-me ringgroup that is provided. |
|---|
| 498 |
; |
|---|
| 499 |
; Ring an extension, if the extension is busy or there is no answer, return |
|---|
| 500 |
; ARGS: $EXTENSION, $RINGTIME |
|---|
| 501 |
;------------------------------------------------------------------------ |
|---|
| 502 |
[macro-simple-dial] |
|---|
| 503 |
exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from follow-me |
|---|
| 504 |
|
|---|
| 505 |
; FROMCONTEXT was in the original macro-exten-vm where this macro was derived from. A |
|---|
| 506 |
; search through all the modules does not come up with any place using this |
|---|
| 507 |
; variable, but it is left here as a reminder in case there is functionality |
|---|
| 508 |
; that eventually behaves in a certain way as a result of this variable being set |
|---|
| 509 |
; and this macro has to masquerade as exten-vm. |
|---|
| 510 |
; |
|---|
| 511 |
exten => s,n,Set(EXTTOCALL=${ARG1}) |
|---|
| 512 |
exten => s,n,Set(RT=${ARG2}) |
|---|
| 513 |
exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})}) |
|---|
| 514 |
exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})}) |
|---|
| 515 |
exten => s,n,Macro(record-enable,${EXTTOCALL},IN) |
|---|
| 516 |
|
|---|
| 517 |
exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL}) |
|---|
| 518 |
|
|---|
| 519 |
exten => s,n,Set(PR_DIALSTATUS=${DIALSTATUS}) |
|---|
| 520 |
|
|---|
| 521 |
; if we return, thus no answer, and they have a CFU setting, then we try that next |
|---|
| 522 |
; |
|---|
| 523 |
exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"="NOANSWER"] & $["foo${CFUEXT}"!="foo"]]?docfu,1) ; check for CFU in use on no answer |
|---|
| 524 |
exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"="BUSY"] & $["foo${CFBEXT}"!="foo"]]?docfb,1) ; check for CFB in use on busy |
|---|
| 525 |
exten => s,n,Set(DIALSTATUS=${PR_DIALSTATUS}) |
|---|
| 526 |
|
|---|
| 527 |
; Nothing yet, then go to the end (which will just return, but in case we decide to do something with certain |
|---|
| 528 |
; return situations, this is left in. |
|---|
| 529 |
; |
|---|
| 530 |
exten => s,n,Goto(s-${DIALSTATUS},1) |
|---|
| 531 |
|
|---|
| 532 |
; Try the Call Forward on No Answer / Unavailable number. |
|---|
| 533 |
; 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 |
|---|
| 534 |
; system ringtimer? - probably not). Then if no answer there (assuming it doesn't drop into their vm or |
|---|
| 535 |
; something we return, which will have the net effect of returning to the followme setup.) |
|---|
| 536 |
; |
|---|
| 537 |
; want to avoid going to other follow-me settings here. So check if the CFUEXT is a user and if it is |
|---|
| 538 |
; then direct it straight to ext-local (to avoid getting intercepted by findmefollow) otherwise send it |
|---|
| 539 |
; to from-internal since it may be an outside line. |
|---|
| 540 |
; |
|---|
| 541 |
exten => docfu,1,GotoIf( $[ "foo${DB(AMPUSER/${CFUEXT}/device)}" = "foo" ]?chlocal) |
|---|
| 542 |
exten => docfu,n,Dial(Local/${CFUEXT}@ext-local,${RT},${DIAL_OPTIONS}) |
|---|
| 543 |
exten => docfu,n,Return |
|---|
| 544 |
exten => docfu,n(chlocal),Dial(Local/${CFUEXT}@from-internal/n,${RT},${DIAL_OPTIONS}) |
|---|
| 545 |
exten => docfu,n,Return |
|---|
| 546 |
|
|---|
| 547 |
; Try the Call Forward on Busy number |
|---|
| 548 |
exten => docfb,1,GotoIf( $[ "foo${DB(AMPUSER/${CFBEXT}/device)}" = "foo" ]?chlocal) |
|---|
| 549 |
exten => docfb,n,Dial(Local/${CFBEXT}@ext-local,${RT},${DIAL_OPTIONS}) |
|---|
| 550 |
exten => docfb,n,Return |
|---|
| 551 |
exten => docfb,n(chlocal),Dial(Local/${CFBEXT}@from-internal/n,${RT},${DIAL_OPTIONS}) |
|---|
| 552 |
exten => docfb,n,Return |
|---|
| 553 |
|
|---|
| 554 |
; In all cases of no connection, come here and simply return, since the calling dialplan will |
|---|
| 555 |
; decide what to do next |
|---|
| 556 |
exten => _s-.,1,NoOp(Extension is reporting ${EXTEN}) |
|---|
| 557 |
;------------------------------------------------------------------------ |
|---|
| 558 |
|
|---|
| 559 |
|
|---|
| 560 |
; get the voicemail context for the user in ARG1 |
|---|
| 561 |
[macro-get-vmcontext] |
|---|
| 562 |
exten => s,1,Set(VMCONTEXT=${DB(AMPUSER/${ARG1}/voicemail)}) |
|---|
| 563 |
exten => s,2,GotoIf($["foo${VMCONTEXT}" = "foo"]?200:300) |
|---|
| 564 |
exten => s,200,Set(VMCONTEXT=default) |
|---|
| 565 |
exten => s,300,NoOp() |
|---|
| 566 |
|
|---|
| 567 |
; For some reason, if I don't run setCIDname, CALLERID(name) will be blank in my AGI |
|---|
| 568 |
; ARGS: none |
|---|
| 569 |
[macro-fixcid] |
|---|
| 570 |
exten => s,1,Set(CALLERID(name)=${CALLERID(name)}) |
|---|
| 571 |
|
|---|
| 572 |
; Ring groups of phones |
|---|
| 573 |
; ARGS: comma separated extension list |
|---|
| 574 |
; 1 - Ring Group Strategy |
|---|
| 575 |
; 2 - ringtimer |
|---|
| 576 |
; 3 - prefix |
|---|
| 577 |
; 4 - extension list |
|---|
| 578 |
[macro-rg-group] |
|---|
| 579 |
exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from ringgroup |
|---|
| 580 |
exten => s,2,GotoIf($["${CALLERID(name):0:${LEN(${RGPREFIX})}}" != "${RGPREFIX}"]?4:3) ; check for old prefix |
|---|
| 581 |
exten => s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ; strip off old prefix |
|---|
| 582 |
exten => s,4,Set(RGPREFIX=${ARG3}) ; set new prefix |
|---|
| 583 |
exten => s,5,Set(CALLERID(name)=${RGPREFIX}${CALLERID(name)}) ; add prefix to callerid name |
|---|
| 584 |
exten => s,6,Set(RecordMethod=Group) ; set new prefix |
|---|
| 585 |
exten => s,7,Macro(record-enable,${MACRO_EXTEN},${RecordMethod}) |
|---|
| 586 |
exten => s,8,Set(RingGroupMethod=${ARG1}) ; |
|---|
| 587 |
exten => s,9,Macro(dial,${ARG2},${DIAL_OPTIONS},${ARG4}) |
|---|
| 588 |
exten => s,10,Set(RingGroupMethod='') ; |
|---|
| 589 |
|
|---|
| 590 |
|
|---|
| 591 |
; |
|---|
| 592 |
; Outgoing channel(s) are busy ... inform the client |
|---|
| 593 |
; but use noanswer features like ringgroups don't break by being answered |
|---|
| 594 |
; just to play the message. |
|---|
| 595 |
; |
|---|
| 596 |
[macro-outisbusy] |
|---|
| 597 |
exten => s,1,Playback(all-circuits-busy-now,noanswer) |
|---|
| 598 |
exten => s,n,Playback(pls-try-call-later,noanswer) |
|---|
| 599 |
exten => s,n,Macro(hangupcall) |
|---|
| 600 |
|
|---|
| 601 |
; What to do on hangup. |
|---|
| 602 |
[macro-hangupcall] |
|---|
| 603 |
exten => s,1,ResetCDR(w) |
|---|
| 604 |
exten => s,n,NoCDR() |
|---|
| 605 |
|
|---|
| 606 |
; Cleanup any remaining RG flag |
|---|
| 607 |
; |
|---|
| 608 |
exten => s,n,GotoIf($[ "x${USE_CONFIRMATION}" = "x" | "x${RINGGROUP_INDEX}" = "x" | "${CHANNEL}" != "${UNIQCHAN}"]?skiprg) |
|---|
| 609 |
exten => s,n,Noop(Cleaning Up Confirmation Flag: RG/${RINGGROUP_INDEX}/${CHANNEL}) |
|---|
| 610 |
exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL}) |
|---|
| 611 |
|
|---|
| 612 |
; Cleanup any remaining BLKVM flag |
|---|
| 613 |
; |
|---|
| 614 |
exten => s,n(skiprg),GotoIf($[ "x${BLKVM_BASE}" = "x" | "BLKVM/${BLKVM_BASE}/${CHANNEL}" != "${BLKVM_OVERRIDE}" ]?skipblkvm) |
|---|
| 615 |
exten => s,n,Noop(Cleaning Up Block VM Flag: ${BLKVM_OVERRIDE}) |
|---|
| 616 |
exten => s,n,DBDel(${BLKVM_OVERRIDE}) |
|---|
| 617 |
|
|---|
| 618 |
; Cleanup any remaining FollowMe DND flags |
|---|
| 619 |
; |
|---|
| 620 |
exten => s,n(skipblkvm),GotoIf($[ "x${FMGRP}" = "x" | "x${FMUNIQUE}" = "x" | "${CHANNEL}" != "${FMUNIQUE}" ]?theend) |
|---|
| 621 |
exten => s,n,DBDel(FM/DND/${FMGRP}/${CHANNEL}) |
|---|
| 622 |
|
|---|
| 623 |
exten => s,n(theend),Hangup |
|---|
| 624 |
|
|---|
| 625 |
[macro-faxreceive] |
|---|
| 626 |
exten => s,1,Set(FAXFILE=${ASTSPOOLDIR}/fax/${UNIQUEID}.tif) |
|---|
| 627 |
exten => s,2,Set(EMAILADDR=${FAX_RX_EMAIL}) |
|---|
| 628 |
exten => s,3,rxfax(${FAXFILE}) |
|---|
| 629 |
exten => s,103,Set(EMAILADDR=${FAX_RX_EMAIL}) |
|---|
| 630 |
exten => s,104,Goto(3) |
|---|
| 631 |
|
|---|
| 632 |
; dialout and strip the prefix |
|---|
| 633 |
[macro-dialout] |
|---|
| 634 |
exten => s,1,Macro(user-callerid,SKIPTTL) |
|---|
| 635 |
exten => s,2,GotoIf($["${ECID${CALLERID(number)}}" = ""]?5) ;check for CID override for exten |
|---|
| 636 |
exten => s,3,Set(CALLERID(all)=${ECID${CALLERID(number)}}) |
|---|
| 637 |
exten => s,4,Goto(7) |
|---|
| 638 |
exten => s,5,GotoIf($["${OUTCID_${ARG1}}" = ""]?7) ;check for CID override for trunk |
|---|
| 639 |
exten => s,6,Set(CALLERID(all)=${OUTCID_${ARG1}}) |
|---|
| 640 |
exten => s,7,Set(length=${LEN(${DIAL_OUT_${ARG1}})}) |
|---|
| 641 |
exten => s,8,Dial(${OUT_${ARG1}}/${ARG2:${length}}) |
|---|
| 642 |
exten => s,9,Playtones(congestion) |
|---|
| 643 |
exten => s,10,Congestion(5) |
|---|
| 644 |
exten => s,109,Macro(outisbusy) |
|---|
| 645 |
|
|---|
| 646 |
|
|---|
| 647 |
; dialout using default OUT trunk - no prefix |
|---|
| 648 |
[macro-dialout-default] |
|---|
| 649 |
exten => s,1,Macro(user-callerid,SKIPTTL) |
|---|
| 650 |
exten => s,2,Macro(record-enable,${CALLERID(number)},OUT) |
|---|
| 651 |
exten => s,3,Macro(outbound-callerid,${ARG1}) |
|---|
| 652 |
exten => s,4,Dial(${OUT}/${ARG1}) |
|---|
| 653 |
exten => s,5,Playtones(congestion) |
|---|
| 654 |
exten => s,6,Congestion(5) |
|---|
| 655 |
exten => s,105,Macro(outisbusy) |
|---|
| 656 |
|
|---|
| 657 |
[macro-dialout-trunk-predial-hook] |
|---|
| 658 |
; this macro intentially left blank so it may be safely overwritten for any custom |
|---|
| 659 |
; requirements that an installatin may have. |
|---|
| 660 |
; |
|---|
| 661 |
; MACRO RETURN CODE: ${PREDIAL_HOOK_RET} |
|---|
| 662 |
; if set to "BYPASS" then this trunk will be skipped |
|---|
| 663 |
; |
|---|
| 664 |
|
|---|
| 665 |
|
|---|
| 666 |
[macro-record-enable] |
|---|
| 667 |
exten => s,1,GotoIf($[${LEN(${BLINDTRANSFER})} > 0]?2:4) |
|---|
| 668 |
exten => s,2,ResetCDR(w) |
|---|
| 669 |
exten => s,3,StopMonitor() |
|---|
| 670 |
exten => s,4,AGI(recordingcheck,${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)},${UNIQUEID}) |
|---|
| 671 |
exten => s,5,Noop(No recording needed) |
|---|
| 672 |
exten => s,999,MixMonitor(${CALLFILENAME}.wav) |
|---|
| 673 |
|
|---|
| 674 |
;exten => s,3,BackGround(for-quality-purposes) |
|---|
| 675 |
;exten => s,4,BackGround(this-call-may-be) |
|---|
| 676 |
;exten => s,5,BackGround(recorded) |
|---|
| 677 |
|
|---|
| 678 |
; This macro is for dev purposes and just dumps channel/app variables. Useful when designing new contexts. |
|---|
| 679 |
[macro-dumpvars] |
|---|
| 680 |
exten => s,1,Noop(ACCOUNTCODE=${ACCOUNTCODE}) |
|---|
| 681 |
exten => s,2,Noop(ANSWEREDTIME=${ANSWEREDTIME}) |
|---|
| 682 |
exten => s,3,Noop(BLINDTRANSFER=${BLINDTRANSFER}) |
|---|
| 683 |
exten => s,4,Noop(CALLERID=${CALLERID(all)}) |
|---|
| 684 |
exten => s,5,Noop(CALLERID(name)=${CALLERID(name)}) |
|---|
| 685 |
exten => s,6,Noop(CALLERID(number)=${CALLERID(number)}) |
|---|
| 686 |
exten => s,7,Noop(CALLINGPRES=${CALLINGPRES}) |
|---|
| 687 |
exten => s,8,Noop(CHANNEL=${CHANNEL}) |
|---|
| 688 |
exten => s,9,Noop(CONTEXT=${CONTEXT}) |
|---|
| 689 |
exten => s,10,Noop(DATETIME=${DATETIME}) |
|---|
| 690 |
exten => s,11,Noop(DIALEDPEERNAME=${DIALEDPEERNAME}) |
|---|
| 691 |
exten => s,12,Noop(DIALEDPEERNUMBER=${DIALEDPEERNUMBER}) |
|---|
| 692 |
exten => s,13,Noop(DIALEDTIME=${DIALEDTIME}) |
|---|
| 693 |
exten => s,14,Noop(DIALSTATUS=${DIALSTATUS}) |
|---|
| 694 |
exten => s,15,Noop(DNID=${DNID}) |
|---|
| 695 |
exten => s,16,Noop(EPOCH=${EPOCH}) |
|---|
| 696 |
exten => s,17,Noop(EXTEN=${EXTEN}) |
|---|
| 697 |
exten => s,18,Noop(HANGUPCAUSE=${HANGUPCAUSE}) |
|---|
| 698 |
exten => s,19,Noop(INVALID_EXTEN=${INVALID_EXTEN}) |
|---|
| 699 |
exten => s,20,Noop(LANGUAGE=${LANGUAGE}) |
|---|
| 700 |
exten => s,21,Noop(MEETMESECS=${MEETMESECS}) |
|---|
| 701 |
exten => s,22,Noop(PRIORITY=${PRIORITY}) |
|---|
| 702 |
exten => s,23,Noop(RDNIS=${RDNIS}) |
|---|
| 703 |
exten => s,24,Noop(SIPDOMAIN=${SIPDOMAIN}) |
|---|
| 704 |
exten => s,25,Noop(SIP_CODEC=${SIP_CODEC}) |
|---|
| 705 |
exten => s,26,Noop(SIPCALLID=${SIPCALLID}) |
|---|
| 706 |
exten => s,27,Noop(SIPUSERAGENT=${SIPUSERAGENT}) |
|---|
| 707 |
exten => s,29,Noop(TXTCIDNAME=${TXTCIDNAME}) |
|---|
| 708 |
exten => s,30,Noop(UNIQUEID=${UNIQUEID}) |
|---|
| 709 |
exten => s,31,Noop(TOUCH_MONITOR=${TOUCH_MONITOR}) |
|---|
| 710 |
exten => s,32,Noop(MACRO_CONTEXT=${MACRO_CONTEXT}) |
|---|
| 711 |
exten => s,33,Noop(MACRO_EXTEN=${MACRO_EXTEN}) |
|---|
| 712 |
exten => s,34,Noop(MACRO_PRIORITY=${MACRO_PRIORITY}) |
|---|
| 713 |
|
|---|
| 714 |
[macro-user-logon] |
|---|
| 715 |
; check device type |
|---|
| 716 |
; |
|---|
| 717 |
exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)}) |
|---|
| 718 |
exten => s,n,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1) |
|---|
| 719 |
; get user's extension |
|---|
| 720 |
; |
|---|
| 721 |
exten => s,n,Set(AMPUSER=${ARG1}) |
|---|
| 722 |
exten => s,n,GotoIf($["${AMPUSER}" != ""]?gotpass) |
|---|
| 723 |
exten => s,n,Playback(please-enter-your&extension) |
|---|
| 724 |
exten => s,n,Read(AMPUSER,then-press-pound) |
|---|
| 725 |
; get user's password and authenticate |
|---|
| 726 |
; |
|---|
| 727 |
exten => s,n(gotpass),Set(AMPUSERPASS=${DB(AMPUSER/${AMPUSER}/password)}) |
|---|
| 728 |
exten => s,n,GotoIf($[${LEN(${AMPUSERPASS})} = 0]?s-NOPASSWORD,1) |
|---|
| 729 |
; do not continue if the user has already logged onto this device |
|---|
| 730 |
; |
|---|
| 731 |
exten => s,n,Set(DEVICEUSER=${DB(DEVICE/${CALLERID(number)}/user)}) |
|---|
| 732 |
exten => s,n,GotoIf($["${DEVICEUSER}" = "${AMPUSER}"]?s-ALREADYLOGGEDON,1) |
|---|
| 733 |
exten => s,n,Authenticate(${AMPUSERPASS}) |
|---|
| 734 |
exten => s,n,DeadAGI(user_login_out.agi,login,${CALLERID(number)},${AMPUSER}) |
|---|
| 735 |
exten => s,n,Playback(vm-goodbye) |
|---|
| 736 |
|
|---|
| 737 |
exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged into) |
|---|
| 738 |
exten => s-FIXED,n,Playback(ha/phone) |
|---|
| 739 |
exten => s-FIXED,n,SayDigits(${CALLERID(number)}) |
|---|
| 740 |
exten => s-FIXED,n,Playback(is-curntly-unavail&vm-goodbye) |
|---|
| 741 |
exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into |
|---|
| 742 |
|
|---|
| 743 |
exten => s-ALREADYLOGGEDON,1,NoOp(This device has already been logged into by this user) |
|---|
| 744 |
exten => s-ALREADYLOGGEDON,n,Playback(vm-goodbye) |
|---|
| 745 |
exten => s-ALREADYLOGGEDON,n,Hangup ;TODO should play msg indicated device is already logged into |
|---|
| 746 |
|
|---|
| 747 |
exten => s-NOPASSWORD,1,NoOp(This extension does not exist or no password is set) |
|---|
| 748 |
exten => s-NOPASSWORD,n,Playback(an-error-has-occured&vm-goodbye) |
|---|
| 749 |
exten => s-NOPASSWORD,n,Hangup ;TODO should play msg indicated device is already logged into |
|---|
| 750 |
|
|---|
| 751 |
[macro-user-logoff] |
|---|
| 752 |
; check device type |
|---|
| 753 |
; |
|---|
| 754 |
exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)}) |
|---|
| 755 |
exten => s,n,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1) |
|---|
| 756 |
exten => s,n,DeadAGI(user_login_out.agi,logout,${CALLERID(number)}) |
|---|
| 757 |
exten => s,n(done),Playback(vm-goodbye) |
|---|
| 758 |
|
|---|
| 759 |
exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged out of) |
|---|
| 760 |
exten => s-FIXED,n,Playback(an-error-has-occured&vm-goodbye) |
|---|
| 761 |
exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into |
|---|
| 762 |
|
|---|
| 763 |
|
|---|
| 764 |
|
|---|
| 765 |
; Privacy Manager Macro makes sure that any calls that don't pass the privacy manager are presented |
|---|
| 766 |
; with congestion since there have been observed cases of the call continuing if not stopped with a |
|---|
| 767 |
; congestion, and this provides a slightly more friendly 'sorry' message in case the user is |
|---|
| 768 |
; legitamately trying to be cooperative. |
|---|
| 769 |
; |
|---|
| 770 |
; Note: the following options are configurable in privacy.conf: |
|---|
| 771 |
; |
|---|
| 772 |
; maxretries = 3 ; default value, number of retries before failing |
|---|
| 773 |
; minlength = 10 ; default value, number of digits to be accepted as valid CID |
|---|
| 774 |
; |
|---|
| 775 |
[macro-privacy-mgr] |
|---|
| 776 |
exten => s,1,Set(KEEPCID=${CALLERID(num)}) |
|---|
| 777 |
exten => s,n,GotoIf($["foo${CALLERID(num):0:1}"="foo+"]?CIDTEST2:CIDTEST1) |
|---|
| 778 |
exten => s,n(CIDTEST1),Set(TESTCID=${MATH(1+${CALLERID(num)})}) |
|---|
| 779 |
exten => s,n,Goto(TESTRESULT) |
|---|
| 780 |
exten => s,n(CIDTEST2),Set(TESTCID=${MATH(1+${CALLERID(num):1})}) |
|---|
| 781 |
exten => s,n(TESTRESULT),GotoIf($["foo${TESTCID}"="foo"]?CLEARCID:PRIVMGR) |
|---|
| 782 |
exten => s,n(CLEARCID),Set(CALLERID(num)=) |
|---|
| 783 |
exten => s,n(PRIVMGR),PrivacyManager() |
|---|
| 784 |
exten => s,n,GotoIf($["${PRIVACYMGRSTATUS}"="FAILED"]?fail) |
|---|
| 785 |
exten => s,n,SetCallerPres(allowed_passed_screen); stop gap until app_privacy.c clears unavailble bit |
|---|
| 786 |
exten => s,PRIVMGR+101(fail),Noop(STATUS: ${PRIVACYMGRSTATUS} CID: ${CALLERID(num)} ${CALLERID(name)} CALLPRES: ${CALLLINGPRES}) |
|---|
| 787 |
exten => s,n,Playback(sorry-youre-having-problems) |
|---|
| 788 |
exten => s,n,Playback(goodbye) |
|---|
| 789 |
exten => s,n,Playtones(congestion) |
|---|
| 790 |
exten => s,n,Congestion(5) |
|---|
| 791 |
|
|---|
| 792 |
|
|---|
| 793 |
|
|---|
| 794 |
; Text-To-Speech related macros |
|---|
| 795 |
; These all follow common actions. First try to playback a file "tts/custom-md5" |
|---|
| 796 |
; where "md5" is the md5() of whatever is going to be played. If that doesn't exist, |
|---|
| 797 |
; try to playback using macro-tts-sayXXXXX (where XXXXX is text/digits/etc, same as |
|---|
| 798 |
; the macro below). If that macro exits with MACRO_OFFSET=100, then it's done, |
|---|
| 799 |
; therwise, fallback to the default asterisk method. |
|---|
| 800 |
; |
|---|
| 801 |
; say text is purely for text-to-speech, there is no fallback |
|---|
| 802 |
[macro-saytext] |
|---|
| 803 |
exten => s,1,Noop(Trying custom SayText playback for "${ARG1}") |
|---|
| 804 |
exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) |
|---|
| 805 |
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) |
|---|
| 806 |
; call tts-saytext. This should set MACRO_OFFSET=101 if it was successful |
|---|
| 807 |
exten => s,n(tts),Macro(tts-saytext,${ARG1},${ARG2},${ARG3}) |
|---|
| 808 |
exten => s,n,Noop(No text-to-speech handler for SayText, cannot say "${ARG1}") |
|---|
| 809 |
exten => s,n,Goto(done) |
|---|
| 810 |
exten => s,tts+101,Noop(tts handled saytext) |
|---|
| 811 |
|
|---|
| 812 |
; say name is for saying names typically, but fallsback to using SayAlpha |
|---|
| 813 |
; (saying the word letter-by-letter) |
|---|
| 814 |
[macro-sayname] |
|---|
| 815 |
exten => s,1,Noop(Trying custom SayName playback for "${ARG1}") |
|---|
| 816 |
exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) |
|---|
| 817 |
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) |
|---|
| 818 |
; call tts-sayalpha. This should set MACRO_OFFSET=101 if it was successful |
|---|
| 819 |
exten => s,n(tts),Macro(tts-sayalpha,${ARG1},${ARG2},${ARG3}) |
|---|
| 820 |
exten => s,n,SayAlpha(${ARG1}) |
|---|
| 821 |
exten => s,n,Goto(done) |
|---|
| 822 |
exten => s,tts+101,Noop(tts handled sayname) |
|---|
| 823 |
|
|---|
| 824 |
; Say number is for saying numbers (eg "one thousand forty six") |
|---|
| 825 |
[macro-saynumber] |
|---|
| 826 |
exten => s,1,Noop(Trying custom SayNumber playback for "${ARG1}") |
|---|
| 827 |
exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) |
|---|
| 828 |
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) |
|---|
| 829 |
; call tts-saynumber. This should set MACRO_OFFSET=101 if it was successful |
|---|
| 830 |
exten => s,n(tts),Macro(tts-saynumber,${ARG1},${ARG2},${ARG3}) |
|---|
| 831 |
exten => s,n,SayNumber(${ARG1}) |
|---|
| 832 |
exten => s,n,Goto(done) |
|---|
| 833 |
exten => s,tts+101,Noop(tts handled saynumber) |
|---|
| 834 |
|
|---|
| 835 |
; Say digits is for saying digits one-by-one (eg, "one zero four six") |
|---|
| 836 |
[macro-saydigits] |
|---|
| 837 |
exten => s,1,Noop(Trying custom SayDigits playback for "${ARG1}") |
|---|
| 838 |
exten => s,n,Playback(tts/custom-${MD5(${ARG1})}) |
|---|
| 839 |
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done) |
|---|
| 840 |
; call tts-saydigits. This should set MACRO_OFFSET=101 if it was successful |
|---|
| 841 |
exten => s,n(tts),Macro(tts-saydigits,${ARG1},${ARG2},${ARG3}) |
|---|
| 842 |
exten => s,n,SayDigits(${ARG1}) |
|---|
| 843 |
exten => s,n,Goto(done) |
|---|
| 844 |
|
|---|
| 845 |
|
|---|
| 846 |
; |
|---|
| 847 |
; ############################################################################ |
|---|
| 848 |
; Inbound Contexts [from] |
|---|
| 849 |
; ############################################################################ |
|---|
| 850 |
|
|---|
| 851 |
[from-sip-external] |
|---|
| 852 |
;give external sip users congestion and hangup |
|---|
| 853 |
; Yes. This is _really_ meant to be _. - I know asterisk whinges about it, but |
|---|
| 854 |
; I do know what I'm doing. This is correct. |
|---|
| 855 |
exten => _.,1,NoOp(Received incoming SIP connection from unknown peer to ${EXTEN}) |
|---|
| 856 |
exten => _.,n,Set(DID=${IF($["${EXTEN:1:2}"=""]?s:${EXTEN})}) |
|---|
| 857 |
exten => _.,n,Goto(s,1) |
|---|
| 858 |
exten => s,1,GotoIf($["${ALLOW_SIP_ANON}"="yes"]?from-trunk,${DID},1) |
|---|
| 859 |
exten => s,n,Set(TIMEOUT(absolute)=15) |
|---|
| 860 |
exten => s,n,Answer |
|---|
| 861 |
exten => s,n,Wait(2) |
|---|
| 862 |
exten => s,n,Playback(ss-noservice) |
|---|
| 863 |
exten => s,n,Playtones(congestion) |
|---|
| 864 |
exten => s,n,Congestion(5) |
|---|
| 865 |
exten => h,1,NoOp(Hangup) |
|---|
| 866 |
exten => i,1,NoOp(Invalid) |
|---|
| 867 |
exten => t,1,NoOp(Timeout) |
|---|
| 868 |
|
|---|
| 869 |
[from-internal-xfer] |
|---|
| 870 |
; applications are now mostly all found in from-internal-additional in _custom.conf |
|---|
| 871 |
include => parkedcalls |
|---|
| 872 |
include => from-internal-custom |
|---|
| 873 |
;allow phones to dial other extensions |
|---|
| 874 |
include => ext-fax |
|---|
| 875 |
;allow phones to access generated contexts |
|---|
| 876 |
; |
|---|
| 877 |
; MODIFIED (PL) |
|---|
| 878 |
; |
|---|
| 879 |
; Currently the include for findmefollow is being auto-generated before ext-local which is the desired behavior. |
|---|
| 880 |
; However, I haven't been able to do anything that I know of to force this. We need to determine if it should |
|---|
| 881 |
; be hardcoded into here to make sure it doesn't change with some configuration. For now I will leave it out |
|---|
| 882 |
; until we can discuss this. |
|---|
| 883 |
; |
|---|
| 884 |
include => ext-local-confirm |
|---|
| 885 |
include => findmefollow-ringallv2 |
|---|
| 886 |
include => from-internal-additional |
|---|
| 887 |
; This causes grief with '#' transfers, commenting out for the moment. |
|---|
| 888 |
; include => bad-number |
|---|
| 889 |
exten => s,1,Macro(hangupcall) |
|---|
| 890 |
exten => h,1,Macro(hangupcall) |
|---|
| 891 |
|
|---|
| 892 |
[from-internal] |
|---|
| 893 |
include => from-internal-xfer |
|---|
| 894 |
include => bad-number |
|---|
| 895 |
|
|---|
| 896 |
[from-zaptel] |
|---|
| 897 |
exten => _X.,1,Set(DID=${EXTEN}) |
|---|
| 898 |
exten => _X.,n,Goto(s,1) |
|---|
| 899 |
exten => s,1,NoOp(Entering from-zaptel with DID == ${DID}) |
|---|
| 900 |
; Some trunks _require_ a RINGING be sent before an Answer. |
|---|
| 901 |
exten => s,n,Ringing() |
|---|
| 902 |
; If ($did == "") { $did = "s"; } |
|---|
| 903 |
exten => s,n,Set(DID=${IF($["${DID}"= ""]?s:${DID})}) |
|---|
| 904 |
exten => s,n,NoOp(DID is now ${DID}) |
|---|
| 905 |
exten => s,n,GotoIf($["${CHANNEL:0:3}"="Zap"]?zapok:notzap) |
|---|
| 906 |
exten => s,n(notzap),Goto(from-pstn,${DID},1) |
|---|
| 907 |
; If there's no ext-did,s,1, that means there's not a no did/no cid route. Hangup. |
|---|
| 908 |
exten => s,n,Macro(hangup) |
|---|
| 909 |
exten => s,n(zapok),NoOp(Is a Zaptel Channel) |
|---|
| 910 |
exten => s,n,Set(CHAN=${CHANNEL:4}) |
|---|
| 911 |
exten => s,n,Set(CHAN=${CUT(CHAN,-,1)}) |
|---|
| 912 |
exten => s,n,Macro(from-zaptel-${CHAN},${DID},1) |
|---|
| 913 |
; If nothing there, then treat it as a DID |
|---|
| 914 |
exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN}) |
|---|
| 915 |
exten => s,n,Goto(from-pstn,${DID},1) |
|---|
| 916 |
exten => fax,1,Goto(ext-fax,in_fax,1) |
|---|
| 917 |
|
|---|
| 918 |
;------------------------------------------------------------------------ |
|---|
| 919 |
; [macro-setmusic] |
|---|
| 920 |
;------------------------------------------------------------------------ |
|---|
| 921 |
; CONTEXT: macro-setmusic |
|---|
| 922 |
; PURPOSE: to turn off moh on routes where it is not desired |
|---|
| 923 |
; |
|---|
| 924 |
;------------------------------------------------------------------------ |
|---|
| 925 |
[macro-setmusic] |
|---|
| 926 |
exten => s,1,NoOp(Setting Outbound Route MoH To: ${ARG1}) |
|---|
| 927 |
exten => s,2,SetMusicOnHold(${ARG1}) |
|---|
| 928 |
;------------------------------------------------------------------------ |
|---|
| 929 |
|
|---|
| 930 |
; ########################################## |
|---|
| 931 |
; ## Ring Groups with Confirmation macros ## |
|---|
| 932 |
; ########################################## |
|---|
| 933 |
; Used by followme and ringgroups |
|---|
| 934 |
|
|---|
| 935 |
;------------------------------------------------------------------------ |
|---|
| 936 |
; [macro-dial-confirm] |
|---|
| 937 |
;------------------------------------------------------------------------ |
|---|
| 938 |
; This has now been incorporated into dialparties. It still only works with ringall |
|---|
| 939 |
; and ringall-prim strategies. Have not investigated why it doesn't work with |
|---|
| 940 |
; hunt and memory hunt. |
|---|
| 941 |
; |
|---|
| 942 |
;------------------------------------------------------------------------ |
|---|
| 943 |
[macro-dial-confirm] |
|---|
| 944 |
; This was written to make it easy to use macro-dial-confirm instead of macro-dial in generated dialplans. |
|---|
| 945 |
; This takes the same paramaters, with an additional paramater of the ring group Number |
|---|
| 946 |
; ARG1 is the timeout |
|---|
| 947 |
; ARG2 is the DIAL_OPTIONS |
|---|
| 948 |
; ARG3 is a list of xtns to call - 203-222-240-123123123#-211 |
|---|
| 949 |
; ARG4 is the ring group number |
|---|
| 950 |
|
|---|
| 951 |
; This sets a unique value to indicate that the channel is ringing. This is used for warning slow |
|---|
| 952 |
; users that the call has already been picked up. |
|---|
| 953 |
; |
|---|
| 954 |
exten => s,1,Set(DB(RG/${ARG4}/${CHANNEL})=RINGING) |
|---|
| 955 |
|
|---|
| 956 |
; We need to keep that channel variable, because it'll change when we do this dial, so set it to |
|---|
| 957 |
; fallthrough to every sibling. |
|---|
| 958 |
; |
|---|
| 959 |
exten => s,n,Set(__UNIQCHAN=${CHANNEL}) |
|---|
| 960 |
|
|---|
| 961 |
; The calling ringgroup should have set RingGroupMethod appropriately. We need to set two |
|---|
| 962 |
; additional parameters: |
|---|
| 963 |
; |
|---|
| 964 |
; USE_CONFIRMATION, RINGGROUP_INDEX |
|---|
| 965 |
; |
|---|
| 966 |
; Thse are passed to inform dialparties to place external calls through the [grps] context |
|---|
| 967 |
; |
|---|
| 968 |
exten => s,n,Set(USE_CONFIRMATION=TRUE) |
|---|
| 969 |
exten => s,n,Set(RINGGROUP_INDEX=${ARG4}) |
|---|
| 970 |
exten => s,n,Set(ARG4=) ; otherwise it gets passed to dialparties.agi which processes it (prob bug) |
|---|
| 971 |
|
|---|
| 972 |
exten => s,n,Macro(dial,${ARG1},${ARG2},${ARG3}) |
|---|
| 973 |
|
|---|
| 974 |
; delete the variable, if we are here, we are done trying to dial and it may have been left around |
|---|
| 975 |
; |
|---|
| 976 |
exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL}) |
|---|
| 977 |
exten => s,n,Set(USE_CONFIRMATION=) |
|---|
| 978 |
exten => s,n,Set(RINGGROUP_INDEX=) |
|---|
| 979 |
;------------------------------------------------------------------------ |
|---|
| 980 |
|
|---|
| 981 |
;------------------------------------------------------------------------ |
|---|
| 982 |
; [macro-auto-confirm] |
|---|
| 983 |
;------------------------------------------------------------------------ |
|---|
| 984 |
; This macro is called from ext-local-confirm to auto-confirm a call so that other extensions |
|---|
| 985 |
; are aware that the call has been answered. |
|---|
| 986 |
; |
|---|
| 987 |
;------------------------------------------------------------------------ |
|---|
| 988 |
[macro-auto-confirm] |
|---|
| 989 |
exten => s,1,Set(__MACRO_RESULT=) |
|---|
| 990 |
exten => s,n,Set(__CWIGNORE=) |
|---|
| 991 |
exten => s,n,DBDel(${BLKVM_OVERRIDE}) |
|---|
| 992 |
exten => s,n,DBDel(RG/${ARG1}/${UNIQCHAN}) |
|---|
| 993 |
|
|---|
| 994 |
;------------------------------------------------------------------------ |
|---|
| 995 |
; [macro-auto-blkvm] |
|---|
| 996 |
;------------------------------------------------------------------------ |
|---|
| 997 |
; This macro is called for any extension dialed form a queue, ringgroup |
|---|
| 998 |
; or followme, so that the answering extension can clear the voicemail block |
|---|
| 999 |
; override allow subsequent transfers to properly operate. |
|---|
| 1000 |
; |
|---|
| 1001 |
;------------------------------------------------------------------------ |
|---|
| 1002 |
[macro-auto-blkvm] |
|---|
| 1003 |
exten => s,1,Set(__MACRO_RESULT=) |
|---|
| 1004 |
exten => s,n,Set(__CWIGNORE=) |
|---|
| 1005 |
exten => s,n,DBDel(${BLKVM_OVERRIDE}) |
|---|
| 1006 |
|
|---|
| 1007 |
;------------------------------------------------------------------------ |
|---|
| 1008 |
; [ext-local-confirm] |
|---|
| 1009 |
;------------------------------------------------------------------------ |
|---|
| 1010 |
; If call confirm is being used in a ringgroup, then calls that do not require confirmation are sent |
|---|
| 1011 |
; to this extension instead of straight to the device. |
|---|
| 1012 |
; |
|---|
| 1013 |
; The sole purpose of sending them here is to make sure we run Macro(auto-confirm) if this |
|---|
| 1014 |
; extension answers the line. This takes care of clearing the database key that is used to inform |
|---|
| 1015 |
; other potential late comers that the extension has been answered by someone else. |
|---|
| 1016 |
; |
|---|
| 1017 |
; ALERT_INFO is deprecated in Asterisk 1.4 but still used throughout the FreePBX dialplan and |
|---|
| 1018 |
; usually set by dialparties.agi. This allows ineritance. Since no dialparties.agi here, set the |
|---|
| 1019 |
; header if it is set. |
|---|
| 1020 |
; |
|---|
| 1021 |
;------------------------------------------------------------------------ |
|---|
| 1022 |
[ext-local-confirm] |
|---|
| 1023 |
exten => _LC-.,1,Noop(IN ext-local-confirm with - RT: ${RT}, RG_IDX: ${RG_IDX}) |
|---|
| 1024 |
exten => _LC-.,n,GotoIf($["x${ALERT_INFO}"="x"]?godial) |
|---|
| 1025 |
exten => _LC-.,n,SIPAddHeader(Alert-Info: ${ALERT_INFO}) |
|---|
| 1026 |
exten => _LC-.,n(godial),dial(${DB(DEVICE/${EXTEN:3}/dial)},${RT},M(auto-confirm^${RG_IDX})${DIAL_OPTIONS}) |
|---|
| 1027 |
|
|---|
| 1028 |
;------------------------------------------------------------------------ |
|---|
| 1029 |
; [macro-confirm] |
|---|
| 1030 |
;------------------------------------------------------------------------ |
|---|
| 1031 |
; CONTEXT: macro-confirm |
|---|
| 1032 |
; PURPOSE: added default message if none supplied |
|---|
| 1033 |
; |
|---|
| 1034 |
; Follom-Me and Ringgroups provide an option to supply a message to be |
|---|
| 1035 |
; played as part of the confirmation. These changes have added a default |
|---|
| 1036 |
; message if none is supplied. |
|---|
| 1037 |
; |
|---|
| 1038 |
;------------------------------------------------------------------------ |
|---|
| 1039 |
[macro-confirm] |
|---|
| 1040 |
exten => s,1,Set(LOOPCOUNT=0) |
|---|
| 1041 |
exten => s,n,Noop(CALLCONFIRMCID: ${CALLCONFIRMCID}) |
|---|
| 1042 |
|
|---|
| 1043 |
; We set ABORT rather than CONTINUE, as we want the server to forget about this channel |
|---|
| 1044 |
; if it's declined, hung up, or timed out. We don't want it to continue on to the next |
|---|
| 1045 |
; step in the dialplan, which could be anything! |
|---|
| 1046 |
exten => s,n,Set(__MACRO_RESULT=ABORT) |
|---|
| 1047 |
|
|---|
| 1048 |
; ARG1 is the announcement to play to tell the user that they've got a call they need |
|---|
| 1049 |
; to confirm. Something along the lines of 'You have an incoming call. Press 1 to accept, 9 to reject' |
|---|
| 1050 |
exten => s,n,Set(MSG1=${IF($["foo${ARG1}" != "foo"]?${ARG1}:"incoming-call-1-accept-2-decline")}) |
|---|
| 1051 |
exten => s,n(start),Read(INPUT,${MSG1},1,,1,5) |
|---|
| 1052 |
|
|---|
| 1053 |
; So. We've now read something, or nothing. We should check to make sure that the call hasn't |
|---|
| 1054 |
; already been answered by someone else. If it has, send this call to toolate |
|---|
| 1055 |
exten => s,n,GotoIf(${DB_EXISTS(RG/${ARG3}/${UNIQCHAN})}?check:toolate) |
|---|
| 1056 |
|
|---|
| 1057 |
; We passed that test, so it means the call hasn't been answered. Has this user pushed 1? If so, |
|---|
| 1058 |
; then go to OK. |
|---|
| 1059 |
exten => s,n(check),GotoIf($["${INPUT}"="1"]?ok) |
|---|
| 1060 |
|
|---|
| 1061 |
; If they've pushed 9, then they definately don't want the call. Just pretend there was no response |
|---|
| 1062 |
; and go to noanswer (or 2 since that will be default for asterisk) |
|---|
| 1063 |
exten => s,n,GotoIf($["${INPUT}"="9"]?noanswer) |
|---|
| 1064 |
exten => s,n,GotoIf($["${INPUT}"="2"]?noanswer) |
|---|
| 1065 |
exten => s,n,GotoIf($["${INPUT}"="3"]?playcid) |
|---|
| 1066 |
|
|---|
| 1067 |
; Increment LOOPCOUNT, and check to make sure we haven't played it 5 times by now. We assume that |
|---|
| 1068 |
; the person is able to push '1' in a reasonably short time. |
|---|
| 1069 |
exten => s,n,Set(LOOPCOUNT=$[ ${LOOPCOUNT} + 1 ]) |
|---|
| 1070 |
exten => s,n,GotoIf($[ ${LOOPCOUNT} < 5 ]?start) |
|---|
| 1071 |
|
|---|
| 1072 |
; If we're here, that means we've played it MORE than 5 times. Set __MACRO_RESULT=ABORT, well, just |
|---|
| 1073 |
; coz, and goto fin, which is the last line, meaning it returns to the previous Dial, and pretends as |
|---|
| 1074 |
; if nothing has happened. |
|---|
| 1075 |
exten => s,n(noanswer),Set(__MACRO_RESULT=ABORT) |
|---|
| 1076 |
exten => s,n,Goto(fin) |
|---|
| 1077 |
|
|---|
| 1078 |
; Test play callerid |
|---|
| 1079 |
; |
|---|
| 1080 |
exten => s,n(playcid),Noop(Playing CID: ${CALLCONFIRMCID}) |
|---|
| 1081 |
exten => s,n,SayDigits(${CALLCONFIRMCID}) |
|---|
| 1082 |
exten => s,n,Goto(start) |
|---|
| 1083 |
|
|---|
| 1084 |
; If we're here, it's because the call was already accepted by someone else. |
|---|
| 1085 |
exten => s,n(toolate),Set(MSG2=${IF($["foo${ARG2}" != "foo"]?${ARG2}:"incoming-call-no-longer-avail")}) |
|---|
| 1086 |
exten => s,n,Playback(${MSG2}) |
|---|
| 1087 |
exten => s,n,Goto(noanswer) |
|---|
| 1088 |
|
|---|
| 1089 |
; If we made it here, it's because the call _WAS_ accepted, AND it's still ringing. We delete the |
|---|
| 1090 |
; database entry (so that the DB_EXISTS line above will trigger a 'toolate' jump), and set the |
|---|
| 1091 |
; MACRO_RESULT variable to NOTHING. This is the magic string that joins both legs of the call together |
|---|
| 1092 |
exten => s,n(ok),DBDel(RG/${ARG3}/${UNIQCHAN}) |
|---|
| 1093 |
exten => s,n,DBDel(${BLKVM_OVERRIDE}) |
|---|
| 1094 |
exten => s,n,Set(__MACRO_RESULT=) |
|---|
| 1095 |
|
|---|
| 1096 |
; The end. |
|---|
| 1097 |
exten => s,n(fin),NoOp(Finished) |
|---|
| 1098 |
exten => h,1,Noop(Hangup Extension in macro-confirm) |
|---|
| 1099 |
exten => h,n,Macro(hangupcall) |
|---|
| 1100 |
|
|---|
| 1101 |
;------------------------------------------------------------------------ |
|---|
| 1102 |
|
|---|
| 1103 |
;------------------------------------------------------------------------ |
|---|
| 1104 |
; [findmefollow-ringallv2] |
|---|
| 1105 |
;------------------------------------------------------------------------ |
|---|
| 1106 |
; This context, to be included in from-internal, implements the PreRing part of findmefollow |
|---|
| 1107 |
; as well as the GroupRing part. It also communicates between the two so that if DND is set |
|---|
| 1108 |
; on the primary extension, and mastermode is enabled, then the other extensions will not ring |
|---|
| 1109 |
; |
|---|
| 1110 |
;------------------------------------------------------------------------ |
|---|
| 1111 |
[findmefollow-ringallv2] |
|---|
| 1112 |
exten => _FMPR-.,1,Noop(In FMPR ${FMGRP} with ${EXTEN:5}) |
|---|
| 1113 |
exten => _FMPR-.,n,Set(RingGroupMethod=) |
|---|
| 1114 |
exten => _FMPR-.,n,Set(USE_CONFIRMATION=) |
|---|
| 1115 |
exten => _FMPR-.,n,Set(RINGGROUP_INDEX=) |
|---|
| 1116 |
exten => _FMPR-.,n,Macro(simple-dial,${EXTEN:5},${FMREALPRERING}) |
|---|
| 1117 |
exten => _FMPR-.,n,GotoIf($["${DIALSTATUS}" != "BUSY"]?nodnd) |
|---|
| 1118 |
exten => _FMPR-.,n,Set(DB(FM/DND/${FMGRP}/${FMUNIQUE})=DND) |
|---|
| 1119 |
exten => _FMPR-.,n(nodnd),Noop(Ending FMPR ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS}) |
|---|
| 1120 |
exten => _FMPR-.,n,Hangup() |
|---|
| 1121 |
|
|---|
| 1122 |
exten => _FMGL-.,1,Noop(In FMGL ${FMGRP} with ${EXTEN:5}) |
|---|
| 1123 |
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) |
|---|
| 1124 |
exten => _FMGL-.,n,Wait(1) |
|---|
| 1125 |
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) |
|---|
| 1126 |
exten => _FMGL-.,n,Wait(1) |
|---|
| 1127 |
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) |
|---|
| 1128 |
exten => _FMGL-.,n,Wait(${FMPRERING}) |
|---|
| 1129 |
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd) |
|---|
| 1130 |
exten => _FMGL-.,n,DBDel(FM/DND/${FMGRP}/${FMUNIQUE}) |
|---|
| 1131 |
exten => _FMGL-.,n(dodial),Macro(dial,${FMGRPTIME},${DIAL_OPTIONS},${EXTEN:5}) |
|---|
| 1132 |
exten => _FMGL-.,n,Noop(Ending FMGL ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS}) |
|---|
| 1133 |
exten => _FMGL-.,n,Hangup() |
|---|
| 1134 |
exten => _FMGL-.,n+10(dodnd),DBDel(FM/DND/${FMGRP}/${FMUNIQUE}) |
|---|
| 1135 |
exten => _FMGL-.,n,GotoIf($["${FMPRIME}" = "FALSE"]?dodial) |
|---|
| 1136 |
exten => _FMGL-.,n,Noop(Got DND in FMGL ${FMGRP} with ${EXTEN:5} in ${RingGroupMethod} mode, aborting) |
|---|
| 1137 |
exten => _FMGL-.,n,Hangup() |
|---|
| 1138 |
|
|---|
| 1139 |
;------------------------------------------------------------------------ |
|---|
| 1140 |
|
|---|
| 1141 |
; ############################################################################ |
|---|
| 1142 |
; Extension Contexts [ext] |
|---|
| 1143 |
; ############################################################################ |
|---|
| 1144 |
|
|---|
| 1145 |
[ext-fax] |
|---|
| 1146 |
exten => s,1,Answer |
|---|
| 1147 |
exten => s,2,Goto(in_fax,1) |
|---|
| 1148 |
exten => in_fax,1,StopPlayTones |
|---|
| 1149 |
exten => in_fax,2,GotoIf($["${FAX_RX}" = "system"]?3:analog_fax,1) |
|---|
| 1150 |
exten => in_fax,3,Macro(faxreceive) |
|---|
| 1151 |
exten => in_fax,4,Hangup |
|---|
| 1152 |
exten => analog_fax,1,GotoIf($["${FAX_RX}" = "disabled"]?4:2) ;if fax is disabled, just hang up |
|---|
| 1153 |
exten => analog_fax,2,Set(DIAL=${DB(DEVICE/${FAX_RX}/dial)}); |
|---|
| 1154 |
exten => analog_fax,3,Dial(${DIAL},20,d) |
|---|
| 1155 |
exten => analog_fax,4,Hangup |
|---|
| 1156 |
;exten => out_fax,1,wait(7) |
|---|
| 1157 |
exten => out_fax,1,txfax(${TXFAX_NAME},caller) |
|---|
| 1158 |
exten => out_fax,2,Hangup |
|---|
| 1159 |
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}); |
|---|
| 1160 |
exten => h,2,Hangup() |
|---|
| 1161 |
|
|---|
| 1162 |
;this is where parked calls go if they time-out. Should probably re-ring |
|---|
| 1163 |
[default] |
|---|
| 1164 |
include => ext-local |
|---|
| 1165 |
exten => s,1,Playback(vm-goodbye) |
|---|
| 1166 |
exten => s,2,Macro(hangupcall) |
|---|