#!/bin/sh # IVR - Interactive Voice Response Menus. ast_add_module voicemenu init_voicemenu() { ast_enable_type voicemenu ast_enable_type voiceoption } check_append_voicemenu() { local context="${1}" eval "local isadded=\"\${dialplan_add_voicemenu_${context}-0}\"" if [ "$isadded" != "1" ] ; then eval "dialplan_add_voicemenu_${context}=1" append voicemenu_contexts "$context" return 0 else return 1 fi } voicemenu_list="greeting timeoutlen timeoutsmax invalidmax includelocal localmenu" handle_voicemenu() { opt_voicemenu_context="$1" check_append_voicemenu "${opt_voicemenu_context}" option_cb() { case "$1" in greeting|timeoutlen|timeoutsmax|invalidmax|includelocal|localmenu) eval "opt_voicemenu_${opt_voicemenu_context}_$1=\"\$2\"" ;; _*) ;; *) logerror "Invalid Voicemenu option: $1" ;; esac } } voiceoption_list="digit menu dial goto" check_add_voiceoption() { [ -z "${last_vo_voicemenu}" ] && return 0 if [ -z "${last_vo_dial}" ] ; then append opt_voicemenu_${last_vo_voicemenu}_action "exten => ${last_vo_digit},1,Goto(${last_vo_goto},s,1)" "${N}" else append opt_voicemenu_${last_vo_voicemenu}_action "exten => ${last_vo_digit},1,Dial(${last_vo_dial})" "${N}" fi append opt_voicemenu_${last_vo_voicemenu}_menu "${last_vo_menu}" "&" for i in ${voiceoption_list} ; do eval "unset last_vo_$i" done } handle_voiceoption() { opt_voicemenu_context="$1" check_add voiceoption option_cb() { case "$1" in voicemenu|digit|menu|dial|goto) eval "last_vo_$1=\"\$2\"" ;; _*) ;; *) logerror "Invalid Voiceoption option in ${opt_voicemenu_context}: $1" ;; esac } } createdialplan_voicemenu(){ logdebug 0 "Creating Voicemenu dialplans" [ -z "${voicemenu_contexts}" ] && return 0 for curvm in ${voicemenu_contexts} ; do check_add_context "${curvm}" for i in ${voicemenu_list} menu action ; do eval "vmc_${i}=\"\${opt_voicemenu_${curvm}_${i}}\"" done [ -z "${vmc_timeoutlen}" ] && vmc_timeoutlen=5 [ -z "${vmc_timeoutsmax}" ] && vmc_timeoutsmax=3 [ -z "${vmc_invalidmax}" ] && vmc_invalidmax=0 # Construct a voicemenu - with as small as possible code. local nn=1 if [ ! -z "${vmc_greeting}" ] ; then append_dialplan_context $curvm "exten => s,${nn},Background(${vmc_greeting})" nn=n fi local againtimeout="(againtimeout)" if [ ${vmc_invalidmax} -gt 0 ] ; then append_dialplan_context $curvm "exten => s,${nn},Set(NUMINVALID=${vmc_invalidmax})" nn=n fi if [ ${vmc_timeoutsmax} -gt 0 ] ; then local labagaininvalid="(againinvalid)" if [ ${vmc_invalidmax} -le 0 ] ; then labagaininvalid="" fi append_dialplan_context $curvm "exten => s,${nn}${labagaininvalid},Set(NUMTIMEOUTS=${vmc_timeoutsmax})" nn=n else if [ ${vmc_invalidmax} -gt 0 ] ; then againtimeout="(againinvalid)" else againtimeout= fi fi if [ ! -z "${vmc_localmenu}" ] ; then append_dialplan_context $curvm "exten => s,${nn}${againtimeout},Background(${vmc_localmenu})" nn=n againtimeout= fi if [ ! -z "${vmc_menu}" ] ; then append_dialplan_context $curvm "exten => s,${nn}${againtimeout},Background(${vmc_menu})" againtimeout= nn=n fi append_dialplan_context $curvm "exten => s,${nn}${againtimeout},WaitExten(${vmc_timeoutlen}) exten => s,n,Goto(t,1) exten => s,n(goodbye),Playback(vm-goodbye) exten => s,n,Hangup()" if [ ${vmc_timeoutsmax} -gt 0 ] ; then append_dialplan_context $curvm "exten => t,1,Set(NUMTIMEOUTS=\$[\${NUMTIMEOUTS} - 1]) exten => t,n,Gotoif(\$[\${NUMTIMEOUTS} >= 0]?s,againtimeout:s,goodbye)" else append_dialplan_context $curvm "exten => t,1,Goto(s,goodbye)" fi append_dialplan_context ${curvm} "${vmc_action}" [ -z "${vmc_includelocal}" ] || append_dialplan_context ${curvm} "include => ${vmc_includelocal}" if [ ${vmc_invalidmax} -gt 0 ] ; then append_dialplan_context $curvm "exten => i,1,Set(NUMINVALID=\$[\${NUMINVALID} - 1]) exten => i,n,Background(invalid) exten => i,n,Gotoif(\$[\${NUMINVALID} >= 0]?s,againinvalid:s,goodbye)" else append_dialplan_context $curvm "exten => i,1,Background(invalid)${N}exten => i,n,Goto(s,goodbye)" fi done } # vim: ts=2 sw=2 noet foldmethod=indent