VM Tweak for FreePBX Users
Thursday, August 6, 2009 at 12:35PM This a quick customization to have callers hear VM instructions when voicemail is set to no-msg. Suppose you just want Allison to quickly give instructions to leave a voicemail when you can't get to a call. No extension announcement (which can confuse callers dialing into extensions tied to incoming DID's, or in residential environments), and no abrupt beep for callers to immediately deal with leaving a message. Just a nice and easy "please leave a message after the tone..." transition into voicemail. Well, setting the voicemail setting to no-msg in the ring group or extension in FreePBX, and a couple minutes under the hood is all you need.
This tweak requires the removal of a single character in line 2212 of the extensions_additional.conf file (asterisk 1.4.x):
from this:
exten => s-NOMESSAGE,n,Voicemail(${ARG1}@${VMCONTEXT},s${VM_OPTS}${VMGAIN})
to this:
exten => s-NOMESSAGE,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VMGAIN})
In case you don't spot the difference, the 's' switch in front of VM_OPTS in the NOMESSAGE context. That's the character that must be removed to have Allison do her thing before the beep. Otherwise, callers will get just the 'beep' with no instructions. But hold it, you can't modify this file, it simply won't work. FreePBX takes control over the extensions_additional.conf file and other critical files. Simply changing and saving will not work as it will be overwritten at the next reload. Instead, the entire module that this line is contained in (macro-vm in this case) must be copied and placed in the extensions_override_freepbx.conf file. The 's' can then be removed, the file saved, and asterisk reloaded.
Below is what I currently have in the extensions_additional.conf for my installation- Asterisk 1.4.21.2 w/ FreePBX 2.5.1.5 installed with PIAF 1.4. This stuffs a moving target, so check your installation examine the [macro-vm] code for any differences before copying to the extensions_override_freepbx.conf file.
Access to copy to the extensions_override_freepbx.conf file can be done using the FreePBX web gui under Tools->Config Edit. Open the extensions_override_freepbx.conf file and copy the code below into the file. Save, and apply changes. Again, have a look at your [macro-vm] module before pasting.
[macro-vm]
include => macro-vm-custom
exten => s,1,Macro(user-callerid,SKIPTTL)
exten => s,n,Set(VMGAIN=${IF($["foo${VM_GAIN}"!="foo"]?"g(${VM_GAIN})":"")})
exten => s,n,GotoIf($["foo${DB(${BLKVM_OVERRIDE})}" != "fooTRUE"]?vmx,1)
exten => s,n,Noop(CAME FROM: ${NODEST} - Blocking VM cause of key: ${DB(BLKVM_OVERRIDE)})
exten => s,n,Hangup
exten => vmx,1,GotoIf($["${ARG2}"="NOMESSAGE"]?s-${ARG2},1)
exten => vmx,n,Set(MODE=${IF($["${ARG2}"="BUSY"]?busy:unavail)})
exten => vmx,n,GotoIf($["${ARG2}" != "DIRECTDIAL"]?notdirect)
exten => vmx,n,Set(MODE=${IF($["${REGEX("[b]" ${VM_DDTYPE})}" = "1"]?busy:${MODE})})
exten => vmx,n(notdirect),Noop(Checking if ext ${ARG1} is enabled: ${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)})
exten => vmx,n,GotoIf($["${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}" != "enabled"]?s-${ARG2},1)
exten => vmx,n,Macro(get-vmcontext,${ARG1})
exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/temp)
exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" = "SUCCESS"]?tmpgreet)
exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE})
exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" != "SUCCESS"]?nofile)
exten => vmx,n,Set(LOOPCOUNT=0)
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/repeat)}" = "0"]?vmxtime)
exten => vmx,n,Set(VMX_REPEAT=${DB_RESULT})
exten => vmx,n(vmxtime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timeout)}" = "0"]?vmxloops)
exten => vmx,n,Set(VMX_TIMEOUT=${DB_RESULT})
exten => vmx,n(vmxloops),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loops)}" = "0"]?vmxanswer)
exten => vmx,n,Set(VMX_LOOPS=${DB_RESULT})
exten => vmx,n(vmxanswer),Answer
exten => vmx,n(loopstart),Read(ACTION,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE},1,skip,${VMX_REPEAT},${VMX_TIMEOUT})
exten => vmx,n,GotoIf($["${EXISTS(${ACTION})}" = "1"]?checkopt)
exten => vmx,n(noopt),Noop(Timeout: going to timeout dest)
exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_TIMEOUT})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/timeout)}" = "0"]?chktime)
exten => vmx,n,Set(VMX_OPTS=${DB_RESULT})
exten => vmx,n(chktime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/ext)}" = "0"]?dotime)
exten => vmx,n,Set(VMX_TIMEDEST_EXT=${DB_RESULT})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/context)}" = "0"]?timepri)
exten => vmx,n,Set(VMX_TIMEDEST_CONTEXT=${DB_RESULT})
exten => vmx,n(timepri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/pri)}" = "0"]?dotime)
exten => vmx,n,Set(VMX_TIMEDEST_PRI=${DB_RESULT})
exten => vmx,n(dotime),Goto(${VMX_TIMEDEST_CONTEXT},${VMX_TIMEDEST_EXT},${VMX_TIMEDEST_PRI})
exten => vmx,n(checkopt),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/ext)}" = "1"]?doopt)
exten => vmx,n,GotoIf($["${ACTION}" = "0"]?o,1)
exten => vmx,n,GotoIf($["${ACTION}" = "*"]?adef,1)
exten => vmx,n,Set(LOOPCOUNT=$[${LOOPCOUNT} + 1])
exten => vmx,n,GotoIf($[${LOOPCOUNT} > ${VMX_LOOPS}]?toomany)
exten => vmx,n,Playback(pm-invalid-option&please-try-again)
exten => vmx,n,Goto(loopstart)
exten => vmx,n(toomany),Noop(Too Many invalid entries, got to invalid dest)
exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_LOOPS})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/loops)}" = "0"]?chkloop)
exten => vmx,n,Set(VMX_OPTS=${DB_RESULT})
exten => vmx,n(chkloop),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/ext)}" = "0"]?doloop)
exten => vmx,n,Set(VMX_LOOPDEST_EXT=${DB_RESULT})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/context)}" = "0"]?looppri)
exten => vmx,n,Set(VMX_LOOPDEST_CONTEXT=${DB_RESULT})
exten => vmx,n(looppri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/pri)}" = "0"]?doloop)
exten => vmx,n,Set(VMX_LOOPDEST_PRI=${DB_RESULT})
exten => vmx,n(doloop),Goto(${VMX_LOOPDEST_CONTEXT},${VMX_LOOPDEST_EXT},${VMX_LOOPDEST_PRI})
exten => vmx,n(doopt),Noop(Got a valid option: ${DB_RESULT})
exten => vmx,n,Set(VMX_EXT=${DB_RESULT})
exten => vmx,n,GotoIf($["${VMX_EXT}" != "dovm"]?getdest)
exten => vmx,n(vmxopts),Set(VMX_OPTS=${VMX_OPTS_DOVM})
exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/dovm)}" = "0"]?vmxdovm)
exten => vmx,n(vmxopts),Set(VMX_OPTS=${DB_RESULT})
exten => vmx,n(vmxdovm),Goto(dovm,1)
exten => vmx,n(getdest),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/context)}" = "0"]?vmxpri)
exten => vmx,n,Set(VMX_CONTEXT=${DB_RESULT})
exten => vmx,n(vmxpri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/pri)}" = "0"]?vmxgoto)
exten => vmx,n,Set(VMX_PRI=${DB_RESULT})
exten => vmx,n(vmxgoto),Goto(${VMX_CONTEXT},${VMX_EXT},${VMX_PRI})
exten => vmx,n(nofile),Noop(File for mode: ${MODE} does not exist, SYSTEMSTATUS: ${SYSTEMSTATUS}, going to normal voicemail)
exten => vmx,n,Goto(s-${ARG2},1)
exten => vmx,n(tmpgreet),Noop(Temporary Greeting Detected, going to normal voicemail)
exten => vmx,n,Goto(s-${ARG2},1)
exten => dovm,1,Noop(VMX Timeout - go to voicemail)
exten => dovm,n,VoiceMail(${ARG1}@${VMCONTEXT},${VMX_OPTS}${VMGAIN})
exten => dovm,n,Goto(exit-${VMSTATUS},1)
exten => s-BUSY,1,Noop(BUSY voicemail)
exten => s-BUSY,n,Macro(get-vmcontext,${ARG1})
exten => s-BUSY,n,VoiceMail(${ARG1}@${VMCONTEXT},${VM_OPTS}b${VMGAIN})
exten => s-BUSY,n,Goto(exit-${VMSTATUS},1)
exten => s-NOMESSAGE,1,Noop(NOMESSAGE (beeb only) voicemail)
exten => s-NOMESSAGE,n,Macro(get-vmcontext,${ARG1})
exten => s-NOMESSAGE,n,VoiceMail(${ARG1}@${VMCONTEXT},s${VM_OPTS}${VMGAIN})
exten => s-NOMESSAGE,n,Goto(exit-${VMSTATUS},1)
exten => s-DIRECTDIAL,1,Noop(DIRECTDIAL voicemail)
exten => s-DIRECTDIAL,n,Macro(get-vmcontext,${ARG1})
exten => s-DIRECTDIAL,n,VoiceMail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VM_DDTYPE}${VMGAIN})
exten => s-DIRECTDIAL,n,Goto(exit-${VMSTATUS},1)
exten => _s-.,1,Macro(get-vmcontext,${ARG1})
exten => _s-.,n,VoiceMail(${ARG1}@${VMCONTEXT},${VM_OPTS}u${VMGAIN})
exten => _s-.,n,Goto(exit-${VMSTATUS},1)
exten => o,1,Background(one-moment-please)
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/ext)}" = "0"]?doopdef)
exten => o,n,Set(VMX_OPDEST_EXT=${DB_RESULT})
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/context)}" = "1"]?opcontext)
exten => o,n,Set(DB_RESULT=${VMX_CONTEXT})
exten => o,n(opcontext),Set(VMX_OPDEST_CONTEXT=${DB_RESULT})
exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/pri)}" = "1"]?oppri)
exten => o,n,Set(DB_RESULT=${VMX_PRI})
exten => o,n(oppri),Set(VMX_OPDEST_PRI=${DB_RESULT})
exten => o,n,Goto(${VMX_OPDEST_CONTEXT},${VMX_OPDEST_EXT},${VMX_OPDEST_PRI})
exten => o,n(doopdef),GotoIf($["x${OPERATOR_XTN}"="x"]?nooper:from-internal,${OPERATOR_XTN},1)
exten => o,n(nooper),GotoIf($["x${FROM_DID}"="x"]?nodid)
exten => o,n,Dial(Local/${FROM_DID}@from-pstn,)
exten => o,n,Macro(hangup,)
exten => o,n(nodid),Dial(Local/s@from-pstn,)
exten => o,n,Macro(hangup,)
exten => a,1,Macro(get-vmcontext,${ARG1})
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/ext)}" = "0"]?adef,1)
exten => a,n,Set(VMX_ADEST_EXT=${DB_RESULT})
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/context)}" = "1"]?acontext)
exten => a,n,Set(DB_RESULT=${VMX_CONTEXT})
exten => a,n(acontext),Set(VMX_ADEST_CONTEXT=${DB_RESULT})
exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/pri)}" = "1"]?apri)
exten => a,n,Set(DB_RESULT=${VMX_PRI})
exten => a,n(apri),Set(VMX_ADEST_PRI=${DB_RESULT})
exten => a,n,Goto(${VMX_ADEST_CONTEXT},${VMX_ADEST_EXT},${VMX_ADEST_PRI})
exten => adef,1,VoiceMailMain(${ARG1}@${VMCONTEXT})
exten => adef,n,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1)
exten => adef,n,Hangup
exten => exit-FAILED,1,Playback(im-sorry&an-error-has-occured)
exten => exit-FAILED,n,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1)
exten => exit-FAILED,n,Hangup
exten => exit-SUCCESS,1,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1)
exten => exit-SUCCESS,n,Playback(goodbye)
exten => exit-SUCCESS,n,Hangup
exten => exit-USEREXIT,1,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1)
exten => exit-USEREXIT,n,Playback(goodbye)
exten => exit-USEREXIT,n,Hangup
exten => exit-RETURN,1,Noop(Returning From Voicemail because macro)
exten => t,1,Hangup
; end of [macro-vm]
Reload asterisk and that's it!
