All pastes #731325 Raw Edit

Stuff

public text v1 · immutable
·published 2007-10-09 23:13 UTC
rendered paste body
[general]
static=yes
writeprotect=no
clearglobalvars=no
[globals]
VM_HOME=/var/spool/asterisk/voicemail		; root directory of the voicemail application
RELOAD_VM_CONFIGURATION=0			; causes the voicemail.conf file to be re-read back into the AstDB
						; enable from the CLI with: 'core set global RELOAD_VM_CONFIGURATION 1' (without the quotes)
;FUNCTION_TEST=${SHELL(echo "foo_bar")}		; currently causes a segfault of Asterisk

[phones]
; Testing Area!

; SAMPLE: Creation of new voicemail envelope
exten => 5,1,Answer()
exten => 5,n,GoSub(setup_mailbox,s,1(default,100,INBOX))
exten => 5,n,GoSub(get_msg_count,s,1())
exten => 5,n,Set(MSG_COUNT=${GOSUB_RETVAL})
exten => 5,n,GoSub(set_msg_number,s,1(${MSG_COUNT}))
exten => 5,n,Set(MSGNUM=${GOSUB_RETVAL})
exten => 5,n,System(touch ${PWD}/msg${MSGNUM}.txt)


; VoiceMail(mailbox[@context][&mailbox[@context]][...][|options])
exten => 100,1,GoSub(voicemail,s,1())
exten => 101,1,Voicemail()

exten => 200,1,GoSub(voicemail,s,1(100&1234))
exten => 201,1,Voicemail(100&1234)

exten => 300,1,GoSub(voicemail,s,1(100,u))
exten => 301,1,Voicemail(100,u)

exten => 400,1,GoSub(voicemail,s,1(100,su))
exten => 401,1,Voicemail(100,us)

; Invalid voicemail
exten => 500,1,GoSub(voicemail,s,1(101,u))
exten => 500,n,DumpChan()
exten => 501,1,Voicemail(101,u)
exten => 501,n,DumpChan()

; VoiceMailMain([mailbox][@context][|options])
exten => 1100,1,GoSub(voicemailmain,s,1())
exten => 1101,1,VoicemailMain()

exten => 1200,1,GoSub(voicemailmain,s,(100))
exten => 1201,1,VoicemailMain(100)

exten => 1,1,GoSub(read_voicemail_conf,s,1())

exten => 2,1,Set(LINE_NUMBER=2)
exten => 2,n,NoOp(${SHELL(sed -e '/\\\;/d' /etc/asterisk/voicemail.conf \| grep '.' \| tr "\\\n"\, "&" \| cut -d \\\& -f ${LINE_NUMBER})})
exten => 2,n,NoOp(${COMMAND})

exten => 3,1,Set(information=foo_bar)
exten => 3,n,Set(RES=${SET(information2=foo_bar)})
exten => 3,n,DumpChan()
exten => 3,n,Answer()

exten => 4,1,NoOp()
exten => 4,n,Set(LINE_NUMBER=1)
exten => 4,n,While($[${LEN(${SHELL(sed -e '/\\\;/d' /etc/asterisk/voicemail.conf \| grep '.' \| tr "\\\n" "~" \| cut -d \\\~ -f ${LINE_NUMBER})})} > 1])
exten => 4,n,Verbose(1|${SHELL(sed -e '/\\\;/d' /etc/asterisk/voicemail.conf \| grep '.' \| tr "\\\n" "~" \| cut -d \\\~ -f ${LINE_NUMBER})})
exten => 4,n,Set(LINE_NUMBER=$[${LINE_NUMBER} + 1])

exten => 4,n,EndWhile()




[voicemail]
; Leif Madsen
;--
[Description]
  VoiceMail(mailbox[@context][&mailbox[@context]][...][|options]): This
application allows the calling party to leave a message for the specified
list of mailboxes. When multiple mailboxes are specified, the greeting will
be taken from the first mailbox specified. Dialplan execution will stop if the
specified mailbox does not exist.
  The Voicemail application will exit if any of the following DTMF digits are
