root/modules/branches/2.3/core/etc/extensions.conf

Revision 8921, 68.3 kB (checked in by p_lindheimer, 2 years ago)

fixes #4075 in previous releases use playback in place of background

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