; ********************************************************************************* ; @Document : extension__20-baseplan.conf ; @Author : vitalpbx ; @Platform : vitalpbx ; ********************************************************************************* [sub-crm-setup] exten => s,1,NoOp(crmnada) same => n,Return() [sub-log-crm-call] exten => s,1,NoOp(crmnada) same => n,Return() [sub-set-crm-headers] exten => s,1,NoOp(crmnada) same => n,Return() [sub-setup-callrec-namex] exten => s,1,NoOp(crmnada) same => n,Return() [sub-setup-callrec-name] exten => s,1,NoOp(Setting up call recording file name for ${TENANT}) same => n,GotoIf($[$["${LEN(${REC_FILENAME})}"!="0"]&$[$["${LEN(${BLINDTRANSFER})}"="0"]|$["${PBX_APP}"="QUEUE"]]]?end) same => n,Set(RECORDING_ID=${IF($["${QUEUE_UID}"=""]?${UNIQUEID}:${QUEUE_UID})}) same => n,Set(APP_TYPE=${IF($["X${SRC_APP}X"="XX"]?NONE:${SRC_APP})}) same => n,Set(AUDIO_FILE=${STRFTIME(${EPOCH},,%H%M%S)}-${CALL_TYPE_LABEL}-${APP_TYPE}-${CALL_SOURCE}-${CALL_DESTINATION}-${RECORDING_ID}) same => n,Set(RECORDING_FORMAT=${IF($["${RECORDING_FORMAT}"="wav49"]?WAV:${RECORDING_FORMAT})}) same => n,Set(__REC_FILENAME=${ASTSPOOLDIR}/monitor/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${AUDIO_FILE}.${RECORDING_FORMAT}) same => n,GotoIf($["${DB(${TENANT}/main)}"="no"]?:end) same => n,NoOp(Append tenant to recording path) same => n,Set(__REC_FILENAME=${ASTSPOOLDIR}/monitor/${TENANT}/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${AUDIO_FILE}.${RECORDING_FORMAT}) same => n(end),Return() ;----------------------------------------- [sub-get-device-tree] exten => s,1,NoOp(Configuring Device Tree) same => n,Set(DEV_TECHNOLOGY=${CHANNEL(channeltype)}) same => n,GoSubIf($["${DEV_TECHNOLOGY}"="Local"]?s-local,1) same => n,GotoIf($["${TECH_DETERMINATED}"="no"]?return) same => n,GotoIf($["${DEV_TECHNOLOGY}"="PJSIP"]?pjsip) same => n(chk_dahdi),GotoIf($["${DEV_TECHNOLOGY}"="DAHDI"]?:digital) same => n,Set(DEV_USER=${CHANNEL(dahdi_channel)}) same => n,Goto(build_interface) same => n(pjsip),NoOp(A PJSIP) same => n,Set(DEV_USER=${IF($["X${CHANNEL(endpoint)}X"="XX"]?${CALL_SOURCE}:${CHANNEL(endpoint)})}) same => n,Goto(build_interface) same => n(digital),Set(DEV_USER=${IF($["X${CHANNEL(peername)}X"="XX"]?${CALL_SOURCE}:${CHANNEL(peername)})}) same => n(build_interface),Set(_INTERFACE=${DEV_TECHNOLOGY}/${DEV_USER}) same => n,Set(DEV_TREE=devices/${INTERFACE}) same => n(return),Return() exten => s-local,1,NoOp(Try to determianate caller technology ${CALL_SOURCE}) same => n,Set(TECH_DETERMINATED=no) same => n,Set(DEV_TECHNOLOGY=${IF($["X${CHANNEL(dahdi_channel)}X"!="XX"]?DAHDI:${DEV_TECHNOLOGY})}) same => n,Set(DEV_TECHNOLOGY=${IF($["X${DB(devices/SIP/${CALL_SOURCE}/assigned_exten)}X"!="XX"]?SIP:${DEV_TECHNOLOGY})}) same => n,Set(DEV_TECHNOLOGY=${IF($["X${DB(devices/IAX2/${CALL_SOURCE}/assigned_exten)}X"!="XX"]?IAX2:${DEV_TECHNOLOGY})}) same => n,Set(TECH_DETERMINATED=${IF($["${DEV_TECHNOLOGY}"!="Local"]?yes:${TECH_DETERMINATED})}) same => n,Return() ;LOCKPHONE CHECK VER. 1.0.0 ;------------------------------------------------------------------- [sub-lockphone-check] exten => s,1,NoOP(SUB: LOCK PHONE CHECK) same => n,GotoIf($["${CALL_TYPE}"="2"]?unlock) same => n,GotoIf($["X${CALL_SOURCE}X"="XX"]?unlock) same => n,GotoIf($["${CALL_ORIGIN}"="feature"]?unlock) same => n,GotoIf($["${EXTENSION_${CALL_SOURCE}_UNLOCKED}"="yes"]?unlock) same => n,GotoIf($["${DB(${TENANT}/extensions/${CALL_SOURCE}/lock)}" = "yes"]?:unlock) same => n,NoOP(Extension ${CALL_SOURCE} is lock) same => n,Set(password=${DB(${TENANT}/extensions/${CALL_SOURCE}/password)}) same => n,GotoIf($["${password}"=""]?unlock) same => n,Authenticate(${password}) same => n,Set(__EXTENSION_${CALL_SOURCE}_UNLOCKED=yes) same => n(unlock),Return() ;END of [sub-lockphone-check] ;------------------------------------------------------------------- ;END LOCKPHONE CHECK [sub-set-global-vars] exten => s,1,NoOp(Setting Global Vars) same => n,Set(TENANT_PATH=${ARG1}) same => n,Set(PREFIX=${IF($["${DB(${TENANT_PATH}/main)}"="no"]?${DB(${TENANT_PATH}/prefix)}:)}) same => n,Set(__PICKUPMARK=${PREFIX}${ARG2}) same => n,Set(__PARKINGLOT=${ARG3}) same => n,Set(__DYNAMIC_FEATURES=${IF($[“${CUSTOM_DYNAMIC_FEATURES}” = “”]?custom-features:custom-features#${CUSTOM_DYNAMIC_FEATURES})}) same => n,Set(ICALL=no) same => n,Return() [sub-set-call-vars] exten => s,1,NoOp(Setting Call Vars) same => n,Set(_TENANT=${ARG1}) same => n,Set(_CALL_DESTINATION=${ARG2}) same => n,Set(_COS_ID=${ARG3}) same => n,Set(_COS_NAME=${ARG4}) same => n,Set(__TRANSFER_CONTEXT=${COS_NAME}) same => n,Set(_ARS=${ARG5}) same => n,Set(CDR(tenant)=${DB(${TENANT}/name)}) same => n,Set(CDR(destination)=${CALL_DESTINATION}) same => n,Set(CDR(trunk)=${TRUNK_ID}) same => n,Set(CDR(did)=${DID_NUMBER}) same => n,Set(__CALLID=${UNIQUEID}) same => n,ExecIf($["${LEN(${INBOUND_LANGUAGE})}"!="0"]?Set(CHANNEL(language)=${INBOUND_LANGUAGE})) same => n,ExecIf($[$["${LEN(${DIVERSION_ORIGIN})}"!="0"]&$["${LEN(${INBOUND_LANGUAGE})}"="0"]]?Set(CHANNEL(language)=${DB(${TENANT}/extensions/${DIVERSION_ORIGIN}/language)})) same => n,Return() exten => s-incoming,1,NoOp(Setting Incoming Call Vars) same => n,Set(__CALLID=${UNIQUEID}) same => n,Set(__INCOMING_SOURCE=${ARG1}) same => n,Set(__INCOMING_DESTINATION=${ARG2}) same => n,Set(__INCOMING_TENANT=${ARG3}) same => n,Set(__CALL_SOURCE=${INCOMING_SOURCE}) same => n,Set(__CS=${INCOMING_SOURCE}) same => n,Set(__CALL_DESTINATION=${INCOMING_DESTINATION}) same => n,Set(__TENANT=${INCOMING_TENANT}) same => n,Set(CDR(tenant)=${DB(${TENANT}/name)}) same => n,Set(CDR(destination)=${CALL_DESTINATION}) same => n,Set(CDR(trunk)=${TRUNK_ID}) same => n,Set(CDR(did)=${DID_NUMBER}) same => n,Set(CDR(calltype)=2) same => n,GoSub(app-incoming,1) same => n,Return() exten => app-incoming,1,NoOp(Incoming Call App CDR) same => n,GotoIf($["${CALL_TYPE}"="2"]?:return) same => n,Set(CDR(source)=${INCOMING_SOURCE}) same => n,Set(CDR(tenant)=${DB(${INCOMING_TENANT}/name)}) same => n,Set(CDR(destination)=${INCOMING_DESTINATION}) same => n(return),Return() [sub-construct-cid] exten => s,1,NoOp(Building CID) same => n,Set(_CALL_SOURCE=${CALLERID(num)}) same => n,Set(_CS=${CALLERID(num)}) same => n,GotoIf($["${CID_CONSTRUCTED}"="yes"]?return) same => n,GoSub(sub-get-device-tree,s,1) same => n,GotoIf($["${DEV_TREE}"=""]?return) same => n,Set(_CALL_SOURCE=${IF($["X${DB(${DEV_TREE}/assigned_exten)}X"="XX"]?${CALL_SOURCE}:${DB(${DEV_TREE}/assigned_exten)})}) same => n,Set(_CS=${CALL_SOURCE}) same => n,ExecIf(${DB_EXISTS(${TENANT}/extensions/${CALL_SOURCE}/internal_cid)}?Set(CALLERID(all)=${DB(${TENANT}/extensions/${CALL_SOURCE}/internal_cid)})) same => n,Set(_CID_CONSTRUCTED=yes) same => n(return),NoOp() same => n,Set(CDR(source)=${CALL_SOURCE}) same => n,Return() exten => s-external,1,NoOp(Setting External CID) same => n,Set(EXTENSION_NUMBER=${IF($["${CALL_ORIGIN}"="diversions"]?${DIVERSION_ORIGIN}:${CALL_SOURCE})}) same => n,GotoIf($["${EXT_CID_CONSTRUCTED}"="yes"]?return) same => n,GotoIf($["${OUT_FROM_TENANT}"="yes"]?return) same => n,Set(EMERGENCY_CALL=${IF($["${ARG1}"="emergency"]?yes:no)}) same => n,Set(EXTENSION_EMERGENCY_CID=) same => n,Set(DYNAMIC_EXTERNAL_CID=no) same => n,ExecIf(${DB_EXISTS(${TENANT}/extensions/${CALL_SOURCE}/emergency_cid)}?Set(EXTENSION_EMERGENCY_CID=${DB(${TENANT}/extensions/${CALL_SOURCE}/emergency_cid)})) same => n,ExecIf(${DB_EXISTS(${TENANT}/extensions/${CALL_SOURCE}/dynamic_external_cid)}?Set(DYNAMIC_EXTERNAL_CID=${DB(${TENANT}/extensions/${CALL_SOURCE}/dynamic_external_cid)})) same => n,GotoIf($["${DYNAMIC_EXTERNAL_CID}"="yes"]?check-emergency) same => n,Set(EXTENSION_EXTERNAL_CID=${DB(${TENANT}/extensions/${CALL_SOURCE}/external_cid)}) same => n,ExecIf(${DB_EXISTS(${TENANT}/extensions/${CALL_SOURCE}/external_cid)}?Set(CALLERID(all)=${EXTENSION_EXTERNAL_CID})) same => n,GotoIf(${DB_EXISTS(${TENANT}/extensions/${CALL_SOURCE}/external_cid)}?:check-emergency) same => n,Set(TENANT_DEFAULT_EXTERNAL_CID=${DB(${TENANT}/default_external_cid)}) same => n,ExecIf($[$["${LEN(${EXTENSION_EXTERNAL_CID})}"="0"]&$["${LEN(${TENANT_DEFAULT_EXTERNAL_CID})}"!="0"]]?Set(CALLERID(all)=${TENANT_DEFAULT_EXTERNAL_CID})) same => n(check-emergency),GotoIf($["${EMERGENCY_CALL}"="yes"]?:info) same => n,Set(EMERGENCY_CID=${EXTENSION_EMERGENCY_CID}) same => n,Set(DEVICE_EMERGENCY_CID=${DB(${DEV_TREE}/emergency_cid)}) same => n,ExecIf($["${LEN(${DEVICE_EMERGENCY_CID})}"!="0"]?Set(EMERGENCY_CID=${DEVICE_EMERGENCY_CID})) same => n,Set(DISPATCHABLE_LOCATION=${DB(${DEV_TREE}/location)}) same => n,GotoIf($["${LEN(${DISPATCHABLE_LOCATION})}"="0"]?get-default-location) same => n,Set(ARRAY(LOC_CID_NAME,LOC_CID_NUMBER)=${GET_EMERGENCY-CID(${DISPATCHABLE_LOCATION},${TENANT})}) same => n,Goto(setup-disp-loc) same => n(get-default-location),NoOp(Read the default emergency location) same => n,Set(ARRAY(LOC_CID_NAME,LOC_CID_NUMBER)=${GET_DEFAULT-EMERGENCY-CID(${TENANT})}) same => n(setup-disp-loc),NoOp(Setting up the CID from the Dispatchable Locations) same => n,ExecIf($[$["${LEN(${LOC_CID_NAME})}"!="0"]&$["${LEN(${LOC_CID_NUMBER})}"!="0"]]?Set(DISPATCHABLE_LOCATION_CID="${LOC_CID_NAME}" <${LOC_CID_NUMBER}>)) same => n,ExecIf($[$["${LEN(${DEVICE_EMERGENCY_CID})}"="0"]&$["${LEN(${DISPATCHABLE_LOCATION_CID})}"!="0"]]?Set(EMERGENCY_CID=${DISPATCHABLE_LOCATION_CID})) same => n,Set(CALLERID(all)=${EMERGENCY_CID}) same => n(info),NoOp(CID Name: ${CALLERID(name)}, CID Number: ${CALLERID(num)}) same => n,Set(SEND_CID=${DB(${TENANT}/extensions/${CALL_SOURCE}/sendcid)}) same => n,ExecIf($[$[$["${SEND_CID}"="no"]|$["${FORCE_HIDE_CID}"="yes"]]&$["${EMERGENCY_CALL}"="no"]]?Set(CALLERID(name-pres)=prohib_passed_screen)) same => n,ExecIf($[$[$["${SEND_CID}"="no"]|$["${FORCE_HIDE_CID}"="yes"]]&$["${EMERGENCY_CALL}"="no"]]?Set(CALLERID(num-pres)=prohib_passed_screen)) same => n,Set(__EXT_CID_CONSTRUCTED=yes) same => n(return),Set(CDR(source)=${EXTENSION_NUMBER}) same => n,Return() exten => s-incoming,1,NoOp(Setting Incoming CID) same => n,GotoIf($["X${CALLERID(num)}X"="XX"]?return) same => n,Set(_CALL_SOURCE=${CALLERID(num)}) same => n,Set(_CS=${CALLERID(num)}) same => n,Set(CDR(source)=${CALLERID(num)}) same => n,Set(__CID_CONSTRUCTED=yes) same => n(return),Return() [sub-local-dialing] exten => s,1,NoOP(Trying to determine if is a local extension) same => n,GotoIf(${DB_EXISTS(${TENANT}/extensions/${CALL_DESTINATION}/dial)}?:return) same => n,Set(EXTENSION_TO_DIAL=${FILTER(0-9+*#,${CALL_DESTINATION})}) same => n,Goto(${EXTENSION_TO_DIAL},1) same => n(return),Return() exten => _[*#0-9]!,1,NoOp(Dialing Local Extension) same => n,ExecIf($["${DISABLE_CDR}"="yes"]?NoCDR()) same => n,GoSub(sub-setup-call-type,s,1(internal)) same => n,Set(_DESTINATION_STATE=${EXTENSION_STATE(${EXTEN}@${HINTS_CONTEXT})}) same => n,Set(_DESTINATION_NUMBER=${EXTEN}) same => n,Set(_DESTINATION_COS_NAME=${DB(${TENANT}/extensions/${CALL_DESTINATION}/context)}) same => n,GoSub(sub-check-cos-privacy,s,1(${DESTINATION_COS_NAME},${COS_ID},${COS_NAME})) same => n,Set(DIAL_STRING=${DB(${TENANT}/extensions/${CALL_DESTINATION}/dial)}) same => n,Set(DB(${TENANT}/LASTCALLER/${EXTEN})=${IF($["${CALL_TYPE}"="2"]?${INCOMING_SOURCE}:${CALL_SOURCE})}) same => n,Set(IGNORE_DIVERSIONS=${IF($["${CALL_ORIGIN}"="diversions"]?yes:${IGNORE_DIVERSIONS})}) same => n,Set(QUEUE_CALL=${IF($["${BLINDTRANSFER}"=""]?${QUEUE_CALL}:FALSE)}) same => n,GoSubIf($["${QUEUE_CALL}"="TRUE"]?sub-queue-members,s,1) same => n,GoSubIf($[$["${IGNORE_DIVERSIONS}"="yes"]&$["${BLINDTRANSFER}"=""]]?:sub-check-diversions,s,1(predialing)) same => n,GotoIf($["${DIAL_STRING}"=""]?post-dial) same => n,Gosub(parse-dial-string,s,1) same => n,NoOp(Configuring Dial Settings) same => n,Set(RING_TIME=${DB(${TENANT}/extensions/${CALL_DESTINATION}/ringtimer)}) same => n,Set(RING_TIME=${IF($["XXX${RING_TIME}"="XXX"]?${RINGTIMEDEF}:${RING_TIME})}) same => n,Set(RING_TIME=${IF($["XXX${O_RING_TIME}"="XXX"]?${RING_TIME}:${O_RING_TIME})}) same => n,Set(DIAL_OPTIONS=${DB(${TENANT}/extensions/${CALL_DESTINATION}/dial_options)}) same => n,Set(DIAL_OPTIONS=${IF($["XXX${DIAL_OPTIONS}"="XXX"]?${DIALOPTIONS}:${DIAL_OPTIONS})}) same => n,GotoIf($[$["${CALL_ORIGIN}"="feature"]|$["${CALL_ORIGIN}"="paging"]]?:answermode) same => n,GotoIf($["${QUEUE_CALL}"="TRUE"]?:answermode) same => n,Set(DIAL_OPTIONS=${STRREPLACE(DIAL_OPTIONS,an(1)p,,1)}) same => n,Set(DIAL_OPTIONS=${STRREPLACE(DIAL_OPTIONS,aP,,1)}) same => n(answermode),Set(ANSWER_MODE=${DB(${TENANT}/extensions/${CALL_DESTINATION}/answermode)}) same => n,Set(ANSWER_MODE=${IF($["${CALL_ORIGIN}"="paging"]?intercom:${ANSWER_MODE})}) same => n,GotoIf($["${SKIP_AA}"="TRUE"]?check-hd) same => n,ExecIf($[$[$[$["${ANSWER_MODE}"="intercom"]&$["${CALL_TYPE}"="1"]]|$["${FORCE_INTERCOM}"="yes"]]&$[$["${DESTINATION_STATE}"="NOT_INUSE"]&$["${DB(${TENANT}/diversions/${CALL_DESTINATION}/FWM/enable)}"="no"]]]?Set(EXEC_AA=yes)) ;Flag for Auto-Answer same => n,ExecIf($[$["${FORCE_INTERCOM}"="yes"]&$["${DESTINATION_STATE}"="NOT_INUSE"]]?Set(EXEC_AA=yes)) ; Force Auto-Answer when using the paging module or the paging feature. same => n(check-hd),Set(IS_HOT_DESK=${DB(${TENANT}/extensions/${CALL_DESTINATION}/hotdesking)}) same => n,Set(MOH_CLASS=${DB(${TENANT}/extensions/${CALL_DESTINATION}/moh)}) same => n,GosubIf($["${IS_HOT_DESK}"="yes"]?sub-set-moh,s,1(${MOH_CLASS}):moh,1) same => n,GotoIf($[$[$["${DESTINATION_STATE}"="INUSE"]|$["${DESTINATION_STATE}"="BUSY"]]&$["${DB(${TENANT}/extensions/${CALL_DESTINATION}/call_waiting)}"="no"]]?busy-here) same => n,Set(FORCE_RECORDING=${IF($["${APP_RECORDING}"="yes"]?yes:no)}) ;Force recordings by apps like: Queues, Ring Groups, Conferences, Paging, etc same => n,Set(DIAL_OPTIONS=${DIAL_OPTIONS}b(sub-before-connecting-call^s^1(${TENANT}^${CALL_SOURCE}^${EXTEN}^${EXEC_AA}^${CUSTOM-ALERT-INFO}))) same => n,Set(DIAL_OPTIONS=${DIAL_OPTIONS}U(sub-before-bridging-call^${TENANT}^${CALL_SOURCE}^${EXTEN}^${FORCE_RECORDING})) same => n,Set(DIAL_OPTIONS=${IF($[$[$["${DESTINATION_STATE}"="INUSE"]|$["${DESTINATION_STATE}"="BUSY"]]&$["${PLAY_CW_TONE}"="yes"]]?${STRREPLACE(DIAL_OPTIONS,r,r(callwaiting),1)}:${DIAL_OPTIONS})}) same => n,Set(__TRANSFERED_CALL=TRUE) same => n,NoOP(Enable Follow-Me Ring Time If needed) same => n,GotoIf($[$[$["${DB(${TENANT}/diversions/${CALL_DESTINATION}/FWM/enable)}"="yes"]&$["${IGNORE_DIVERSIONS}"!="yes"]]|$[$["${LEN(${BLINDTRANSFER})}"!="0"]&$["${DB(${TENANT}/diversions/${CALL_DESTINATION}/FWM/enable)}"="yes"]]]?:check-rt) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_DESTINATION}/FWM/time_group)}"!=""]?:set-fw-rt) same => n,Set(FWM_TG=${DB(${TENANT}/diversions/${CALL_DESTINATION}/FWM/time_group)}) same => n,Gosub(${FWM_TG},s,1) same => n,GotoIf($[${TGMATCH}=1]?:check-rt) same => n(set-fw-rt),NoOP(Using Follow-me Ring Time) same => n,Set(RING_TIME=${DB(${TENANT}/extensions/${CALL_DESTINATION}/followme/ringtime)}) same => n(check-rt),GotoIf($["${RING_TIME}"="0"]?post-dial) same => n,GotoIf($[$["${SKIP_BUSY}"="yes"]&$["${DESTINATION_STATE}"!="NOT_INUSE"]]?end_call) same => n,Gosub(sub-udpate-virtual-dev-state,s,1(${CALL_DESTINATION},BUSY)) same => n,Dial(${DIAL_STRING},${RING_TIME},${DIAL_OPTIONS}) same => n(post-dial),Set(_CALL_STATUS=${DIALSTATUS}) same => n,Set(_CALL_STATUS=${IF($[$["${DESTINATION_STATE}"="BUSY"]|$["${DESTINATION_STATE}"="INUSE"]]?BUSY:${CALL_STATUS})}) same => n,Gosub(sub-udpate-virtual-dev-state,s,1(${CALL_DESTINATION},NOT_INUSE)) same => n,Goto(check-post-diversions) same => n(busy-here),Set(_CALL_STATUS=BUSY) same => n(check-post-diversions),GoSubIf($[$["${IGNORE_DIVERSIONS}"="yes"]&$["${BLINDTRANSFER}"=""]]?:sub-check-diversions,s,1(postdialing)) same => n,GotoIf($["${QUEUE_CALL}"="TRUE"]?end_call) same => n,GotoIf($[$[$["${SKIP_CONTACT_SERVICES}"="TRUE"]&$["${BLINDTRANSFER}"=""]]&$["${LEN(${PARKER})}"="0"]]?end_call) same => n,GotoIf($[$[$["${NO_POST_SERVICES}"="TRUE"]&$["${BLINDTRANSFER}"=""]]&$["${LEN(${PARKER})}"="0"]]?end_call) same => n,GoSub(sub-leave-vm,s,1) same => n,GoSubIf($["${FEATURE_SERVICE}"!="call_completion"]?sub-request-cc,s,1) same => n(end_call),ExecIf($["${CALL_STATUS}"="BUSY"]?Busy(5)) same => n,Hangup() exten => set_dial,1,NoOp(Set Dial options) same => n,Set(CHANNEL(namedcallgroup)=${DB(${TENANT}/extensions/${DESTINATION_NUMBER}/callgroup)}) same => n,GotoIf($[${EXISTS(${hotdesk_moh})}]?:end) same => n,Set(CHANNEL(musicclass)=${hotdesk_moh}) same => n(end),Return() exten => moh,1,NoOp(Set Music on Hold) same => n,GotoIf($[${DB_EXISTS(${TENANT}/queues/${QUEUE_NUMBER}/moh)}]?:return) same => n,ExecIf($["${DB(${TENANT}/queues/${QUEUE_NUMBER}/moh)}"!=""]?Set(CHANNEL(musicclass)=${DB(${TENANT}/queues/${QUEUE_NUMBER}/moh)}):)) same => n(return),Return() exten => h,1,NoOp(Finishing the call) same => n,Gosub(sub-udpate-virtual-dev-state,s,1(${CALL_DESTINATION},NOT_INUSE)) same => n,GoSubIf($["${DYNROUTING}"="yes"]?dynamic-routing-connected,s,1(${DIALSTATUS},${CALL_SOURCE})) same => n,GotoIf($["${QUEUE_CALL}"="TRUE"]?call_ended) same => n,GoSubIf($["${FEATURE_SERVICE}"="wake_up"]?wake-up-no-answered,s,1) same => n,Gosub(sub-call-completion-check,s,1) same => n(call_ended),NoOp(Call ended) same => n,Gosub(notify-call-hangup,s,1) same => n,Hangup() [sub-before-connecting-call] exten => s,1,NoOP(Executing routines in the newly created channel before initiaing the call) same => n,Set(TENANT=${ARG1}) same => n,Set(CALLER=${ARG2}) same => n,Set(CALLEE=${ARG3}) same => n,Set(EXEC_AA=${ARG4}) same => n,Set(CUSTOM_ALERT_INFO=${ARG5}) same => n,Set(APP_TYPE=${IF($["X${SRC_APP}X"="XX"]?NONE:${SRC_APP})}) same => n,GosubIf($["${EXEC_AA}"="yes"]?sub-auto-answer,s,1) same => n,GosubIf($["${LEN(${CUSTOM_ALERT_INFO})}"!="0"]?sub-set-custom-header,s,1(Alert-Info,${CUSTOM_ALERT_INFO})) same => n,GosubIf($["${LEN(${CUSTOM_ALERT_INFO})}"!="0"]?sub-set-custom-header,s,1(Call-Info,${CUSTOM_ALERT_INFO})) same => n,Gosub(sub-set-custom-header,s,1(CALL-TYPE,${CALL_TYPE_LABEL})) same => n,Gosub(sub-set-custom-header,s,1(APPLICATION,${APP_TYPE})) same => n,GosubIf($["${LEN(${QUEUE_NAME})}"!="0"]?sub-set-custom-header,s,1(QUEUE-NAME,${QUEUE_NAME})) same => n,GosubIf($[${DIALPLAN_EXISTS(${TENANT_PREFIX}before-connecting-call-hook,s,1)}=1]?${TENANT_PREFIX}before-connecting-call-hook,s,1) same => n,Return() [sub-set-custom-header] exten => s,1,NoOP(Setting up custom header) same => n,GotoIf($["${CHANNEL(channeltype)}"="SIP"]?set-sip) same => n,NoOP(Add PJSIP Headers) same => n,Set(PJSIP_HEADER(add,${ARG1})=${ARG2}) same => n,Goto(end) same => n(set-sip),NoOP(Add SIP Headers) same => n,SIPAddHeader(${ARG1}: ${ARG2}) same => n(end),Return() [parse-dial-string] exten => s,1,NoOp(Parsing dial string: ${DIAL_STRING}) same => n,Set(NEW_DIAL_STRING=) same => n,Set(COUNTER=1) same => n,Set(CURRENT_DEVICE=${CUT(DIAL_STRING,&,${COUNTER})}) same => n,While($[${EXISTS(${CURRENT_DEVICE})}]) same => n,Set(TECHNOLOGY=${CUT(CURRENT_DEVICE,/,1)}) same => n,Set(USER=${CUT(CURRENT_DEVICE,/,2)}) same => n,GotoIf($["${TECHNOLOGY}"="PJSIP"]?:regular) same => n,Goto(regular-pjsip) same => n,Set(PARSED_DEV=Local/${USER}@pjsip-push) same => n,Goto(append) same => n(regular-pjsip),Set(PARSED_DEV=${PJSIP_DIAL_CONTACTS(${USER})}) same => n,ExecIf($["${LEN(${PARSED_DEV})}"="0"]?Set(PARSED_DEV=${CURRENT_DEVICE})) same => n,Goto(append) same => n(regular),Set(PARSED_DEV=${CURRENT_DEVICE}) same => n(append),GotoIf($["${COUNTER}"="1"]?:concatenate) same => n,Set(NEW_DIAL_STRING=${PARSED_DEV}) same => n,Goto(next) same => n(concatenate),GotoIf($["XX${PARSED_DEV}XX"!="XXXX"]?:next) same => n,Set(NEW_DIAL_STRING=${NEW_DIAL_STRING}&${PARSED_DEV}) same => n(next),Set(COUNTER=$[${COUNTER} + 1]) same => n,Set(CURRENT_DEVICE=${CUT(DIAL_STRING,&,${COUNTER})}) same => n,EndWhile() same => n,NoOp(New dialstring: ${NEW_DIAL_STRING}) same => n,Set(DIAL_STRING=${NEW_DIAL_STRING}) same => n,Return() [sub-check-diversions] exten => s,1,NoOp(Checking diversions for extension ${CALL_DESTINATION}) same => n,Set(OLD_CALLER_ID=${CALLERID(all)}) same => n,GosubIf($["${DB(${TENANT}/diversions/${CALL_DESTINATION}/has_enable_diversions)}"="yes"]?:return) same => n,ExecIf($["${DB(${TENANT}/extensions/${CALL_DESTINATION}/cid_on_diversions)}"="callee"]?Set(CALLERID(all)=${DB(${TENANT}/extensions/${CALL_DESTINATION}/internal_cid)})) same => n,Set(__CALL_ORIGIN=diversions) same => n,Set(__DIVERSION_ORIGIN=${CALL_DESTINATION}) same => n,Gosub(s-${ARG1},1) same => n,Set(CALLERID(all)=${OLD_CALLER_ID}) same => n(return),Return() exten => s-predialing,1,NoOp(Diversions on pre-dialing) same => n,GosubIf($["${QUEUE_CALL}"="TRUE"]?:diversion-testing,1(Do not Disturb,DND,,,dnd)) same => n,Gosub(diversion-testing,1(Call Forward Immeditely,CFI,,,toggle_cfi)) same => n,GosubIf($["${QUEUE_CALL}"="TRUE"]?:diversion-testing,1(Boss Secretray,BOSS,,,boss_secretary)) same => n,GosubIf($["${QUEUE_CALL}"="TRUE"]?:diversion-testing,1(Personal Assistant,PEA,sub-personal-assistant,s,1)) same => n,Return() exten => s-postdialing,1,NoOp(Diversions on post-dialing) same => n,Gosub(diversion-testing,1(Follow Me,FWM,${FOLLOWME_CONTEXT},FW${CALL_DESTINATION},follow_me)) same => n,GosubIf($["${CALL_STATUS}"="CHANUNAVAIL"]?call-forward,1(CFU,toggle_cfu)) same => n,GosubIf($["${CALL_STATUS}"="CONGESTION"]?call-forward,1(CFU,toggle_cfu)) same => n,GosubIf($["${CALL_STATUS}"="BUSY"]?call-forward,1(CFB,toggle_cfb)) same => n,GosubIf($["${CALL_STATUS}"="NOANSWER"]?call-forward,1(CFN,toggle_cfn)) same => n,Return() exten => diversion-testing,1,NoOp() same => n,Set(FROM_NUMBER=${IF($[${LEN(${DID_NUMBER})}=0]?${CALL_DESTINATION}:${DID_NUMBER})}) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_DESTINATION}/${ARG2}/enable)}"="yes"]?:next-diversion) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_DESTINATION}/${ARG2}/time_group)}"!=""]?:play-diversion) same => n,Set(DIVERSION_TG=${DB(${TENANT}/diversions/${CALL_DESTINATION}/${ARG2}/time_group)}) same => n,Gosub(${DIVERSION_TG},s,1) same => n,GotoIf($[${TGMATCH}=1]?:next-diversion) same => n(play-diversion),NoOp(Executing Diversion: ${ARG1}) same => n,GoSubIf($["${ARG2}"="FWM"]?sub-diversion-headers,s,1(${FROM_NUMBER},follow_me)) same => n,GoSubIf($["${ARG2}"="CFI"]?sub-diversion-headers,s,1(${FROM_NUMBER},cfu)) same => n,GotoIf($["${ARG2}"="BOSS"]?boss) same => n,GotoIf($["${ARG2}"="DND"]?dnd) same => n,GotoIf($["${ARG2}"="CFI"]?diversion_forward) same => n,Gosub(${ARG3},${ARG4},1) same => n,Goto(next-diversion) same => n(diversion_forward),Set(DIVERSION_DESTINATION=${DB(${TENANT}/diversions/${CALL_DESTINATION}/${ARG2}/destination)}) same => n,GotoIf($["${DIVERSION_DESTINATION}"=""]?next-diversion) same => n,ExecIf($[$["${CALL_TYPE}"!="1"]&$["DISABLE_CF_AA"!="TRUE"]]?Answer()) ;Answer call before performing a diversion, but, only if is not internal same => n,Gosub(${DIVERSION_DESTINATION}(${DESTINATION_COS_NAME},${CALL_DESTINATION})) same => n,Return() same => n(dnd),NoOP(DND Enabled) same => n,GotoIf($["${DB(${TENANT}/extensions/${CALL_DESTINATION}/vmenabled)}" = "yes"]?:play_prompt) same => n,GotoIf($[$["${SKIP_CONTACT_SERVICES}"="TRUE"]&$["${LEN(${BLINDTRANSFER})}"="0"]]?play_prompt) same => n,Set(_CALL_STATUS=BUSY) same => n,GoSub(sub-leave-vm,s,1) same => n,Hangup() same => n(play_prompt),GoSub(sub-dnd-prompt,s,1) same => n,Hangup() same => n(boss),GotoIf(${DB_EXISTS(${TENANT}/extensions/${CALL_DESTINATION}/${ARG2}/WHL/${CALL_SOURCE})}?next-diversion) same => n,Set(SECRETARY_EXTEN=${DB(${TENANT}/extensions/${CALL_DESTINATION}/secretary)}) same => n,GotoIf($[$["${SECRETARY_EXTEN}"=""]|$["${SECRETARY_BLIND}"="TRUE"]]?next-diversion) same => n,GotoIf($["${DB(${TENANT}/extensions/${SECRETARY_EXTEN}/absent_secretary)}"="yes"]?next-diversion) same => n,GotoIf($["${SECRETARY_EXTEN}"="${CALL_SOURCE}"]?next-diversion) same => n,Set(_SECRETARY_BLIND=TRUE) ;FOR BOSS Blind Transer same => n,Goto(${DESTINATION_COS_NAME},${SECRETARY_EXTEN},1) ;We can make a dial here same => n(next-diversion),Return() exten => call-forward,1,NoOp(CALL FOWARDING) same => n,Set(FROM_NUMBER=${IF($[${LEN(${DID_NUMBER})}=0]?${CALL_DESTINATION}:${DID_NUMBER})}) same => n,GotoIf($[$["${DB(${TENANT}/diversions/${CALL_DESTINATION}/${ARG1}/enable)}"="yes"] & $["${DB(${TENANT}/diversions/${CALL_DESTINATION}/${ARG1}/destination)}"!=""]]?:return) same => n,Set(FORWARD_TG=${DB(${TENANT}/diversions/${CALL_DESTINATION}/${ARG1}/time_group)}) same => n,GotoIf($["${FORWARD_TG}"=""]?forward_continue) same => n,Gosub(${FORWARD_TG},s,1) same => n,GotoIf($["XXX${TGMATCH}"="XXX1"]?:return) same => n(forward_continue),Set(FORWARD_DESTINATION=${DB(${TENANT}/diversions/${CALL_DESTINATION}/${ARG1}/destination)}) same => n,ExecIf($[$["${CALL_TYPE}"!="1"]&$["DISABLE_CF_AA"!="TRUE"]]?Answer()) ;Answer call before performing a diversion, but, only if is not internal same => n,GoSubIf($["${ARG1}"="CFN"]?sub-diversion-headers,s,1(${FROM_NUMBER},cfnr)) same => n,GoSubIf($["${ARG1}"="CFB"]?sub-diversion-headers,s,1(${FROM_NUMBER},cfb)) same => n,GoSubIf($["${ARG1}"="CFU"]?sub-diversion-headers,s,1(${FROM_NUMBER},unavailable)) same => n,Gosub(${FORWARD_DESTINATION}(${DESTINATION_COS_NAME},${CALL_DESTINATION})) same => n(return),Return() [sub-leave-vm] exten => s,1,NoOp(Leave Voicemail) same => n,Set(VM_OPTIONS=${IF($["${CALL_STATUS}"="BUSY"]?b:u)}) same => n,Set(VM_OPTIONS=${IF($["${DB(${TENANT}/extensions/${CALL_DESTINATION}/skip_vm_instructions)}"="yes"]?${VM_OPTIONS}s:${VM_OPTIONS})}) same => n,GotoIf($["${DB(${TENANT}/extensions/${CALL_DESTINATION}/vmenabled)}" = "yes"]?:vm_disabled) same => n,Set(MAILBOX=${DB(${TENANT}/extensions/${CALL_DESTINATION}/voicemail)}) same => n,Answer() same => n,Gosub(sub-vm,s,1(${MAILBOX},${VM_OPTIONS})) same => n(vm_disabled),Return() [sub-request-cc] exten => s,1,NoOp(Trying to request call completion) same => n,GotoIf($["${CALL_TYPE}"="1"]?:return) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_DESTINATION}/CC/enable)}"="yes"]?:return) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_DESTINATION}/CC/time_group)}"!=""]?:execute-cc) same => n,Set(CC_TG=${DB(${TENANT}/diversions/${CALL_DESTINATION}/CC/time_group)}) same => n,Goto(${CC_TG},s,1) same => n,GotoIf($["XXX${TGMATCH}"="XXX1"]?:return) same => n(execute-cc),NoOp() same => n,GotoIf($["${DB(${TENANT}/extensions/${CALL_SOURCE}/CC/extension)}"="${CALL_DESTINATION}"]?return) same => n,Gosub(sub-cc-request,s,1(${CALL_STATUS})) same => n(return),Return() [sub-setup-call-type] exten => s,1,NoOp(Determinating Call Type) same => n,GotoIf($[$["${CALL_TYPE_CONFIGURED}"="yes"] & $["${ARG1}"!="outgoing"]]?return) same => n,Gosub(s-${ARG1},1(${ARG2})) same => n,Set(__CALL_TYPE_CONFIGURED=yes) same => n(return),Set(CDR(calltype)=${CALL_TYPE}) same => n,Return() exten => s-internal,1,NoOp(Internal Call) same => n,Set(__CALL_TYPE=1) same => n,Set(__CALL_TYPE_LABEL=LOCAL) same => n,Return() exten => s-incoming,1,NoOp(Incoming Call) same => n,Set(__CALL_TYPE=2) same => n,Set(__CALL_TYPE_LABEL=IN) same => n,Return() exten => s-outgoing,1,NoOp(Outgoing Call) same => n,Set(__CALL_TYPE=3) same => n,Set(__CALL_TYPE_LABEL=OUT) same => n,GoSubIf($["${ARG1}"="yes"]?s-transit,1) ; Check if is a transit call same => n,Return() exten => s-transit,1,NoOp(Transit Call) same => n,Set(__CALL_TYPE=4) same => n,Set(__CALL_TYPE_LABEL=TRANSIT) same => n,Return() [sub-call-recordingx] exten => s,1,NoOp(Check if call will be recorded on tenant ${TENANT}) same => n,NoOp(Call Type: ${CALL_TYPE} ) same => n,Set(TENANT=${ARG1}) same => n,Set(CALLER=${ARG2}) same => n,Set(CALLEE=${ARG3}) same => n,Set(APP_FORCE=${ARG4}) same => n,GotoIf($["${DB(${TENANT}/allow_recordings)}"="yes"]?:rec_no_available) same => n,GotoIf($["${APP_FORCE}"="yes"]?perform-recording) same => n,GotoIf($[$["${CALL_TYPE}"="1"]&$["${DB(${TENANT}/extensions/${CALLEE}/internal_rec)}"="yes"]]?perform-recording) same => n,GotoIf($[$["${CALL_TYPE}"="1"]&$["${DB(${TENANT}/extensions/${CALLER}/internal_rec)}"="yes"]]?perform-recording) same => n,GotoIf($[$[$["${CALL_TYPE}"="2"]|$["${CALL_TYPE}"="4"]]&$["${DB(${TENANT}/extensions/${CALLEE}/incoming_rec)}"="yes"]]?perform-recording) same => n,GotoIf($[$[$["${CALL_TYPE}"="3"]|$["${CALL_TYPE}"="4"]]&$["${DB(${TENANT}/extensions/${CALLER}/outgoing_rec)}"="yes"]]?perform-recording) same => n,Goto(return) same => n(perform-recording),Gosub(sub-perform-recording,s,1) same => n,Goto(return) same => n(rec_no_available),NoOP(Recordins are not available for tenant ${DB(${TENANT}/name)}) same => n(return),Return() exten => conference,1,NoOp(Recording Conference ${ARG1}) same => n,Set(CONFERENCE=${ARG1}) same => n,GotoIf($["${DB(${TENANT}/allow_recordings)}"="yes"]?:rec_no_available) same => n,Set(DB_TREE=${TENANT}/conferences/${CONFERENCE}) same => n,Set(AUDIO_FILE=${STRFTIME(${EPOCH},,%H%M%S)}-${CALL_TYPE_LABEL}-CONF-${CALL_SOURCE}-${CONFERENCE}-${UNIQUEID}) same => n,Set(RECORDING_FORMAT=${IF($["${RECORDING_FORMAT}"="wav49"]?WAV:${RECORDING_FORMAT})}) same => n,Set(REC_FILENAME=${ASTSPOOLDIR}/monitor/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${AUDIO_FILE}.${RECORDING_FORMAT}) same => n,GotoIf($["${DB(${TENANT}/main)}"="no"]?:set_conf_rec_file) same => n,NoOp(Append tenant to recording path) same => n,Set(REC_FILENAME=${ASTSPOOLDIR}/monitor/${TENANT}/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${AUDIO_FILE}.${RECORDING_FORMAT}) same => n(set_conf_rec_file),Set(CONF_REC_FILE=${IF($[${CONFBRIDGE_INFO(parties,${CONFERENCE})}>0]?${DB(${DB_TREE})}:${REC_FILENAME})}) same => n,ExecIf($[${CONFBRIDGE_INFO(parties,${CONFERENCE})}<=0]?Set(DB(${DB_TREE})=${REC_FILENAME})) same => n,GotoIf($[${CONFBRIDGE_INFO(parties,${CONFERENCE})}>0]?cdr) same => n,MixMonitor(${REC_FILENAME},b,${RECORDING_SCRIPT}) same => n(cdr),Set(CDR(recfile)=${CONF_REC_FILE}) same => n,Goto(return) same => n(rec_no_available),NoOP(Recordins are not available for tenant ${DB(${TENANT}/name)}) same => n(return),Return() [sub-call-recording-on-demandx] exten => s,1,NoOp(Check if call recording on demand is allowed) same => n,GotoIf($["${DB(${TENANT}/allow_recordings)}"="yes"]?:rec_no_available) same => n,Set(CALL_SRC_PATH=${TENANT}/extensions/${CALL_SOURCE}/rec_on_demand) same => n,Set(CALL_DST_PATH=${TENANT}/extensions/${CALL_DESTINATION}/rec_on_demand) same => n,GotoIf($[$[$["${CALL_TYPE}"="1"]|$["${CALL_TYPE}"="2"]]&$["${DB(${CALL_DST_PATH})}"="yes"]]?perform-recording) same => n,GotoIf($[$[$["${CALL_TYPE}"="1"]|$["${CALL_TYPE}"="3"]]&$["${DB(${CALL_SRC_PATH})}"="yes"]]?perform-recording) same => n,Goto(return) same => n(perform-recording),Gosub(sub-perform-recording,s,1) same => n,Goto(return) same => n(rec_no_available),NoOP(Recordins are not available for tenant ${DB(${TENANT}/name)}) same => n(return),Return() [sub-perform-recordingx] exten => s,1,NoOp(Perform Call Recording) same => n,Set(RECORDING_ID=${IF($["${QUEUE_UID}"=""]?${UNIQUEID}:${QUEUE_UID})}) same => n,Set(APP_TYPE=${IF($["X${SRC_APP}X"="XX"]?NONE:${SRC_APP})}) same => n,Set(AUDIO_FILE=${STRFTIME(${EPOCH},,%H%M%S)}-${CALL_TYPE_LABEL}-${APP_TYPE}-${CALL_SOURCE}-${CALL_DESTINATION}-${RECORDING_ID}) same => n,Set(RECORDING_FORMAT=${IF($["${RECORDING_FORMAT}"="wav49"]?WAV:${RECORDING_FORMAT})}) same => n,Set(__REC_FILENAME=${ASTSPOOLDIR}/monitor/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${AUDIO_FILE}.${RECORDING_FORMAT}) same => n,GotoIf($["${DB(${TENANT}/main)}"="no"]?:set_rec_file) same => n,NoOp(Append tenant to recording path) same => n,Set(__REC_FILENAME=${ASTSPOOLDIR}/monitor/${TENANT}/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${AUDIO_FILE}.${RECORDING_FORMAT}) same => n(set_rec_file),Set(CDR(recfile)=${REC_FILENAME}) same => n,MixMonitor(${REC_FILENAME},b,${RECORDING_SCRIPT}) same => n,Return() ;CALL COMPLETION VER. 1.0.0 ;------------------------------------------------------------------- [sub-call-completion-state] exten => s,1,NoOp(SUB: CALL COMPLETION ENABLED/DISABLED) same => n,Answer() same => n,Wait(1) same => n,GotoIf($["${DB(${TENANT}/extensions/${CALL_SOURCE}/hints)}"="yes"]?hint:nohint) same => n(hint),GotoIf($["${DB(${TENANT}/extensions/${CALL_SOURCE}/CC/state)}"="yes"]?hint_disabled) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}CCS_${CALL_SOURCE})=BUSY) same => n,Goto(enable) same => n(hint_disabled),NoOp(${DB_DELETE(${TENANT}/extensions/${CALL_SOURCE}/CC/state)}) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}CCS_${CALL_SOURCE})=NOT_INUSE) same => n,Goto(disable) same => n(nohint),GotoIf($["${DB(${TENANT}/extensions/${CALL_SOURCE}/CC/state)}"="yes"]?nohint_disabled) same => n,Goto(enable) same => n(nohint_disabled),NoOp(${DB_DELETE(${TENANT}/extensions/${CALL_SOURCE}/CC/state)}) same => n,Goto(disable) same => n(enable),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG2}/enable)=yes) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)=yes) same => n,Set(DB(${TENANT}/extensions/${CALL_SOURCE}/CC/state)=yes) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "enable-CC" "${TENANT}" "${CALL_SOURCE}") same => n,Playback(vpbx/vital-call-completion&activated) same => n,Hangup() same => n(disable),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG2}/enable)=no) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "disable-CC" "${TENANT}" "${CALL_SOURCE}") same => n,Gosub(sub-cf-checkall,s,1) same => n,Playback(vpbx/vital-call-completion&de-activated) same => n,Hangup() ;END of [sub-call-completion-state] ;------------------------------------------------------------------ [sub-cc-request] exten => s,1,NoOp(Call Completion Request) same => n,NoCDR() same => n,Answer() same => n,Set(X=1) same => n,Set(MAX_TRIES=3) same => n,Set(CC_REQUEST_MODE=${IF($["${ARG1}"="BUSY"]?is-curntly-busy:is-curntly-unavail)}) same => n,Playback(extension&${CC_REQUEST_MODE}) same => n(loop),GotoIf($[${X}>${MAX_TRIES}]?max_retries,1) same => n,Read(DIGITS,vpbx/vital-call-completion-request&digits/5,1,,3,5) same => n,GotoIf($["${DIGITS}"="5"]?enable-cc) same => n,Set(X=$[${X} + 1]) same => n,Goto(loop) same => n(enable-cc),NoOp(Enabling Call Completion) same => n,Set(DB(${TENANT}/extensions/${CALL_DESTINATION}/CC/request)=${CALL_SOURCE}) same => n,Set(DB(${TENANT}/extensions/${CALL_SOURCE}/CC/extension)=${CALL_DESTINATION}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "remove-CC" "${TENANT}" "${CALL_DESTINATION}") same => n,System(/usr/share/vitalpbx/scripts/synchronizer "add-CC" "${TENANT}" "${CALL_SOURCE}" "${CALL_DESTINATION}") same => n,Playback(activated) same => n,Hangup() exten => max_retries,1,NoOp(Max Retries Reached) same => n,Playback(vpbx/vital-max-tries&please-try-again-later) same => n,Hangup() exten => t,1,NoOp(Timeout Reached) same => n,Goto(max_retries,2) same => n,Hangup() ;END of [sub-call-completion-request] ;------------------------------------------------------------------- [sub-call-completion-cancel] exten => s,1,NoOp(FEATURE: CALL COMPLETION REQUEST CANCEL) same => n,Answer same => n,Wait(1) same => n,Set(cc_extension=${DB(${TENANT}/extensions/${CALL_SOURCE}/CC/extension)}) same => n,NoOp(${DB_DELETE(${TENANT}/extensions/${CALL_SOURCE}/CC/extension)}) same => n,NoOp(${DB_DELETE(${TENANT}/extensions/${cc_extension}/CC/request)}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "remove-CC" "${TENANT}" "${cc_extension}") same => n,Playback(vpbx/vital-call-completion-cancelled) same => n,Hangup() ;END of [sub-call-completion-cancel] ;------------------------------------------------------------------- [sub-call-completion-check] exten => s,1,NoOp(FEATURE: CALL COMPLETION CHECK) same => n,Set(CC_MODE=none) same => n,Set(CC_MODE=${IF(${DB_EXISTS(${TENANT}/extensions/${CALL_SOURCE}/CC/request)}?CALLER:${CC_MODE})}) same => n,Set(CC_MODE=${IF(${DB_EXISTS(${TENANT}/extensions/${CALL_DESTINATION}/CC/request)}?CALLEE:${CC_MODE})}) same => n,GotoIf($["${CC_MODE}"="none"]?end) same => n,Set(NUMBER=${IF($["${CC_MODE}"="CALLER"]?${CALL_SOURCE}:${CALL_DESTINATION})}) same => n,Set(CC_CALLER=${DB(${TENANT}/extensions/${NUMBER}/CC/request)}) same => n,Set(CC_CALLEE=${DB(${TENANT}/extensions/${CC_CALLER}/CC/extension)}) same => n,NoOp(${DB_DELETE(${TENANT}/extensions/${NUMBER}/CC/request)}) same => n,NoOp(${DB_DELETE(${TENANT}/extensions/${CC_CALLER}/CC/extension)}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "remove-CC" "${TENANT}" "${CC_CALLEE}") same => n,Set(CALLER_ID=${DB(${TENANT}/extensions/${CC_CALLER}/internal_cid)}) same => n,System(echo "Channel: Local/${CC_CALLER}@${COS_NAME} \nMaxRetries: 3 \nRetryTime: 1 \nWaitTime: 30 \nCallerID: "Call Completion" <${CC_CALLEE}> \nExtension: ${CC_CALLEE} \nContext: ${COS_NAME} \nSetvar: Language=${CHANNEL(language)} \nSetvar: CALL_ORIGIN=feature \nSetvar: FEATURE_SERVICE=call_completion" > ${ASTSPOOLDIR}/${UNIQUEID}.call) same => n,Set(OUTGOING_TIME=${STRFTIME(${EPOCH},,%Y%m%d%H%M%S)}) same => n,System(touch -t ${OUTGOING_TIME} ${ASTSPOOLDIR}/${UNIQUEID}.call) same => n,System(mv ${ASTSPOOLDIR}/${UNIQUEID}.call ${ASTSPOOLDIR}/outgoing/${OUTGOING_TIME}.${UNIQUEID}.call) same => n(end),Return() ;END of [sub-call-completion-check] ;------------------------------------------------------------------- ;END CALL COMPLETION ;FEATURE NOT AVAILABLE VER. 1.0.0 ;------------------------------------------------------------------- [app-feature-not-available] exten => s,1,NoOp(SUB: FEATURE NOT AVAILABLE) same => n,Answer same => n,Wait(1) same => n,PlayBack(feature-not-avail-line) same => n,Hangup() ;END of [app-feature-not-available] ;------------------------------------------------------------------- ;FEATURE NOT AVAILABLE ;HOT DESKING VER. 1.0.0 ;------------------------------------------------------------------- [sub-hot-desking] exten => s,1,NoOP(SUB: HOT DESKING SERVICE) same => n,Gosub(sub-get-device-tree,s,1) same => n,NoOp(Testing if device is hot desking) same => n,Set(IS_HOT_DESK=${DB(${DEV_TREE}/hot_desk)}) same => n,GotoIf($["${IS_HOT_DESK}"="yes"]?:invalid_device) same => n,Goto(assign_exten,1) same => n,Hangup() same => n(invalid_device),NoOp(Sorry, but this device is not hot desking) same => n,Playback(vpbx/vital-no-hotdesking-service) same => n,Hangup() exten => assign_exten,1,NoOp(Assign extension to device ${INTERFACE}) same => n,Set(tries=0) same => n,Set(HD_CONFIRMED=no) same => n(read_extension),NoOp(Please enter the extension that you wish assign to this device) same => n,Read(EXTEN_TO_ASSIGN,vpbx/vital-hotdesking-login,,,3,5) same => n,GotoIf($["XXX{EXTEN_TO_ASSIGN}"="XXX"]?read_extension) same => n,Set(IS_HOT_DESK=${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/hotdesking)}) same => n,GotoIf($["${IS_HOT_DESK}"="yes"]?valid_extension) same => n,Set(tries=$[${tries}+1]) same => n,GotoIf($[${tries}>=3]?invalid_extension) same => n,Playback(vpbx/vital-no-hotdesking-extension&please-try-again) same => n,Goto(read_extension) same => n(valid_extension),NoOp(Assigning extension ${EXTEN_TO_ASSIGN} to device ${INTERFACE}) same => n,Set(ASSIGNED_EXTEN=${DB(${DEV_TREE}/assigned_exten)}) same => n,GoSubIf($["${EXTEN_TO_ASSIGN}"="${ASSIGNED_EXTEN}"]?unassign_exten,s,1) same => n,NoOp(${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/dial)}) same => n,Set(EXTENSION_PASSWORD=${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/password)}) same => n,GotoIf($["XXX${EXTENSION_PASSWORD}"="XXX"]?no_authenticate) same => n,gosub(authenticate,s,1(${EXTENSION_PASSWORD})) same => n(no_authenticate),Set(HD_CONFIRMED=yes) same => n,PlayBack(vpbx/vital-hotdesking-login-confirm) same => n,Hangup() same => n(invalid_extension),Playback(vpbx/vital-max-tries&please-try-again-later&goodbye) same => n,Hangup() exten => h,1,NoOp(Check if need processing) same => n,GotoIf($["${HD_CONFIRMED}"!="yes"]?end) same => n,NoOp(${EXTEN_TO_ASSIGN}) same => n,GotoIf($[${EXISTS(${EXTEN_TO_ASSIGN})}]?:end) same => n,Set(IS_HOT_DESK=${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/hotdesking)}) same => n,GotoIf($["${IS_HOT_DESK}"!="yes"]?end) same => n,ExecIf($["${DB(${TENANT}/extensions/${ASSIGNED_EXTEN}/dial)}"!=""]?Set(prev_dial=${DB(${TENANT}/extensions/${ASSIGNED_EXTEN}/dial)}):Set(prev_dial=no) ; if has previously assigned same => n,GotoIf($[$["${prev_dial}"="no"]|$["${EXTEN_TO_ASSIGN}"="${ASSIGNED_EXTEN}"]]?next) same => n,gosub(unassign_device,s,1(${prev_dial},${ASSIGNED_EXTEN})) same => n,GoSub(sub-queues-logout,s,1(${ASSIGNED_EXTEN})) ; unassign previous extension same => n,Gosub(sub-get-device-tree,s,1) ; because unassign_device breaks INTERFACE variable same => n(next),ExecIf($["${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/dial)}"!=""]?Set(current_dial=${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/dial)}):Set(current_dial=no)) ; check for assgined same => n,GotoIf($[$["${current_dial}"="no"]|$["${prev_dial}"="no"]|$["${EXTEN_TO_ASSIGN}"="${ASSIGNED_EXTEN}"]]?continue) same => n,gosub(unassign_device,s,1(${current_dial},${EXTEN_TO_ASSIGN})) same => n,ExecIf($[$["${current_dial}"!=""]&$[${DB_EXISTS(devices/${current_dial}/assigned_exten)}]]?Set(DB(devices/${current_dial}/assigned_exten)=)) same => n(continue),Set(DB(${TENANT}/extensions/${ASSIGNED_EXTEN}/dial)=) same => n,ExecIf($["${current_dial}"!="no"]?Gosub(unassign_device,s,1(${current_dial},${EXTEN_TO_ASSIGN}))) same => n,Set(DB(${DEV_TREE}/assigned_exten)=${EXTEN_TO_ASSIGN}) same => n,ExecIf(${DB_EXISTS(${DEV_TREE}/hot_desk_ringdevice)}?Set(ring_device=${DB(${DEV_TREE}/hot_desk_ringdevice)}):Set(ring_device=no)) same => n,ExecIf($["${ring_device}"="yes"]?Set(DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/dial)=${INTERFACE})) same => n,System(/usr/share/vitalpbx/scripts/synchronizer hotdesk-login "${DEV_USER}" "${DEV_TECHNOLOGY}" "${EXTEN_TO_ASSIGN}" "${TENANT}") same => n,UserEvent("UserDeviceAdded","Data: ${EXTEN_TO_ASSIGN},${INTERFACE}") same => n,GoSubIf($["${HD_LOGIN_TO_QUEUES}"="TRUE"]?sub-queues-login,s,1(${EXTEN_TO_ASSIGN})) same => n(end),Hangup() ; END [sub-hot-desking-direct] exten => s,1,NoOp(SUB: Hot Desking Direct ${CALL_DESTINATION}) same => n,Set(OPTION=${CALL_DESTINATION:${ARG1}}) same => n,Set(OPTION=${OPTION:1}) ; remove the '*' same => n,GotoIf($["${DB(${DEV_TREE}/hot_desk)}"="yes"]?:sub-hot-desking,s,invalid_device) same => n,Set(_ASSIGNED_EXTEN=${DB(${DEV_TREE}/assigned_exten)}) same => n,GotoIf($["${OPTION}"="1"]?:un-assign) same => n,GoSub(sub-hot-desking-assign-extension,s,1) same => n(un-assign),GoSub(sub-hot-desking-remove-extension,s,1) same => n,Hangup() [sub-hot-desking-remove-extension] exten => s,1,NoOP(SUB:Remove Extension) same => n,GotoIf($["XXX{ASSIGNED_EXTEN}"="XXX"]?end) same => n,Set(_REMOVE_EXTEN=1) same => n,Set(_EXTEN_TO_ASSIGN=${ASSIGNED_EXTEN}) same => n,Goto(unassign_exten,s,remove-accepted) same => n(end),Hangup() [sub-hot-desking-assign-extension] exten => s,1,NoOP(SUB: Assign Extension) same => n,Set(tries=0) same => n,Set(EXTEN_TO_ASSIGN=${HD_EXTENSION_TO_LOGIN}) same => n,Set(PROVIDED_PASSWORD=${HD_EXTENSION_PWD}) same => n,Set(CHANNEL(hangup_handler_push)=sub-hot-desking,h,1()); same => n,GotoIf($[${ISNULL(${EXTEN_TO_ASSIGN})}]?:check-extension) same => n(read_extension),Read(EXTEN_TO_ASSIGN,vpbx/vital-hotdesking-login,,,3,5) same => n,GotoIf($["XXX{EXTEN_TO_ASSIGN}"="XXX"]?read_extension) same => n(check-extension),Set(IS_HOT_DESK=${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/hotdesking)}) same => n,GotoIf($["${IS_HOT_DESK}"="yes"]?valid_extension) same => n,Set(tries=$[${tries}+1]) same => n,GotoIf($[${tries}>=3]?invalid_extension) same => n,Playback(vpbx/vital-no-hotdesking-extension&please-try-again) same => n,Goto(read_extension) same => n(valid_extension),NoOp(Assigning extension ${EXTEN_TO_ASSIGN} to device ${INTERFACE}) same => n,NoOp(${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/dial)}) same => n,Set(EXTENSION_PASSWORD=${DB(${TENANT}/extensions/${EXTEN_TO_ASSIGN}/password)}) same => n,GotoIf($["XXX${EXTENSION_PASSWORD}"="XXX"]?no_authenticate) same => n,GotoIf($[${ISNULL(${PROVIDED_PASSWORD})}]?auth) same => n,GotoIf($["${PROVIDED_PASSWORD}"="${EXTENSION_PASSWORD}"]?no_authenticate) same => n(auth),gosub(authenticate,s,1(${EXTENSION_PASSWORD})) same => n(no_authenticate),Set(HD_CONFIRMED=yes) same => n,PlayBack(vpbx/vital-hotdesking-login-confirm) same => n,Hangup() same => n(invalid_extension),Playback(vpbx/vital-max-tries&please-try-again-later&goodbye) same => n,Hangup() [unassign_exten] exten => s,1,NoOp(Your extension is already assigned to this device, for remove press 1, for cancel press 2 or hangup) same => n(read_remove_opts),Read(REMOVE_EXTEN,vpbx/vital-hotdesking-logout,1,,3,5) same => n,GotoIf($["${REMOVE_EXTEN}"=""]?read_remove_opts) same => n,NoOp(${REMOVE_EXTEN}) same => n,GotoIf($[$[${REMOVE_EXTEN}=1]|$[${REMOVE_EXTEN}=2]]?:read_remove_opts) same => n,GotoIf($[${REMOVE_EXTEN}=2]?cancel) same => n(remove-accepted),NoOp(This extension have been removed correctly, Good Bye) same => n,PlayBack(vpbx/vital-hotdesking-logout-remove&goodbye) same => n,Goto(end) same => n(cancel),PlayBack(vpbx/vital-hotdesking-logout-cancel&goodbye) same => n(end),hangup() exten => h,1,NoOp(Check if need removing) same => n,GotoIf($[${EXISTS(${REMOVE_EXTEN})}]?:end) same => n,GotoIf($[${REMOVE_EXTEN}=1]?:end) ; cannot do on the same line same => n,Set(DB(${DEV_TREE}/assigned_exten)=) same => n,Set(DB(${TENANT}/extensions/${ASSIGNED_EXTEN}/dial)=) same => n,System(/usr/share/vitalpbx/scripts/synchronizer hotdesk-logout "${DEV_USER}" "${DEV_TECHNOLOGY}" "${EXTEN_TO_ASSIGN}" "${TENANT}") same => n,UserEvent("UserDeviceRemoved","Data: ${EXTEN_TO_ASSIGN},${INTERFACE}") same => n,GoSub(sub-queues-logout,s,1(${EXTEN_TO_ASSIGN})) same => n(end),Hangup() ;END of [sub-hot-desking] [unassign_device] exten => s,1,NoOp(unassign hot desk device) same => n,Set(current_dial=${ARG1}) same => n,Set(DB(devices/${current_dial}/assigned_exten)=) ; unassign previous device same => n,Set(dev_tech=${CUT(current_dial,/,1)}) ; get the technology same => n,Set(dev_user=${CUT(current_dial,/,2)}) ; get the user same => n,System(/usr/share/vitalpbx/scripts/synchronizer hotdesk-logout "${dev_user}" "${dev_tech}" "${ARG2}" "${TENANT}") same => n,UserEvent("UserDeviceRemoved","Data: ${ARG2},${INTERFACE}") same => n,return() ; ARG1: Password to validate ; ARG2: Prompt to ask the password ; ARG3: ERROR Prompt after reaching the maximum number of allowed tries ; ARG4: ERROR Prompt to play in every try [authenticate] exten => s,1,NoOp(authenticate password) same => n,Set(tries=0) same => n,Set(PROMPT=${IF($["${LEN(${ARG2})}"!="0"]?${ARG2}:agent-pass)}) same => n,Set(PROMPT_ERROR=${IF($["${LEN(${ARG3})}"!="0"]?${ARG3}:im-sorry&please-try-again-later&goodbye)}) same => n(read_password),NoOp(Please enter the password) same => n,Read(PASSWORD,${PROMPT},,,3,5) same => n,Set(tries=$[${tries}+1]) same => n,GotoIf($[${tries}>3]?end) same => n,GotoIf($["${PASSWORD}"!="${ARG1}"]?:match) same => n,ExecIf($["${LEN(${ARG4})}"!="0"]?Playback(${ARG4})) same => n,Goto(read_password) same => n(match),Return() same => n(end),Playback(${PROMPT_ERROR}) same => n,Hangup() ; END [sub-hot-desking-call] exten => s,1,NoOp(Trying to connect call) same => n,Set(EXTENSION=${ARG1}) same => n,Gosub(sub-get-device-tree,s,1) same => n,Set(ASSIGNED_EXTEN=${DB(${DEV_TREE}/assigned_exten)}) same => n,GotoIf($["${ASSIGNED_EXTEN}"=""]?no_exten_assigned,1) same => n,GotoIf($["${DB(${TENANT}/extensions/${ASSIGNED_EXTEN}/hotdesking)}"!="yes"]?no_exten_assigned,1) same => n,Set(CALL_CONTEXT=${DB(${TENANT}/extensions/${ASSIGNED_EXTEN}/context)}) same => n,Set(CALLERID(num)=${ASSIGNED_EXTEN}) same => n,Set(__hotdesk_moh=${DB(${TENANT}/extensions/${ASSIGNED_EXTEN}/moh)}) same => n,Set(CHANNEL(namedpickupgroup)=${DB(${TENANT}/extensions/${ASSIGNED_EXTEN}/pickupgroup)}) same => n,Goto(${CALL_CONTEXT},${ARG1},1) same => n,Hangup() exten => no_exten_assigned,1,NoOp(This device don't have any extension assigned) same => n,GotoIf($[${DIALPLAN_EXISTS(emergency-calls,${EXTENSION},1)}=1]?emergency-calls,${EXTENSION},1) same => n,Playback(sorry-cant-let-you-do-that&goodbye) same => n,Hangup() ;------------------------------------------------------------------- ;END HOT DESKING ;WAKEUP CALL VER. 1.0.0 ;------------------------------------------------------------------- [sub-wake-up-call-request] exten => s,1,NoOp(Wakeup Call Request) same => n,Answer() same => n,Set(TIMEOUT(response)=10) same => n,Playback(vpbx/vital-welcome-wake-up-call) same => n,Set(EXTENSION_NUMBER=${CALL_SOURCE}) same => n,Set(CALL_CONTEXT=${COS_NAME}) same => n,Set(LANGUAGE=${CHANNEL(language)}) same => n,Set(WKP_TREE=${TENANT}/WAKE_UP) same => n,Set(EXT_TREE=${TENANT}/extensions) same => n,Set(WKP_REMOTE=no) same => n,GotoIf($["${ARG1}"="remote"]?:cwkp) same => n,Set(WKP_REMOTE=yes) same => n,Set(password=${REMOTEWAKEUPCALL}) same => n,GotoIf($["${password}"=""]?read_extension) same => n,Authenticate(${password}) same => n(read_extension),Read(EXTENSION_NUMBER,vpbx/vital-remote-wake-up-call-number,,,3,5) same => n,GotoIf($["${EXTENSION_NUMBER}"=""]?read_extension) same => n,GotoIf(${DB_EXISTS(${EXT_TREE}/${EXTENSION_NUMBER}/context)}?:read_extension) same => n,Set(CALL_CONTEXT=${DB(${EXT_TREE}/${EXTENSION_NUMBER}/context)}) same => n,Set(LANGUAGE=${DB(${EXT_TREE}/${EXTENSION_NUMBER}/language)}) same => n(cwkp),Goto(create_wkp,1) exten => create_wkp,1,NoOp(Wakeup Call ${ARG1}) same => n,NoOp(New Wakeup Call) same => n,Set(WKP_CALLEE=Local/${EXTENSION_NUMBER}@${CALL_CONTEXT}) same => n(read_time),Read(TIME,enter-a-time,4,,3,5) same => n,GotoIf($[${TIME:0:2}<24]?:time_error) same => n,GotoIf($[${TIME:2:2}<60]?:time_error) same => n,Goto(time_ok) same => n(time_error),Playback(time&error) same => n,Goto(read_time) same => n(time_ok),NoOp() same => n,Set(CURRENT_DATE=${STRFTIME($[${EPOCH}],,%Y%m%d)}) same => n,Set(CURRENT_TIME=${STRFTIME($[${EPOCH}],,%H%M)}) same => n,GotoIf($[${CURRENT_TIME} < ${TIME}]?:tomorrow) same => n,Set(EPOCH_TIME=${EPOCH}) same => n,Set(WKP_TIME=${STRFTIME(${EPOCH_TIME},,%Y%m%d)}${TIME}) same => n,Goto(continue_creation) same => n(tomorrow),NoOp(Wakeup Call for Tomorrow) same => n,Set(EPOCH_TIME=$[${EPOCH}+86400]) same => n,Set(WKP_TIME=${STRFTIME(${EPOCH_TIME},,%Y%m%d)}${TIME}) same => n(continue_creation),NoOp() same => n,Set(WKP_ID=WKP_${UNIQUEID}) same => n,Set(WKP_NAME=${WKP_TIME}.${WKP_ID}.call) same => n,GotoIf(${DB_EXISTS(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_TIME})}?:create_call_file) same => n,NoOp(Wake up call already exist) same => n,Set(WKP_ID=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_TIME})}) same => n,Set(WKP_NAME=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID})}) same => n,Read(CANCEL_WKP,to-cancel-wakeup&press-1,1,,3,5) same => n,GotoIf($["${CANCEL_WKP}"="1"]?:end) same => n,DBdeltree(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}) same => n,DBdeltree(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_TIME}) same => n,System(rm -f ${ASTSPOOLDIR}/outgoing/${WKP_NAME}) same => n,Playback(wakeup-call-cancelled&for&extension) same => n,Saydigits(${EXTENSION_NUMBER}) same => n,Playback(goodbye) same => n,Hangup() same => n(create_call_file),NoOp() same => n(read_options),Read(OPTION,"wakeup-for-one-time&press-1&for-a-daily-wakeup-call&press-2",1,,3,5) same => n,GotoIf($["${OPTION}"="1"]?:second_opt) same => n,Set(WKP_MODE=one_time) same => n,Goto(continue_file_creation) same => n(second_opt),GotoIf($["${OPTION}"="2"]?:read_options) same => n,Set(WKP_MODE=permanent) same => n(continue_file_creation),GoSub(sub-create-wake-up-file,s,1(${WKP_TIME},${WKP_CALLEE},${CALL_SOURCE},${WKP_ID},${WKP_TREE})) same => n,Playback(rqsted-wakeup-for&extension) same => n,Saydigits(${EXTENSION_NUMBER}) same => n,Playback(goodbye) same => n(end),Hangup() exten => h,1,NoOp(Hangup Call) same => n,GotoIf($["${WAKE_UP_CALL}"="yes"]?:end) same => n,Gosub(sub-create-wake-up-tree,s,1(${WKP_TREE},${EXTENSION_NUMBER},${WKP_TIME},${WKP_ID},${WKP_NAME},${WKP_MODE},${EPOCH_TIME},${TIME},${WKP_CALLEE},${LANGUAGE})) same => n,System(mv ${TEMP_FILE} ${ASTSPOOLDIR}/outgoing/${WKP_NAME}) same => n(end),NoOp() [sub-create-wake-up-tree] exten => s,1,NoOp(Create Wake up tree) same => n,Set(DB(${ARG1}/${ARG2}/${ARG3})=${ARG4}) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4})=${ARG5}) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4}/time_id)=${ARG3}) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4}/mode)=${ARG6}) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4}/tries)=0) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4}/max_tries)=3) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4}/epoch_time)=${ARG7}) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4}/time)=${ARG8}) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4}/callee)=${ARG9}) same => n,Set(DB(${ARG1}/${ARG2}/${ARG4}/language)=${ARG10}) same => n,Return() [sub-create-wake-up-file] exten => s,1,NoOp(Create Wake Up Call Outgoing File) same => n,Set(WKP_CONTEXT=wake-up-call) same => n,Set(__TEMP_FILE=${ASTSPOOLDIR}/${ARG4}.call) same => n,System(echo "Channel: ${ARG2} \nMaxRetries: 2 \nRetryTime: 45 \nWaitTime: 30 \nCallerid: "WAKEUP CALL" <${ARG3}> \nContext: ${WKP_CONTEXT} \nExtension: s \nSetvar: EXTENSION_NUMBER=${ARG3} \nSetvar: WKP_TREE=${ARG5} \nSetvar: IGNORE_DIVERSIONS=yes \nSetvar: CALL_ORIGIN=feature \nSetvar: FEATURE_SERVICE=wake_up \nSetvar: WKP_ID=${ARG4}" > ${TEMP_FILE}) same => n,System(touch -t ${ARG1} ${TEMP_FILE}) same => n,Set(__WAKE_UP_CALL=yes) same => n,Return() [wake-up-call] exten => s,1,NoOp(WAKEUP CALL) same => n,NoCDR() same => n,GotoIf($["${WKP_NO_ANSWERED}"="yes"]?no_answer) same => n,Answer() same => n(no_answer),Set(WKP_TIME_ID=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/time_id)}) same => n,Set(WKP_MODE=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/mode)}) same => n,Set(WKP_LANG=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/language)}) same => n,Set(WKP_TIME=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/time)}) same => n,Set(EPOCH_TIME=${EPOCH}) same => n,Set(WKP_CALLEE=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/callee)}) same => n,Set(CHANNEL(language)=${WKP_LANG}) same => n,GotoIf($["${WKP_MODE}"="permanent"]?:continue_wkp) same => n,Set(NEW_EPOCH_TIME=$[${EPOCH_TIME}+86400]) same => n,Set(NEXT_WKP_TIME=${STRFTIME(${NEW_EPOCH_TIME},,%Y%m%d)}${WKP_TIME}) same => n,Set(WKP_NAME=${NEXT_WKP_TIME}.${WKP_ID}.call) same => n,GoSub(sub-create-wake-up-file,s,1(${NEXT_WKP_TIME},${WKP_CALLEE},${EXTENSION_NUMBER},${WKP_ID},${WKP_TREE})) same => n,GotoIf($["${WKP_NO_ANSWERED}"="yes"]?end) same => n(continue_wkp),NoOp() same => n,Playback(this-is-yr-wakeup-call) same => n,GotoIf($["${WKP_SKIP_SNOOZE}"="yes"]?say-time) same => n,Read(SNOOZE_OPTION,"to-snooze-for&digits/5&minutes&press-1&digits/10&minutes&press-2&digits/15&minutes&press-3",1,,3,5) same => n,GotoIf($["${SNOOZE_OPTION}"=""]?say-time) same => n,GotoIf($[$[${SNOOZE_OPTION}=1]|$[${SNOOZE_OPTION}=2]|$[${SNOOZE_OPTION}=3]]?snooze,1) same => n(say-time),Playback(at-tone-time-exactly) same => n,Playback(beep) same => n,SayUnixTime(,,IMp) same => n(end),Hangup() exten => snooze,1,NoOp(You've Decided to take a nap) same => n,Playback(vpbx/vital-snooze-for&digits/$[${SNOOZE_OPTION}*5]&minutes&activated&silence/1&goodbye) same => n,Set(WKP_POSTPONED=yes) same => n,Hangup() exten => h,1,NoOp(Hangup Call) same => n,NoCDR() same => n,Set(__FEATURE_SERVICE=none) same => n,DBdeltree(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_TIME_ID}) same => n,GotoIf($["${WAKE_UP_CALL}"="yes"]?:one_time) same => n,Set(DB(${WKP_TREE}/${EXTENSION_NUMBER}/${NEXT_WKP_TIME})=${WKP_ID}) same => n,Set(DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID})=${WKP_NAME}) same => n,Set(DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/time_id)=${NEXT_WKP_TIME}) same => n,Set(DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/tries)=0) same => n,Set(DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/epoch_time)=${EPOCH_TIME}) same => n,System(mv ${TEMP_FILE} ${ASTSPOOLDIR}/outgoing/${WKP_NAME}) same => n(one_time),GotoIf($["${WKP_MODE}"="one_time"]?:test_snooze) same => n,DBdeltree(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}) same => n,ExecIf($["X${WKP_DB_ID}X"!="XX"]?Set(ODBC_WK-STATE()=${WKP_DB_ID},E)) same => n(test_snooze),NoOp() same => n,GotoIf($["${WKP_POSTPONED}"="yes"]?:end) same => n,Set(SNOOZE_TIME=5) same => n,ExecIf($[${SNOOZE_OPTION}=2]?Set(SNOOZE_TIME=10)) same => n,ExecIf($[${SNOOZE_OPTION}=3]?Set(SNOOZE_TIME=15)) same => n,Set(SNOOZE_EPOCH=$[${EPOCH}+$[${SNOOZE_TIME}*60]]) same => n,Set(SNOOZE_WKP_TIME=${STRFTIME(${SNOOZE_EPOCH},,%H%M)}) same => n,Set(SNOOZE_WKP_DATE_TIME=${STRFTIME(${SNOOZE_EPOCH},,%Y%m%d%H%M)}) same => n,Set(SNOOZE_WKP_ID=WKP_${UNIQUEID}) same => n,Set(SNOOZE_WKP_NAME=${SNOOZE_WKP_DATE_TIME}.${SNOOZE_WKP_ID}.call) same => n,GoSub(sub-create-wake-up-file,s,1(${SNOOZE_WKP_DATE_TIME},${WKP_CALLEE},${EXTENSION_NUMBER},${SNOOZE_WKP_ID},${WKP_TREE})) same => n,Gosub(sub-create-wake-up-tree,s,1(${WKP_TREE},${EXTENSION_NUMBER},${SNOOZE_WKP_DATE_TIME},${SNOOZE_WKP_ID},${SNOOZE_WKP_NAME},one_time,${SNOOZE_EPOCH},${SNOOZE_WKP_TIME},${WKP_CALLEE},${WKP_LANG})) same => n,System(mv ${TEMP_FILE} ${ASTSPOOLDIR}/outgoing/${SNOOZE_WKP_NAME}) same => n(end),NoOp() [wake-up-no-answered] exten => s,1,NoOp(Wake up call was not answered by ${EXTENSION_NUMBER}) same => n,NoCDR() same => n,Set(FEATURE_SERVICE=none) same => n,Set(__WKP_NO_ANSWERED=yes) same => n,GotoIf(${DB_EXISTS(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID})}?:end) same => n,Set(TRIES=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/tries)}) same => n,Set(MAX_TRIES=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/max_tries)}) same => n,Set(WKP_MODE=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/mode)}) same => n,Set(WKP_TIME_ID=${DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/time_id)}) same => n,Set(TRIES=$[${TRIES}+1]) same => n,Set(DB(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}/tries)=${TRIES}) same => n,GotoIf($[${TRIES}=${MAX_TRIES}]?:end) same => n,GoSubIf($["${WKP_MODE}"="permanent"]?wake-up-call,s,4) same => n,DBdeltree(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_TIME_ID}) same => n,DBdeltree(${WKP_TREE}/${EXTENSION_NUMBER}/${WKP_ID}) same => n,ExecIf($["X${WKP_DB_ID}X"!="XX"]?Set(ODBC_WK-STATE()=${WKP_DB_ID},F)) same => n(end),Return() ;------------------------------------------------------------------- ;END WAKEUP CALL ;VOICE MAIL VER. 0.0.0 ;------------------------------------------------------------------- [sub-send-voicemail] exten => s,1,NoOp(SUB: VOICE MAIL) same => n,Set(VOICEMAIL_BOX=${DB(${TENANT}/extensions/${ARG1}/voicemail)}) same => n,GotoIf($[${VM_INFO(${VOICEMAIL_BOX},exists)}]?:vm_disabled) same => n,Gosub(sub-vm,s,1(${VOICEMAIL_BOX},${ARG2})) same => n,Goto(end) same => n(vm_disabled),PlayBack(sorry&but&vpbx/vital-vm-no-available) same => n(end),Hangup() ;END of [sub-send-voicemail] ;------------------------------------------------------------------- ;VOICE MAIL ;HANDLE HANGUP CAUSE VER. 1.0.0 ;------------------------------------------------------------------- [sub-hangup-cause] exten => s,1,NoOp(Executing Hangup Cause ${ARG1}) same => n,GotoIf($[$["${ARG1}"="16"]|$["${SKIP_HANGUP_AUDIOS}"="yes"]]?hangup) same => n,NoCDR() same => n,Progress() same => n,GotoIf($[$["${ARG1}"="1"]|$["${ARG1}"="2"]|$["${ARG1}"="3"]]?invalid_route,1) same => n,GotoIf($[$["${ARG1}"="17"]|$["${ARG1}"="19"]|$["${ARG1}"="18"]|$["${ARG1}"="21"]]?busy,1) same => n,GotoIf($[$["${ARG1}"="20"]|$["${ARG1}"="27"]|$["${ARG1}"="44"]]?out_of_service,1) same => n,GotoIf($["${ARG1}"="28"]?wrong_number,1) same => n,GotoIf($[$["${ARG1}"="38"]|$["${ARG1}"="41"]|$["${ARG1}"="42"]|["${ARG1}"="127"]]?network_error,1) same => n(hangup),Hangup() exten => invalid_route,1,NoOp(Invalid Route) same => n,Playback(im-sorry&no-route-exists-to-dest&goodbye,noanswer) same => n,Hangup() exten => busy,1,NoOp(Busy) same => n,Busy(5) same => n,Hangup() exten => out_of_service,1,NoOp(Out of Service) same => n,Playback(vpbx/trunk-out-service,noanswer) same => n,Hangup() exten => wrong_number,1,NoOp(Wrong Number) same => n,Playback(im-sorry&you-dialed-wrong-number&check-number-dial-again,noanswer) same => n,Hangup() exten => network_error,1,NoOp(Network Error) same => n,Playback(im-sorry&cannot-complete-network-error&please-try-again-later,noanswer) same => n,Hangup() ;END of [sub-all-circuits-busy] ;------------------------------------------------------------------- ;HANGUP CAUSE ;DIAL STATUS VER. 0.0.0 ;------------------------------------------------------------------- [sub-dial-status] exten => s,1,NoOp(FEATURE: DIAL STATUS) same => n,GotoIf($[${DIALSTATUS} = CHANUNAVAIL]?unavail) same => n,GotoIf($[${DIALSTATUS} = NOANSWER]?unavail) same => n,GotoIf($[${DIALSTATUS} = BUSY]?busy) same => n,GotoIf($[${DIALSTATUS} = CONGESTION]?busy) same => n,GotoIf($[${DIALSTATUS} = CANCEL]?busy) same => n,GotoIf($[${DIALSTATUS} = DONTCALL]?busy) same => n,GotoIf($[${DIALSTATUS} = TORTURE]?busy) same => n,GotoIf($[${DIALSTATUS} = INVALIDARGS]?busy) same => n(unavail), Goto(sub-send-voicemail,s,1(u)) same => n(busy), Goto(sub-send-voicemail,s,1(b)) same => n,Return ;END of [sub-dial-status] ;------------------------------------------------------------------- ;DIAL STATUS ;PICKUP GROUP VER. 0.0.0 ;------------------------------------------------------------------- [sub-pickup-group] exten => s,1,NoOp(Feature: Pickup Group) same => n,Pickup() same => n,Return ;END of [sub-pickup-group] ;------------------------------------------------------------------- ;END PICKUP GROUP ;DIRECT PICKUP VER. 0.0.0 ;------------------------------------------------------------------- [sub-direct-pickup] exten => s,1,NoOp(Feature: Direct Pickup) same => n,Pickup(${TENANT_PREFIX}${CALL_DESTINATION:${ARG1}}@PICKUPMARK) same => n,Return ;END of [sub-direct-pickup] ;------------------------------------------------------------------- ;END DIRECT PICKUP ;BOSS/SECRETARY MODE VER. 1.0.0 ;------------------------------------------------------------------- [sub-boss-secretary-state] exten => s,1,NoOp(SUB: BOSS/SECRETARY ENABLED/DISABLED) same => n,Answer same => n,Wait(1) same => n,GotoIf($["${DB(${TENANT}/extensions/${CALL_SOURCE}/is_secretary)}"="yes"]?secretary) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/BOSS/enable)}"="yes"]?:enable) same => n,Gosub(sub-cf-checkall,s,1) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/BOSS/enable)=no) same => n,Set(secretaryexten=${DB(${TENANT}/extensions/${CALL_SOURCE}/secretary)}) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}BOSS_${CALL_SOURCE})=NOT_INUSE) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "disable-BOSS" "${TENANT}" "${CALL_SOURCE}") same => n,Playback(vpbx/secretary-deactivated) same => n,SayDigits(${secretaryexten}) same => n,Hangup() same => n(enable),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/BOSS/enable)=yes) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)=yes) same => n,Set(secretaryexten=${DB(${TENANT}/extensions/${CALL_SOURCE}/secretary)}) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}BOSS_${CALL_SOURCE})=BUSY) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "enable-BOSS" "${TENANT}" "${CALL_SOURCE}") same => n,Playback(vpbx/secretary-activated) same => n,SayDigits(${secretaryexten}) same => n,Hangup() same => n(secretary),NoOp(Setting up secretary Status) same => n,Set(ABSENT_SECRETARY=${DB(${TENANT}/extensions/${CALL_SOURCE}/absent_secretary)}) same => n,GotoIf($[$["${ABSENT_SECRETARY}"=""]|$["${ABSENT_SECRETARY}"="no"]]?:enable_secretary) same => n,Gosub(sub-cf-checkall,s,1) same => n,Set(DB(${TENANT}/extensions/${CALL_SOURCE}/absent_secretary)=yes) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "absent-secretary" "${TENANT}" "${CALL_SOURCE}") same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}BOSS_${CALL_SOURCE})=NOT_INUSE) same => n,Playback(vpbx/vital-boss-secretary) same => n,Playback(de-activated) same => n,Hangup() same => n(enable_secretary),NoOp() same => n,Set(DB(${TENANT}/extensions/${CALL_SOURCE}/absent_secretary)=no) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "enable-secretary" "${TENANT}" "${CALL_SOURCE}") same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}BOSS_${CALL_SOURCE})=BUSY) same => n,Playback(vpbx/vital-boss-secretary) same => n,Playback(activated) same => n,Hangup() ;END of [sub-boss-secretary-state] ;------------------------------------------------------------------- ;END BOSS/SECRETARY MODE ;PERSONAL ASSISTANT VER. 1.0.0 ;------------------------------------------------------------------- [sub-personal-assistant] exten => s,1,NoOp(SUB: PERSONAL ASSISTANT) same => n,Set(TIMEOUT(digit)=1) same => n,Set(TIMEOUT(response)=3) same => n,Set(TRY_P=0) same => n(PAINVALID),Set(TRY_P=$[${TRY_P}+1]) same => n,Gotoif($[${TRY_P} > 3]?VM) same => n,BackGround(${ASTSPOOLDIR}/${TENANT}/pa/${CALL_DESTINATION}/pamsg) same => n,WaitExten() ;Default Option same => n(default_dest),Set(DEST0_P=${DB(${TENANT}/diversions/${CALL_DESTINATION}/PEA/destination_0)}) same => n,GotoIf($["${DEST0_P}"=""]?VM) same => n,Gosub(${DEST0_P}) ;Voice Mail same => n(VM),Set(VMENABLED_P=${DB(${TENANT}/extensions/${CALL_DESTINATION}/vmenabled)}) same => n,GotoIf($[$["${VMENABLED_P}"="no"]|$["${VMENABLED_P}"=""]]?NOVM) same => n,Set(VOICEMAIL_P=${DB(${TENANT}/extensions/${CALL_DESTINATION}/voicemail)}) same => n,Gosub(sub-vm,s,1(${VOICEMAIL_P},u)) same => n,Hangup() same => n(NOVM),Playback(vpbx/vital-vm-no-available) same => n,Hangup() ;PEA OPTIONS exten => _[1-4],1,Gosub(exec_dest_opt,1(${EXTEN})) exten => exec_dest_opt,1,NoOp(Executing option ${ARG1}) same => n,Set(DESTINATION=${DB(${TENANT}/diversions/${CALL_DESTINATION}/PEA/destination_${ARG1})}) same => n,GotoIf($["${DESTINATION}"=""]?s,default_dest) same => n,Gosub(${DESTINATION}(${DESTINATION_COS_NAME},${CALL_DESTINATION})) ;Option Invalid exten => i,1,Playback(invalid) same => n,Gosub(s,PAINVALID) ;Option TimeOut exten => t,1,Playback(invalid) same => n,Gosub(s,PAINVALID) ;END of [sub-personal-assitant] ;------------------------------------------------------------------- [sub-personal-assistant-state] exten => s,1,NoOp(SUB: PERSONAL ASSISTANT ENABLED/DISABLED) same => n,Answer same => n,Wait(1) same => n,System(test -e ${ASTSPOOLDIR}/${TENANT}/pa/${CALL_SOURCE}/pamsg.wav) same => n,Noop(${SYSTEMSTATUS}) same => n,GotoIf($["${SYSTEMSTATUS}" = "SUCCESS"]?:recording_no_exist) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/PEA/enable)}"="yes"]?disable_pea) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/PEA/enable)=yes) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)=yes) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}PEA_${CALL_SOURCE})=BUSY) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "enable-PEA" "${TENANT}" "${CALL_SOURCE}") same => n,Playback(vpbx/vital-personal-assistant&activated) same => n,Hangup() same => n(disable_pea),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/PEA/enable)=no) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}PEA_${CALL_SOURCE})=NOT_INUSE) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "disable-PEA" "${TENANT}" "${CALL_SOURCE}") same => n,Gosub(sub-cf-checkall,s,1) same => n,Playback(vpbx/vital-personal-assistant&de-activated) same => n,Hangup() same => n(recording_no_exist),Noop( FILE NOT PRESENT ${SYSTEMSTATUS}) same => n,Playback(vpbx/vital-personal-assistant-no-recording) same => n,Hangup() ;------------------------------------------------------------------ [sub-personal-assistant-rec-msg] exten => s,1,NoOp(SUB: PERSONAL ASSISTANT RECORD MESSAGE) same => n,Answer same => n,Wait(1) same => n,Set(RecordedFilename=pamsg) same => n,Set(RandomNumber=${RAND()}) same => n(record),Playback(vpbx/vital-personal-assistant-rec-message&astcc-followed-by-the-pound-key) same => n,Wait(1) same => n,Record(${ASTSPOOLDIR}/${TENANT}/pa/${CALL_SOURCE}/temporaryRecording-${RandomNumber}.wav) same => n(handle_recording),Read(ActionItem,vm-review,1) same => n,GotoIf($['${ActionItem}' = '1' | '${ActionItem}' = '2' | '${ActionItem}' = '3']?valid_action) same => n,Playback(wrong-try-again-smarty) same => n,Goto(handle_recording) same => n(valid_action),NoOp() same => n,GotoIf($['${ActionItem}' = '1']?accept,1) ; keep this recording same => n,GotoIf($['${ActionItem}' = '3']?record) ; re-record it same => n,Playback(${ASTSPOOLDIR}/${TENANT}/pa/${CALL_SOURCE}/temporaryRecording-${RandomNumber}) same => n,Goto(handle_recording) exten => accept,1,Verbose(2,Recording accepted!) same => n,System(mkdir -p ${ASTSPOOLDIR}/${TENANT}/pa/${CALL_SOURCE}) same => n,System(mv ${ASTSPOOLDIR}/${TENANT}/pa/${CALL_SOURCE}/temporaryRecording-${RandomNumber}.wav ${ASTSPOOLDIR}/${TENANT}/pa/${CALL_SOURCE}/${RecordedFilename}.wav) same => n,Playback(vm-message&recorded) exten => h,1,Verbose(2,Cleanup tmp recording if recording wasn't finished) same => n,System(test -e ${ASTSPOOLDIR}/${TENANT}/pa/${CALL_SOURCE}/temporaryRecording-${RandomNumber}.wav) same => n,GotoIf($["${SYSTEMSTATUS}" = "SUCCESS"]?:no_recodring) same => n,System(rm -f ${ASTSPOOLDIR}/${TENANT}/pa/${CALL_SOURCE}/temporaryRecording-${RandomNumber}.wav) same => n(no_recodring),hangup(); ;FOLLOWME VER. 1.0.0 ;------------------------------------------------------------------- [sub-followme-state] exten => s,1,NoOp(SUB: FOLLOWME ENABLED/DISABLED) same => n,Answer() same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/FWM/enable)}"="yes"]?disable_fwm) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/FWM/enable)=yes) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)=yes) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}FWM_${CALL_SOURCE})=BUSY) same => n,Set(ODBC_DIVERSIONS(${CALL_SOURCE},${TENANT},FWM)=yes) same => n,Playback(vpbx/vital-follow-me&activated) same => n,Hangup() same => n(disable_fwm),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/FWM/enable)=no) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}FWM_${CALL_SOURCE})=NOT_INUSE) same => n,Set(ODBC_DIVERSIONS(${CALL_SOURCE},${TENANT},FWM)=no) same => n,Gosub(sub-cf-checkall,s,1) same => n,Playback(vpbx/vital-follow-me&de-activated) same => n,Hangup() ;END of [sub-followme-state] ;------------------------------------------------------------------- ;END FOLLOWME ;DND VER. 1.0.0 ;------------------------------------------------------------------- [sub-dnd-state] exten => s,1,NoOp(SUB: DND ENABLED/DISABLED) same => n,Answer() same => n,Set(DND_OPTION=${ARG1}) same => n,GotoIf($["${DND_OPTION}"="1"]?enable_dnd) same => n,GotoIf($["${DND_OPTION}"="2"]?disable_dnd) same => n,Wait(1) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/DND/enable)}"="yes"]?disable_dnd) same => n(enable_dnd),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/DND/enable)=yes) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)=yes) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}DND_${CALL_SOURCE})=INUSE) same => n,Set(DND_ACTION=yes) same => n,Playback(do-not-disturb&activated) same => n,Hangup() same => n(disable_dnd),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/DND/enable)=no) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}DND_${CALL_SOURCE})=UNAVAILABLE) same => n,Gosub(sub-cf-checkall,s,1) same => n,Set(DND_ACTION=no) same => n,Playback(do-not-disturb&de-activated) same => n,Hangup() exten => h,1,NoOP(Finish DND Call) same => n,Set(ODBC_DIVERSIONS(${CALL_SOURCE},${TENANT},DND)=${DND_ACTION}) same => n,Hangup() [sub-dnd-state-direct] exten => s,1,NoOp(SUB: Direct DND) same => n,Set(OPTION=${CALL_DESTINATION:${ARG1}}) same => n,Set(OPTION=${OPTION:1}) ; remove the '*' same => n,Gosub(sub-dnd-state,s,1(${OPTION})) same => n,Hangup() ;------------------------------------------------------------------- ;END DND ;CALL FOWARDING STATE VER. 1.0.0 ;------------------------------------------------------------------- [sub-cf-state] exten => s,1,NoOp(SUB: CALL FOWARDING ENABLED/DISABLED) same => n,Answer() same => n,Wait(1) same => n,Set(CURRENT_CF_NUMBER=${DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG2}/destination)}) same => n,GoSubIf($[ $["${CURRENT_CF_NUMBER}"=""]|$["${LEN(${CFNUMBER})}"!="0"] ]?sub-cf-set,s,1(${ARG1},${ARG2},from-cf-state,${CFNUMBER})) same => n,GotoIf($[$["${DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG2}/enable)}"="yes"]&$["${LEN(${CFNUMBER})}"="0"]]?disable_cf) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG2}/enable)=yes) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}${ARG2}_${CALL_SOURCE})=BUSY) same => n,Set(ODBC_DIVERSIONS(${CALL_SOURCE},${TENANT},${ARG2})=yes) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)=yes) same => n,Playback(${ARG1}&activated) same => n,Hangup() same => n(disable_cf),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG2}/enable)=no) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}${ARG2}_${CALL_SOURCE})=NOT_INUSE) same => n,Set(ODBC_DIVERSIONS(${CALL_SOURCE},${TENANT},${ARG2})=no) same => n,Gosub(sub-cf-checkall,s,1) same => n,Playback(${ARG1}&de-activated) same => n,Hangup() ;END of [sub-cf-state] ;------------------------------------------------------------------- [sub-cf-set] exten => s,1,NoOp(SUB: CALL FOWARDING SET NUMBER) same => n,ExecIf($["${ARG3}"!="from-cf-state"]?Answer()) same => n,ExecIf($["${ARG3}"!="from-cf-state"]?Wait(1)) same => n,Set(number=${ARG4}) same => n,GotoIf($["${number}"=""]?continue) same => n,Set(NUMBER_TO_BE_SET=${number}) same => n,Goto(skip_read) same => n(continue),Playback(${ARG1}) same => n(readnumber),Read(NUMBER_TO_BE_SET,ent-target-attendant&then-press-pound) same => n,GotoIf($["${NUMBER_TO_BE_SET}"=""]?readnumber) same => n,Wait(1) same => n(skip_read),Set(DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG2}/destination)=sub-custom-numbers,${NUMBER_TO_BE_SET},1) same => n,System(${SCRIPTS_PATH}/vitalpbx "setCFNumber" "${ARG2}" "${TENANT}" "${CALL_SOURCE}" "${NUMBER_TO_BE_SET}") same => n,ExecIf($["${ARG3}"="from-cf-state"]?return()) same => n,Playback(${ARG1}&to-extension) same => n,SayDigits(${CALL_SOURCE}) same => n,Playback(is-set-to) same => n,SayDigits(${NUMBER_TO_BE_SET}) same => n,Playback(goodbye) same => n,Hangup() ;END of [sub-cf-set] ;----------------------------------------------------------------- [sub-cfclear-all] exten => s,1,NoOp(SUB: CLEAR ALL CALL FOWARDING, DND, PERSONAL ASSISTANT BOSS/SECRETARY AND FOLLOW ME) same => n,Answer same => n,Wait(1) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)}"="no"]?end) same => n,Gosub(disable_diversion,1(BOSS,secretary&mode&de-activated)) same => n,Gosub(disable_diversion,1(PEA,vpbx/vital-personal-assistant&de-activated)) same => n,Gosub(disable_diversion,1(FWM,call-forwarding&de-activated)) same => n,Gosub(disable_diversion,1(DND,do-not-disturb&de-activated)) same => n,Gosub(disable_diversion,1(CFI,call-forwarding&de-activated)) same => n,Gosub(disable_diversion,1(CFB,call-fwd-on-busy&de-activated)) same => n,Gosub(disable_diversion,1(CFU,call-fwd-unconditional&de-activated)) same => n,Gosub(disable_diversion,1(CFN,call-fwd-no-ans&de-activated)) same => n,Gosub(disable_diversion,1(CC,vpbx/vital-call-completion&de-activated)) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)=no) same => n(end),Wait(1) same => n,Playback(vpbx/vital-all-diversions-are&de-activated&goodbye) same => n,Hangup() exten => disable_diversion,1,NoOp() same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG1}/enable)}"="no"]?return) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/${ARG1}/enable)=no) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}${ARG1}_${CALL_SOURCE})=NOT_INUSE) same => n,Set(ODBC_DIVERSIONS(${CALL_SOURCE},${TENANT},${ARG1})=no) same => n,Playback(${ARG2}) same => n(return),Return() ;END of [sub-cfclear-all] ;----------------------------------------------------------------- [sub-cf-checkall] exten => s,1,NoOp(SUB: CHECK ALL CALL FOWARDING, DND, PERSONAL ASSISTANT AND FOLLOWME) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/BOSS/enable)}" = "yes"]?END) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/PEA/enable)}" = "yes"]?END) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/FWM/enable)}" = "yes"]?END) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/DND/enable)}" = "yes"]?END) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/CC/enable)}" = "yes"]?END) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/CFI/enable)}" = "yes"]?END) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/CFB/enable)}" = "yes"]?END) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/CFN/enable)}" = "yes"]?END) same => n,GotoIf($["${DB(${TENANT}/diversions/${CALL_SOURCE}/CFU/enable)}" = "yes"]?END) same => n,Set(DB(${TENANT}/diversions/${CALL_SOURCE}/has_enable_diversions)=no) same => n(END),Return ;END of [sub-check-all] ;------------------------------------------------------------------- ;END CALL FOWARDING ;LOCK PHONE FEATURE VER. 0.0.0 ;------------------------------------------------------------------- [sub-lock-phone-state] exten => s,1,NoOp(FEATURE: LOCK/UNLOCK PHONE) same => n,Answer same => n,Set(hints_enabled=${DB(${TENANT}/extensions/${CALL_SOURCE}/hints)}) same => n,Set(phone_locked=${DB(${TENANT}/extensions/${CALL_SOURCE}/lock)}) same => n,Set(DB(${TENANT}/extensions/${CALL_SOURCE}/lock)=${IF($["${phone_locked}"="yes"]?no:yes)}) same => n,Set(sound=${IF($["${phone_locked}"="yes"]?vpbx/vital-phone-unlock:vpbx/vital-phone-lock)}) same => n,Set(LOCK_VALUE=${IF($["${phone_locked}"="yes"]?no:yes)}) same => n,Set(ODBC_LOCK-PHONE(${CALL_SOURCE},${TENANT})=${LOCK_VALUE}) same => n,PlayBack(silence/1&${sound}) same => n,GotoIf($["${hints_enabled}" = "yes"]?:end_call) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}LOK_${CALL_SOURCE})=${IF($["${phone_locked}"="yes"]?NOT_INUSE:BUSY)}) same => n(end_call),Hangup() ;END of [sub-lock-phone-state] ;END LOCK PHONE FEATURE ;------------------------------------------------------------------- ;ACCOUNT CODE VER. 1.0.0 ;------------------------------------------------------------------- [sub-account-code] exten => s,1,NoOp(FEATURE: CUSTOMER ACCOUNT CODE) same => n,Answer same => n,Wait(1) same => n,Set(TIMEOUT(response)=10) same => n,Set(TRY=1) same => n(try_again),Read(accountcode,vpbx/vital-customer-account-number) same => n,GotoIf($["${DB(${TENANT}/accountcodes/${accountcode})}"="no"]?acc_disabled) same => n,GotoIf($["${DB(${TENANT}/accountcodes/${accountcode})}"="yes"]?:repeat) same => n(read_number),Read(NUMBER_TO_DIAL,pls-entr-num-uwish2-call&followed_pound) same => n,GotoIf($["XXX${NUMBER_TO_DIAL}"="XXX"]?read_number) same => n,ResetCDR() same => n,Set(CDR(customer_code)=${accountcode}) same => n,Set(CDR(destination)=${NUMBER_TO_DIAL}) same => n,Goto(${COS_NAME},${NUMBER_TO_DIAL},1) same => n,Goto(hangup) same => n(invalid),Playback(im-sorry&vpbx/vital-max-tries&vm-goodbye) same => n,Goto(hangup) same => n(repeat),Set(TRY=$[${TRY}+1]) same => n,GotoIf($[${TRY} > 3]?invalid) same => n,Playback(vpbx/vital-customer-account-number-invalid&vm-pls-try-again) same => n,Goto(try_again) same => n(acc_disabled),Playback(im-sorry&vpbx/vital-customer-account-number-disabled&vm-goodbye) same => n(hangup),Hangup() ;END of [sub-account-code] ;------------------------------------------------------------------- ;END ACCOUNT CODE ;AUTORIZATION CODE VER. 1.0.0 ;------------------------------------------------------------------- [sub-autorization-code] ;TODO: Look for better audio files exten => s,1,NoOp(FEATURE: AUTORIZATION CODE) same => n,Answer() same => n,Set(TRIES=1) same => n,Set(MAX_TRIES=3) same => n(get_password), NoOp() same => n,Read(AUTH_CODE,vpbx/vital-authorization-code,,,3,5) same => n,GotoIf($["${READSTATUS}"="TIMEOUT"]?auth_fail,1) same => n,GotoIf($["${DB(${TENANT}/authcodes/${AUTH_CODE}/enabled)}"="no"]?auth_disabled) same => n,GotoIf($["${DB(${TENANT}/authcodes/${AUTH_CODE}/enabled)}"="yes"]?ok) same => n,Set(TRIES=$[${TRIES}+1]) same => n,GotoIf($[${TRIES} <= ${MAX_TRIES}]?:auth_fail,1) same => n,Playback(im-sorry&vpbx/vital-auth-code-invalid&vm-pls-try-again) same => n,Goto(get_password) same => n(ok),NoOp() same => n,Set(COS_FOR_CALL=${DB(${TENANT}/authcodes/${AUTH_CODE}/cos)}) same => n,Set(AUTH_ALIAS=${DB(${TENANT}/authcodes/${AUTH_CODE}/alias)}) same => n,Set(AUTH_ALIAS=${IF($["${AUTH_ALIAS}"=""]?${AUTH_CODE}:${AUTH_ALIAS})}) same => n(read_numaber),Read(NUMBER_TO_DIAL,pls-entr-num-uwish2-call&followed_pound,,,3,5) same => n,GotoIf($["${READSTATUS}"="TIMEOUT"]?auth_fail,1) same => n,ResetCDR() same => n,Set(CDR(auth_code)=${AUTH_ALIAS}) same => n,Set(CDR(destination)=${NUMBER_TO_DIAL}) same => n,Goto(${COS_FOR_CALL},${NUMBER_TO_DIAL},1) same => n,Hangup() same => n(auth_disabled),Playback(im-sorry&vpbx/vital-auth-code-disabled&vm-goodbye) same => n,Hangup() exten => auth_fail,1,NoOp(Authorization Reach MAX Tries/Timeout) same => n,Playback(vpbx/vital-max-tries&vm-goodbye) same => n,Hangup() exten => t,1,Goto(timeout-reached,s,1) same => n,Hangup() ;END of [sub-autorization-code] ;------------------------------------------------------------------- ;END AUTORIZATION CODE ;REMOTE SUSTITUTION VER. 1.0.0 ;------------------------------------------------------------------- [sub-remote-substitution] exten => s,1,NoOp(Execution of remote substitution) same => n,Set(TRIES=3) same => n,Set(TRY=0) same => n(enter_substitution_number),Set(TRY=$[${TRY}+1]) same => n,GotoIf($[${TRY}>${TRIES}]?end_call) same => n,Read(SUBSTITUTION_NUMBER,please-enter-the&extension&followed_pound) same => n,Set(CONTEXT_TO_DIAL=${DB(${TENANT}/extensions/${SUBSTITUTION_NUMBER}/context)}) same => n,GotoIf($["${CONTEXT_TO_DIAL}"!=""]?:enter_substitution_number) same => n,Set(EXT_PASSWORD=${DB(${TENANT}/extensions/${SUBSTITUTION_NUMBER}/password)}) same => n,GotoIf($["XXX${EXT_PASSWORD}"="XXX"]?nopassword) same => n,Authenticate(${EXT_PASSWORD}) same => n(nopassword),NoOp(Ask for number to dial) same => n,Set(INTERNAL_CID=${DB(${TENANT}/extensions/${SUBSTITUTION_NUMBER}/internal_cid)}) same => n,Set(TRY=0) same => n(enter_number_to_dial),Set(TRY=$[${TRY}+1]) same => n,GotoIf($[${TRY}>${TRIES}]?end_call) same => n,Read(NUMBER_TO_DIAL,pls-entr-num-uwish2-call&followed_pound) same => n,GotoIf($["XXX${NUMBER_TO_DIAL}"="XXX"]?enter_number_to_dial) same => n,Set(CALLERID(all)=${INTERNAL_CID}) same => n,ResetCDR() same => n,Set(CDR(destination)=${NUMBER_TO_DIAL}) same => n,Goto(${CONTEXT_TO_DIAL},${NUMBER_TO_DIAL},1) same => n(end_call),Hangup() exten => t,1,NoOp(Time out) same => n,Goto(timeout-reached,s,1) exten => i,1,NoOp(Invalid Dial) same => n,Goto(invalid-dest,s,1) ;END of [sub-remote-substitution] ;------------------------------------------------------------------- ;END REMOTE SUSTITUTION ;TERMINATION VER. 1.0.0 ;------------------------------------------------------------------- [app-termination] exten => hangup,1,Noop(Termination: Hangup Call) same => n,ForkCDR(e) same => n,NoCDR() same => n,Hangup() exten => musiconhold,1,Noop(Termination: Music on Hold Until Caller Hangup) same => n,Answer same => n,ForkCDR(e) same => n,NoCDR() same => n,MusicOnHold() exten => congestion,1,Noop(Termination: Signal the other end of congestion. Wait for hangup) same => n,ForkCDR(e) same => n,NoCDR() same => n,Progress() same => n,Playtones(congestion) same => n,Wait(2) same => n,Congestion(10) same => n,Hangup() exten => busy,1,Noop(Termination: Signal the other end that the line is busy) same => n,ForkCDR(e) same => n,NoCDR() same => n,Progress() same => n,Playtones(busy) same => n,Wait(2) same => n,Busy(10) same => n,Hangup() exten => ring,1,Noop(Termination: Ring Tone Until Caller Hangup) same => n,ForkCDR(e) same => n,NoCDR() same => n,Progress() same => n,Playtones(ring) same => n,Wait(100) same => n,Hangup() exten => _X.,1,NoOp(No valid number found) same => n,ExecIf($[$["${FROM_QUEUE_CALLBACK}"="yes"]|$["${SRC_APP}"="IVR"]]?Hangup()) same => n,ForkCDR(e) same => n,Goto(invalid-dest-cos,s,1) ;END of [app-termination] ;------------------------------------------------------------------- ;END TERMINATION ;CUSTOM RECORDING VER. 1.0.0 ;------------------------------------------------------------------- [sub-custom-recording] ;${ARG1}-->Tenant exten => s,1,NoOp(FEATURE: CUSTOM RECORDING) same => n,Answer same => n,Wait(1) same => n,Set(CURRENT_TIME=${STRFTIME($[${EPOCH}],,%Y%m%d)}) same => n,Set(FILENAME=/tmp/${CURRENT_TIME}_${CALLERID(num)}_${UNIQUEID}.wav) same => n,NoOp(Recording File: ${FILENAME}) same => n(rerecord),Playback(vpbx/vital-custom-recording) same => n,Record("${FILENAME}",,,k) same => n,Set(TIMEOUT(digit)=1) same => n,Set(TIMEOUT(response)=15) same => n(menu),Background(to-listen-to-it&press-1) same => n(accept),Background(to-accept-recording&press-2) same => n,Background(to-rerecord-announce&digits/3) same => n,Background(to-cancel-this-msg&press-4) same => n,Wait(2) same => n,Goto(menu) exten => 1,1,Playback("${FILENAME:0:-4}") same => n,Goto(s,accept) exten => 2,1,Playback(auth-thankyou) same => n,System(/usr/share/vitalpbx/scripts/custom_recording "${FILENAME}" "${TENANT}" "${RECORDING_ID}") same => n,Hangup() exten => 3,1,Goto(s,rerecord) exten => 4,1,Playback(cancelled) same => n,System(rm -f "${FILENAME}") same => n,Hangup() exten => i,1,Goto(menu) exten => t,1,Goto(menu) exten => h,1,NoOp(Finish Custom Recording) same => n,System(rm -f "${FILENAME}") ;END of [sub-custom-recording] ;------------------------------------------------------------------- ;END CUSTOM RECORDING ;DICTATE RECORD VER. 1.0.0 ;------------------------------------------------------------------- [sub-dictate-record] exten => s,1,NoOp(FEATURE: DICTATE RECORD) same => n,Answer same => n,Set(DICTATE_ENABLE=${DB(${TENANT}/extensions/${CALL_SOURCE}/dictate/enabled)}) same => n,Gotoif($["${DICTATE_ENABLE}"="yes"]?start) same => n,Playback(feature-not-avail-line) same => n,Hangup() same => n(start),Noop(CallerID is ${CALLERID(num)}) same => n,Set(FILENAME=${UNIQUEID}) same => n,Set(DIRECTORY=${ASTSPOOLDIR}/dictate/${TENANT}/${CALL_SOURCE}) same => n,Dictate(${DIRECTORY},${FILENAME}) same => n,Playback(wait-moment) same => n,System(/usr/share/vitalpbx/scripts/dictation "${TENANT}" "${DB(${TENANT}/extensions/${CALL_SOURCE}/dictate/email)}" "${CALL_SOURCE}" "${DB(${TENANT}/extensions/${CALL_SOURCE}/name)}" "${DIRECTORY}/${FILENAME}.raw" "${DB(${TENANT}/extensions/${CALL_SOURCE}/dictate/format)}") same => n,Playback(vm-goodbye) same => n,Hangup() ;END of [sub-dictate-record] ;------------------------------------------------------------------- ;END DICTATE RECORD ;LAST NUMBER THAT CALLED YOUR EXTENSION VER. 1.0.0 ;------------------------------------------------------------------- [sub-speak-last-number] exten => s,1,NoOp(SUB: LAST NUMBER THAT CALLED YOUR LINE) same => n,Answer() same => n,Set(LAST_CALLER=${DB(${TENANT}/LASTCALLER/${CALL_SOURCE})}) same => n,GotoIf($["X${LAST_CALLER}X"="XX"]?no-number) same => n,Playback(last-num-to-call) same => n,SayDigits(${LAST_CALLER}) same => n(read),Read(OPTIONS,to-call-num-press&digits/1,1,,,5) same => n,GotoIf($["X${OPTIONS}X"="XX"]?read) same => n,GotoIf($[${OPTIONS}=1]?make_call:read) same => n,Hangup() same => n(make_call),Goto(${COS_NAME},${LAST_CALLER},1) same => n(no-number),NoOp(No last caller found) same => n,Playback(num-not-in-db) same => n,Hangup() ;END of [sub-speak-last-number] ;------------------------------------------------------------------- ;END LAST NUMBER THAT CALLED YOUR LINE ;SPEAK MY EXTENSION NUMBER VER. 1.0.0 ;------------------------------------------------------------------- ;Sub for Speak Extension Number [sub-speakextennum] exten => s,1,NoOp(FEATURE: SPEAK MY EXTENSION NUMBER) same => n,Answer same => n,Wait(1) same => n,Playback(vpbx/vital-your-extension-number-is) same => n,Wait(1) same => n,SayDigits(${CALLERID(num)}) same => n,Wait(2) same => n,Hangup() ;END of [sub-speakextennum] ;------------------------------------------------------------------- ;END SPEAK MY EXTENSION NUMBER ;ECHO TEST VER. 1.0.0 ;------------------------------------------------------------------- [sub-echotest] exten => s,1,NoOp(FEATURE: ECHO TEST) same => n,Answer same => n,Wait(1) same => n,Playback(demo-echotest) same => n,Echo() same => n,Playback(demo-echodone) same => n,Hangup() ;END of [sub-echotest] ;------------------------------------------------------------------- ;END ECHO TEST ;SAY CLOCK VER. 1.0.0 ;------------------------------------------------------------------- [sub-say-clock] exten => s,1,NoOp(FEATURE: SAY CLOCK) same => n,Answer same => n,Wait(1) same => n,Playback(at-tone-time-exactly) same => n,Playback(beep) same => n,SayUnixTime(,,AdBY) same => n,Wait(1) same => n,SayUnixTime(,,IMp) same => n,Wait(2) same => n,Hangup() ;END of [sub-say-clock] ;------------------------------------------------------------------- ;END SAY CLOCK ;NIGHT MODE STATE VER. 1.0.0 ;------------------------------------------------------------------- [sub-night-mode-state] ;{ARG1}-->Index, {ARG2}-->Password exten => s,1,NoOp(FEATURE: NIGHT MODE STATE) same => n,Answer same => n,Wait(1) same => n,GotoIf($["${ARG2}" = ""]?skip) same => n,Authenticate(${ARG2},j) same => n(skip),Set(state_p=${DB(${TENANT}/nightmodes/${ARG1}/state)}) same => n,GotoIf($["${state_p}" = "yes"]?:enable) same => n,NoOp(${DB_DELETE(${TENANT}/nightmodes/${ARG1}/state)}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "disable-nm" "${ARG1}" > /dev/null 2>&1 &) same => n,GotoIf($["${ARG3}" = "hint"]?:playback-1) same => n,Set(DEVICE_STATE(Custom:NM_${ARG1})=NOT_INUSE) same => n(playback-1),ExecIf($["${ARG1}"="nm_all"]?PlayBack(vpbx/vital-night-mode-all&de-activated):PlayBack(vpbx/vital-night-mode&de-activated)) same => n,Hangup() same => n(enable),NoOp() same => n,Set(DB(${TENANT}/nightmodes/${ARG1}/state)=yes) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "enable-nm" "${ARG1}" > /dev/null 2>&1 &) same => n,GotoIf($["${ARG3}" = "hint"]?:playback-2) same => n,Set(DEVICE_STATE(Custom:NM_${ARG1})=BUSY) same => n(playback-2),ExecIf($["${ARG1}"="nm_all"]?PlayBack(vpbx/vital-night-mode-all&activated):PlayBack(vpbx/vital-night-mode&activated)) same => n,Hangup() ;END of [sub-night-mode-state] ;------------------------------------------------------------------- ;END NIGHT MODE STATE ;CHANGE PASSWORD VER. 1.0.0 ;------------------------------------------------------------------- [sub-change-password] exten => s,1,NoOp(FEATURE: CHANGE PASSWORD) same => n,Answer same => n,Wait(1) same => n(unlock),Set(password=${DB(${TENANT}/extensions/${CALL_SOURCE}/password)}) same => n,GotoIf($["${password}"=""]?ask_password) same => n,Authenticate(${password}) ;New Password same => n(ask_password),Read(NEW_PASSWORD01_P,vm-newpassword) same => n,Read(NEW_PASSWORD02_P,vm-reenterpassword) same => n,GotoIf($["${NEW_PASSWORD01_P}"!="${NEW_PASSWORD02_P}"]?mismatch) ;Infinite bucle until match same => n,Set(DB(${TENANT}/extensions/${CALL_SOURCE}/password)=${NEW_PASSWORD01_P}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "feature-password" "${TENANT}" "${CALL_SOURCE}" "${NEW_PASSWORD01_P}") same => n,Playback(vm-passchanged) same => n,Hangup() same => n(mismatch),Playback(vm-mismatch) same => n,Goto(ask_password) ;END of [sub-change-password] ;------------------------------------------------------------------- ;END CHANGE PASSWORD ;BLACK LIST VER. 1.0.0 ;------------------------------------------------------------------- [sub-blacklist-add] exten => s,1,NoOp(FEATURE: BLACK LIST ADD) same => n,Answer same => n,Set(TIMEOUT(digit)=5) same => n,Set(TIMEOUT(response)=60) same => n(re_enter),Read(number_p,enter-num-blacklist&then-press-pound) same => n,GotoIf($[${LEN(${number_p})} < 2]?re_enter) same => n,GotoIf(${DB_EXISTS(${TENANT}/blacklist/${number_p})}?already-in-blacklist,1) same => n,SayDigits(${number_p}) same => n,Read(numberconfimation_p,if-correct-press&digits/1&to-enter-a-diff-number&press&digits/0,1,,,5) same => n,GotoIf($["${numberconfimation_p}" = "1"]?accept:re_enter) same => n,Hangup() same => n(accept),Set(DB(${TENANT}/blacklist/${number_p})=Added By ${CALL_SOURCE}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "blacklist-add" "${TENANT}" "${number_p}") same => n,Playback(num-was-successfully&added&goodbye) same => n,Hangup() exten => already-in-blacklist,1,NoOp(Number ${number_p} Already in Blacklist) same => n,Playback(the-number-u-dialed&is-currently&privacy-blacklisted&goodbye) same => n,Hangup() ;END of [sub-blacklist-add] ;------------------------------------------------------------------- [sub-blacklist-remove] exten => s,1,NoOp(FEATURE: BLACK LIST REMOVE) same => n,Answer same => n,Set(TIMEOUT(digit)=5) same => n,Set(TIMEOUT(response)=60) same => n,Read(number_p,entr-num-rmv-blklist&then-press-pound,,,,) same => n,SayDigits(${number_p}) same => n,Read(numberconfimation_p,if-correct-press&digits/1,1,,,5) same => n,GotoIf($["${numberconfimation_p}" = "1"]?OK:NOK) same => n(NOK),Playback(sorry-youre-having-problems&goodbye) same => n,Hangup() same => n(OK),Noop(Deleting: ${TENANT}/blacklist/${number_p} ${DB_DELETE(${TENANT}/blacklist/${number_p})}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "blacklist-del" "${TENANT}" "${number_p}") same => n,Playback(num-was-successfully&removed&goodbye) same => n,Hangup() ;END of [sub-blacklist-remove] ;------------------------------------------------------------------- [sub-blacklist-last] exten => s,1,NoOp(FEATURE: BLACK LIST LAST) same => n,Answer same => n,Set(lastcaller_p=${DB(${TENANT}/LASTCALLER/${CALL_SOURCE})}) same => n,GotoIf($[$["${lastcaller_p}"=""] | $["${lastcaller_p}"="unknown"]]?noinfo:addnumber) same => n(noinfo),Playback(unidentified-no-callback) same => n,Hangup() same => n(addnumber),GotoIf(${DB_EXISTS(${TENANT}/blacklist/${lastcaller_p})}?already-in-blacklist,1) same => n,Playback(privacy-to-blacklist-last-caller) same => n,SayDigits(${lastcaller_p}) same => n,Set(TIMEOUT(digit)=3) same => n,Set(TIMEOUT(response)=7) same => n,Read(lastcallerconfimation_p,if-correct-press&digits/1,1,,,5) same => n,GotoIf($["${lastcallerconfimation_p}" = "1"]?OK) same => n,Playback(cancelled&goodbye) same => n,Hangup() same => n(OK),Set(DB(${TENANT}/blacklist/${lastcaller_p})=Added By ${CALL_SOURCE}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "blacklist-add" "${TENANT}" "${lastcaller_p}") same => n,Playback(num-was-successfully&added&goodbye) same => n,Hangup() exten => already-in-blacklist,1,NoOp(Number ${lastcaller_p} Already in Blacklist) same => n,Playback(im-sorry&but&number) same => n,SayDigits(${lastcaller_p}) same => n,Playback(is-currently&privacy-blacklisted&goodbye) same => n,Hangup() ;END of [macro-blacklist-last] ;------------------------------------------------------------------- [sub-check-blacklist] exten => s,1,NoOp(Testing if ${ARG2} is in Black List) same => n,GotoIf(${DB_EXISTS(${ARG1}/blacklist/${ARG2})}?banned) same => n,Return same => n(banned),NoCDR() same => n,Answer() same => n,GoSub(sub-blacklisted-prompt,s,1) same => n,Hangup() ;END of [sub-in-blacklist] ;------------------------------------------------------------------- ;END BLACK LIST ;SPY ANY CHANNEL VER. 1.0.0 ;------------------------------------------------------------------- [sub-chanspy] exten => s,1,NoOp(FEATURE: SPY ANY CHANNEL) same => n,Answer same => n,Wait(1) same => n,ChanSpy() same => n,Hangup() ;END of [sub-chanspy] ;------------------------------------------------------------------- ;END SPY ANY CHANNEL ;SPY EXTENSIONS ;------------------------------------------------------------------- [sub-spy-ext] exten => s,1,NoOp(FEATURE: SPY SPECIFIED EXTENSION) same => n,Gosub(sub-extension-spy,s,1) same => n,Hangup() ;END of [sub-spy-ext] [sub-spy-ext-whisper] exten => s,1,NoOp(FEATURE: SPY SPECIFIED EXTENSION WITH WISPER) same => n,Gosub(sub-extension-spy,s,1(whisper)) same => n,Hangup() ;END of [sub-spy-ext-whisper] [sub-spy-ext-barge] exten => s,1,NoOp(FEATURE: SPY SPECIFIED EXTENSION (BARGE MODE)) same => n,Gosub(sub-extension-spy,s,1(barge)) same => n,Hangup() ;END of [sub-spy-ext-barge] [sub-extension-spy] exten => s,1,Set(SPY_OPTIONS=${IF($["${ARG1}"="whisper"]?qwS:${IF($["${ARG1}"="barge"]?qBS:qS)})}) same => n(read_ext),Read(EXTENSION_NUMBER,vpbx/vital-spy-extension-number) same => n,GotoIf($["${EXTENSION_NUMBER}"=""]?read_ext) same => n,Set(EXTENSION_DIAL=${DB(${TENANT}/extensions/${EXTENSION_NUMBER}/dial)}) same => n,GotoIf($["${EXTENSION_DIAL}"=""]?read_ext) same => n,GotoIf($["${DB(${TENANT}/extensions/${EXTENSION_NUMBER}/spyb)}"="yes"]?:skip_pwd) same => n,Set(EXTENSION_PASSWORD=${DB(${TENANT}/extensions/${EXTENSION_NUMBER}/password)}) same => n,GotoIf($["${EXTENSION_PASSWORD}"=""]skip_pwd) same => n,Authenticate(${EXTENSION_PASSWORD},,${LEN(${EXTENSION_PASSWORD})},please-enter-the&extension&vm-password&followed_pound) same => n(skip_pwd),NoOp() same => n,Set(DEVICE_TO_SPY=) same => n,Set(COUNTER=1) same => n,Set(CURRENT_DEVICE=${CUT(EXTENSION_DIAL,&,${COUNTER})}) same => n,While($[${EXISTS(${CURRENT_DEVICE})}]) same => n,Set(DEVICE_STATUS=${DEVICE_STATE(${CURRENT_DEVICE})}) same => n,GotoIf($["${DEVICE_STATUS}"="INUSE"]?:next) same => n,Set(DEVICE_TO_SPY=${CURRENT_DEVICE}) same => n,Set(CURRENT_DEVICE=) same => n,Goto(end) same => n(next),Set(COUNTER=$[${COUNTER} + 1]) same => n,Set(CURRENT_DEVICE=${CUT(EXTENSION_DIAL,&,${COUNTER})}) same => n(end),EndWhile() same => n,GotoIf($[${LEN(${DEVICE_TO_SPY})}=0]?h-call) same => n,ChanSpy(${DEVICE_TO_SPY},${SPY_OPTIONS}) same => n(h-call),Hangup() ;------------------------------------------------------------------- ;END SPY EXTENSIONS ;INTERNAL DIRECTORY VER. 1.0.0 ;------------------------------------------------------------------- [sub-internal-directory] exten => s,1,NoOp(FEATURE: INTERNAL DIRECTORY) same => n,Answer same => n,Wait(1) same => n,Set(COUNTER=0) same => n,Set(COMPLETED=no) same => n,Set(MAXTRIES=2) same => n,While($[$[${COUNTER}<=${MAXTRIES}]&$["${COMPLETED}"="no"]]) same => n,Directory(${TOLOWER(${DB(${TENANT}/name)})}-voicemail,${DEFAULT_COS},ebp(2000)) same => n,GotoIf($[$["${DIRECTORY_RESULT}"="TIMEOUT"]|$["${DIRECTORY_RESULT}"="FAILED"]]?next) same => n,Set(COMPLETED=yes) same => n(next),Set(COUNTER=$[${COUNTER} + 1]) same => n(end-tries),EndWhile() same => n,Hangup() ;END of [sub-internal-directory] ;------------------------------------------------------------------- ;END INTERNAL DIRECTORY ;CALL CENTER VER. 1.0.0 ;------------------------------------------------------------------- [sub-queue-agent] exten => s,1,Verbose(LOGIN/LOGOUT QUEUE MEMBER) same => n,Answer same => n,Wait(1) same => n,Set(QUEUE_NUMBER=${ARG1}) same => n,GotoIf($["${QUEUE_NUMBER}"=""]?:continue) same => n(read_q_number),Read(QUEUE_NUMBER,please-enter-the&vpbx/vital-agent-queue-number&followed_pound) same => n,GotoIf($["${QUEUE_NUMBER}"=""]?read_q_number) same => n(continue),NoOp() same => n,Set(QUEUE_NAME=${DB(${TENANT}/queues/${QUEUE_NUMBER}/name)}) same => n,GotoIf($["${QUEUE_NAME}"=""]?read_q_number) same => n,GotoIf(${QUEUE_EXISTS(${QUEUE_NAME})}?:read_q_number) same => n,Set(MEMBER_TYPE=${DB(${TENANT}/queues/${QUEUE_NUMBER}/member/${CALL_SOURCE}/type)}) same => n,GosubIf($["${MEMBER_TYPE}"="dynamic"]?:no-member,1) same => n,Set(MEMBER_PENALTY=${DB(${TENANT}/queues/${QUEUE_NUMBER}/member/${CALL_SOURCE}/penalty)}) same => n,Set(CoS=${DB(${TENANT}/extensions/${CALL_SOURCE}/context)}) same => n,Set(INTERFACE=Local/${CALL_SOURCE}@${CoS}) same => n,Set(LOGIN_STATUS=${DEVICE_STATE(Custom:${TENANT_PREFIX}QAL_${CALL_SOURCE}_${QUEUE_NUMBER})}) same => n,GotoIf($["${LOGIN_STATUS}"="BUSY"]?turn_off) same => n,Set(RING_UNAVAILABLE=${DB(${TENANT}/queues/${QUEUE_NUMBER}/ring_unavailable)}) same => n,Set(AGENT_HINT=${IF($["${RING_UNAVAILABLE}"="yes"]?Agent${CALL_SOURCE}@${HINTS_CONTEXT}:${CALL_SOURCE}@${HINTS_CONTEXT})}) same => n,AddQueueMember(${QUEUE_NAME},Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n,${MEMBER_PENALTY},,${CALL_SOURCE},hint:${AGENT_HINT}) same => n,ExecIf($["${AQMSTATUS}"="ADDED"]?Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAL_${CALL_SOURCE}_${QUEUE_NUMBER})=BUSY):Goto(invalid)) same => n,Playback(vpbx/vital-agent-login) same => n,Goto(end) same => n(turn_off),RemoveQueueMember(${QUEUE_NAME},${INTERFACE});Legacy same => n,RemoveQueueMember(${QUEUE_NAME},Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAL_${CALL_SOURCE}_${QUEUE_NUMBER})=NOT_INUSE) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${CALL_SOURCE}_${QUEUE_NUMBER})=NOT_INUSE) same => n,Playback(vpbx/vital-agent-logoff) same => n,Goto(end) same => n(invalid),Playback(invalid) same => n(end),Hangup() exten => no-member,1,NoOp(No Dynamic Member) same => n,Playback(vpbx/vital-queue-no-dyn-member) same => n,Hangup() [sub-queue-pause-agent] exten => s,1,Verbose(PAUSE/UN-PAUSE QUEUE MEMBER) same => n,Answer same => n,Wait(1) same => n,Set(QUEUE_NUMBER=${ARG1}) same => n,GotoIf($["${QUEUE_NUMBER}"=""]?:continue) same => n(read_q_number),Read(QUEUE_NUMBER,please-enter-the&vpbx/vital-agent-queue-number&followed_pound) same => n,GotoIf($["${QUEUE_NUMBER}"=""]?read_q_number) same => n(continue),NoOp() same => n,Set(QUEUE_NAME=${DB(${TENANT}/queues/${QUEUE_NUMBER}/name)}) same => n,GotoIf($["${QUEUE_NAME}"=""]?read_q_number) same => n,GotoIf($[${QUEUE_EXISTS(${QUEUE_NAME})}]?:read_q_number) same => n,Set(MEMBER_TYPE=${DB(${TENANT}/queues/${QUEUE_NUMBER}/member/${CALL_SOURCE}/type)}) same => n,Set(CoS=${DB(${TENANT}/extensions/${CALL_SOURCE}/context)}) same => n,Set(INTERFACE=Local/${CALL_SOURCE}@${CoS}) same => n,Set(PAUSE_STATUS=${DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${CALL_SOURCE}_${QUEUE_NUMBER})}) same => n,GotoIf($["${PAUSE_STATUS}"="BUSY"]?turn_off) same => n,PauseQueueMember(${QUEUE_NAME},${INTERFACE});Legacy same => n,GotoIf($["${PQMSTATUS}"="PAUSED"]?check-status) same => n,PauseQueueMember(${QUEUE_NAME},Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n) same => n(check-status),ExecIf($["${PQMSTATUS}"="PAUSED"]?Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${CALL_SOURCE}_${QUEUE_NUMBER})=BUSY):Goto(invalid)) same => n,System( echo "${EPOCH},${UNIQUEID},NONE,Agent/${CALL_SOURCE},AGENTPAUSED,-" >> ${ASTLOGDIR}/queue_log ) same => n,UserEvent(RefreshQueue) same => n,Playback(vpbx/vital-agent-pause) same => n,Goto(end) same => n(turn_off),UnpauseQueueMember(${QUEUE_NAME},${INTERFACE});Legacy same => n,UnpauseQueueMember(${QUEUE_NAME},Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${CALL_SOURCE}_${QUEUE_NUMBER})=NOT_INUSE) same => n,System( echo "${EPOCH},${UNIQUEID},NONE,Agent/${CALL_SOURCE},AGENTPAUSED,-" >> ${ASTLOGDIR}/queue_log ) same => n,UserEvent(RefreshQueue) same => n,Playback(vpbx/vital-agent-unpause) same => n,Goto(end) same => n(invalid),Playback(spy-agent¬-yet-connected) same => n(end),Hangup() [app-queue-viplist] ;${ARG1}-->Queue, ${ARG2}-->VIP Number exten => s,1,NoOp(FEATURE: CALL CENTER VIP QUEUE) same => n,GotoIf(${DB_EXISTS(${TENANT}/queues/${ARG1}/${ARG2})}?YES:NO) same => n(YES),Set(QUEUE_PRIO=99) same => n(NO),MacroExit() ;END of [app-queue-viplist] [sub-queues-login] exten => s,1,NoOp(Login to All Queues) same => n,Set(Ext=${ARG1}) same => n,Set(CALL_SOURCE=${Ext}) same => n,Set(QUEUES=${ODBC_QUEUES-LIST(${TENANT})}) same => n,GotoIf($[${ISNULL(${QUEUES})}]?no-queues,1) same => n,GoSub(queue_login,s,1(${QUEUES},${CALL_SOURCE})) same => n(no-queues),Return() [sub-queues-logout] exten => s,1,NoOp(Logout from All Queues) same => n,Set(Ext=${ARG1}) same => n,Set(CALL_SOURCE=${Ext}) same => n,Set(QUEUES=${ODBC_QUEUES-LIST(${TENANT})}) same => n,GotoIf($[${ISNULL(${QUEUES})}]?no-queues,1) same => n,GoSub(queue_logout,s,1(${QUEUES},${CALL_SOURCE})) same => n(no-queues),Return() ;END [sub-queues-login-logout-direct] exten => s,1,NoOp(SUB: Direct Queues Loging/Logout) same => n,Set(OPTION=${CALL_DESTINATION:${ARG1}}) same => n,Set(OPTION=${OPTION:1}) ; remove the '*' same => n,Gosub(sub-queues-login-logout,s,1(${OPTION})) same => n,Hangup() [sub-queues-login-logout] exten => s,1,NoOp() same => n,Answer() same => n,Set(CHOOSE=${ARG1}) same => n,GotoIf($[${ISNULL(${CHOOSE})}]?:validate) same => n,Read(CHOOSE,vpbx/vital-agent-login-logout,1,,3,5) same => n(validate),GotoIf($[$["${CHOOSE}" = "1"]|$["${CHOOSE}" = "2"]]?:invalid) same => n,Set(ACTION=${IF($["${CHOOSE}" = "1"]?login:logout)}) same => n,Set(QUEUES=${ODBC_QUEUES-LIST(${TENANT})}) same => n,GotoIf($[${ISNULL(${QUEUES})}]?no-queues,1) same => n,GotoIf($["${ACTION}"="login"]?:logout) same => n,PlayBack(vpbx/vital-agent-login) same => n,Hangup() same => n(logout),PlayBack(vpbx/vital-agent-logoff) same => n,Hangup() same => n(invalid),PlayBack(confbridge-invalid&please-try-again-later) same => n,Hangup() exten => no-queues,1,NoOp(No queues available) same => n,Playback(vpbx/vital-no-queues) ;Should say: No queues available to login or logout same => n,Hangup() exten => h,1,NoOp(Check if need processing) same => n,GotoIf($[${EXISTS(${ACTION})}]?:end) same => n,NoOp(${ACTION}) same => n,GotoIf($["${ACTION}"="login"]?:logout) same => n,GoSub(queue_login,s,1(${QUEUES},${CALL_SOURCE})) same => n,hangup() same => n(logout),GoSub(queue_logout,s,1(${QUEUES},${CALL_SOURCE})) same => n(end),hangup() [queue_login] exten => s,1,NoOp(Login to queue) same => n,Set(QUEUES=${ARG1}) same => n,Set(CALL_SOURCE=${ARG2}) same => n,Set(QUEUE_COUNTER=1) same => n,Set(ACTUAL_QUEUE=${CUT(QUEUES,^,${QUEUE_COUNTER})}) same => n,While($[${EXISTS(${ACTUAL_QUEUE})}]) same => n,Set(QUEUE_NAME=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/name)}) same => n,GotoIf($[${QUEUE_EXISTS(${QUEUE_NAME})}]?:next) same => n,Set(MEMBER_TYPE=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/member/${CALL_SOURCE}/type)}) same => n,GotoIf($["${MEMBER_TYPE}"="dynamic"]?:next) same => n,Set(CoS=${QUEUE_AGENTS_CONTEXT}) same => n,Set(INTERFACE=Local/${CALL_SOURCE}@${CoS}/n) same => n,Set(MEMBER_PENALTY=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/member/${CALL_SOURCE}/penalty)}) same => n,NoOp(Login ${CALL_SOURCE} to Queue ${ACTUAL_QUEUE}) same => n,Set(RING_UNAVAILABLE=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/ring_unavailable)}) same => n,Set(AGENT_HINT=${IF($["${RING_UNAVAILABLE}"="yes"]?Agent${CALL_SOURCE}@${HINTS_CONTEXT}:${CALL_SOURCE}@${HINTS_CONTEXT})}) same => n,AddQueueMember(${QUEUE_NAME},${INTERFACE},${MEMBER_PENALTY},,${CALL_SOURCE},hint:${AGENT_HINT}) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAL_${CALL_SOURCE}_${ACTUAL_QUEUE})=BUSY) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAL_${CALL_SOURCE})=BUSY) same => n(next),Set(QUEUE_COUNTER=$[${QUEUE_COUNTER} + 1]) same => n,Set(ACTUAL_QUEUE=${CUT(QUEUES,^,${QUEUE_COUNTER})}) same => n,EndWhile() same => n,Return() ;END [queue_unset_hints] exten => s,1,NoOp(Unsetting hints) same => n,Set(QUEUE=${ARG1}) same => n,Set(SOURCE=${ARG2}) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAL_${SOURCE})=NOT_INUSE) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAL_${SOURCE}_${QUEUE})=NOT_INUSE) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${SOURCE}_${QUEUE})=NOT_INUSE) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${SOURCE})=NOT_INUSE) same => n,Return() [queue_logout] exten => s,1,NoOp(Log out from queue) same => n,Set(QUEUES=${ARG1}) same => n,Set(CALL_SOURCE=${ARG2}) same => n,Set(QUEUE_COUNTER=1) same => n,Set(ACTUAL_QUEUE=${CUT(QUEUES,^,${QUEUE_COUNTER})}) same => n,While($[${EXISTS(${ACTUAL_QUEUE})}]) same => n,Set(QUEUE_NAME=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/name)}) same => n,GotoIf($[${QUEUE_EXISTS(${QUEUE_NAME})}]?:next) same => n,NoOP(${ACTUAL_QUEUE}) same => n,NoOP(${CALL_SOURCE}) same => n,Set(MEMBER_TYPE=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/member/${CALL_SOURCE}/type)}) same => n,GotoIf($["${MEMBER_TYPE}"="dynamic"]?:next) same => n,Set(CoS=${DB(${TENANT}/extensions/${CALL_SOURCE}/context)}) same => n,Set(INTERFACE=Local/${CALL_SOURCE}@${CoS}) same => n,NoOp(Logout ${CALL_SOURCE} from Queue ${ACTUAL_QUEUE}) same => n,Set(PAUSED=${QUEUE_MEMBER(${QUEUE_NAME},paused,Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n)}) same => n,GotoIf($["${PAUSED}"="1"]?:logout) same => n,UnpauseQueueMember(${QUEUE_NAME},Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n) same => n(logout),RemoveQueueMember(${QUEUE_NAME},Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n) same => n,Gosub(queue_unset_hints,s,1(${ACTUAL_QUEUE},${CALL_SOURCE})) same => n(next),Set(QUEUE_COUNTER=$[${QUEUE_COUNTER} + 1]) same => n,Set(ACTUAL_QUEUE=${CUT(QUEUES,^,${QUEUE_COUNTER})}) same => n,EndWhile() same => n,Return() [sub-queues-pause-unpause-direct] exten => s,1,NoOp(SUB: Direct Queues Pause/Unpause) same => n,Set(OPTION=${CALL_DESTINATION:${ARG1}}) same => n,Set(OPTION=${OPTION:1}) ; remove the '*' same => n,Gosub(sub-queues-pause-unpause,s,1(${OPTION})) same => n,Hangup() [sub-queues-pause-unpause] exten => s,1,NoOp() same => n,Answer() same => n,Set(CHOOSE=${ARG1}) same => n,GotoIf($[${ISNULL(${CHOOSE})}]?:validate) same => n(re_enter),Read(CHOOSE,vpbx/vital-queues-pause&press-1&vpbx/vital-queues-unpause&press-2,1,,3,5) same => n(validate),GotoIf($[$["${CHOOSE}" = "1"]|$["${CHOOSE}" = "2"]]?:re_enter) same => n,Set(QUEUES=${ODBC_QUEUES-LIST(${TENANT})}) same => n,GotoIf($[${ISNULL(${QUEUES})}]?no-queues) same => n,Set(ACTION=${IF($["${CHOOSE}" = "1"]?pause:unpause)}) ; set same => n,GotoIf($["${ACTION}"="pause"]?:unpause) ; check same => n,Playback(vpbx/vital-agent-pause) same => n,Hangup() same => n(unpause),Playback(vpbx/vital-agent-unpause) same => n,Hangup() same => n(no-queues),Playback(vpbx/vital-no-queues) ;No queues available to un/pause same => n,Hangup() exten => h,1,NoOp(Check if need un/pause) same => n,GotoIf($[${EXISTS(${ACTION})}]?:end) same => n,GotoIf($[$["${ACTION}"="pause"]|$["${ACTION}"="unpause"]]?:end) same => n,GotoIf($["${ACTION}"="pause"]?:unpause) same => n,GoSub(queue_pause,s,1) same => n,hangup() same => n(unpause),GoSub(queue_unpause,s,1) same => n(end),hangup() [queue_pause] exten => s,1,NoOp(pause agent on queues) same => n,Set(PAUSE_REASON=${ARG1}) same => n,Set(QUEUES=${ODBC_QUEUES-LIST(${TENANT})}) same => n,Set(QUEUE_COUNTER=1) same => n,Set(ACTUAL_QUEUE=${CUT(QUEUES,^,${QUEUE_COUNTER})}) same => n,While($[${EXISTS(${ACTUAL_QUEUE})}]) same => n,Set(QUEUE_NAME=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/name)}) same => n,GotoIf($[${QUEUE_EXISTS(${QUEUE_NAME})}]?:next) same => n,Set(MEMBER_TYPE=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/member/${CALL_SOURCE}/type)}) same => n,GotoIf($[${ISNULL(${MEMBER_TYPE})}]?next) same => n,Set(CoS=${DB(${TENANT}/extensions/${CALL_SOURCE}/context)}) same => n,Set(INTERFACE=Local/${CALL_SOURCE}@${CoS}) same => n,Set(MEMBER_PENALTY=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/member/${CALL_SOURCE}/penalty)}) same => n,NoOp(Pausing ${CALL_SOURCE} to Queue ${ACTUAL_QUEUE}) same => n,Set(PAUSED=${QUEUE_MEMBER(${QUEUE_NAME},paused,Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n)}) same => n,GotoIf($["${PAUSED}"="1"]?:pause) same => n,NoOP(Interface Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n is paused already) same => n,Goto(next) same => n(pause),PauseQueueMember(${QUEUE_NAME},Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n,,${PAUSE_REASON}) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${CALL_SOURCE}_${ACTUAL_QUEUE})=BUSY) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${CALL_SOURCE})=BUSY) same => n(next),Set(QUEUE_COUNTER=$[${QUEUE_COUNTER} + 1]) same => n,Set(ACTUAL_QUEUE=${CUT(QUEUES,^,${QUEUE_COUNTER})}) same => n,EndWhile() same => n,Hangup() [queue_unpause] exten => s,1,NoOp(unpause agent from queues) same => n,Set(QUEUES=${ODBC_QUEUES-LIST(${TENANT})}) same => n,Set(QUEUE_COUNTER=1) same => n,Set(ACTUAL_QUEUE=${CUT(QUEUES,^,${QUEUE_COUNTER})}) same => n,While($[${EXISTS(${ACTUAL_QUEUE})}]) same => n,Set(QUEUE_NAME=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/name)}) same => n,GotoIf($[${QUEUE_EXISTS(${QUEUE_NAME})}]?:next) same => n,Set(MEMBER_TYPE=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/member/${CALL_SOURCE}/type)}) same => n,GotoIf($[${ISNULL(${MEMBER_TYPE})}]?next) same => n,Set(CoS=${DB(${TENANT}/extensions/${CALL_SOURCE}/context)}) same => n,Set(INTERFACE=Local/${CALL_SOURCE}@${CoS}) same => n,Set(MEMBER_PENALTY=${DB(${TENANT}/queues/${ACTUAL_QUEUE}/member/${CALL_SOURCE}/penalty)}) same => n,NoOp(Un-Pausing ${CALL_SOURCE} from Queue ${ACTUAL_QUEUE}) same => n,Set(PAUSED=${QUEUE_MEMBER(${QUEUE_NAME},paused,Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n)}) same => n,GotoIf($["${PAUSED}"="1"]?unpause) same => n,NoOP(Interface Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n is unpaused already) same => n,Goto(next) same => n(unpause),UnpauseQueueMember(${QUEUE_NAME},Local/${CALL_SOURCE}@${QUEUE_AGENTS_CONTEXT}/n) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${CALL_SOURCE}_${ACTUAL_QUEUE})=NOT_INUSE) same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}QAP_${CALL_SOURCE})=NOT_INUSE) same => n(next),Set(QUEUE_COUNTER=$[${QUEUE_COUNTER} + 1]) same => n,Set(ACTUAL_QUEUE=${CUT(QUEUES,^,${QUEUE_COUNTER})}) same => n,EndWhile() same => n,Hangup() ;------------------------------------------------------------------- ;END CALL CENTER ;ACCESS TO VOICEMAIL VER. 1.0.0 ;------------------------------------------------------------------- [sub-direct-voicemail] exten => s,1,NoOp(FEATURE: DIRECT ACCESS TO MY VOICEMAIL) same => n,Answer same => n,Wait(1) same => n,Set(MAILBOX=${DB(${TENANT}/extensions/${CALL_SOURCE}/voicemail)}) same => n,GotoIf($[${VM_INFO(${MAILBOX},exists)}]?:vm_disabled) same => n,Set(VM_EXIST=yes) same => n,GotoIf(${DB_EXISTS(${TENANT}/extensions/${CALL_SOURCE}/ask_vm_password)}?:vm) same => n,Set(VMOPTS=${IF($["${DB(${TENANT}/extensions/${CALL_SOURCE}/ask_vm_password)}"="no"]?s:)}) same => n,Set(OLD_PWD=${VM_INFO(${MAILBOX},password)}) same => n(vm),VoicemailMain(${MAILBOX},${VMOPTS}) same => n,Goto(end) same => n(vm_disabled),Playback(vpbx/vital-vm-no-available) same => n(end),Hangup() exten => h,1,NoOp(Ending Call) same => n,GotoIf($["${VM_EXIST}"="yes"]?:hangup) same => n,Set(DB(${TENANT}/extensions/${CALL_SOURCE}/vm_password)=${VM_INFO(${MAILBOX},password)}) same => n,Set(ODBC_VOICEMAIL-PASSWORD(${CALL_SOURCE},${TENANT})=${VM_INFO(${MAILBOX},password)}) same => n,System(${SCRIPTS_PATH}/vitalpbx "helperUpdateVMPassword" "${TENANT}" "${CALL_SOURCE}" "${OLD_PWD}" "${VM_INFO(${MAILBOX},password)}") same => n(hangup),NoOp() ;END of [sub-direct-voicemail] ;------------------------------------------------------------------- [sub-remote-voicemail] exten => s,1,NoOp(FEATURE: REMOTE ACCESS TO VOICEMAIL) same => n,Answer same => n,Wait(1) same => n,Set(vmextension=${ARG1}) same => n,GotoIf($["XX${vmextension}XX"="XXXX"]?:vm_validate) same => n,Set(TRY=0) same => n(try_again),Set(TRY=$[${TRY}+1]) same => n,Gotoif($[${TRY} > 3]?end) same => n,Read(vmextension,vm-login,,,,5) same => n(vm_validate),GotoIf(${DB_EXISTS(${TENANT}/extensions/${vmextension}/voicemail)}?:invalid) same => n,Set(VOICEMAIL_P=${DB(${TENANT}/extensions/${vmextension}/voicemail)}) same => n,GotoIf($[${VM_INFO(${VOICEMAIL_P},exists)}]?:vm_disabled) same => n,Set(VM_EXIST=yes) same => n,Set(OLD_PWD=${VM_INFO(${VOICEMAIL_P},password)}) same => n,VoicemailMain(${VOICEMAIL_P}) same => n,Goto(end) same => n(invalid),PlayBack(invalid) same => n,Goto(try_again) same => n(vm_disabled),Playback(vpbx/vital-vm-no-available) same => n(end),Hangup() exten => h,1,NoOp(Ending Call) same => n,GotoIf($["${VM_EXIST}"="yes"]?:hangup) same => n,Set(DB(${TENANT}/extensions/${vmextension}/vm_password)=${VM_INFO(${VOICEMAIL_P},password)}) same => n,Set(ODBC_VOICEMAIL-PASSWORD(${vmextension},${TENANT})=${VM_INFO(${VOICEMAIL_P},password)}) same => n,System(${SCRIPTS_PATH}/vitalpbx "helperUpdateVMPassword" "${TENANT}" "${vmextension}" "${OLD_PWD}" "${VM_INFO(${VOICEMAIL_P},password)}") same => n(hangup),NoOp() ;END of [sub-remote-voicemail] ;------------------------------------------------------------------- ;END ACCESS TO VOICEMAIL ;PAGING VER. 1.0.0 ;------------------------------------------------------------------- [sub-paging] exten => s,1,NoOp(APPLICATION: PAGING AND INTERCOM) same => n,Set(__CALL_ORIGIN=paging) same => n,Set(__IGNORE_DIVERSIONS=yes) same => n,NoOp(Filtering Paging Members) same => n,Set(FILTERED_PAGING_STRING=) same => n,Set(PAGING_STRING=${ARG1}) same => n,Set(PAGING_CALLER=${IF($[${LEN(${CALL_SOURCE})}=0]?${CALLERID(num)}:${CALL_SOURCE})}) same => n,Set(COUNTER=1) same => n,Set(CURRENT_DEVICE=${CUT(PAGING_STRING,&,${COUNTER})}) same => n,While($[${EXISTS(${CURRENT_DEVICE})}]) same => n,Set(MEMBER_TYPE=${CUT(CURRENT_DEVICE,/,1)}) same => n,GotoIf($["${MEMBER_TYPE}"="MulticastRTP"]?post-filter) ; Do not Filter MultiCast Items same => n,Set(EXTENSION_WITH_CTXT=${CUT(CURRENT_DEVICE,/,2)}) same => n,Set(EXTENSION=${CUT(EXTENSION_WITH_CTXT,@,1)}) same => n,GotoIf($["${PAGING_CALLER}"="${EXTENSION}"]?next) ; Remove from list if match with the caller same => n(post-filter),NoOP() same => n,GotoIf($[${LEN(${FILTERED_PAGING_STRING})}=0]?:concatenate) same => n,Set(FILTERED_PAGING_STRING=${CURRENT_DEVICE}) same => n,Goto(next) same => n(concatenate),NoOp() same => n,Set(FILTERED_PAGING_STRING=${FILTERED_PAGING_STRING}&${CURRENT_DEVICE}) same => n(next),Set(COUNTER=$[${COUNTER} + 1]) same => n,Set(CURRENT_DEVICE=${CUT(PAGING_STRING,&,${COUNTER})}) same => n,EndWhile() same => n,GotoIf($[${LEN(${FILTERED_PAGING_STRING})}=0]?return) same => n,NoOp(Executing the Paging) same => n,Page(${FILTERED_PAGING_STRING},${ARG2},${ARG3}) same => n(return),Return() ;END of [sub-paging] ;------------------------------------------------------------------- ;END PAGING [sub-auto-answer] exten => s,1,NoOp(Set up ${CHANNEL(channeltype)} Headers) same => n,GotoIf($["${CHANNEL(channeltype)}"="SIP"]?set-sip) same => n,NoOP(Add PJSIP Headers) same => n,Set(PJSIP_HEADER(add,Call-Info)=\;answer-after=0) same => n,Set(PJSIP_HEADER(add,Alert-Info)=Answer) same => n,Set(PJSIP_HEADER(add,Alert-Info)=Ring Answer) same => n,Set(PJSIP_HEADER(add,intercom)=true) same => n,Set(PJSIP_HEADER(add,Call-Info)=\;answer-after=0) same => n,Set(PJSIP_HEADER(add,Alert-Info)=Intercom) same => n,Set(PJSIP_HEADER(add,Alert-Info)=info=Auto Answer) same => n,Set(PJSIP_HEADER(add,Alert-Info)=ring-answer) same => n(set-sip),NoOP(Add SIP Headers) same => n,SIPAddHeader(Call-Info: \;answer-after=0) same => n,SIPAddHeader(Alert-Info: Answer) same => n,SIPAddHeader(Alert-Info: Ring Answer) same => n,SIPAddHeader(intercom=true) same => n,SIPAddHeader(Call-Info: \;answer-after=0) same => n,SIPAddHeader(Alert-Info: Intercom) same => n,SIPAddHeader(Alert-Info: info=Auto Answer) same => n,SIPAddHeader(Alert-Info: ring-answer) same => n,Return() ;SIMULATE INCOMING CALL VER. 1.0.0 ;------------------------------------------------------------------- [sub-simulate-incoming-call] exten => s,1,NoOp(FEATURE: SIMULATE INCOMING CALL) same => n,Set(DIAL_CTXT=incoming-calls) same => n,Set(DID=${CALLERID(num)}) same => n,Set(CID=${CALLERID(num)}) same => n(read-data),Set(TRY=1) same => n,Set(MAX_TRIES=3) same => n(invalid_exten),Gotoif($[${TRY} > ${MAX_TRIES}]?end_tries) same => n,Set(TRY=$[${TRY}+1]) same => n,Read(EXT,vpbx/vital-sim-incoming-call-did,,,3,5) same => n,Gotoif($["${EXT}"=""]?:continue_steps) same => n,Playback(im-sorry&you-dialed-wrong-number) same => n,Goto(invalid_exten) same => n(continue_steps),NoOp(DID PROVIDED WAS: ${EXT}) same => n,Set(DID=${EXT}) same => n(end_tries),NoOp(DID TO CALL IS: ${DID}) same => n,GotoIf(${DIALPLAN_EXISTS(${DIAL_CTXT},${DID},1)}?:noexist) same => n,Read(CID_NUMBER,vpbx/vital-sim-incoming-cid,,,1,5) ; Audio like: Please enter your Caller ID number if you want to change it, followed by pound same => n,ExecIf($["${CID_NUMBER}"!=""]?Set(CID=${CID_NUMBER})) same => n,NoOp(CID NUMBER IS: ${CID}) same => n,Set(CALLERID(all)="Incoming Call Simulation" <${CID}>) same => n,Set(CDR(source)=${CID}) same => n,Set(CDR(destination)=${DID}) same => n,Goto(${DIAL_CTXT},${DID},1) same => n,Hangup() same => n(noexist),Playback(no-route-exists-to-dest) same => n,Goto(read-data) ;------------------------------------------------------------------- ;END SIMULATE INCOMING CALL ;REMINDER VER. 2.0.0 ;------------------------------------------------------------------- [sub-reminder] exten => s,1,NoOp(Reminder Service) same => n,Set(REMINDER_FILENAME=/var/spool/asterisk/tmp/reminder-${UNIQUEID}.wav) same => n,Answer() same => n,Playback(welcome) same => n(read_did),Read(REMINDER_DID,vpbx/vital-reminder) same => n,GotoIf($["${REMINDER_DID}"=""]?read_did) same => n(confirm_did),Playback(you-entered) same => n,SayDigits(${REMINDER_DID}) same => n,Read(RESPONSE,if-this-is-correct&press-1&otherwise&press-2,1) same => n,GotoIf($["${RESPONSE}"="1"]?read_year) same => n,GotoIf($["${RESPONSE}"="2"]?read_did) same => n,Goto(confirm_did) same => n(read_year),Read(REMINDER_YEAR,please-enter-the&digits/4&digit&year&or&press-1&for&digits/today&followed_pound,4) same => n,GotoIf($["${REMINDER_YEAR}"="1"]?set_today) same => n,GotoIf($[${LEN(${REMINDER_YEAR})}=4]?read_day) same => n,Goto(read_year) same => n(read_day),Read(REMINDER_DATE,please-enter-the&digits/2&digit&month&and&digits/2&digit&day,4) same => n,GotoIf($[${LEN(${REMINDER_DATE})}=4]?read_time) same => n,Goto(read_day) same => n(read_time),Read(REMINDER_TIME,enter-a-time,4) same => n,GotoIf($[${LEN(${REMINDER_TIME})}=4]?parse_datetime) same => n,Goto(read_time) same => n(parse_datetime),Set(REMINDER_UNIX=${STRPTIME(${REMINDER_YEAR}-${REMINDER_DATE:0:2}-${REMINDER_DATE:2:2} ${REMINDER_TIME},,%Y-%m-%d %H%M)}) same => n(confirm_datetime),Playback(you-entered) same => n,SayUnixTime(${REMINDER_UNIX}) same => n,Read(RESPONSE,if-this-is-correct&press-1&otherwise&press-2,1) same => n,GotoIf($["${RESPONSE}"="1"]?record) same => n,GotoIf($["${RESPONSE}"="2"]?read_year) same => n,Goto(confirm_datetime) same => n(record),Playback(vm-rec-temp) same => n,Record(/var/spool/asterisk/tmp/reminder-${UNIQUEID}.wav,5,120) same => n(confirm_recording),Read(RESPONSE,to-accept-recording&press-1&otherwise&press-2,1) same => n,GotoIf($["${RESPONSE}"="1"]?done) same => n,GotoIf($["${RESPONSE}"="2"]?record) same => n,Goto(confirm_recording) same => n(done),System(/usr/share/vitalpbx/scripts/synchronizer reminder "${TENANT}" "${REMINDER_FILENAME}" "${REMINDER_DID}" "${REMINDER_UNIX}") same => n,Playback(num-was-successfully&added&goodbye) same => n,Return() same => n(set_today),Set(REMINDER_TODAY=${STRFTIME($[${EPOCH}],,%Y%m%d)}) same => n,Set(REMINDER_YEAR=${REMINDER_TODAY:0:4}) same => n,Set(REMINDER_DATE=${REMINDER_TODAY:4:4}) same => n,Goto(read_time) exten => h,1,System(rm -f "${REMINDER_FILENAME}") same => n,Return() ;------------------------------------------------------------------- ;END REMINDER ;CALL BACK VER. 1.0.0 ;------------------------------------------------------------------- [sub-call-back] exten => s,1,NoOp(FEATURE: CALL BACK) same => n,Answer() same => n,Wait(1) same => n,Playback(beep) same => n,Set(numbertodial=${DB(${TENANT}/callbacks/${ARG1}/dialnumber)}) same => n,GotoIf($["${numbertodial}" = ""]?:skipcallerid) same => n,Set(numbertodial=${CALL_SOURCE}) same => n(skipcallerid),Set(context=${DB(${TENANT}/callbacks/${ARG1}/cos)}) same => n,Set(destination=${DB(${TENANT}/callbacks/${ARG1}/destination)}) same => n,Set(dialprefix=${DB(${TENANT}/callbacks/${ARG1}/dialprefix)}) same => n,Set(delay=${DB(${TENANT}/callbacks/${ARG1}/delay)}) same => n,ExecIf($["${delay}"=""]?Set(delay=0)) same => n,Set(time_p=${STRFTIME($[${EPOCH}+${delay}] ,,%Y%m%d%H%M.%S)}) same => n,System(echo "Channel: Local/${dialprefix}${numbertodial}@${context} \nMaxRetries: 3 \nRetryTime: 30 \nWaitTime: 30 \nCallerid: "CALL BACK" <${CALL_DESTINATION}> \nExtension: ${CUT(destination,\,,2)} \nContext: ${context} \nPriority: 1 \nSetvar: Language=${CHANNEL(language)} \nSetvar: IGNORE_DIVERSIONS=yes \nSetvar: CALL_ORIGIN=feature \nSetvar: FEATURE_SERVICE=call_back" > ${ASTSPOOLDIR}/${UNIQUEID}.call) same => n,System(touch -t ${time_p} ${ASTSPOOLDIR}/${UNIQUEID}.call) same => n,Hangup() exten => h,1,System(mv ${ASTSPOOLDIR}/${UNIQUEID}.call ${ASTSPOOLDIR}/outgoing/${time_p}.${UNIQUEID}.call) same => n,NoOp() same => n,Verbose(2,Good Bye) ;END of [sub-call-back] ;PARKING ;------------------------------------------------------------------- [park-dial] ; Route here if the party that initiated the call parking cannot be reached after a period of time equaling the ; value specified in the 'comebackdialtime' option elapses. exten => t,1,NoOp(End of the line for a timed-out parked call.) same => n,Playback(sorry2&vm-goodbye) same => n,Hangup() exten => i,1,NoOp(End of the line for a timed-out parked call.) same => n,Playback(sorry2&vm-goodbye) same => n,Hangup() ;INVALID DIAL ;------------------------------------------------------------------- [invalid-dest] exten => s,1,NoOp(Invalid Route to Dial) same => n,GotoIf($["${SKIP_PLAYBACK}"="TRUE"]?end) same => n,Playback(im-sorry&no-route-exists-to-dest&vm-goodbye) same => n(end),Hangup() [invalid-dest-cos] exten => s,1,NoOp(Invalid Route Dialed in COS) same => n,GotoIf($["${QUEUE_CALL}"="TRUE"]?end) same => n,GotoIf($["${SKIP_PLAYBACK}"="TRUE"]?end) same => n,Progress() same => n,Playback(silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer) same => n(end),Hangup() ;TIMEOUT REACHED ;------------------------------------------------------------------- [timeout-reached] exten => s,1,NoOp(Timeout has been reached) same => n,Playback(im-sorry&connection-timed-out&vm-goodbye) same => n,Hangup [dahdi-incoming] exten => s,1,Set(channel=$["${CHANNEL}":"^DAHDI/([0-9]+)"]) same => n,Goto(default-trunk,${channel}fxo,1) exten => _[*#0-9ABCD],1,Set(did=${EXTEN}) same => n,Goto(dial,1) exten => _[*#0-9ABCD].,1,Set(did=${EXTEN}) same => n,Goto(dial,1) exten => dial,1,Set(channel=$["${CHANNEL}":"^(DAHDI/[0-9]+)"]) ; Check for hotdesking cause our dialplan is split in two same => n,GotoIf($["${DB(devices/${channel}/hot_desk)}"="yes"]?hotdesk,1) same => n,Set(user=${DB(devices/${channel}/assigned_exten)}) ; If it is not a hot_desk device and there is no an associated extension then it's a trunk channel. same => n,GotoIf($["${user}"=""]?default-trunk,${did},1) same => n,Set(__TENANT=${DB(devices/${channel}/tenant)}) same => n,Set(context=${DB(${TENANT}/extensions/${user}/context)}) same => n,ExecIf($["${context}"=""]?Hangup) ; sub-set-callerid requires CALLERID(num) and devices/{CALLERID(num)} to be set same => n,Set(CALLERID(num)=${user}) same => n,Goto(${context},${did},1) ; hot-desking-context and hot-desking-set require CALLERID(num) and devices/{CALLERID(num)} to be set exten => hotdesk,1,Set(CALLERID(num)=${channel}) same => n,Set(__TENANT=${DB(devices/${channel}/tenant)}) same => n,Goto(hot-desking-context,${did},1) ;PROCCESS QUEUE MEMBER SETTINGS ;------------------------------------------------------------------- [sub-queue-members] exten => s,1,NoOP(Queue Member ${CALL_DESTINATION}) same => n,Set(QUEUE_PREFIX=${DB(${TENANT}/queues/${QUEUE_NUMBER}/prefix)}) same => n,Set(CID_NAME_PREFIX=${INHERITED_PREFIX}) same => n,GotoIf($["${QUEUE_PREFIX}"!=""]?:set_prefix) same => n,Set(CID_NAME_PREFIX=${QUEUE_PREFIX}) same => n(set_prefix),Set(CALLERID(name)=${CID_NAME_PREFIX}${CALLERID(name)}) same => n,Set(ALLOW_DIVERSIONS=${DB(${TENANT}/queues/${QUEUE_NUMBER}/member/${CALL_DESTINATION}/diversions)}) same => n,ExecIf($["${ALLOW_DIVERSIONS}"="no"]?Set(_IGNORE_DIVERSIONS=yes)) same => n,Return() [sub-extensions-vm] exten => _[*#A-Za-z0-9].,1,NoOp(Trying To reach extension voicemail) same => n,Set(CALLEE=${EXTEN}) same => n,Set(VM_TYPE=${CUT(CALLEE,-,1)}) same => n,Set(VM_EXTEN=${CUT(CALLEE,-,2)}) same => n,Set(VM_MODE=${IF($["${VM_TYPE}"="VMB"]?b)}) same => n,Set(VM_MODE=${IF($["${VM_TYPE}"="VMU"]?u:${VM_MODE})}) same => n,Set(VM_MODE=${IF($["${DB(${TENANT}/extensions/${VM_EXTEN}/skip_vm_instructions)}"="yes"]?${VM_MODE}s:${VM_MODE})}) same => n,Gosub(sub-send-voicemail,s,1(${VM_EXTEN},${VM_MODE})) same => n,Hangup [sub-extensions-fwm] exten => _[*#A-Za-z0-9].,1,NoOp(Trying To reach extension follow-me) same => n,Set(CALLEE=${EXTEN}) same => n,Set(FWM_EXTEN=FW${CUT(CALLEE,-,2)}) same => n,Set(FWM_CTXT=${FOLLOWME_CONTEXT}) same => n,GotoIf(${DIALPLAN_EXISTS(${FWM_CTXT},${FWM_EXTEN},1)}?:noexist) same => n,Gosub(${FWM_CTXT},${FWM_EXTEN},1) same => n,Playback(followme/sorry) same => n,Goto(end) same => n(noexist),Goto(invalid-dest,s,1) same => n(end),Hangup [sub-fax-receiver] exten => s,1,NoOp(FAX RCV: Start) same => n,Set(FAXOPT(faxdetect)=no) same => n,System(/usr/share/vitalpbx/scripts/virtual_faxes "configureStorage") same => n,Set(STORAGE_PATH=/var/lib/vitalpbx/fax/recvd) same => n,Set(FAX_DEVICE=${ARG1}) same => n,Set(FAX_FILE_NAME=${STORAGE_PATH}/fax-in-${UNIQUEID}.tif) same => n,StopPlaytones() same => n,ReceiveFAX(${FAX_FILE_NAME},f) same => n,Hangup() exten => h,1,NoOP(Finish FAX RCV: ${FAXSTATUS}) same => n,GotoIf($["${FAXSTATUS}"!="FAILED"]?store) same => n,NoOp(FAX RCV: failed. Error code: ${FAXERROR}. Error desc: ${FAXSTATUSSTRING}) same => n(store),NoOP(Storing received fax) same => n,System(/usr/share/vitalpbx/scripts/virtual_faxes "receiveFax" "${TENANT}" "${FAX_DEVICE}" "${FAX_FILE_NAME}" "${CALLERID(name)}" "${CALLERID(num)}" "${INCOMING_DESTINATION}" "${FAXPAGES}" "${FAXSTATUS}" "${FAXSTATUSSTRING}") same => n,Hangup() [send-vm-msg] exten => s,1,NoOp(Send Voicemail Message) same => n,Set(DEST=${CALL_DESTINATION:${ARG1}}) same => n,Set(VM_DEST=${DEST:1}) ; remove the '*' same => n,Set(VM_OPTIONS=${IF($["${DB(${TENANT}/extensions/${VM_DEST}/skip_vm_instructions)}"="yes"]?us:u)}) same => n,Gosub(sub-send-voicemail,s,1(${VM_DEST},${VM_OPTIONS})) same => n,Hangup() [sub-cf-set-direct] exten => s,1,NoOp(SUB: Direct Call Forward Immediately) same => n,Set(que=${CALL_DESTINATION:${ARG1}}) same => n,Set(que=${que:1}) ; remove the '*' same => n,Gosub(sub-cf-set,s,1(${ARG2},${ARG3},,${que})) same => n,Hangup() [sub-queue-pause-agent-direct] exten => s,1,NoOp(SUB: Direct PAUSE/UN-PAUSE QUEUE MEMBER) same => n,Set(que=${CALL_DESTINATION:${ARG1}}) same => n,Set(que=${que:1}) ; remove the '*' same => n,Gosub(sub-queue-pause-agent,s,1(${que})) same => n,Hangup() [sub-queue-agent-direct] exten => s,1,NoOp(SUB: Direct LOGIN/LOGOUT QUEUE MEMBER) same => n,Set(que=${CALL_DESTINATION:${ARG1}}) same => n,Set(que=${que:1}) ; remove the '*' same => n,Gosub(sub-queue-agent,s,1(${que})) same => n,Hangup() [sub-parking-lots] exten => s,1,NoOp(Parking lots) same => n,Set(PARKING_LOT=${ARG1}) same => n,Set(PARKING_NAME=${ARG2}) same => n,Set(PARKING_HINT_CTXT=${ARG3}) same => n,Set(PARKING_LOT_STATE=${DEVICE_STATE(park:${PARKING_LOT}@${PARKING_HINT_CTXT})}) same => n,GotoIf($["${PARKING_LOT_STATE}"="NOT_INUSE"]?park_call) same => n,NoOp(Retrieve Call on Slot ${PARKING_LOT}) same => n,Set(PARKING_INFO=${SHELL(${SCRIPTS_PATH}/vitalpbx "getParkingSlotInfo" "${PARKING_NAME}" "${PARKING_LOT}")}) same => n,Set(ARRAY(PARKEE_NUM,PARKEE_NAME)=${PARKING_INFO}) same => n,Answer() same => n,Set(CONNECTEDLINE(name,i)=${PARKEE_NAME}) same => n,Set(CONNECTEDLINE(num,i)=${PARKEE_NUM}) same => n,Set(CONNECTEDLINE(pres)=allowed) same => n,GotoIf($["${CHANNEL(channeltype)}"="PJSIP"]?:set_src) same => n,Set(PJSIP_HEADER(add,P-Asserted-Identity)="${PARKEE_NAME}" ) same => n,Set(PJSIP_HEADER(add,Remote-Party-ID)="${PARKEE_NAME}" ) same => n,Set(PJSIP_SEND_SESSION_REFRESH()=update) same => n(set_src),Set(SRC_APP=PARKING) same => n,ExecIf($["${RECORD_PARKING_LOT}"="yes"]?Gosub(sub-call-recording,s,1(${TENANT},${CALL_SOURCE},${PARKING_LOT},yes))) same => n,ParkedCall(${PARKING_NAME},${PARKING_LOT}) same => n,Hangup() same => n(park_call),NoOp(Parking Call on Slot ${PARKING_LOT}) same => n,Set(PARKINGEXTEN=${PARKING_LOT}) same => n,Park(${PARKING_NAME}) [sub-vm] exten => s,1,NoOp(Leave a Voicemail) same => n,Voicemail(${ARG1},${ARG2}) same => n,Return() [sub-check-cos-privacy] exten => s,1,NoOp(Checking Privacy of CoS: ${ARG1}) same => n,GotoIf($[$["${CALL_TYPE}"="1"]|$["${LEN(${BLINDTRANSFER})}"!="0"]]?:no_local) same => n,Set(CALLER_COS_ID=${ARG2}) same => n,Set(CALLER_COS_NAME=${ARG3}) same => n,Set(CALLED_COS_ID=${DB(${TENANT}/classes_of_service/${ARG1})}) same => n,GotoIf($["${CALLER_COS_ID}"="${CALLED_COS_ID}"]?same_cos) same => n,Set(PRIVATE_COS=${DB(${TENANT}/classes_of_service/${CALLED_COS_ID}/private)}) same => n,GotoIf($["${PRIVATE_COS}"="no"]?no_private) same => n,Set(ALLOWED_COS_LIST=${DB(${TENANT}/classes_of_service/${CALLED_COS_ID}/allowed_calls_by)}) same => n,Set(ALLOWED_COS=${SHELL(/usr/share/vitalpbx/scripts/check_cos_privacy "${ALLOWED_COS_LIST}" "${CALLER_COS_ID}")}) same => n,GotoIf($["${ALLOWED_COS}"="TRUE"]?allowed) same => n,NoOp(The CoS ${CALLER_COS_NAME} is not allowed, dropping call) same => n,Playback(privacy-blocked) same => n,Hangup() same => n(no_local),NoOp(No Local Call, Allow any CoS) same => n,Goto(return) same => n(same_cos),NoOP(The caller CoS and Callee CoS are the same) same => n,Goto(return) same => n(no_private),NoOp(No private CoS, Allow any CoS) same => n,Goto(return) same => n(allowed),NoOp(The CoS ${CALLER_COS_NAME} is allowed) same => n(return),Return() [sub-remote-voicemail-direct] exten => s,1,NoOp(SUB: Direct Remote Voicemail) same => n,Set(MAILBOX=${CALL_DESTINATION:${ARG1}}) same => n,Set(MAILBOX=${MAILBOX:1}) ; remove the '*' same => n,Gosub(sub-remote-voicemail,s,1(${MAILBOX})) same => n,Hangup() ; It proccess SIP Messages ; Modified by EINM to match the header "To" with format pjsip:"1234" [messages] exten => _[-+*#0-9a-zA-Z].,1,NoOp(Receiving SMS) same => n,Answer() same => n,NoOp(To: ${MESSAGE(to)}) same => n,NoOp(From: ${MESSAGE(from)}) same => n,NoOp(Body: ${MESSAGE(body)}) same => n,GotoIf($["X${CUT(MESSAGE(to),<,2)}X"="XX"]?noname) same => n,Set(SMS_NUM=${CUT(MESSAGE(to),<,2)}) same => n,Set(SMS_NUM=${CUT(SMS_NUM,>,1)}) same => n,Set(SMS_TECH=${CUT(SMS_NUM,:,1)}) same => n,Set(SMS_REAL_TECH=${CUT(MESSAGE(to),:,1)}) same => n,GotoIf($["${SMS_TECH}"="${SMS_REAL_TECH}"]?noname) same => n,Set(MESSAGE(to)=${STRREPLACE(SMS_NUM,${SMS_TECH},${SMS_REAL_TECH})}) same => n(noname),Set(SMS_TO=${CUT(MESSAGE(to),@,1)}) same => n,Set(DEST_SERVER=${CUT(MESSAGE(to),@,2)}) same => n,Set(FROM_TECHNOLOGY=${CUT(SMS_TO,:,1)}) same => n,Set(SMS_TO=${CUT(SMS_TO,:,2)}) same => n,Set(FROM=${CUT(MESSAGE(from),<,2)}) same => n,Set(ACTUALFROM=${CUT(FROM,@,1)}) same => n,Set(FROM_TECHNOLOGY=${TOUPPER(${FROM_TECHNOLOGY})}) same => n,Set(DEVICE=${CUT(ACTUALFROM,:,2)}) same => n,NoOp(devices/${FROM_TECHNOLOGY}/${DEVICE}/assigned_exten) same => n,Set(EXTENSION=${DB(devices/${FROM_TECHNOLOGY}/${DEVICE}/assigned_exten)}) same => n,Set(TENANT=${DB(devices/${FROM_TECHNOLOGY}/${DEVICE}/tenant)}) same => n,Set(SMS_FROM=${MESSAGE(from)}) same => n,Set(SMS_FROM=${STRREPLACE(SMS_FROM,${DEVICE},${EXTENSION})}) same => n,Set(DIAL_STRING=${DB(${TENANT}/extensions/${SMS_TO}/dial)}) same => n,GotoIf($["${DIAL_STRING}"=""]?sendfailedmsg) same => n,Set(COUNTER=1) same => n,Set(CURRENT_DEVICE=${CUT(DIAL_STRING,&,${COUNTER})}) same => n,While($[${EXISTS(${CURRENT_DEVICE})}]) same => n,Set(TECHNOLOGY=${CUT(CURRENT_DEVICE,/,1)}) same => n,Set(USER=${CUT(CURRENT_DEVICE,/,2)}) same => n,GotoIf($[$["${TECHNOLOGY}"="IAX2"]|$["${TECHNOLOGY}"="DAHDI"]]?next) same => n,MessageSend(${TOLOWER(${TECHNOLOGY})}:${USER},${SMS_FROM}) same => n,NoOp(SMS Status to ${CURRENT_DEVICE}: ${MESSAGE_SEND_STATUS}) same => n(next),Set(COUNTER=$[${COUNTER} + 1]) same => n,Set(CURRENT_DEVICE=${CUT(DIAL_STRING,&,${COUNTER})}) same => n,EndWhile() same => n(failed),Goto(h,1) ; Handle failed messaging exten => _[-+*#0-9a-zA-Z].,n(sendfailedmsg),Set(MESSAGE(body)=The message to extension ${EXTEN} has failed.) same => n,MessageSend(${TOLOWER(${FROM_TECHNOLOGY})}:${DEVICE},"Message Center" ) same => n,NoOp(SMS Status: ${MESSAGE_SEND_STATUS}) same => n,Goto(h,1) exten => h,1,NoOP(End Sending Messages) same => n,Hangup() [sub-paging-and-intercom] exten => s,1,NoOp(Feature: Paging) same => n,ExecIf($["${LEN(${ARG1})}"="0"]?Hangup()) ; Hangup Call if not length received. This avoid an infinite loop. same => n,Set(NTP=${CALL_DESTINATION:${ARG1}}) same => n,Set(NTP=Local/${NTP}@${COS_NAME}) same => n,Set(__FORCE_INTERCOM=yes) same => n,Gosub(sub-paging,s,1(${NTP},iq,30)) same => n,Return() [sub-paging-duplex] exten => s,1,NoOp(Feature: Paging Duplex) same => n,ExecIf($["${LEN(${ARG1})}"="0"]?Hangup()) ; Hangup Call if not length received. This avoid an infinite loop. same => n,Set(NTP=${CALL_DESTINATION:${ARG1}}) same => n,Set(NTP=Local/${NTP}@${COS_NAME}) same => n,Set(__FORCE_INTERCOM=yes) same => n,Gosub(sub-paging,s,1(${NTP},diq,30)) same => n,Return() [sub-set-moh] exten => s,1,NoOp(Configuring MoH Class) same => n,Set(MOH_CLASS=${ARG1}) same => n,Set(MOH_FORCE=${ARG2}) same => n,GotoIf($["${MOH_CLASS}"="ringback"]?end) same => n,GotoIf($[$["${MOH_SET}"!="YES"]|$["${MOH_FORCE}"="YES"]]?:end) same => n,Set(CHANNEL(musicclass)=${MOH_CLASS}) same => n,Set(__MOH_SET=YES) same => n(end),Return() [sub-cf-remote-set] exten => s,1,NoOp(SUB: CALL FOWARDING TO REMOTE EXTENSION) same => n,Answer() same => n,Wait(1) same => n,Set(REMOTE_EXTENSION=${ARG4}) same => n,Set(REMOTE_EXTENSION_PWD=${ARG5}) same => n,Set(EXTENSION_TO_FWD=${ARG6}) same => n,GotoIf($["${REMOTE_EXTENSION}"=""]?:ask_pasword) same => n(read_ext),NoOp(Read Remote Extension) same => n,Read(REMOTE_EXTENSION,please-enter-the&extension&then-press-pound) same => n,GotoIf($["${REMOTE_EXTENSION}"=""]?read_ext) same => n,GotoIf(${DB_EXISTS(${TENANT}/extensions/${REMOTE_EXTENSION}/name)}?ask_pasword) same => n,Playback(invalid) same => n,Goto(read_ext) same => n(ask_pasword),NoOp(Ask Password of Remote Extension) same => n,GotoIf($["${REMOTE_EXTENSION_PWD}"=""]?:check_password) same => n,Playback(please-enter-the&extension&vm-password&then-press-pound) same => n(read_pwd),Read(REMOTE_EXTENSION_PWD) same => n,GotoIf($["${REMOTE_EXTENSION_PWD}"=""]?ask_pasword) same => n(check_password),Set(CURRENT_PWD=${DB(${TENANT}/extensions/${REMOTE_EXTENSION}/password)}) same => n,GotoIf($["${REMOTE_EXTENSION_PWD}"="${CURRENT_PWD}"]?ask_ext_to_fwd) same => n,Playback(auth-incorrect) same => n,Goto(read_pwd) same => n(ask_ext_to_fwd),NoOp(Ask Extension to Forward) same => n,GotoIf($["${EXTENSION_TO_FWD}"=""]?:configure) same => n,Read(EXTENSION_TO_FWD,ent-target-attendant&then-press-pound) same => n,GotoIf($["${EXTENSION_TO_FWD}"=""]?ask_ext_to_fwd) same => n(configure),Set(DB(${TENANT}/diversions/${REMOTE_EXTENSION}/${ARG2}/destination)=${EXTENSION_TO_FWD}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "set-${ARG2}" ${TENANT} "${REMOTE_EXTENSION}" "${EXTENSION_TO_FWD}") ; Uncomment this to automatically enable the requested diversion ;same => n,Set(DB(${TENANT}/diversions/${REMOTE_EXTENSION}/${ARG2}/enable)=yes) ;same => n,Set(DEVICE_STATE(Custom:${TENANT_PREFIX}${ARG2}_${REMOTE_EXTENSION})=BUSY) ;same => n,System(/usr/share/vitalpbx/scripts/synchronizer "enable-${ARG2}" "${TENANT}" "${REMOTE_EXTENSION}") ;same => n,Set(DB(${TENANT}/diversions/${REMOTE_EXTENSION}/has_enable_diversions)=yes) same => n,ExecIf($["${ARG3}"="advanced_mode"]?return()) same => n,Playback(${ARG1}&to-extension) same => n,SayDigits(${REMOTE_EXTENSION}) same => n,Playback(is-set-to) same => n,SayDigits(${EXTENSION_TO_FWD}) same => n,Playback(goodbye) same => n,Hangup() [sub-set-remote-diversions] exten => s,1,NoOp(SUB: Set Remote Diversions) same => n,Set(que=${DIAL_STR:${ARG1}}) same => n,Set(que=${que:1}) ; remove the '*' same => n,Set(REMOTE_EXTENSION=${CUT(que,*,1)}) same => n,Set(PASSWD=${CUT(que,*,2)}) same => n,Set(EXT_TO_FWD=${CUT(que,*,3)}) same => n,Gosub(sub-cf-remote-set,s,1(${ARG2},${ARG3},,${REMOTE_EXTENSION},${PASSWD},${EXT_TO_FWD})) same => n,Hangup() ; Clean some variables after answering a call to avoid some limitations on Voicemail, Transfer, etc [clean-variables] exten => s,1,NoOP(SUB: Cleaning Variables) same => n,Set(__CALL_ORIGIN=none) same => n,Set(__IGNORE_DIVERSIONS=no) same => n,Set(__SKIP_CONTACT_SERVICES=no) same => n,Set(__SKIP_PLAYBACK=no) same => n,Return() [sub-toggle-tc-state] exten => s,1,NoOP(SUB: Toggle Time Condition State) same => n,Set(TC_ID=${ARG1}) same => n,Set(TC=TC${ARG1}) same => n,Set(TG=${ARG2}) same => n,Set(PIN=${ARG3}) same => n,Answer() same => n,Wait(1) same => n,GotoIf($["${ARG3}" = ""]?get_state) ; if no pin provided then skip authentication same => n,Authenticate(${ARG3},j) same => n(get_state),Set(OVERRIDE_STATE=${DB(${TENANT}/time_conditions/${TC}/override)}) same => n,GotoIf($["${OVERRIDE_STATE}"!="no"]?reset) ; if the state is currently overwritten, then, return to the default state same => n,Gosub(${TG},s,1) same => n,Set(NEW_OVERRIDE_STATE=${IF($[${TGMATCH} > 0]?force_unmatch:force_match)}) ; If is matching, then, set to unmatch, otherwise, set to match same => n,Set(AUDIO=${IF($[${TGMATCH} > 0]?vital-tc-temporary-unmatch:vital-tc-temporary-match)}) same => n,Playback(vpbx/${AUDIO}) same => n,Goto(end) same => n(reset),NoOP(Return to the default state) same => n,Set(NEW_OVERRIDE_STATE=no) same => n,Playback(vpbx/vital-tc-default) same => n(end),Hangup() exten => h,1,NoOP() same => n,GotoIf($["X${NEW_OVERRIDE_STATE}X"="XX"]?end) ; if the new overrie state is empty do nothing same => n,Set(DB(${TENANT}/time_conditions/${TC}/override)=${NEW_OVERRIDE_STATE}) same => n,System(/usr/share/vitalpbx/scripts/synchronizer "update-TC-state" "${TENANT}" "${TC_ID}" "${NEW_OVERRIDE_STATE}") same => n,System(/usr/share/vitalpbx/scripts/update_tc "${TENANT}" "${TC_ID}") same => n(end),Hangup() [click-to-call] exten => _[-+*#0-9a-zA-Z].,1,NoOP(SUB: Executing Click to Call) same => n,ExecIf($["${CTC_EXECUTED}"="yes"]?Hangup()) same => n,Set(__SKIP_ANSWER=yes) same => n,Set(__FROM_QUEUE_CALLBACK=yes) same => n,Set(__CTC_EXECUTED=yes) same => n,Goto(${COS},${EXTEN},1) same => n,Hangup() exten => failed,1,NoOP(Sub: System Call failed) same => n,Hangup() [sub-custom-numbers] exten => _[-+*#0-9a-zA-Z]!,1,NoOP(Dialing custom number ${EXTEN}) same => n,Goto(${ARG1},${EXTEN},1) same => n,Hangup() [verify-did] exten => _[-+*#0-9a-zA-Z]!,1,NoOP(SUB: Verify DID Number) same => n,NoOP(DID Number: ${EXTEN}) same => n,Playback(vpbx/verify-did) same => n,SayDigits(${EXTEN}) same => n,Hangup() exten => h,1,NoOP(End Inbound Number Verification) same => n,Hangup() [sub-hot-desking-cc] exten => s,1,NoOP(SUB: HotDesking Call Center) same => n,Set(_HD_LOGIN_TO_QUEUES=TRUE) same => n,Set(_HD_EXTENSION_TO_LOGIN=) same => n,Set(_HD_EXTENSION_PWD=) same => n,Set(TYPE=${ARG2}) same => n,GotoIf($["${TYPE}"="extension"]?:check-pwd-type) same => n,Set(_HD_EXTENSION_TO_LOGIN=${CUT(CALL_DESTINATION,#,2)}) same => n,Goto(run) same => n(check-pwd-type),GotoIf($["${TYPE}"="extension_pwd"]?:run) same => n,Set(_HD_EXTENSION_TO_LOGIN=${CUT(CALL_DESTINATION,#,2)}) same => n,Set(_HD_EXTENSION_PWD=${CUT(CALL_DESTINATION,#,3)}) same => n(run),NoOP(Executing Hot Desking Sub Routines) same => n,GotoIf($["${DB(${DEV_TREE}/hot_desk)}"="yes"]?:sub-hot-desking,s,invalid_device) same => n,Set(_ASSIGNED_EXTEN=${DB(${DEV_TREE}/assigned_exten)}) same => n,GotoIf($[${ISNULL(${ASSIGNED_EXTEN})}]?:un-assign) same => n,GoSub(sub-hot-desking-assign-extension,s,1) same => n(un-assign),GoSub(sub-hot-desking-remove-extension,s,1) same => n,Hangup() [sub-cf-state-direct] exten => s,1,NoOP(Direct CallForward) same => n,Set(FEATURE_LENGTH=${ARG1}) same => n,Set(CFW_AUDIO=${ARG2}) same => n,Set(CFW_TYPE=${ARG3}) same => n,Set(ARGUMENTS=${CALL_DESTINATION:${FEATURE_LENGTH}}) same => n,Set(ARGUMENTS=${ARGUMENTS:1}) same => n,Set(_CFNUMBER=${CUT(ARGUMENTS,*,1)}) same => n,Set(DIGITS_TO_SKIP=$[${LEN(${CFNUMBER})}+1]) same => n,Set(_CFEXTENSION=${ARGUMENTS:${DIGITS_TO_SKIP}}) same => n,Set(_CF_DIRECT=TRUE) same => n,GoSub(sub-cf-state,s,1(${CFW_AUDIO},${CFW_TYPE})) same => n,Retrun() [pjsip-push] exten => _[-+*#0-9a-zA-Z].,1,NoOP(Doing PJSIP PUSH) same => n,Gosub(send-mobile-push,s,1(${EXTEN},PJSIP)) same => n,Hangup() exten => _[-+*#0-9a-zA-Z],1,NoOP(Doing PJSIP PUSH) same => n,Gosub(send-mobile-push,s,1(${EXTEN},PJSIP)) same => n,Hangup() [sip-push] exten => _[-+*#0-9a-zA-Z].,1,NoOP(Doing SIP PUSH) same => n,Gosub(send-mobile-push,s,1(${EXTEN},SIP)) same => n,Hangup() exten => _[-+*#0-9a-zA-Z],1,NoOP(Doing SIP PUSH) same => n,Gosub(send-mobile-push,s,1(${EXTEN},SIP)) same => n,Hangup() [send-mobile-push] exten => s,1,NoOP(Sending push notifications for mobile devices) same => n,Set(DEVICE=${ARG1}) same => n,Set(TECH=${ARG2}) same => n,Set(MAX_TRIES=10) same => n,Set(TRY=1) same => n,Set(DEVICE_STATUS=${DEVICE_STATE(${TECH}/${DEVICE})}) same => n,GotoIf($["${DEVICE_STATUS}"!="UNAVAILABLE"]?dial) same => n,System(/usr/share/vitalpbx/scripts/push_notifications "${TECH}/${DEVICE}" "Call From VitalPBX" "VitalPBX LLC") same => n(loop),GotoIf($[${TRY} > ${MAX_TRIES}]?end) same => n,Set(DEVICE_STATUS=${DEVICE_STATE(${TECH}/${DEVICE})}) same => n,NoOP(Try: ${TRY}, Device Status: ${DEVICE_STATUS}) same => n,GotoIf($["${DEVICE_STATUS}"!="UNAVAILABLE"]?dial) same => n,Wait(2) same => n,Set(TRY=$[${TRY}+1]) same => n,Goto(loop) same => n(dial),NoOP(Dialing the device) same => n,Set(DIALING_STRING=${TECH}/${DEVICE}) same => n,GotoIf($["${TECH}"="PJSIP"]?:do-dial) same => n,Set(DIALING_STRING=${PJSIP_DIAL_CONTACTS(${DEVICE})}) same => n(do-dial),Dial(${DIALING_STRING}) same => n(end),Hangup() [custom_atxfer] exten => s,1,NoOp(Custom ATXFER) same => n,Playback(pbx-transfer) same => n,Read(NUMBER_TO_TRANSER_TO,dial,10,i,3,3) same => n,GotoIf($["${LEN(${NUMBER_TO_TRANSER_TO})}"="0"]?end) same => n(transfer),AttendedTransfer(${NUMBER_TO_TRANSER_TO}) same => n,Noop(${QUEUE_VARIABLES(${QUEUE_NAME})}) same => n,GotoIf($[$["${LEN(${QUEUE_NAME})}"="0"]&$["${ATTENDEDTRANSFERSTATUS}"="SUCCESS"]]?end) same => n,QueueLog(${QUEUE_NAME},${CHANNEL(linkedid)},${NUMBER_TO_TRANSER_TO},ATXFER,BRIDGE|${UNIQUEID}) same => n(end),Return() [custom_blindxfer] exten => s,1,NoOp(Custom BLINDXFER) same => n,Playback(pbx-transfer) same => n,Read(NUMBER_TO_TRANSER_TO,dial,10,i,3,3) same => n,GotoIf($["${LEN(${NUMBER_TO_TRANSER_TO})}"="0"]?end) same => n(transfer),BlindTransfer(${NUMBER_TO_TRANSER_TO},${TRANSFER_CONTEXT}) same => n,Noop(${QUEUE_VARIABLES(${QUEUE_NAME})}) same => n,GotoIf($[$["${LEN(${QUEUE_NAME})}"="0"]&$["${BLINDTRANSFERSTATUS}"="SUCCESS"]]?end) same => n,QueueLog(${QUEUE_NAME},${CHANNEL(linkedid)},${NUMBER_TO_TRANSER_TO},BLINDXFER,BRIDGE|${UNIQUEID}) same => n(end),Return() [sub-fax-sender] exten => fax-out,1,NoOp(Outbound Fax from ${FAX_SENDER_NUMBER} to ${FAX_RECIPIENT}) same => n,Set(FAXOPT(headerinfo)=${FAX_SENDER_NAME}) same => n,Set(FAXOPT(localstationid)=${FAX_SENDER_NUMBER}) same => n,SendFax(${FAX_FILE},fz) same => n,Hangup() exten => h,1,NoOP(Finish FAX Sending: ${FAXSTATUS}) same => n,System(/usr/share/vitalpbx/scripts/virtual_faxes "updateFaxLogStatus" "${TENANT}" "${FAX_LOG}" "${FAXSTATUS}" "${FAXSTATUSSTRING}") same => n,GotoIf($["${FAXSTATUS}"!="FAILED"]?info) same => n,NoOp(FAX Sending: failed. Error desc: ${FAXSTATUSSTRING}) same => n,Goto(finish) same => n(info),NoOP(FAX Pages: ${FAXPAGES}) same => n,NoOP(FAX Mode: ${FAXMODE}) same => n,NoOP(FAX Resolution: ${FAXRESOLUTION}) same => n,NoOP(FAX BITRate: ${FAXBITRATE}) same => n(finish),Hangup() [sub-diversion-headers] exten => s,1,NoOP(Configuring diversion headers) same => n,GotoIf($["${SEND_DIVERSION_HEADERS}"="yes"]?setup) same => n,NoOP(The sending of diversion headers is disabled) same => n,Goto(end) same => n(setup),NoOP(Setting up diversion headers) same => n,Set(REDIRECTING(from-num,i)=${ARG1}) same => n,Set(REDIRECTING(from-num-pres,i)=allowed) same => n,Set(REDIRECTING(count,i)=$[${REDIRECTING(count)} + 1]) same => n,Set(REDIRECTING(reason,i)=${ARG2}) same => n(end),Return() [ms-team-transfer] exten => s,1,NoOp(MS Teams Transfer) same => n,GotoIf($["${LEN(${SIPREFERTOHDR})}"="0"]?end) same => n,Dial(PJSIP/${TRUNK_ENDPOINT}/${SIPREFERTOHDR}) same => n(end),Hangup() exten => _[*#0-9a-zA-Z].,1,NoOp(Bilind Transfer from Teams) same => n,GotoIf($["${LEN(${SIPREFERTOHDR})}"="0"]?end) same => n,Dial(PJSIP/${TRUNK_ENDPOINT}/${SIPREFERTOHDR}) same => n,Hangup() exten => _+[*#0-9a-zA-Z].,1,NoOp(Attended Transfer from Teams) same => n,GotoIf($["${LEN(${SIPREFERTOHDR})}"="0"]?end) same => n,Set(FILTERED_CHANNELS=${CHANNELS(^(PJSIP|SIP)\/${EXTEN:2}-*)}) same => n,Set(CHANNEL_TO_XFER=${CUT(FILTERED_CHANNELS, ,1)}) same => n,Bridge(${CHANNEL_TO_XFER}) same => n,Hangup() exten => h,1,NoOp(End MS Teams Transfer) same => n,Hangup() [notify-trunk-hangup] exten => s,1,Verbose(0, Trunk Hangup) same => n,Set(CALLER=${IF($["${LEN(${INTERFACE})}"="0"]?${CALL_SOURCE}:${INTERFACE})}) same => n,UserEvent("EXTENSIONS_SUMMARY","Data: OUTBOUND,${CALLER},${EXTENSION},${CALL_TYPE_LABEL}") same => n(end),Return() [notify-call-hangup] exten => s,1,Verbose(0, Extension Hangup) same => n,GotoIf($["${CALL_TYPE_LABEL}"="LOCAL"]?:incoming) same => n,UserEvent("EXTENSIONS_SUMMARY","Data: EXT_TO_EXT,${INTERFACE}-0000001v,${DIALEDPEERNAME},${CALL_TYPE_LABEL}") same => n,Goto(end) same => n(incoming),Verbose(0, Extension Hangup - Incoming Call) same => n,UserEvent("EXTENSIONS_SUMMARY","Data: INCOMING,${INCOMING_SOURCE},${DIALEDPEERNAME},${CALL_TYPE_LABEL}") same => n(end),Return() [local-call-hangup] exten => s,1,Verbose(0, Hangup Local Call) same => n,UserEvent("EXTENSIONS_SUMMARY","Data: EXT_TO_FC,${INTERFACE},LOCAL") same => n,Return() [sub-anonymous-calling] exten => s,1,NoOp(Feature: Anonymous Calling) same => n,ExecIf($["${LEN(${ARG1})}"="0"]?Hangup()) ; Hangup Call if not length received. This avoid an infinite loop. same => n,Set(NTP=${CALL_DESTINATION:${ARG1}}) same => n,Set(__FORCE_HIDE_CID=yes) same => n,Goto(${COS_NAME},${NTP},1) same => n,Return() [switchboard-call] exten => _[-+*#0-9a-zA-Z].,1,NoOP(Call from switchboard) same => n,NoCDR() same => n,Set(_DISABLE_CDR=yes) same => n,Dial(Local/${EXTEN}@${Call-Context}/n) same => n,Hangup() [sub-drop-anon-calls] exten => s,1,NoOp(Verifying if it is an anonymous call) same => n,GotoIf($["${LEN(${CALLERID(num)})}"="0"]?empty) same => n,GotoIf($[$["${CALLERID(num)}"="asterisk"]|$["${CALLERID(num)}"="Asterisk"]]?end) same => n,GotoIf($[$["${CALLERID(num)}"="Anonymous"]|$["${CALLERID(num)}"="anonymous"]]?end) same => n,GotoIf($[$["${CALLERID(num)}"="+Anonymous"]|$["${CALLERID(num)}"="+anonymous"]]?end) same => n,GotoIf($[$["${CALLERID(num)}"="Unknown"]|$["${CALLERID(num)}"="unknown"]]?end) same => n,GotoIf($[$["${CALLERID(num)}"="Private"]|$["${CALLERID(num)}"="private"]]?end) same => n,GotoIf($[$["${CALLERID(num)}"="Restricted"]|$["${CALLERID(num)}"="restricted"]]?end) same => n,Return() same => n(empty),NoOp(Droping call with empty CID) same => n,Goto(h-call) same => n(end),NoOp(Droping call with CID ${CALLERID(num)}) same => n(h-call),Hangup(603) [sub-pbx-dialer] exten => _[-+*#0-9a-zA-Z].,1,NoOP(SUB: Executing PBX Dialer) same => n,ExecIf($["${PD_EXECUTED}"="yes"]?Hangup()) same => n,Set(__FROM_DIALER=yes) same => n,Set(__SKIP_ANSWER=yes) same => n,Set(__FROM_QUEUE_CALLBACK=yes) same => n,Set(__PD_EXECUTED=yes) same => n,Goto(${COS},${EXTEN},1) same => n,Hangup() exten => failed,1,NoOP(Sub: System Call failed) same => n,Hangup() [sub-outbound-queue-call] exten => s,1,NoOp(Outbound Call From Queue) same => n,QueueUpdate(${QNAME},${UNIQUEID},${AGENT_EXT},${DIALSTATUS},${ANSWEREDTIME},${CAMPAIGN}|${CUSTOMER_PHONE}) same => n,Return() [sub-udpate-virtual-dev-state] exten => s,1,NoOp(Update Virtual Devices State) same => n,Set(EXT_NUM=${ARG1}) same => n,Set(NEW_STATUS=${ARG2}) same => n,Set(EXTENSION_ID=${GET_EXTENSION-ID(${EXT_NUM},${TENANT})}) same => n,Set(ODBC_ID=${GET_VIRTUAL-DEVICES(${EXTENSION_ID},${TENANT})}) same => n,GotoIf($[${ODBCROWS} < 1]?no_rows) same => n,Set(COUNTER=1) same => n,While($[${COUNTER}<=${ODBCROWS}]) same => n,Set(VDevice=${ODBC_FETCH(${ODBC_ID})}) same => n,Set(DEVICE_STATE(Custom:VirtualDev${VDevice})=${NEW_STATUS}) same => n,Set(COUNTER=$[${COUNTER} + 1]) same => n,EndWhile() same => n,ODBCFinish() same => n(no_rows),Return() [sub-stir-shaken-verify] exten => s,1,NoOp(STIR Shaken Verify) same => n,Set(STIR_SHAKEN_IDENTITIES=${STIR_SHAKEN(count)}) same => n,NoOp(Number of STIR/SHAKEN identities: ${STIR_SHAKEN_IDENTITIES}) same => n,GotoIf($[${STIR_SHAKEN_IDENTITIES}=0]?end) same => n,NoOp(Identity ${STIR_SHAKEN(0, identity)} has attestation level ${STIR_SHAKEN(0, attestation)}) same => n(end),Return() [sub-before-bridging-call] exten => s,1,NoOp(Executing sub-routine before connecting to the calling channel) same => n,Set(TENANT=${ARG1}) same => n,Set(CALLER=${ARG2}) same => n,Set(CALLEE=${ARG3}) same => n,Set(FORCE_CALL_RECORDING=${ARG4}) same => n,NoOp(Check if the follow-me confirmation sub-routine needs to be executed) same => n,GotoIf($["${LEN(${FWM_CONFIRMATION_CONTEXT})}"="0"]?call-recording) same => n,Gosub(${FWM_CONFIRMATION_CONTEXT},s,1(${CALLEE})) same => n(call-recording),NoOP(Executing the call-recording sub-routine) same => n,Gosub(sub-call-recording,s,1(${TENANT},${CALLER},${CALLEE},${FORCE_CALL_RECORDING})) same => n,NoOp(Check if there's a custom sub-routine defined for executing it) same => n,GosubIf($[${DIALPLAN_EXISTS(${TENANT_PREFIX}before-bridging-call-hook,s,1)}=1]?${TENANT_PREFIX}before-bridging-call-hook,s,1) same => n(return),Return() [sub-call-recording] exten => s,1,NoOp(Check if call will be recorded on tenant ${TENANT}) same => n,NoOp(Call Type: ${CALL_TYPE} ) same => n,Set(TENANT=${ARG1}) same => n,Set(CALLER=${ARG2}) same => n,Set(CALLEE=${ARG3}) same => n,Set(APP_FORCE=${ARG4}) same => n,GotoIf($["${DB(${TENANT}/allow_recordings)}"="yes"]?:rec_no_available) same => n,GotoIf($["${APP_FORCE}"="yes"]?perform-recording) same => n,Set(INTERNAL_REC=${ODBC_EXTENSION-SETTING(internal_rec,${CALLEE},${TENANT})}) same => n,GotoIf($[$["${CALL_TYPE}"="1"]&$["${INTERNAL_REC}"="yes"]]?perform-recording) same => n,Set(INTERNAL_REC=${ODBC_EXTENSION-SETTING(internal_rec,${CALLER},${TENANT})}) same => n,GotoIf($[$["${CALL_TYPE}"="1"]&$["${INTERNAL_REC}"="yes"]]?perform-recording) same => n,Set(INCOMING_REC=${ODBC_EXTENSION-SETTING(incoming_rec,${CALLEE},${TENANT})}) same => n,GotoIf($[$[$["${CALL_TYPE}"="2"]|$["${CALL_TYPE}"="4"]]&$["${INCOMING_REC}"="yes"]]?perform-recording) same => n,Set(OUTGOING_REC=${ODBC_EXTENSION-SETTING(outgoing_rec,${CALLER},${TENANT})}) same => n,GotoIf($[$[$["${CALL_TYPE}"="3"]|$["${CALL_TYPE}"="4"]]&$["${OUTGOING_REC}"="yes"]]?perform-recording) same => n,Goto(return) same => n(perform-recording),Gosub(sub-perform-recording,s,1) same => n,Goto(return) same => n(rec_no_available),NoOP(Recordins are not available for tenant ${DB(${TENANT}/name)}) same => n(return),Return() exten => conference,1,NoOp(Recording Conference ${ARG1}) same => n,Set(CONFERENCE=${ARG1}) same => n,GotoIf($["${DB(${TENANT}/allow_recordings)}"="yes"]?:rec_no_available) same => n,Set(DB_TREE=${TENANT}/conferences/${CONFERENCE}) same => n,Set(AUDIO_FILE=${STRFTIME(${EPOCH},,%H%M%S)}-${CALL_TYPE_LABEL}-CONF-${CALL_SOURCE}-${CONFERENCE}-${UNIQUEID}) same => n,Set(RECORDING_FORMAT=${IF($["${RECORDING_FORMAT}"="wav49"]?WAV:${RECORDING_FORMAT})}) same => n,Set(REC_FILENAME=${ASTSPOOLDIR}/monitor/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${AUDIO_FILE}.${RECORDING_FORMAT}) same => n,GotoIf($["${DB(${TENANT}/main)}"="no"]?:set_conf_rec_file) same => n,NoOp(Append tenant to recording path) same => n,Set(REC_FILENAME=${ASTSPOOLDIR}/monitor/${TENANT}/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${AUDIO_FILE}.${RECORDING_FORMAT}) same => n(set_conf_rec_file),Set(CONF_REC_FILE=${IF($[${CONFBRIDGE_INFO(parties,${CONFERENCE})}>0]?${DB(${DB_TREE})}:${REC_FILENAME})}) same => n,ExecIf($[${CONFBRIDGE_INFO(parties,${CONFERENCE})}<=0]?Set(DB(${DB_TREE})=${REC_FILENAME})) same => n,GotoIf($[${CONFBRIDGE_INFO(parties,${CONFERENCE})}>0]?cdr) same => n,MixMonitor(${REC_FILENAME},b,${RECORDING_SCRIPT}) same => n(cdr),Set(CDR(recfile)=${CONF_REC_FILE}) same => n,Goto(return) same => n(rec_no_available),NoOP(Recordins are not available for tenant ${DB(${TENANT}/name)}) same => n(return),Return() [sub-call-recording-on-demand] exten => s,1,NoOp(Processing Call Recording on Demand) same => n,GotoIf($[$["${REC_STARTED}"="yes"]&$["${ONDEMAND_REC_INITIALIZED}"="yes"]]?:check-resume) same => n,NoOp(If the recording is already started, then stop it) same => n,Gosub(sub-pause-recording,s,1) same => n,Goto(return) same => n(check-resume),GotoIf($[$["${REC_STARTED}"="no"]&$["${ONDEMAND_REC_INITIALIZED}"="yes"]]?:init) same => n,NoOp(Resume the recording if it is already started but stopped) same => n,Gosub(sub-unpause-recording,s,1) same => n,Goto(return) same => n(init),GotoIf($["${DB(${TENANT}/allow_recordings)}"="yes"]?:rec_no_available) same => n,GotoIf($["${REC_STARTED}"="yes"]?return) same => n,Set(TRIGGERED_BY_NO_SUFIX=${CUT(DYNAMIC_WHO_ACTIVATED,-,1)}) same => n,Set(TRIGGERED_BY=${DB(devices/${TRIGGERED_BY_NO_SUFIX}/assigned_exten)}) same => n,Set(REC_ONDEMAND_ENABLED=${ODBC_EXTENSION-SETTING(rec_on_demand,${TRIGGERED_BY},${TENANT})}) same => n,GotoIf($["${REC_ONDEMAND_ENABLED}"="yes"]?perform-recording) same => n,Goto(return) same => n(perform-recording),Gosub(sub-perform-recording,s,1(yes)) same => n,Set(__ONDEMAND_REC_INITIALIZED=yes) same => n,Goto(return) same => n(rec_no_available),NoOP(Recordins are not available for tenant ${DB(${TENANT}/name)}) same => n(return),Return() [sub-auto-recording-switch] exten => s,1,NoOp(Switching Recording Status) same => n,GotoIf($["${REC_STARTED}"="yes"]?:check-resume) same => n,NoOp(If the recording is already started, then stop it) same => n,Gosub(sub-pause-recording,s,1) same => n,Goto(return) same => n(check-resume),GotoIf($["${REC_STARTED}"="no"]?:return) same => n,NoOp(Resume the recording if it is already started but stopped) same => n,Gosub(sub-unpause-recording,s,1) same => n(return),Return() [sub-pause-recording] exten => s,1,NoOp(Pausing Recording) same => n,GotoIf($["${REC_STARTED}"="yes"]?:return) same => n,StopMixMonitor() same => n,Set(__REC_STARTED=no) same => n(return),Return() [sub-unpause-recording] exten => s,1,NoOp(Resuming Recording) same => n,GotoIf($[$["${REC_STARTED}"="no"]&$["X${REC_FILENAME}X"!="XX"]]?:return) same => n,MixMonitor(${REC_FILENAME},apP,${RECORDING_SCRIPT}) same => n,Set(__REC_STARTED=yes) same => n(return),Return() [sub-perform-recording] exten => s,1,NoOp(Perform Call Recording) same => n,GotoIf($["${REC_STARTED}"="yes"]?:record) same => n,NoOp(Already recording on file ${REC_FILENAME}) same => n,Set(MIXMON_OPTS=a) same => n(record),Set(PLAY_BEEP_ON_START=${ARG1}) same => n(set_rec_file),Set(CDR(recfile)=${REC_FILENAME}) same => n,Set(MIXMON_OPTS=${MIXMON_OPTS}P) same => n,Set(MIXMON_OPTS=${IF($["${RECORD_UNBRIDGE_CHANNELS}"="yes"]?${MIXMON_OPTS}:b${MIXMON_OPTS})}) same => n,Set(MIXMON_OPTS=${IF($["${PLAY_BEEP_ON_START}"="yes"]?${MIXMON_OPTS}p:${MIXMON_OPTS})}) same => n,MixMonitor(${REC_FILENAME},${MIXMON_OPTS},${RECORDING_SCRIPT}) same => n,Set(__REC_STARTED=yes) same => n(return),Return()