received:
    0 - Jump to the 'o' extension in the current dialplan context.
    * - Jump to the 'a' extension in the current dialplan context.
  This application will set the following channel variable upon completion:
    VMSTATUS - This indicates the status of the execution of the VoiceMail
               application. The possible values are:
               SUCCESS | USEREXIT | FAILED

  Options:
    b    - Play the 'busy' greeting to the calling party.
    g(#) - Use the specified amount of gain when recording the voicemail
           message. The units are whole-number decibels (dB).
    s    - Skip the playback of instructions for leaving a message to the
           calling party.
    u    - Play the 'unavailable' greeting.
    j    - Jump to priority n+101 if the mailbox is not found or some other
           error occurs.
--;

exten => s,1,NoOp()
exten => s,n,Set(REQUESTED_MAILBOXES=${ARG1})
exten => s,n,Set(OPTIONS=${ARG2})								; save the options requested for Voicemail()

; Get the value of VM_RELOAD_CONFIGURATION so we can determine if it needs to be reset
exten => s,n,Set(RESET_RELOAD_VM_CONFIGURATION=${GLOBAL(RELOAD_VM_CONFIGURATION)})
exten => s,n,GoSubIf($[${RELOAD_VM_CONFIGURATION}]?read_voicemail_conf,s,1())	; Load the voicemail.conf file into the AstDB

; Reset the Global variable VM_RELOAD_CONFIGURATION so we don't load it again next time a call comes in
exten => s,n,Exec(${IF($[${RESET_RELOAD_VM_CONFIGURATION}]?Set(GLOBAL(RELOAD_VM_CONFIGURATION)=0):NoOp())})

; Define some starter variables
exten => s,n,Set(MAX_TRIES=3) 									; default tries for when we ask the user for input

; Parse for multiple mailboxes
exten => s,n,Set(MBX=1)		; Mailbox Counter
exten => s,n,Set(HASH_POSITION=0)
exten => s,n,While($[${EXISTS(${CUT(REQUESTED_MAILBOXES,&,${MBX})})}])
exten => s,n,Set(THIS_DATA=${CUT(REQUESTED_MAILBOXES,&,${MBX})})					; the current mailbox@context we're working with
exten => s,n,Set(THIS_MAILBOX=${CUT(THIS_DATA,@,1)})
exten => s,n,Set(THIS_CONTEXT=${IF($[${EXISTS(${CUT(THIS_DATA,@,2)})}]?${CUT(THIS_DATA,@,2)}:default)})
;
; Save the requested mailboxes to an associative array
; ${HASH(MAILBOXES,--POSITION--)}
; If the mailbox exists in the local database, then we'll save it to the MAILBOXES hash
;
; --- start of data into the hash ---
exten => s,n,GotoIf($[!${DB_EXISTS(voicemail/conf/[${THIS_CONTEXT}]/${THIS_MAILBOX})}]?check_next_box)
exten => s,n,Set(HASH(MAILBOXES|${HASH_POSITION})=${THIS_MAILBOX}@${THIS_CONTEXT})
exten => s,n,Set(HASH_POSITION=$[${HASH_POSITION} + 1])
; --- end of data put into the hash ---


; Check the next box
exten => s,n(check_next_box),NoOp()
exten => s,n,Set(MBX=$[${MBX} + 1])
exten => s,n,EndWhile()


; Check if the voicemail exists in our configuration
exten => s,n,GoSubIf($[${ISNULL(${HASH(MAILBOXES|0)})}]?get_mailbox,1)	; if no mailbox passed to us, get it from the user

exten => s,n,GotoIf($[${EXISTS(${HASH(MAILBOXES|0)})}]?set_options)
exten => s,n,Verbose(1|No known mailbox passed to the [voicemail] subroutine)
exten => s,n,Set(VMSTATUS=FAILED)	; invalid voicemail box, return with status
exten => s,n,Return()

; Save status of options
exten => s,n(set_options),NoOp()			; if we have a valid mailbox, we can continue
exten => s,n,Set(b_option=${REGEX("b" ${OPTIONS})})
exten => s,n,Set(g_option=${REGEX("g" ${OPTIONS})})
exten => s,n,Set(s_option=${REGEX("s" ${OPTIONS})})
exten => s,n,Set(u_option=${REGEX("u" ${OPTIONS})})
exten => s,n,Set(j_option=${REGEX("j" ${OPTIONS})})

exten => s,n,GoSub(setup_mailbox,s,1(${HASH(MAILBOXES|0)}))	; setup the mailbox present working directory (PWD)

; Check options so we can determine which greeting to play
;
exten => s,n,GoSubIf($[${u_option} & !$[0${STAT(e,${PWD}/unavail.gsm)} = 0 & 0${STAT(e,${PWD}/unavail.wav)} = 0 & 0${STAT(e,${PWD}/unavail.WAV)} = 0]]?cust_greeting,1(unavail))
exten => s,n,GotoIf($[${EXISTS(${RECORDED_FILE})}]?goodbye)		; if a file exists, we recorded something, and we're done

exten => s,n,GoSubIf($[${b_option} & !$[0${STAT(e,${PWD}/busy.gsm)} = 0 & 0${STAT(e,${PWD}/busy.wav)} = 0 & 0${STAT(e,${PWD}/busy.WAV)} = 0]]?cust_greeting,1(busy))
exten => s,n,GotoIf($[${EXISTS(${RECORDED_FILE})}]?goodbye)		; we're done, file was recorded

exten => s,n,GoSub(std_greeting,1(${IF($[${u_option}]?unavail:${IF($[${b_option}]?busy)})}))
exten => s,n,GotoIf($[${EXISTS(${RECORDED_FILE})}]?goodbye)		; we're done, file was recorded

exten => s,n,Verbose(1|File recording: ${IF($[${EXISTED(${RECORDED_FILE})}]?SUCCESSFUL:FAILED)})

exten => s,n(goodbye),NoOp()
exten => s,n,Set(VMSTATUS=SUCCESS)
exten => s,n,Return()


exten => get_mailbox,1,NoOp()
exten => get_mailbox,n,Read(READ_IN_MAILBOX|vm-whichbox|||${MAX_TRIES})
exten => get_mailbox,n,Set(HASH(MAILBOXES|0)=${READ_IN_MAILBOX}@default)
exten => get_mailbox,n,Return()

exten => cust_greeting,1,NoOp()
exten => cust_greeting,n,Set(GREETING=${ARG1})
exten => cust_greeting,n,Playback(${PWD}/${GREETING})
exten => cust_greeting,n,Exec(${IF($[${s_option} = 0]?Playback(vm-intro):NoOp())})
exten => cust_greeting,n,GoSub(record_voicemail,s,1())
exten => cust_greeting,n,Return()

exten => std_greeting,1,NoOp()
exten => std_greeting,n,Set(GREETING=${ARG1})
exten => std_greeting,n,GotoIf($["${GREETING}" != "unavail" | "${GREETING}" != "busy"]?no_greeting)	; if no greeting requested, just play an intro file
exten => std_greeting,n,Background(vm-theperson)
exten => std_greeting,n,Set(STDGREET=0)
exten => std_greeting,n,Set(MAILBOX=${CUT(HASH(MAILBOXES|0),@,1)})
exten => std_greeting,n,While($[${STDGREET} < ${LEN(${MAILBOX})}])
exten => std_greeting,n,Background(digits/${MAILBOX:${STDGREET}:1})
exten => std_greeting,n,Set(STDGREET=$[${STDGREET} + 1])
exten => std_greeting,n,EndWhile()
exten => std_greeting,n,Background(vm-is${GREETING})
exten => std_greeting,n,Exec(${IF($[${s_option} = 0]?Background(vm-intro):NoOp())})
exten => std_greeting,n,Goto(record)	; don't play the intro file, just record

; If we don't request a greeting type, then just play the intro
exten => std_greeting,n(no_greeting),Background(vm-intro)
exten => std_greeting,n(record),GoSub(record_voicemail,s,1())
exten => std_greeting,n,Return()




[voicemailmain]
; Drop in replacement for the dialplan application VoicemailMain()
; Leif Madsen
;--
[Description]
  VoiceMailMain([mailbox][@context][|options]): This application allows the
calling party to check voicemail messages. A specific mailbox, and optional
corresponding context, may be specified. If a mailbox is not provided, the
calling party will be prompted to enter one. If a context is not specified,
the 'default' context will be used.

  Options:
    p    - Consider the mailbox parameter as a prefix to the mailbox that
           is entered by the caller.
    g(#) - Use the specified amount of gain when recording a voicemail
           message. The units are whole-number decibels (dB).
    s    - Skip checking the passcode for the mailbox.
    a(#) - Skip folder prompt and go directly to folder specified.
           Defaults to INBOX
--;

exten => s,1,NoOp()

exten => s,n,GoSub(setup_mailbox,s,1(default,100,INBOX)
exten => s,n,GoSub(get_msg_count,s,1())
exten => s,n,Set(TOTAL_MSGS=${GOSUB_RETVAL})

exten => s,n,GoSub(play_msg,s,1(0))
exten => s,n,Playback(vm-goodbye)





[read_voicemail_conf]
; Purpose: To read the voicemail.conf file into AstDB
; LIMITATION: The regex's in the SHELL() command will remove all lines that contain a comment (even if the start of the line is uncommented)
;             That means you'll have to make sure your comments are on separate lines from the options you want activated.
;
; Leif Madsen
;
exten => s,1,NoOp()
exten => s,n,DBdeltree(voicemail)	; clear out the current values and reload them
exten => s,n,Set(LINE_NUMBER=1)

; While we have data, loop through the file, pulling it in one line at a time
exten => s,n,While($[${LEN(${SHELL(sed -e '/\\\;/d' /etc/asterisk/voicemail.conf \| grep '.' \| tr "\\\n" "~" \| cut -d \\\~ -f ${LINE_NUMBER})})} > 1])

; Save the data to the VM_FILE_DATA channel variable (one line from voicemail.conf)
exten => s,n,NoOp(${SET(VM_FILE_DATA=${SHELL(sed -e '/\\\;/d' /etc/asterisk/voicemail.conf \| grep '.' \| tr "\\\n" "~" \| cut -d \\\~ -f ${LINE_NUMBER})})})

; If the line starts with an alphanumeric string (not a square brace), then goto the write_data label, otherwise, save the data to the SECTION_NAME channel var
exten => s,n,Exec(${IF(${REGEX("^[a-z A-Z 0-9]" ${VM_FILE_DATA})}?Goto(write_data):Set(SECTION_NAME=${VM_FILE_DATA}))})
exten => s,n,Goto(next_iteration)		; if we hit here, then we're going to go to the next iteration of the loop
						; because we've already set the SECTION_NAME variable, which will be used
						; as part of the family keyname in AstDB

; Write the database to the AstDB
exten => s,n(write_data),NoOp()

; NOTE: We're using the SET() function because the Set() application will take commas and pipes as argument separators
;	In order to make it literally assign the whole string to the AstDB, we have to write it out with the SET() function
;	which does not have multiple arguments
;
; Split the data we're getting into 2 separate variables (left and right of the equals sign)
exten => s,n,NoOp(${SET(VARNAME=${CUT(VM_FILE_DATA,=,1)})})
exten => s,n,NoOp(${SET(VARVALUE=${CUT(VM_FILE_DATA,=,2)})})

; Save the value to the AstDB because once we parse it again, Asterisk likes to forget the values for some reason...
exten => s,n,NoOp(${SET(DB(voicemail/conf/${SECTION_NAME}/${VARNAME})=${VARVALUE})})

; If the start of the VARVALUE variable contains a >, then we want to strip it out in the next priority. Otherwise, go to the next loop iteration
exten => s,n,Exec(${IF($[${EXISTS(${CUT(VARVALUE,>,2)})}]?NoOp():Goto(next_iteration))})

; If we make it here, then we've gotta strip the > from the beginning of the line and assign the remainder to the AstDB
exten => s,n,NoOp(${SET(DB(voicemail/conf/${SECTION_NAME}/${VARNAME})=${CUT(VARVALUE,>,2)})})

exten => s,n(next_iteration),Set(LINE_NUMBER=$[${LINE_NUMBER} + 1])
exten => s,n,EndWhile()
exten => s,n,Return()




[get_msg_count]
; get_msg_count: Get the number of messages in the current folder
; Leif Madsen
; 
exten => s,1,Verbose(1|Getting number of messages in the mailbox)
exten => s,n,Set(MSG_COUNT=0000)
exten => s,n,Verbose(2|DEBUG: $[${STAT(e,${PWD}/msg${MSG_COUNT}.txt)}])
exten => s,n,Verbose(2|DEBUG: ${PWD})
exten => s,n,While($[${STAT(e,${PWD}/msg${MSG_COUNT}.txt)}])
exten => s,n,Verbose(1|Current message count: ${MSG_COUNT})
exten => s,n,Set(MSG_COUNT=$[${MSG_COUNT} + 1])
exten => s,n,GoSub(set_msg_number,s,1(${MSG_COUNT}))
exten => s,n,Set(MSG_COUNT=${GOSUB_RETVAL})
exten => s,n,EndWhile()
exten => s,n,Return(${MSG_COUNT})




[set_msg_number]
; set_msg_number: Pad numbers with a LEN < 4 with zeros
; Leif Madsen
;
exten => s,1,NoOp()
exten => s,n,Set(MSGNUM=${IF($[${LEN(${ARG1})} = 1]?000:${IF($[${LEN(${ARG1})} = 2]?00:${IF($[${LEN(${ARG1})} = 3]?0)})})}${ARG1})
exten => s,n,Return(${MSGNUM})





[setup_mailbox]
; setup_mailbox: Setup the path to a folder in a mailbox to work in
; Leif Madsen
;
; ARG1: mailbox@context
; ARG2: mailbox sub-folder (optional)
;
exten => s,1,NoOp()
exten => s,n,Set(VM_CONTEXT=${CUT(ARG1,@,2)})
exten => s,n,Set(MAILBOX=${CUT(ARG1,@,1)})
exten => s,n,Set(FOLDER=${ARG2})
exten => s,n,Set(PWD=${VM_HOME}/${VM_CONTEXT}/${MAILBOX}${IF($[${EXISTS(${ARG2})}]?/${FOLDER})})
exten => s,n,Return()





[get_envelope]
; get_envelope: Get the contents of an envelope an assign the contents to variables
; Leif Madsen
;
; Returns and Sets: 
; 
; - origmailbox
; - context
; - macrocontext
; - exten
; - priority
; - callerchan
; - callerid
; - origdate
; - origtime
; - category
; - duration6
;
exten => s,1,NoOp()
exten => s,n,Set(LINE_NUMBER=5)
exten => s,n,While($[${LEN(${SHELL(tr "\\\n"\, "&" < ${PWD}/msg${ARG1}.txt \| cut -d \\\& -f ${LINE_NUMBER})})} > 1])
exten => s,n,Set(DATA=${SHELL(tr "\\\n"\, "&" < ${PWD}/msg${ARG1}.txt \| cut -d \\\& -f ${LINE_NUMBER})})
exten => s,n,Set(${CUT(DATA,=,1)}=${CUT(DATA,=,2)})
exten => s,n,Set(LINE_NUMBER=$[${LINE_NUMBER} + 1])
exten => s,n,EndWhile()
exten => s,n,Return()





[record_voicemail]
; record_voicemail: Record audio and save to disk (saved to INBOX)
; Leif Madsen
exten => s,1,NoOp()

; LIMITATIONS: 
;              * Can't record to multiple formats
;              * Can't save the file if the user hangs up (have to press #)
;              * Need duration of recording
;             
exten => s,n,Record(/tmp/vm-${SIPCALLID}-%d.wav)

exten => s,n,Set(REC_COUNT=0)
exten => s,n,While($[${EXISTS(${HASH(MAILBOXES|${REC_COUNT})})}])
exten => s,n,GoSub(create_envelope,s,1(${HASH(MAILBOXES|${REC_COUNT})}))			; by creating the envelope, we setup the PWD to copy the recording to
exten => s,n,System(cp ${RECORDED_FILE}.wav ${PWD}/msg${MSGNUM}.wav)
exten => s,n,Set(REC_COUNT=$[${REC_COUNT} + 1])
exten => s,n,EndWhile()
exten => s,n,Playback(auth-thankyou)
exten => s,n,Return()





[create_envelope]
; create_envelope: Create the message envelope in the filesystem
; Leif Madsen
;
; ARG1: mailbox@context
;
exten => s,1,NoOp()
exten => s,n,GoSub(setup_mailbox,s,1(${ARG1},INBOX))
exten => s,n,GoSub(get_msg_count,s,1())
exten => s,n,Set(MSG_COUNT=${GOSUB_RETVAL})
exten => s,n,GoSub(set_msg_number,s,1(${MSG_COUNT}))
exten => s,n,Set(MSGNUM=${GOSUB_RETVAL})
exten => s,n,System(touch ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "\;" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "\; Message Information file" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "\;" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "[message]" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "origmailbox=${MAILBOX}" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "context=INACCURATE" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "exten=INACCURATE" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "priority=INACCURATE" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "callerchan=INACCURATE" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "callerid=\\"${CALLERID(name)}\\" ${CALLERID(num)}" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "origdate=${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)}" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "origtime=${EPOCH}" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "category=" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,System(echo "duration=${ANSWEREDTIME}" >> ${PWD}/msg${MSGNUM}.txt)
exten => s,n,Return()