Move the includes/install to resources/install

This commit is contained in:
Mark Crane
2013-06-09 02:42:36 +00:00
parent 0407ee236d
commit 896fdb37b2
203 changed files with 0 additions and 0 deletions
@@ -1,20 +0,0 @@
<configuration name="cdr_csv.conf" description="CDR CSV Format">
<settings>
<!-- 'cdr-csv' will always be appended to log-base -->
<!--<param name="log-base" value="/var/log"/>-->
<param name="default-template" value="sql"/>
<!-- This is like the info app but after the call is hung up -->
<!--<param name="debug" value="true"/>-->
<param name="rotate-on-hup" value="false"/>
<!-- may be a b or ab -->
<param name="legs" value="a"/>
</settings>
<templates>
<template name="sql">INSERT INTO v_cdr (domain_uuid, caller_id_name, caller_id_number, destination_number, context, start_stamp, answer_stamp, end_stamp, duration, billsec, hangup_cause, uuid, bleg_uuid, accountcode, read_codec, write_codec, remote_media_ip, network_addr) VALUES ("{domain_uuid}", "${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}", "${accountcode}", "${read_codec}", "${write_codec}", "${remote_media_ip}", "${network_addr}");</template>
<template name="example">"${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}","${accountcode}","${read_codec}","${write_codec}"</template>
<template name="snom">"${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}", "${accountcode}","${read_codec}","${write_codec}","${sip_user_agent}","${call_clientcode}","${sip_rtp_rxstat}","${sip_rtp_txstat}","${sofia_record_file}"</template>
<template name="linksys">"${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}","${accountcode}","${read_codec}","${write_codec}","${sip_user_agent}","${sip_p_rtp_stat}"</template>
<template name="asterisk">"${accountcode}","${caller_id_number}","${destination_number}","${context}","${caller_id}","${channel_name}","${bridge_channel}","${last_app}","${last_arg}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${amaflags}","${uuid}","${userfield}"</template>
</templates>
</configuration>
-832
View File
@@ -1,832 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
NOTICE:
This context is usually accessed via authenticated callers on the sip profile on port 5060
or transfered callers from the public context which arrived via the sip profile on port 5080.
Authenticated users will use the user_context variable on the user to determine what context
they can access. You can also add a user in the directory with the cidr= attribute acl.conf.xml
will build the domains ACL using this value.
-->
<!-- http://wiki.freeswitch.org/wiki/Dialplan_XML -->
<include>
<context name="default">
<extension name="unloop">
<condition field="${unroll_loops}" expression="^true$"/>
<condition field="${sip_looped_call}" expression="^true$">
<action application="deflect" data="${destination_number}"/>
</condition>
</extension>
<extension name="call_direction" continue="true">
<condition field="${call_direction}" expression="^(inbound|outbound|local)$">
<anti-action application="set" data="call_direction=local"/>
</condition>
</extension>
<!-- Example of doing things based on time of day.
year = 4 digit year. Example year="2009"
yday = 1-365
mon = 1-12
mday = 1-31
week = 1-52
mweek= 1-6
wday = 1-7
hour = 0-23
minute = 0-59
minute-of-day = 1-1440
Example:
<condition minute-of-day="540-1080"> (9am to 6pm EVERY day)
do something ...
</condition>
-->
<extension name="tod_example" continue="true">
<condition wday="2-6" hour="9-18">
<action application="set" data="open=true"/>
</condition>
</extension>
<!-- Example of routing based on holidays
This example covers all US Federal holidays except for inauguration day.
-->
<extension name="holiday_example" continue="true">
<condition mday="1" mon="1">
<!-- new year's day -->
<action application="set" data="open=false"/>
</condition>
<condition wday="2" mweek="3" mon="1">
<!-- martin luther king day is the 3rd monday in january -->
<action application="set" data="open=false"/>
</condition>
<condition wday="2" mweek="3" mon="2">
<!-- president's day is the 3rd monday in february -->
<action application="set" data="open=false"/>
</condition>
<condition wday="2" mon="5" mday="25-31">
<!-- memorial day is the last monday in may (the only monday between the 25th and the 31st) -->
<action application="set" data="open=false"/>
</condition>
<condition mday="4" mon="7">
<!-- independence day -->
<action application="set" data="open=false"/>
</condition>
<condition wday="2" mweek="1" mon="9">
<!-- labor day is the 1st monday in september -->
<action application="set" data="open=false"/>
</condition>
<condition wday="2" mweek="2" mon="10">
<!-- columbus day is the 2nd monday in october -->
<action application="set" data="open=false"/>
</condition>
<condition mday="11" mon="11">
<!-- veteran's day -->
<action application="set" data="open=false"/>
</condition>
<condition wday="5-6" mweek="4" mon="11">
<!-- thanksgiving is the 4th thursday in november and usually there's an extension for black friday -->
<action application="set" data="open=false"/>
</condition>
<condition mday="25" mon="12">
<!-- Christmas -->
<action application="set" data="open=false"/>
</condition>
</extension>
<!--
<extension name="global-intercept">
<condition field="destination_number" expression="^\*886$">
<action application="answer"/>
<action application="intercept" data="${hash(select/${domain_name}-last_dial/global)}"/>
<action application="sleep" data="2000"/>
</condition>
</extension>
-->
<extension name="group-intercept">
<condition field="destination_number" expression="^\*8$">
<action application="answer"/>
<action application="intercept" data="${hash(select/${domain_name}-last_dial/${call_group})}"/>
<action application="sleep" data="2000"/>
</condition>
</extension>
<extension name="redial">
<condition field="destination_number" expression="^(redial|\*870)$">
<action application="transfer" data="${hash(select/${domain_name}-last_dial/${caller_id_number})}"/>
</condition>
</extension>
<extension name="global" continue="true">
<condition field="${call_debug}" expression="^true$" break="never">
<action application="info"/>
</condition>
<!--
This is an example of how to auto detect if telephone-event is missing and activate inband detection
-->
<!--
<condition field="${switch_r_sdp}" expression="a=rtpmap:(\d+)\stelephone-event/8000" break="never">
<action application="set" data="rtp_payload_number=$1"/>
<anti-action application="start_dtmf"/>
</condition>
-->
<condition field="${sip_has_crypto}" expression="^(AES_CM_128_HMAC_SHA1_32|AES_CM_128_HMAC_SHA1_80)$" break="never">
<action application="set" data="sip_secure_media=true"/>
<!-- Offer SRTP on outbound legs if we have it on inbound. -->
<!-- <action application="export" data="sip_secure_media=true"/> -->
</condition>
<condition>
<action application="hash" data="insert/${domain_name}-spymap/${caller_id_number}/${uuid}"/>
<action application="hash" data="insert/${domain_name}-last_dial/${caller_id_number}/${destination_number}"/>
<action application="hash" data="insert/${domain_name}-last_dial/global/${uuid}"/>
<action application="set" data="RFC2822_DATE=${strftime(%a, %d %b %Y %T %z)}"/>
</condition>
</extension>
<!-- If sip_req_host is not a local domain then this has to be an external sip uri -->
<!--
<extension name="external_sip_uri" continue="true">
<condition field="source" expression="mod_sofia"/>
<condition field="${outside_call}" expression="^$"/>
<condition field="${domain_exists(${sip_req_host})}" expression="true">
<anti-action application="bridge" data="sofia/${use_profile}/${sip_to_uri}"/>
</condition>
</extension>
-->
<!--
Snom button demo, call 9000 to make button 2 mapped to transfer the current call to a conference
-->
<extension name="snom-demo-2">
<condition field="destination_number" expression="^\*9001$">
<action application="eval" data="${snom_bind_key(2 off DND ${sip_from_user} ${sip_from_host} ${sofia_profile_name} message notused)}"/>
<action application="transfer" data="3000"/>
</condition>
</extension>
<extension name="snom-demo-1">
<condition field="destination_number" expression="^\*9000$">
<!--<key> <light> <label> <user> <host> <profile> <action_name> <action>-->
<action application="eval" data="${snom_bind_key(2 on DND ${sip_from_user} ${sip_from_host} ${sofia_profile_name} message api+uuid_transfer ${uuid} 9001)}"/>
<action application="playback" data="$${hold_music}"/>
</condition>
</extension>
<!--
<extension name="eavesdrop">
<condition field="destination_number" expression="^\*88(\d{2,7})$|^\*0(.*)$">
<action application="answer"/>
<action application="eavesdrop" data="${hash(select/${domain_name}-spymap/$1)}"/>
</condition>
</extension>
-->
<!--
<extension name="eavesdrop">
<condition field="destination_number" expression="^\*779$">
<action application="answer"/>
<action application="set" data="eavesdrop_indicate_failed=tone_stream://%(500, 0, 320)"/>
<action application="set" data="eavesdrop_indicate_new=tone_stream://%(500, 0, 620)"/>
<action application="set" data="eavesdrop_indicate_idle=tone_stream://%(250, 0, 920)"/>
<action application="eavesdrop" data="all"/>
</condition>
</extension>
-->
<extension name="call_privacy">
<condition field="destination_number" expression="^\*67(\d+)$">
<action application="privacy" data="full"/>
<action application="set" data="sip_h_Privacy=id"/>
<action application="set" data="privacy=yes"/>
<action application="transfer" data="$1 XML default"/>
</condition>
</extension>
<extension name="call_return">
<condition field="destination_number" expression="^\*69$|^869$|^lcr$">
<action application="transfer" data="${hash(select/${domain_name}-call_return/${caller_id_number})}"/>
</condition>
</extension>
<extension name="del-group">
<condition field="destination_number" expression="^\*\*80(\d{2})$">
<action application="answer"/>
<action application="group" data="delete:$1@${domain_name}:${sofia_contact(${sip_from_user}@${domain_name})}"/>
<action application="gentones" data="%(1000, 0, 320)"/>
</condition>
</extension>
<extension name="add-group">
<condition field="destination_number" expression="^\*\*81(\d{2})$">
<action application="answer"/>
<action application="group" data="insert:$1@${domain_name}:${sofia_contact(${sip_from_user}@${domain_name})}"/>
<action application="gentones" data="%(1000, 0, 640)"/>
</condition>
</extension>
<extension name="call-group-simo">
<condition field="destination_number" expression="^\*\*82(\d{2})$">
<action application="bridge" data="{leg_timeout=15,ignore_early_media=true}${group(call:$1@${domain_name})}"/>
</condition>
</extension>
<extension name="call-group-order">
<condition field="destination_number" expression="^\*83(\d{2})$">
<action application="bridge" data="{leg_timeout=15,ignore_early_media=true}${group(call:$1@${domain_name}:order)}"/>
</condition>
</extension>
<extension name="intercept-ext">
<condition field="destination_number" expression="^\*\*(\d+)$">
<action application="answer"/>
<action application="intercept" data="${hash(select/${domain_name}-last_dial_ext/$1)}"/>
<action application="sleep" data="2000"/>
</condition>
</extension>
<!--
<extension name="extension-intercom">
<condition field="destination_number" expression="^\*8(\d{2,7})$">
<action application="set" data="dialed_extension=$1"/>
<action application="export" data="sip_auto_answer=true"/>
<action application="bridge" data="user/${dialed_extension}@${domain_name}"/>
</condition>
</extension>
-->
<extension name="Local_Extension_Skinny">
<condition field="destination_number" expression="^(11[01][0-9])$">
<action application="bridge" data="skinny/internal/${destination_number}"/>
</condition>
</extension>
<extension name="send_to_voicemail">
<condition field="destination_number" expression="^\*99(\d{2,7})$">
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="set" data="dialed_extension=$1"/>
<action application="export" data="dialed_extension=$1"/>
<action application="voicemail" data="default ${domain_name} ${dialed_extension}"/>
</condition>
</extension>
<X-PRE-PROCESS cmd="include" data="default/*.xml"/>
<extension name="group_dial_sales">
<condition field="destination_number" expression="^\*2000$">
<action application="bridge" data="${group_call(sales@${domain_name})}"/>
</condition>
</extension>
<extension name="group_dial_support">
<condition field="destination_number" expression="^\*2001$">
<action application="bridge" data="group/support@${domain_name}"/>
</condition>
</extension>
<extension name="group_dial_billing">
<condition field="destination_number" expression="^\*2002$">
<action application="bridge" data="group/billing@${domain_name}"/>
</condition>
</extension>
<!-- voicemail operator extension -->
<extension name="operator">
<condition field="destination_number" expression="^operator$">
<action application="set" data="transfer_ringback=$${hold_music}"/>
<action application="transfer" data="1000 XML features"/>
</condition>
</extension>
<!-- voicemail main extension, used when * is pressed from an external number -->
<extension name="vmain">
<condition field="destination_number" expression="^vmain$">
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="voicemail" data="check default ${domain_name} ${dialed_extension}"/>
</condition>
</extension>
<!-- voicemail main extension -->
<extension name="vmain1">
<condition field="destination_number" expression="^vmain1$|^\*97$|^\*4000$">
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="voicemail" data="check default ${domain_name}"/>
</condition>
</extension>
<!-- voicemail main1 extension -->
<extension name="vmain2">
<condition field="destination_number" expression="^vmain2$|^\*98$">
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="voicemail" data="check default ${domain_name} ${sip_from_user}"/>
</condition>
</extension>
<!--
This extension is used by mod_portaudio so you can pa call sip:someone@example.com
mod_portaudio will pass the entire string to the dialplan for routing.
-->
<extension name="sip_uri">
<condition field="destination_number" expression="^sip:(.*)$">
<action application="bridge" data="sofia/${use_profile}/$1"/>
</condition>
</extension>
<!--
start a dynamic conference with the settings of the "default" conference profile in conference.conf.xml
-->
<extension name="nb_conferences">
<condition field="destination_number" expression="^\*(30\d{2})$">
<action application="answer"/>
<action application="conference" data="$1-${domain_name}@default"/>
</condition>
</extension>
<extension name="wb_conferences">
<condition field="destination_number" expression="^\*(31\d{2})$">
<action application="answer"/>
<action application="conference" data="$1-${domain_name}@wideband"/>
</condition>
</extension>
<extension name="uwb_conferences">
<condition field="destination_number" expression="^\*(32\d{2})$">
<action application="answer"/>
<action application="conference" data="$1-${domain_name}@ultrawideband"/>
</condition>
</extension>
<!-- MONO 48kHz conferences -->
<extension name="cdquality_conferences">
<condition field="destination_number" expression="^\*(33\d{2})$">
<action application="answer"/>
<action application="conference" data="$1-${domain_name}@cdquality"/>
</condition>
</extension>
<!-- dial the FreeSWITCH conference via SIP-->
<extension name="freeswitch_public_conf_via_sip">
<condition field="destination_number" expression="^\*9(888|8888|1616|3232)$">
<action application="export" data="hold_music=silence"/>
<!--
This will take the SAS from the b-leg and send it to the display on the a-leg phone.
Known working with Polycom and Snom maybe others.
-->
<!--
<action application="set" data="exec_after_bridge_app=${sched_api(+4 zrtp expand uuid_display ${uuid} \${uuid_getvar(\${uuid_getvar(${uuid} signal_bond)} zrtp_sas1_string )} \${uuid_getvar(\${uuid_getvar(${uuid} signal_bond)} zrtp_sas2_string )} )}"/>
<action application="export" data="nolocal:zrtp_secure_media=true"/>
-->
<action application="bridge" data="sofia/${use_profile}/$1@conference.freeswitch.org"/>
</condition>
</extension>
<!--
This extension will start a conference and invite a group.
At anytime the participant can dial *2 to bridge directly to the boss.
All other callers are then hung up on.
-->
<!--
<extension name="mad_boss_intercom">
<condition field="destination_number" expression="^\*0911$">
<action application="set" data="conference_auto_outcall_caller_id_name=Mad Boss1"/>
<action application="set" data="conference_auto_outcall_caller_id_number=0911"/>
<action application="set" data="conference_auto_outcall_timeout=60"/>
<action application="set" data="conference_auto_outcall_flags=mute"/>
<action application="set" data="conference_auto_outcall_prefix={sip_auto_answer=true,execute_on_answer='bind_meta_app 2 a s1 transfer::intercept:${uuid} inline'}"/>
<action application="set" data="sip_exclude_contact=${network_addr}"/>
<action application="conference_set_auto_outcall" data="${group_call(sales)}"/>
<action application="conference" data="madboss_intercom1@default+flags{endconf|deaf}"/>
</condition>
</extension>
-->
<!--
This extension will start a conference and invite a few of people.
At anytime the participant can dial *2 to bridge directly to the boss.
All other callers are then hung up on.
-->
<!--
<extension name="mad_boss_intercom">
<condition field="destination_number" expression="^\*0912$">
<action application="set" data="conference_auto_outcall_caller_id_name=Mad Boss2"/>
<action application="set" data="conference_auto_outcall_caller_id_number=0912"/>
<action application="set" data="conference_auto_outcall_timeout=60"/>
<action application="set" data="conference_auto_outcall_flags=mute"/>
<action application="set" data="conference_auto_outcall_prefix={sip_auto_answer=true,execute_on_answer='bind_meta_app 2 a s1 transfer::intercept:${uuid} inline'}"/>
<action application="set" data="sip_exclude_contact=${network_addr}"/>
<action application="conference_set_auto_outcall" data="loopback/*9664"/>
<action application="conference" data="madboss_intercom2@default+flags{endconf|deaf}"/>
</condition>
</extension>
-->
<!--This extension will start a conference and invite several people upon entering -->
<!--These params effect the outcalls made once you join-->
<!--<action application="set" data="conference_auto_outcall_announce=say:You have been called into an emergency conference"/>-->
<!--Add as many of these as you need, These are the people you are going to call-->
<!--
<extension name="mad_boss">
<condition field="destination_number" expression="^\*0913$">
<action application="set" data="conference_auto_outcall_caller_id_name=Mad Boss"/>
<action application="set" data="conference_auto_outcall_caller_id_number=0911"/>
<action application="set" data="conference_auto_outcall_timeout=60"/>
<action application="set" data="conference_auto_outcall_flags=none"/>
<action application="conference_set_auto_outcall" data="loopback/*9664"/>
<action application="conference" data="madboss3@default"/>
</condition>
</extension>
-->
<!-- a sample IVR -->
<extension name="ivr_demo">
<condition field="destination_number" expression="^\*5000$">
<action application="answer"/>
<action application="sleep" data="2000"/>
<action application="ivr" data="demo_ivr"/>
</condition>
</extension>
<!-- Create a conference on the fly and pull someone in at the same time. -->
<extension name="dynamic_conference">
<condition field="destination_number" expression="^\*5001$">
<action application="conference" data="bridge:mydynaconf:sofia/${use_profile}/1234@conference.freeswitch.org"/>
</condition>
</extension>
<extension name="rtp_multicast_page">
<condition field="destination_number" expression="^pagegroup$|^\*7243$">
<action application="answer"/>
<action application="esf_page_group"/>
</condition>
</extension>
<!--
Parking extensions... transferring calls to *5900 - *5999 will park them in a queue.
-->
<extension name="parking_slots">
<condition field="destination_number" expression="^(\*59[0-9][0-9])$" break="on-false">
<!-- Get count of callers in the specified parking slot (FIFO) -->
<action inline="true" application="set" data="slot_count=${fifo(count $1@${domain_name})}"/>
<action inline="true" application="set" data="slot_count=${slot_count:-3:2}"/>
</condition>
<condition field="${slot_count}" expression="^\:0$" break="always">
<!-- FIFO settings for parking FIFOs -->
<action application="unset" data="fifo_chime_list"/>
<action application="set" data="fifo_chime_freq=0"/>
<!-- FIFO is empty, so park the caller: -->
<action application="fifo" data="${destination_number}@${domain_name} in undef local_stream://moh"/>
<!-- FIFO has a caller, so un-park the caller: -->
<anti-action application="fifo" data="${destination_number}@${domain_name} out nowait"/>
</condition>
</extension>
<!--
Valet Park Drop off
The valet parking will find the first stall between 6001 and 6099,
park the call there, and then voice the stall number to the transferring user.
The call can then be retrieved in the normal fashion by dialing the slot number:
-->
<extension name="valet_park_in">
<condition field="destination_number" expression="^\*(6000)$">
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="valet_park" data="valet_parking_lot auto in 6001 6099"/>
</condition>
</extension>
<!--
Valet Park Pick Up
Call the number that was announced when parking the call prefix it with a * to pickup the call.
After the call is retrieved the valet parking slot is free for another call.
-->
<extension name="valet_park_out">
<condition field="destination_number" expression="^\*(60\d\d)$">
<action application="answer"/>
<action application="valet_park" data="valet_parking_lot $1"/>
</condition>
</extension>
<!--
This extension is used with Snom phones.
Set a function key to park+lot (lot being a number or name.)
Set type to Park+Orbit. You can then park and pickup using
the softkey on the phone. Should work with other phones.
-->
<extension name="park">
<condition field="source" expression="mod_sofia"/>
<condition field="destination_number" expression="park\+(\d+)">
<action application="fifo" data="$1@${domain_name} in undef $${hold_music}"/>
</condition>
</extension>
<!--
The extension is parking pickup with a to param of the fifo we are calling
Some phones send things like orbit= and you can extract that info.
-->
<extension name="unpark">
<condition field="source" expression="mod_sofia"/>
<condition field="destination_number" expression="^parking$"/>
<condition field="${sip_to_params}" expression="fifo\=(\d+)">
<action application="answer"/>
<action application="fifo" data="$1@${domain_name} out nowait"/>
</condition>
</extension>
<!--
This extension is used with Linksys phones.
Set a Phone tab option Call Park Serv to yes. You can park and
pickup using soft keys "park" and "unpark" found during
active call when moving navigation button. The other option
is to use phone's star codes (defaults to *38 and *39).
-->
<extension name="park">
<condition field="source" expression="mod_sofia"/>
<condition field="destination_number" expression="callpark"/>
<condition field="${sip_refer_to}">
<expression><![CDATA[<sip:callpark@${domain_name};orbit=(\d+)>]]></expression>
<action application="fifo" data="$1@${domain_name} in undef $${hold_music}"/>
</condition>
</extension>
<!--
This extension is used with Linksys phones.
The extension is parking pickup with a to param of the fifo
we are calling. Linksys sends orbit=<parkingslotnumber>
and we extract that info.
-->
<extension name="unpark">
<condition field="source" expression="mod_sofia"/>
<condition field="destination_number" expression="pickup"/>
<condition field="${sip_to_params}" expression="orbit\=(\d+)">
<action application="answer"/>
<action application="fifo" data="$1@${domain_name} out nowait"/>
</condition>
</extension>
<!--
Here are some examples of how to override the ringback heard by the
far end. You have two variables that you can use to override this.
ringback - used when a call isn't answered. (early media)
transfer_ringback - used when the call is already answered. (post answer)
-->
<!-- Demonstration of how to override the ringback in various situations -->
<extension name="wait">
<condition field="destination_number" expression="^wait$">
<action application="pre_answer"/>
<action application="sleep" data="20000"/>
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="playback" data="voicemail/vm-goodbye.wav"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="fax_receive">
<condition field="destination_number" expression="^\*9178$">
<action application="answer" />
<action application="playback" data="silence_stream://2000"/>
<action application="rxfax" data="/tmp/rxfax.tif"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="fax_transmit">
<condition field="destination_number" expression="^\*9179$">
<action application="txfax" data="/tmp/txfax.tif"/>
<action application="hangup"/>
</condition>
</extension>
<!-- Send a 180 and let the far end generate ringback. -->
<extension name="ringback_180">
<condition field="destination_number" expression="^\*9180$">
<action application="ring_ready"/>
<action application="sleep" data="20000"/>
<action application="answer"/>
<action application="sleep" data="1000"/>
<action application="playback" data="voicemail/vm-goodbye.wav"/>
<action application="hangup"/>
</condition>
</extension>
<!-- Send a 183 and send uk-ring as the ringtone. (early media) -->
<extension name="ringback_183_uk_ring">
<condition field="destination_number" expression="^\*9181$">
<action application="set" data="ringback=$${uk-ring}"/>
<action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition>
</extension>
<!-- Send a 183 and use music as the ringtone. (early media) -->
<extension name="ringback_183_music_ring">
<condition field="destination_number" expression="^\*9182$">
<action application="set" data="ringback=$${hold_music}"/>
<action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition>
</extension>
<!-- Answer the call and use music as the ringtone. (post answer) -->
<extension name="ringback_post_answer_uk_ring">
<condition field="destination_number" expression="^\*9183$">
<action application="set" data="transfer_ringback=$${uk-ring}"/>
<action application="answer"/>
<action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition>
</extension>
<!-- Answer the call and use music as the ringtone. (post answer) -->
<extension name="ringback_post_answer_music">
<condition field="destination_number" expression="^\*9184$">
<action application="set" data="transfer_ringback=$${hold_music}"/>
<action application="answer"/>
<action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition>
</extension>
<extension name="ClueCon">
<condition field="destination_number" expression="^\*9191$">
<action application="set" data="effective_caller_id_name=ClueCon IVR"/>
<action application="bridge" data="sofia/$${domain}/2000@bkw.org"/>
</condition>
</extension>
<extension name="show_info">
<condition field="destination_number" expression="^\*9192$">
<action application="answer"/>
<action application="info"/>
<action application="sleep" data="250"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="video_record">
<condition field="destination_number" expression="^\*9193$">
<action application="answer"/>
<action application="record_fsv" data="/tmp/testrecord.fsv"/>
</condition>
</extension>
<extension name="video_playback">
<condition field="destination_number" expression="^\*9194$">
<action application="answer"/>
<action application="play_fsv" data="/tmp/testrecord.fsv"/>
</condition>
</extension>
<extension name="delay_echo">
<condition field="destination_number" expression="^\*9195$">
<action application="answer"/>
<action application="delay_echo" data="5000"/>
</condition>
</extension>
<extension name="echo">
<condition field="destination_number" expression="^\*9196$">
<action application="answer"/>
<action application="echo"/>
</condition>
</extension>
<extension name="milliwatt">
<condition field="destination_number" expression="^\*9197$">
<action application="answer"/>
<action application="playback" data="tone_stream://%(251,0,1004);loops=-1"/>
</condition>
</extension>
<extension name="tone_stream">
<condition field="destination_number" expression="^\*9198$">
<action application="answer"/>
<action application="playback" data="tone_stream://path=${base_dir}/conf/tetris.ttml;loops=10"/>
</condition>
</extension>
<!-- install zrtp_agent.lua into scripts (ZRTP == 9787) -->
<extension name="zrtp_enrollement">
<condition field="destination_number" expression="^\*9787$">
<action application="answer"/>
<action application="lua" data="zrtp_agent.lua"/>
</condition>
</extension>
<!--
You will no longer hear the bong tone. The wav file is playing stating the call is secure.
The file will not play unless you have both TLS and SRTP active.
-->
<extension name="hold_music">
<condition field="destination_number" expression="^\*9664$"/>
<condition field="${sip_has_crypto}" expression="^(AES_CM_128_HMAC_SHA1_32|AES_CM_128_HMAC_SHA1_80)$">
<action application="answer"/>
<action application="execute_extension" data="is_secure XML features"/>
<action application="playback" data="$${hold_music}"/>
<anti-action application="set" data="zrtp_secure_media=true"/>
<anti-action application="answer"/>
<anti-action application="playback" data="silence_stream://2000"/>
<anti-action application="execute_extension" data="is_zrtp_secure XML features"/>
<anti-action application="playback" data="$${hold_music}"/>
</condition>
</extension>
<!--
dial the extension (1000-1019) for 30 seconds and go to voicemail if the
call fails (continue_on_fail=true), otherwise hang up after a successful
bridge (hangup_after-bridge=true)
-->
<extension name="Local_Extension">
<condition field="destination_number" expression="(^\d{2,7}$)">
<action application="set" data="dialed_extension=$1"/>
<action application="export" data="dialed_extension=$1"/>
<action application="limit" data="hash ${domain_name} $1 ${limit_max} ${limit_destination}"/>
<!-- bind_meta_app can have these args <key> [a|b|ab] [a|b|o|s] <app> -->
<action application="bind_meta_app" data="1 b s execute_extension::dx XML features"/>
<action application="bind_meta_app" data="2 b s record_session::$${recordings_dir}/archive/${strftime(%Y)}/${strftime(%b)}/${strftime(%d)}/${uuid}.wav"/>
<action application="bind_meta_app" data="3 b s execute_extension::cf XML features"/>
<action application="bind_meta_app" data="4 b s execute_extension::att_xfer XML features"/>
<action application="set" data="ringback=${us-ring}"/>
<action application="set" data="transfer_ringback=$${hold_music}"/>
<action application="set" data="call_timeout=30"/>
<!-- <action application="set" data="sip_exclude_contact=${network_addr}"/> -->
<action application="set" data="hangup_after_bridge=true"/>
<!--<action application="set" data="continue_on_fail=NORMAL_TEMPORARY_FAILURE,USER_BUSY,NO_ANSWER,TIMEOUT,NO_ROUTE_DESTINATION"/> -->
<action application="set" data="continue_on_fail=true"/>
<action application="hash" data="insert/${domain_name}-call_return/${dialed_extension}/${caller_id_number}"/>
<action application="hash" data="insert/${domain_name}-last_dial_ext/${dialed_extension}/${uuid}"/>
<action application="set" data="called_party_call_group=${user_data(${dialed_extension}@${domain_name} var call_group)}"/>
<!--<action application="export" data="nolocal:sip_secure_media=${user_data(${dialed_extension}@${domain_name} var sip_secure_media)}"/>-->
<action application="hash" data="insert/${domain_name}-last_dial/${called_party_call_group}/${uuid}"/>
<!-- standard method -->
<!--<action application="bridge" data="user/${dialed_extension}@${domain_name}"/> -->
<!-- sofia contact -->
<!--<action application="bridge" data="${sofia_contact(${dialed_extension}@${domain_name})}"/>-->
<!-- number-alias / http://wiki.freeswitch.com/wiki/XML_User_Directory_Guide -->
<action application="bridge" data="user/${user_data(${destination_number}@${domain_name} attr id)}@${domain_name}"/>
<action application="answer"/>
<action application="sleep" data="1000"/>
<!--<action application="bridge" data="loopback/app=voicemail:default ${domain_name} ${dialed_extension}"/>-->
<action application="voicemail" data="default ${domain_name} ${dialed_extension}"/>
</condition>
</extension>
<!--
You can place files in the default directory to get included.
-->
<!--<X-PRE-PROCESS cmd="include" data="default/*.xml"/>-->
<!--
<extension name="refer">
<condition field="${sip_refer_to}">
<expression><![CDATA[<sip:${destination_number}@${domain_name}>]]></expression>
</condition>
<condition field="${sip_refer_to}">
<expression><![CDATA[<sip:(.*)@(.*)>]]></expression>
<action application="set" data="refer_user=$1"/>
<action application="set" data="refer_domain=$2"/>
<action application="info"/>
<action application="bridge" data="sofia/${use_profile}/${refer_user}@${refer_domain}"/>
</condition>
</extension>
-->
<!--
This is an example of how to override the RURI on an outgoing invite to a registered contact.
-->
<!--
<extension name="ruri">
<condition field="destination_number" expression="^ruri$">
<action application="bridge" data="sofia/${ruri_profile}/${ruri_user}${regex(${sofia_contact(${ruri_contact})}|^[^\@]+(.*)|%1)}"/>
</condition>
</extension>
<extension name="7004">
<condition field="destination_number" expression="^7004$">
<action application="set" data="ruri_profile=default"/>
<action application="set" data="ruri_user=2000"/>
<action application="set" data="ruri_contact=1001@${domain_name}"/>
<action application="execute_extension" data="ruri"/>
</condition>
</extension>
<extension name="enum">
<condition field="${module_exists(mod_enum)}" expression="true"/>
<condition field="destination_number" expression="^(.*)$">
<action application="transfer" data="$1 enum"/>
</condition>
</extension>
-->
</context>
</include>
-10
View File
@@ -1,10 +0,0 @@
Copyright (c) 2005, Fabricio Zuardi
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Binary file not shown.
-23
View File
@@ -1,23 +0,0 @@
<p>
You can find more infos about slim.swf here:
</p>
<p>
http://musicplayer.sourceforge.net/#documentation
</p>
<p>
<br/>
Please remember that you should record your MP3s at 11Khz for slim.swf to play correctly
A quick example follows:
</p>
<object type="application/x-shockwave-flash" width="400" height="17"
data="/slim.swf?song_url=/data.mp3&song_title=This%20is%20the%20title">
<param name="movie" value="/slim.swf?song_url=/data.mp3&song_title=This%20is%20the%20title" />
<param name="quality" value="high"/>
<param name="bgcolor" value="#E6E6E6"/>
</object>
<p>
Remember that if this is not working for you, you should most probably point the song_url GET parameter to a real MP3 file that should be reachable through the web server.
</p>
-15
View File
@@ -1,15 +0,0 @@
<include>
<language name="en" say-module="en" sound-prefix="$${sounds_dir}/en/us/callie" tts-engine="cepstral" tts-voice="callie">
<phrases>
<macros>
<X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
<!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/> <!-- vm/tts.xml if you want to use tts and have cepstral -->
<X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/> <!-- dir/tts.xml if you want to use tts and have cepstral -->
<X-PRE-PROCESS cmd="include" data="ivr/*.xml"/> <!-- IVR and custom phrases go here -->
<X-PRE-PROCESS cmd="include" data="wakeup/*.xml"/> <!-- IVR and custom phrases go here -->
<X-PRE-PROCESS cmd="include" data="vm/voicemail_ivr.xml"/>
</macros>
</phrases>
</language>
</include>
-129
View File
@@ -1,129 +0,0 @@
<include>
<macro name="wakeup-greeting">
<input pattern="(.*)">
<match>
<!-- To schedule a wakeup call enter a 4 digit number -->
<!-- For 6:30 am press 0630. Enter the digits now. -->
<action function="execute" data="sleep(750)"/>
<action function="play-file" data="custom/to.wav"/>
<action function="play-file" data="custom/schedule.wav"/>
<action function="play-file" data="custom/a.wav"/>
<action function="play-file" data="custom/wakeup.wav"/>
<action function="play-file" data="custom/call.wav"/>
<action function="play-file" data="custom/enter.wav"/>
<action function="play-file" data="custom/a.wav"/>
<action function="play-file" data="custom/4.wav"/>
<action function="play-file" data="custom/digit.wav"/>
<action function="play-file" data="custom/number.wav"/>
<action function="execute" data="sleep(750)"/>
<action function="play-file" data="custom/for.wav"/>
<action function="play-file" data="digits/6.wav"/>
<action function="play-file" data="digits/30.wav"/>
<action function="play-file" data="custom/a.wav"/>
<action function="play-file" data="custom/m.wav"/>
<action function="execute" data="sleep(750)"/>
<action function="play-file" data="custom/press.wav"/>
<action function="play-file" data="digits/0.wav"/>
<action function="play-file" data="digits/6.wav"/>
<action function="play-file" data="digits/3.wav"/>
<action function="play-file" data="digits/0.wav"/>
<action function="execute" data="sleep(750)"/>
<action function="play-file" data="custom/enter.wav"/>
<action function="play-file" data="custom/the.wav"/>
<action function="play-file" data="custom/digits.wav"/>
<action function="play-file" data="custom/now.wav"/>
</match>
</input>
</macro>
<macro name="wakeup-get-extension">
<input pattern="(.*)">
<match>
<!-- Tnter the extension number now -->
<action function="execute" data="sleep(750)"/>
<action function="play-file" data="custom/enter.wav"/>
<action function="play-file" data="custom/the.wav"/>
<action function="play-file" data="custom/extension.wav"/>
<action function="play-file" data="custom/number.wav"/>
<action function="play-file" data="custom/now.wav"/>
<action function="execute" data="sleep(100)"/>
</match>
</input>
</macro>
<macro name="wakeup-scheduled">
<input pattern="(.*)">
<match>
<!-- Your wakeup call has been scheduled for 0715 -->
<action function="execute" data="sleep(750)"/>
<action function="play-file" data="custom/your.wav"/>
<action function="play-file" data="custom/wakeup.wav"/>
<action function="play-file" data="custom/call.wav"/>
<action function="play-file" data="custom/has.wav"/>
<action function="play-file" data="custom/been.wav"/>
<action function="play-file" data="custom/scheduled.wav"/>
<action function="play-file" data="custom/for.wav"/>
<action function="execute" data="sleep(100)"/>
</match>
</input>
</macro>
<macro name="wakeup-accept">
<input pattern="(.*)">
<match>
<!-- To accept press 1 to cancel press 2 -->
<action function="execute" data="sleep(750)"/>
<action function="play-file" data="custom/to.wav"/>
<action function="play-file" data="custom/accept.wav"/>
<action function="play-file" data="custom/press.wav"/>
<action function="play-file" data="digits/1.wav"/>
<action function="play-file" data="custom/to.wav"/>
<action function="play-file" data="custom/cancel.wav"/>
<action function="play-file" data="custom/press.wav"/>
<action function="play-file" data="digits/2.wav"/>
<action function="execute" data="sleep(100)"/>
</match>
</input>
</macro>
<macro name="wakeup-cancel">
<input pattern="(.*)">
<match>
<!-- To cancel the wakeup call press * -->
<action function="execute" data="sleep(750)"/>
<action function="play-file" data="custom/to.wav"/>
<action function="play-file" data="custom/cancel.wav"/>
<action function="play-file" data="custom/the.wav"/>
<action function="play-file" data="custom/wakeup.wav"/>
<action function="play-file" data="custom/call.wav"/>
<action function="play-file" data="custom/press.wav"/>
<action function="play-file" data="digits/*.wav"/>
<action function="execute" data="sleep(100)"/>
</match>
</input>
</macro>
<macro name="wakeup-call">
<input pattern="(.*)">
<match>
<!-- This is your wakeup call to exit press 1 to snooze for 10 minutes press 2 -->
<action function="execute" data="sleep(1000)"/>
<action function="play-file" data="custom/this.wav"/>
<action function="play-file" data="custom/is.wav"/>
<action function="play-file" data="custom/your.wav"/>
<action function="play-file" data="custom/wakeup.wav"/>
<action function="play-file" data="custom/call.wav"/>
<action function="play-file" data="custom/to.wav"/>
<action function="play-file" data="custom/exit.wav"/>
<action function="play-file" data="custom/press.wav"/>
<action function="play-file" data="digits/1.wav"/>
<action function="play-file" data="custom/to.wav"/>
<action function="play-file" data="custom/snooze.wav"/>
<action function="play-file" data="custom/for.wav"/>
<action function="play-file" data="digits/10.wav"/>
<action function="play-file" data="custom/minutes.wav"/>
<action function="play-file" data="custom/press.wav"/>
<action function="play-file" data="digits/2.wav"/>
<action function="execute" data="sleep(100)"/>
</match>
</input>
</macro>
</include>
-49
View File
@@ -1,49 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--get the argv values
script_name = argv[0];
app_name = argv[1];
--example use command
--luarun app.lua name 'a' 'b 123' 'c'
--for loop through arguments
arguments = "";
for key,value in pairs(argv) do
if (key > 1) then
arguments = arguments .. " '" .. value .. "'";
freeswitch.consoleLog("notice", "[voicemail] argv["..key.."]: " .. argv[key] .. "\n");
end
end
--route the request to the application
--freeswitch.consoleLog("notice", "[app] lua route: ".. scripts_dir .. "/app/" .. app_name .. "/index.lua" .. arguments .."\n");
dofile(scripts_dir .. "/app/" .. app_name .. "/index.lua" .. arguments);
@@ -1,630 +0,0 @@
-- conference.lua
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set variables
flags = "";
max_tries = 3;
digit_timeout = 5000;
--debug
debug["sql"] = true;
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--prepare the api object
api = freeswitch.API();
--general functions
dofile(scripts_dir.."/resources/functions/base64.lua");
dofile(scripts_dir.."/resources/functions/trim.lua");
dofile(scripts_dir.."/resources/functions/file_exists.lua");
dofile(scripts_dir.."/resources/functions/explode.lua");
dofile(scripts_dir.."/resources/functions/format_seconds.lua");
dofile(scripts_dir.."/resources/functions/mkdir.lua");
--get the session variables
uuid = session:getVariable("uuid");
--answer the call
session:answer();
--define a function to send email
function send_email(email, attachment, default_language, default_dialect)
--require the email address to send the email
if (string.len(email) > 2) then
--format the message length and date
--message_length_formatted = format_seconds(message_length);
--if (debug["info"]) then
-- freeswitch.consoleLog("notice", "[conference_center] message length: " .. message_length .. "\n");
--end
local conference_date_end = os.date("%A, %d %b %Y %I:%M %p");
--os.time();
--prepare the files
file_subject = scripts_dir.."/app/conference_center/resources/templates/"..default_language.."/"..default_dialect.."email_subject.tpl";
file_body = scripts_dir.."/app/conference_center/resources/templates/"..default_language.."/"..default_dialect.."/email_body.tpl";
if (not file_exists(file_subject)) then
file_subject = scripts_dir.."/app/conference_center/resources/templates/en/us/email_subject.tpl";
file_body = scripts_dir.."/app/conference_center/resources/templates/en/us/email_body.tpl";
end
--get the moderator_pin
sql = [[SELECT moderator_pin FROM v_meetings
WHERE meeting_uuid = ']] .. meeting_uuid ..[[']];
freeswitch.consoleLog("notice", "[voicemail] sql: " .. sql .. "\n");
status = dbh:query(sql, function(row)
moderator_pin = string.lower(row["moderator_pin"]);
end);
--prepare the subject
local f = io.open(file_subject, "r");
local subject = f:read("*all");
f:close();
subject = subject:gsub("${moderator_pin}", moderator_pin);
subject = subject:gsub("${conference_date_end}", conference_date_end);
--subject = subject:gsub("${conference_duration}", message_length_formatted);
subject = subject:gsub("${domain_name}", domain_name);
subject = trim(subject);
subject = '=?utf-8?B?'..base64.enc(subject)..'?=';
--prepare the body
local f = io.open(file_body, "r");
local body = f:read("*all");
f:close();
body = body:gsub("${moderator_pin}", moderator_pin);
body = body:gsub("${conference_date_end}", conference_date_end);
body = body:gsub("${conference_uuid}", conference_session_uuid);
--body = body:gsub("${conference_duration}", message_length_formatted);
body = body:gsub("${domain_name}", domain_name);
body = body:gsub(" ", "&nbsp;");
body = body:gsub("%s+", "");
body = body:gsub("&nbsp;", " ");
body = body:gsub("\n", "");
body = body:gsub("\n", "");
body = body:gsub("'", "&#39;");
body = body:gsub([["]], "&#34;");
body = trim(body);
--send the email
if (string.len(attachment) > 4) then
cmd = "luarun email.lua "..email.." "..email.." '"..subject.."' '"..body.."' '"..attachment.."'";
else
cmd = "luarun email.lua "..email.." "..email.." '"..subject.."' '"..body.."'";
end
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail] cmd: " .. cmd .. "\n");
end
result = api:executeString(cmd);
end
end
--define the session hangup
function session_hangup_hook()
--get the session variables
conference_session_detail_uuid = api:executeString("create_uuid");
--conference_name = session:getVariable("conference_name");
conference_session_uuid = session:getVariable("conference_uuid");
--conference_recording = session:getVariable("conference_recording");
conference_moderator = session:getVariable("conference_moderator");
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
--recording = session:getVariable("recording");
--set the end epoch
end_epoch = os.time();
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--get the conference sessions
if (conference_session_uuid) then
sql = [[SELECT count(*) as num_rows
FROM v_conference_sessions
WHERE conference_session_uuid = ']] .. conference_session_uuid ..[[']];
status = dbh:query(sql, function(row)
num_rows = string.lower(row["num_rows"]);
end);
freeswitch.consoleLog("notice", "[conference] SQL: " .. sql .. " Rows:"..num_rows.."\n");
if (tonumber(num_rows) == 0) then
local sql = {}
table.insert(sql, "INSERT INTO v_conference_sessions ");
table.insert(sql, "(");
table.insert(sql, "conference_session_uuid, ");
table.insert(sql, "domain_uuid, ");
table.insert(sql, "meeting_uuid, ");
--if (conference_recording) then
-- table.insert(sql, "recording, ");
--end
--if (wait_mod) then
-- table.insert(sql, "wait_mod, ");
--end
--table.insert(sql, "start_epoch, ");
table.insert(sql, "profile ");
table.insert(sql, ") ");
table.insert(sql, "VALUES ");
table.insert(sql, "( ");
table.insert(sql, "'".. conference_session_uuid .."', ");
table.insert(sql, "'".. domain_uuid .."', ");
table.insert(sql, "'".. meeting_uuid .."', ");
--if (conference_recording) then
-- table.insert(sql, "'".. conference_recording .."', ");
--end
--if (wait_mod) then
-- table.insert(sql, "'".. wait_mod .."', ");
--end
--table.insert(sql, "'".. start_epoch .."', ");
table.insert(sql, "'".. profile .."' ");
table.insert(sql, ") ");
SQL_STRING = table.concat(sql, "\n");
dbh:query(SQL_STRING);
freeswitch.consoleLog("notice", "[conference] SQL: " .. SQL_STRING .. "\n");
end
end
--add the conference sessions details
if (conference_session_uuid) then
local sql = {}
table.insert(sql, "INSERT INTO v_conference_session_details ");
table.insert(sql, "(");
table.insert(sql, "conference_session_detail_uuid, ");
table.insert(sql, "domain_uuid, ");
table.insert(sql, "conference_session_uuid, ");
table.insert(sql, "meeting_uuid, ");
table.insert(sql, "username, ");
table.insert(sql, "caller_id_name, ");
table.insert(sql, "caller_id_number, ");
table.insert(sql, "network_addr, ");
table.insert(sql, "uuid, ");
if (conference_moderator) then
table.insert(sql, "moderator, ");
end
table.insert(sql, "start_epoch, ");
table.insert(sql, "end_epoch ");
table.insert(sql, ") ");
table.insert(sql, "VALUES ");
table.insert(sql, "( ");
table.insert(sql, "'".. conference_session_detail_uuid .."', ");
table.insert(sql, "'".. domain_uuid .."', ");
table.insert(sql, "'".. conference_session_uuid .."', ");
table.insert(sql, "'".. meeting_uuid .."', ");
table.insert(sql, "'".. username .."', ");
table.insert(sql, "'".. caller_id_name .."', ");
table.insert(sql, "'".. caller_id_number .."', ");
table.insert(sql, "'".. network_addr .."', ");
table.insert(sql, "'".. uuid .."', ");
if (conference_moderator) then
table.insert(sql, "'".. conference_moderator .."', ");
end
table.insert(sql, "'".. start_epoch .."', ");
table.insert(sql, "'".. end_epoch .."' ");
table.insert(sql, ") ");
SQL_STRING = table.concat(sql, "\n");
dbh:query(SQL_STRING);
end
--if the conference is empty
if (conference_session_uuid) then
cmd = "conference "..meeting_uuid.."-"..domain_name.." xml_list";
result = trim(api:executeString(cmd));
if (string.sub(result, -9) == "not found") then
--get the conference start_epoch
sql = [[SELECT start_epoch
FROM v_conference_session_details
WHERE conference_session_uuid = ']] .. conference_session_uuid ..[['
ORDER BY start_epoch ASC
LIMIT 1]];
status = dbh:query(sql, function(row)
start_epoch = string.lower(row["start_epoch"]);
end);
freeswitch.consoleLog("notice", "[conference] <conference_start_epoch> sql: " .. sql .. "\n");
--set the conference_recording
conference_recording = recordings_dir.."/archive/"..os.date("%Y", start_epoch).."/"..os.date("%b", start_epoch).."/"..os.date("%d", start_epoch) .."/"..conference_session_uuid;
--conference has ended set the end_epoch
local sql = {}
table.insert(sql, "update v_conference_sessions set ");
table.insert(sql, "recording = '".. conference_recording .."', ");
table.insert(sql, "start_epoch = '".. start_epoch .."', ");
table.insert(sql, "end_epoch = '".. end_epoch .."' ");
table.insert(sql, "where conference_session_uuid = '"..conference_session_uuid.."' ");
SQL_STRING = table.concat(sql, "\n");
freeswitch.consoleLog("notice", "[conference] SQL: " .. SQL_STRING .. "\n");
dbh:query(SQL_STRING);
--convert the wav to an mp3
if (record == "true") then
--cmd = "sox "..conference_recording..".wav -r 16000 -c 1 "..conference_recording..".mp3";
cmd = "/usr/bin/lame -b 32 --resample 8 -a "..conference_recording..".wav "..conference_recording..".mp3";
freeswitch.consoleLog("notice", "[conference] cmd: " .. cmd .. "\n");
os.execute(cmd);
--if (file_exists(conference_recording..".mp3")) then
-- cmd = "rm "..conference_recording..".wav";
-- os.execute(cmd);
--end
end
--send the email addresses
sql = [[SELECT c.contact_email FROM v_users as u, v_meeting_users as m, v_contacts as c
WHERE m.domain_uuid = ']] .. domain_uuid ..[['
AND u.user_uuid = m.user_uuid
AND m.meeting_uuid = ']] .. meeting_uuid ..[['
and u.contact_uuid = c.contact_uuid]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[conference] <email> SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
if (row["contact_email"] ~= nil) then
contact_email = string.lower(row["contact_email"]);
if (string.len(contact_email) > 3) then
freeswitch.consoleLog("notice", "[conference] contact_email: " .. contact_email .. "\n");
if (record == "true") then
if (file_exists(conference_recording..".wav")) then
send_email(contact_email, "", default_language, default_dialect);
end
end
end
end
end);
end
end
--close the database connection
if (conference_session_uuid) then
dbh:release();
end
end
--make sure the session is ready
if (session:ready()) then
--answer the call
session:answer();
--set the hangup hook function
session:setHangupHook("session_hangup_hook");
--get session variables
sounds_dir = session:getVariable("sounds_dir");
hold_music = session:getVariable("hold_music");
domain_name = session:getVariable("domain_name");
pin_number = session:getVariable("pin_number");
--get the domain_uuid
if (domain_name ~= nil) then
sql = "SELECT domain_uuid FROM v_domains ";
sql = sql .. "WHERE domain_name = '" .. domain_name .."' ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[conference] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(rows)
domain_uuid = string.lower(rows["domain_uuid"]);
end);
end
--add the domain to the recording directory
if (domain_count > 1) then
recordings_dir = recordings_dir.."/"..domain_name;
end
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--sounds
enter_sound = "tone_stream://v=-20;%(100,1000,100);v=-20;%(90,60,440);%(90,60,620)";
exit_sound = "tone_stream://v=-20;%(90,60,620);/%(90,60,440)";
--get the variables
username = session:getVariable("username");
caller_id_name = session:getVariable("caller_id_name");
caller_id_number = session:getVariable("caller_id_number");
callee_id_name = session:getVariable("callee_id_name");
callee_id_number = session:getVariable("callee_id_number");
dialplan = session:getVariable("dialplan");
network_addr = session:getVariable("network_addr");
uuid = session:getVariable("uuid");
--context = session:getVariable("context");
chan_name = session:getVariable("chan_name");
--define the function get_pin_number
function get_pin_number(domain_uuid)
--if the pin number is provided then require it
if (not pin_number) then
min_digits = 3;
max_digits = 12;
max_tries = 1;
digit_timeout = 5000;
pin_number = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/conference/conf-pin.wav", "", "\\d+");
end
if (pin_number ~= "") then
sql = [[SELECT * FROM v_conference_rooms as r, v_meetings as m
WHERE r.domain_uuid = ']] .. domain_uuid ..[['
AND r.meeting_uuid = m.meeting_uuid
AND m.domain_uuid = ']] .. domain_uuid ..[['
AND (m.moderator_pin = ']] .. pin_number ..[[' or m.participant_pin = ']] .. pin_number ..[[')
AND r.enabled = 'true' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[conference] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
conference_room_uuid = string.lower(row["conference_room_uuid"]);
end);
end
if (conference_room_uuid == nil) then
return nil;
else
return pin_number;
end
end
--get the pin
pin_number = session:getVariable("pin_number");
if (not pin_number) then
pin_number = nil;
pin_number = get_pin_number(domain_uuid);
end
if (pin_number == nil) then
pin_number = get_pin_number(domain_uuid);
end
if (pin_number == nil) then
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/conference/conf-bad-pin.wav");
pin_number = get_pin_number(domain_uuid);
end
if (pin_number == nil) then
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/conference/conf-bad-pin.wav");
pin_number = get_pin_number(domain_uuid);
end
if (pin_number ~= nil) then
sql = [[SELECT * FROM v_conference_rooms as r, v_meetings as m
WHERE r.domain_uuid = ']] .. domain_uuid ..[['
AND r.meeting_uuid = m.meeting_uuid
AND m.domain_uuid = ']] .. domain_uuid ..[['
AND (m.moderator_pin = ']] .. pin_number ..[[' or m.participant_pin = ']] .. pin_number ..[[')
AND r.enabled = 'true' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[conference] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
conference_room_uuid = string.lower(row["conference_room_uuid"]);
conference_center_uuid = string.lower(row["conference_center_uuid"]);
meeting_uuid = string.lower(row["meeting_uuid"]);
record = string.lower(row["record"]);
profile = string.lower(row["profile"]);
max_members = row["max_members"];
wait_mod = row["wait_mod"];
moderator_pin = row["moderator_pin"];
participant_pin = row["participant_pin"];
announce = row["announce"];
mute = row["mute"];
sounds = row["sounds"];
created = row["created"];
created_by = row["created_by"];
enabled = row["enabled"];
description = row["description"];
return pin_number;
end);
freeswitch.consoleLog("INFO","conference_room_uuid: " .. conference_room_uuid .. "\n");
end
--set the member type
if (pin_number == moderator_pin) then
member_type = "moderator";
end
if (pin_number == participant_pin) then
member_type = "participant";
end
--close the database connection
dbh:release();
--set the meeting uuid
if (meeting_uuid) then
session:setVariable("meeting_uuid", meeting_uuid);
end
if (conference_center_uuid == nil) then
--invalid pin number
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/conference/conf-bad-pin.wav");
session:hangup("NORMAL_CLEARING");
else
--check if the conference exists
cmd = "conference "..meeting_uuid.."-"..domain_name.." xml_list";
result = trim(api:executeString(cmd));
if (string.sub(result, -9) == "not found") then
conference_exists = false;
else
conference_exists = true;
end
--check if the conference is locked
if (string.find(result, [[locked="true"]]) == nil) then
conference_locked = false;
else
conference_locked = true;
end
--set a conference parameter
if (max_members ~= nil) then
if (tonumber(max_members) > 0) then
--max members must be 2 or more
session:execute("set","conference_max_members="..max_members);
if (conference_exists) then
cmd = "conference "..meeting_uuid.."-"..domain_name.." get count";
count = trim(api:executeString(cmd));
if (count ~= nil) then
if (tonumber(count) >= tonumber(max_members)) then
session:execute("playback", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/conference/conf-locked.wav");
session:hangup("CALL_REJECTED");
end
end
end
end
end
--announce the caller
if (conference_locked) then
announce = "false";
end
if (announce == "true") then
--prompt for the name of the caller
session:execute("playback", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-say_name.wav");
session:execute("playback", "tone_stream://v=-7;%%(500,0,500.0)");
--record the response
max_len_seconds = 5;
silence_threshold = "500";
silence_secs = "3";
session:recordFile("/tmp/conference-"..uuid..".wav", max_len_seconds, silence_threshold, silence_secs);
end
--play a message that the conference is being a recorded
--if (record == "true") then
--session:execute("playback", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-recording_started.wav");
--end
--wait for moderator
if (wait_mod == "true") then
if (conference_exists) then
--continue
else
if (member_type == "participant") then
profile = "wait_mod";
end
end
end
--set the exit sound
if (sounds == "true") then
session:execute("set","conference_exit_sound="..exit_sound);
end
--set flags and moderator controls
if (wait_mod == "true") then
if (member_type == "participant") then
flags = flags .. "wait-mod";
end
end
if (mute == "true") then
if (member_type == "participant") then
flags = flags .. "|mute";
end
end
if (member_type == "moderator") then
--set as the moderator
flags = flags .. "|moderator";
--when the moderator leaves end the conference
--flags = flags .. "|endconf";
--set the moderator controls
session:execute("set","conference_controls=moderator");
end
--get the conference xml_list
cmd = "conference "..meeting_uuid.."-"..domain_name.." xml_list";
freeswitch.consoleLog("INFO","" .. cmd .. "\n");
result = trim(api:executeString(cmd));
--get the content to the <conference> tag
result = string.match(result,[[<conference (.-)>]],1);
--get the uuid out of the xml tag contents
if (result ~= nil) then
conference_session_uuid = string.match(result,[[uuid="(.-)"]],1);
end
--log entry
if (conference_session_uuid ~= nil) then
freeswitch.consoleLog("INFO","conference_session_uuid: " .. conference_session_uuid .. "\n");
end
--set the start epoch
start_epoch = os.time();
--set the recording variable
if (conference_session_uuid ~= nil) then
if (record == "true") then
recordings_dir = recordings_dir.."/archive/"..os.date("%Y", start_epoch).."/"..os.date("%b", start_epoch).."/"..os.date("%d", start_epoch);
mkdir(recordings_dir);
recording = recordings_dir.."/"..conference_session_uuid;
session:execute("set","recording="..recording);
end
end
--record the conference
if (record == "true") then
--play a message that the conference is being a recorded
session:execute("playback", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-recording_started.wav");
--play a message that the conference is being a recorded
--cmd = "conference "..meeting_uuid.."-"..domain_name.." play "..sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-recording_started.wav";
--freeswitch.consoleLog("notice", "[conference] ".. cmd .."\n");
--response = api:executeString(cmd);
--record the conference when it exists
if (conference_exists) then
--send a command to record the conference
if (not file_exists(recording..".wav")) then
cmd = "conference "..meeting_uuid.."-"..domain_name.." record "..recording..".wav";
freeswitch.consoleLog("notice", "[conference] cmd: " .. cmd .. "\n");
response = api:executeString(cmd);
end
end
end
--announce the caller
if (announce == "true") then
--announce the caller - play the recording
cmd = "conference "..meeting_uuid.."-"..domain_name.." play /tmp/conference-"..uuid..".wav";
freeswitch.consoleLog("notice", "[conference] ".. cmd .."\n");
response = api:executeString(cmd);
--play has entered the conference
cmd = "conference "..meeting_uuid.."-"..domain_name.." play "..sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/conference/conf-has_joined.wav";
freeswitch.consoleLog("notice", "[conference] ".. cmd .."\n");
response = api:executeString(cmd);
else
if (not conference_locked) then
if (sounds == "true") then
cmd = "conference "..meeting_uuid.."-"..domain_name.." play "..enter_sound;
response = api:executeString(cmd);
end
end
end
--close the database connection
dbh:release();
--send the call to the conference
profile = "default";
cmd = meeting_uuid.."-"..domain_name.."@"..profile.."+flags{".. flags .."}";
session:execute("conference", cmd);
end
end
@@ -1,7 +0,0 @@
<font face="arial">
<p>The conference moderator pin is ${moderator_pin} and it ended on ${conference_date_end}.</p>
<p>You can download your conference recording by clicking <a href='http://${domain_name}/app/conference_centers/conference_session_details.php?uuid=${conference_uuid}'>here</a>.</p>
<hr noshade="noshade" size="1"/>
Moderator PIN: ${moderator_pin}
Ended: ${conference_date_end}<br/>
</font>
@@ -1 +0,0 @@
New recording available for conference ${moderator_pin} ${conference_date_end}.
@@ -1,328 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set default values
min_digits = 1;
max_digits = 8;
max_tries = 3;
max_timeouts = 3;
digit_timeout = 3000;
--direct dial
direct_dial = {}
direct_dial["enabled"] = "true";
direct_dial["max_digits"] = 4;
--debug
debug["info"] = false;
debug["sql"] = false;
--get the argv values
script_name = argv[0];
voicemail_action = argv[1];
--starting values
dtmf_digits = '';
timeouts = 0;
password_tries = 0;
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--set the api
api = freeswitch.API();
--if the session exists
if (session ~= nil) then
--answer the session
if (session:ready()) then
session:answer();
end
--unset bind meta app
session:execute("unbind_meta_app", "");
--set the callback function
if (session:ready()) then
session:setVariable("playback_terminators", "#");
session:setInputCallback("on_dtmf", "");
end
--get session variables
context = session:getVariable("context");
sounds_dir = session:getVariable("sounds_dir");
domain_name = session:getVariable("domain_name");
uuid = session:getVariable("uuid");
voicemail_id = session:getVariable("voicemail_id");
voicemail_action = session:getVariable("voicemail_action");
base_dir = session:getVariable("base_dir");
destination_number = session:getVariable("destination_number");
caller_id_name = session:getVariable("caller_id_name");
caller_id_number = session:getVariable("caller_id_number");
skip_instructions = session:getVariable("skip_instructions");
skip_greeting = session:getVariable("skip_greeting");
vm_message_ext = session:getVariable("vm_message_ext");
if (not vm_message_ext) then vm_message_ext = 'wav'; end
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--get the domain_uuid
domain_uuid = session:getVariable("domain_uuid");
if (domain_count > 1) then
if (domain_uuid == nil) then
--get the domain_uuid using the domain name required for multi-tenant
if (domain_name ~= nil) then
sql = "SELECT domain_uuid FROM v_domains ";
sql = sql .. "WHERE domain_name = '" .. domain_name .. "' ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(rows)
domain_uuid = rows["domain_uuid"];
end);
end
end
end
if (domain_uuid ~= nil) then
domain_uuid = string.lower(domain_uuid);
end
--set the voicemail_dir
voicemail_dir = base_dir.."/storage/voicemail/default/"..domain_name;
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail] voicemail_dir: " .. voicemail_dir .. "\n");
end
--get the voicemail settings
if (voicemail_id ~= nil) then
if (session:ready()) then
--get the information from the database
sql = [[SELECT * FROM v_voicemails
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_id = ']] .. voicemail_id ..[['
AND voicemail_enabled = 'true' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
voicemail_uuid = string.lower(row["voicemail_uuid"]);
voicemail_password = row["voicemail_password"];
greeting_id = row["greeting_id"];
voicemail_mail_to = row["voicemail_mail_to"];
voicemail_attach_file = row["voicemail_attach_file"];
voicemail_local_after_email = row["voicemail_local_after_email"];
end);
--set default values
if (voicemail_local_after_email == nil) then
voicemail_local_after_email = "true";
end
if (voicemail_attach_file == nil) then
voicemail_attach_file = "true";
end
end
end
end
--general functions
dofile(scripts_dir.."/resources/functions/base64.lua");
dofile(scripts_dir.."/resources/functions/trim.lua");
dofile(scripts_dir.."/resources/functions/file_exists.lua");
dofile(scripts_dir.."/resources/functions/explode.lua");
dofile(scripts_dir.."/resources/functions/format_seconds.lua");
dofile(scripts_dir.."/resources/functions/mkdir.lua");
--voicemail functions
dofile(scripts_dir.."/app/voicemail/resources/functions/on_dtmf.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/get_voicemail_id.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/check_password.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/change_password.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/macro.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/play_greeting.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/record_message.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/record_menu.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/forward_to_extension.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/main_menu.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/listen_to_recording.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/message_waiting.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/send_email.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/delete_recording.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/message_saved.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/return_call.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/menu_messages.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/advanced.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/record_greeting.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/choose_greeting.lua");
dofile(scripts_dir.."/app/voicemail/resources/functions/record_name.lua");
--send a message waiting event
if (voicemail_action == "mwi") then
--get the mailbox info
account = argv[2];
array = explode("@", account);
voicemail_id = array[1];
domain_name = array[2];
--send information the console
debug["info"] = "true";
--get voicemail message details
sql = [[SELECT * FROM v_domains WHERE domain_name = ']] .. domain_name ..[[']]
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
domain_uuid = string.lower(row["domain_uuid"]);
end);
--get the message count and send the mwi event
message_waiting(voicemail_id, domain_uuid);
end
--check messages
if (voicemail_action == "check") then
if (session:ready()) then
--check the voicemail password
check_password(voicemail_id, password_tries);
--send to the main menu
timeouts = 0;
main_menu();
end
end
--leave a message
if (voicemail_action == "save") then
--valid voicemail
if (voicemail_uuid ~= nil) then
--save the recording
timeouts = 0;
play_greeting();
record_message();
--save the message to the voicemail messages
if (message_length > 2) then
local sql = {}
table.insert(sql, "INSERT INTO v_voicemail_messages ");
table.insert(sql, "(");
table.insert(sql, "voicemail_message_uuid, ");
table.insert(sql, "domain_uuid, ");
table.insert(sql, "voicemail_uuid, ");
table.insert(sql, "created_epoch, ");
table.insert(sql, "caller_id_name, ");
table.insert(sql, "caller_id_number, ");
table.insert(sql, "message_length ");
--table.insert(sql, "message_status, ");
--table.insert(sql, "message_priority, ");
table.insert(sql, ") ");
table.insert(sql, "VALUES ");
table.insert(sql, "( ");
table.insert(sql, "'".. uuid .."', ");
table.insert(sql, "'".. domain_uuid .."', ");
table.insert(sql, "'".. voicemail_uuid .."', ");
table.insert(sql, "'".. start_epoch .."', ");
table.insert(sql, "'".. caller_id_name .."', ");
table.insert(sql, "'".. caller_id_number .."', ");
table.insert(sql, "'".. message_length .."' ");
--table.insert(sql, "'".. message_status .."', ");
--table.insert(sql, "'".. message_priority .."' ");
table.insert(sql, ") ");
sql = table.concat(sql, "\n");
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
dbh:query(sql);
end
--set the message waiting event
if (message_length > 2) then
local event = freeswitch.Event("message_waiting");
event:addHeader("MWI-Messages-Waiting", "yes");
event:addHeader("MWI-Message-Account", "sip:"..voicemail_id.."@"..domain_name);
event:fire();
end
--send the email with the voicemail recording attached
if (message_length > 2) then
send_email(voicemail_id, uuid);
end
else
--voicemail not enabled or does not exist
referred_by = session:getVariable("sip_h_Referred-By");
if (referred_by) then
referred_by = referred_by:match('[%d]+');
session:transfer(referred_by, "XML", context);
end
end
end
--close the database connection
dbh:release();
--notes
--record the video
--records audio only
--result = session:execute("set", "enable_file_write_buffering=false");
--mkdir(voicemail_dir.."/"..voicemail_id);
--session:recordFile("/tmp/recording.fsv", 200, 200, 200);
--records audio and video
--result = session:execute("record_fsv", "file.fsv");
--freeswitch.consoleLog("notice", "[voicemail] SQL: " .. result .. "\n");
--play the video recording
--plays the video
--result = session:execute("play_fsv", "/tmp/recording.fsv");
--plays the file but without the video
--dtmf = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "/tmp/recording.fsv", "", "\\d+");
--freeswitch.consoleLog("notice", "[voicemail] SQL: " .. result .. "\n");
--callback (works with DTMF)
--http://wiki.freeswitch.org/wiki/Mod_fsv
--mkdir(voicemail_dir.."/"..voicemail_id);
--session:recordFile(file_name, max_len_secs, silence_threshold, silence_secs)
--session:sayPhrase(macro_name [,macro_data] [,language]);
--session:sayPhrase("voicemail_menu", "1:2:3:#", default_language);
--session:streamFile("directory/dir-to_select_entry.wav"); --works with setInputCallback
--session:streamFile("tone_stream://L=1;%(1000, 0, 640)");
--session:say("12345", default_language, "number", "pronounced");
--speak
--session:set_tts_parms("flite", "kal");
--session:speak("Please say the name of the person you're trying to contact");
--callback (execute and executeString does not work with DTMF)
--session:execute(api_string);
--session:executeString("playback "..mySound);
--uuid_video_refresh
--uuid_video_refresh,<uuid>,Send video refresh.,mod_commands
--may be used to clear video buffer before using record_fsv
@@ -1,90 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define a function for the advanced menu
function advanced ()
--clear the dtmf
dtmf_digits = '';
--flush dtmf digits from the input buffer
session:flushDigits();
--To record a greeting press 1
if (session:ready()) then
dtmf_digits = macro(session, "to_record_greeting", 1, 100, '');
end
--To choose greeting press 2
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "choose_greeting", 1, 100, '');
end
end
--To record your name 3
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "to_record_name", 1, 100, '');
end
end
--To change your password press 6
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "change_password", 1, 100, '');
end
end
--For the main menu press 0
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "main_menu", 1, 5000, '');
end
end
--process the dtmf
if (session:ready()) then
if (dtmf_digits == "1") then
--To record a greeting press 1
timeouts = 0;
record_greeting();
elseif (dtmf_digits == "2") then
--To choose greeting press 2
timeouts = 0;
choose_greeting();
elseif (dtmf_digits == "3") then
--To record your name 3
record_name();
elseif (dtmf_digits == "6") then
--To change your password press 6
change_password(voicemail_id);
elseif (dtmf_digits == "0") then
--For the main menu press 0
timeouts = 0;
main_menu();
else
timeouts = timeouts + 1;
if (timeouts <= max_timeouts) then
advanced();
else
macro(session, "goodbye", 1, 1000, '');
session:hangup();
end
end
end
end
@@ -1,51 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--check the voicemail password
function change_password(voicemail_id)
if (session:ready()) then
--flush dtmf digits from the input buffer
session:flushDigits();
--please enter your password followed by pound
dtmf_digits = '';
password = macro(session, "password_new", 20, 5000, '');
--update the voicemail password
sql = [[UPDATE v_voicemails
set voicemail_password = ']] .. password ..[['
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_id = ']] .. voicemail_id ..[['
AND voicemail_enabled = 'true' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
dbh:query(sql);
--has been changed to
dtmf_digits = '';
macro(session, "password_changed", 20, 3000, password);
--advanced menu
timeouts = 0;
advanced();
end
end
@@ -1,85 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--check the voicemail password
function check_password(voicemail_id, password_tries)
if (session:ready()) then
--flush dtmf digits from the input buffer
session:flushDigits();
--please enter your id followed by pound
if (voicemail_id) then
--do nothing
else
timeouts = 0;
voicemail_id = get_voicemail_id();
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail] voicemail id: " .. voicemail_id .. "\n");
end
end
--get the voicemail settings from the database
if (voicemail_id) then
if (session:ready()) then
sql = [[SELECT * FROM v_voicemails
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_id = ']] .. voicemail_id ..[['
AND voicemail_enabled = 'true' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
voicemail_uuid = string.lower(row["voicemail_uuid"]);
voicemail_password = row["voicemail_password"];
greeting_id = row["greeting_id"];
voicemail_mail_to = row["voicemail_mail_to"];
voicemail_attach_file = row["voicemail_attach_file"];
voicemail_local_after_email = row["voicemail_local_after_email"];
end);
end
end
--please enter your password followed by pound
dtmf_digits = '';
password = macro(session, "voicemail_password", 20, 5000, '');
--freeswitch.consoleLog("notice", "[voicemail] password: " .. password .. "\n");
--compare the password from the database with the password provided by the user
if (voicemail_password ~= password) then
--incorrect password
dtmf_digits = '';
macro(session, "password_not_valid", 1, 1000, '');
if (session:ready()) then
password_tries = password_tries + 1;
if (password_tries < max_tries) then
check_password(voicemail_id, password_tries);
else
macro(session, "goodbye", 1, 1000, '');
session:hangup();
end
end
end
end
end
--dofile(scripts_dir.."/app/voicemail/resources/functions/check_password.lua");
@@ -1,110 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define a function to choose the greeting
function choose_greeting()
--flush dtmf digits from the input buffer
session:flushDigits();
--select the greeting
if (session:ready()) then
dtmf_digits = '';
greeting_id = macro(session, "choose_greeting_choose", 1, 5000, '');
end
--check to see if the greeting file exists
if (greeting_id ~= "0") then
if (not file_exists(voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav")) then
--invalid greeting_id file does not exist
greeting_id = "invalid";
end
end
--validate the greeting_id
if (greeting_id == "0"
or greeting_id == "1"
or greeting_id == "2"
or greeting_id == "3"
or greeting_id == "4"
or greeting_id == "5"
or greeting_id == "6"
or greeting_id == "7"
or greeting_id == "8"
or greeting_id == "9") then
--valid greeting_id update the database
if (session:ready()) then
if (greeting_id == "0") then
sql = [[UPDATE v_voicemails SET greeting_id = null ]];
else
sql = [[UPDATE v_voicemails SET greeting_id = ']]..greeting_id..[[' ]];
end
sql = sql ..[[WHERE domain_uuid = ']] .. domain_uuid ..[[' ]]
sql = sql ..[[AND voicemail_uuid = ']] .. voicemail_uuid ..[[' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
dbh:query(sql);
end
--play the greeting
if (session:ready()) then
if (file_exists(voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav")) then
session:streamFile(voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav");
end
end
--greeting selected
if (session:ready()) then
dtmf_digits = '';
macro(session, "greeting_selected", 1, 100, greeting_id);
end
--advanced menu
if (session:ready()) then
timeouts = 0;
advanced();
end
else
--invalid greeting_id
if (session:ready()) then
dtmf_digits = '';
greeting_id = macro(session, "choose_greeting_fail", 1, 100, '');
end
--send back to choose the greeting
if (session:ready()) then
timeouts = timeouts + 1;
if (timeouts < max_timeouts) then
choose_greeting();
else
timeouts = 0;
advanced();
end
end
end
end
@@ -1,61 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--delete the message
function delete_recording(voicemail_id, uuid)
--message deleted
if (session ~= nil) then
if (session:ready()) then
dtmf_digits = '';
macro(session, "message_deleted", 1, 100, '');
end
end
--get the voicemail_uuid
sql = [[SELECT * FROM v_voicemails
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_id = ']] .. voicemail_id ..[[']];
status = dbh:query(sql, function(row)
db_voicemail_uuid = row["voicemail_uuid"];
end);
--flush dtmf digits from the input buffer
session:flushDigits();
--delete the file
os.remove(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext);
--delete from the database
sql = [[DELETE FROM v_voicemail_messages
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_uuid = ']] .. db_voicemail_uuid ..[['
AND voicemail_message_uuid = ']] .. uuid ..[[']];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
dbh:query(sql);
--log to console
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail][deleted] message: " .. uuid .. "\n");
end
--clear the variable
db_voicemail_uuid = '';
end
@@ -1,133 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define a function to forward a message to an extension
function forward_to_extension(voicemail_id, uuid)
--flush dtmf digits from the input buffer
session:flushDigits();
--save the voicemail message
message_saved(voicemail_id, uuid);
--request the forward_voicemail_id
if (session:ready()) then
dtmf_digits = '';
forward_voicemail_id = macro(session, "forward_enter_extension", 20, 5000, '');
if (session:ready()) then
if (string.len(forward_voicemail_id) == 0) then
dtmf_digits = '';
forward_voicemail_id = macro(session, "forward_enter_extension", 20, 5000, '');
end
end
end
if (session:ready()) then
if (string.len(forward_voicemail_id) == 0) then
dtmf_digits = '';
forward_voicemail_id = macro(session, "forward_enter_extension", 20, 5000, '');
end
end
--get voicemail message details
if (session:ready()) then
sql = [[SELECT * FROM v_voicemail_messages
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_uuid = ']] .. voicemail_uuid ..[['
AND voicemail_message_uuid = ']] .. uuid ..[[']]
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
--get the values from the database
created_epoch = row["created_epoch"];
caller_id_name = row["caller_id_name"];
caller_id_number = row["caller_id_number"];
message_length = row["message_length"];
message_status = row["message_status"];
message_priority = row["message_priority"];
end);
end
--get the voicemail settings
sql = [[SELECT * FROM v_voicemails
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_id = ']] .. forward_voicemail_id ..[['
AND voicemail_enabled = 'true' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
forward_voicemail_uuid = string.lower(row["voicemail_uuid"]);
forward_voicemail_mail_to = row["voicemail_mail_to"];
forward_voicemail_attach_file = row["voicemail_attach_file"];
forward_voicemail_local_after_email = row["voicemail_local_after_email"];
end);
--save the message to the voicemail messages
local sql = {}
table.insert(sql, "INSERT INTO v_voicemail_messages ");
table.insert(sql, "(");
table.insert(sql, "voicemail_message_uuid, ");
table.insert(sql, "domain_uuid, ");
table.insert(sql, "voicemail_uuid, ");
table.insert(sql, "created_epoch, ");
table.insert(sql, "caller_id_name, ");
table.insert(sql, "caller_id_number, ");
table.insert(sql, "message_length ");
--table.insert(sql, "message_status, ");
--table.insert(sql, "message_priority, ");
table.insert(sql, ") ");
table.insert(sql, "VALUES ");
table.insert(sql, "( ");
table.insert(sql, "'".. uuid .."', ");
table.insert(sql, "'".. domain_uuid .."', ");
table.insert(sql, "'".. forward_voicemail_uuid .."', ");
table.insert(sql, "'".. created_epoch .."', ");
table.insert(sql, "'".. caller_id_name .."', ");
table.insert(sql, "'".. caller_id_number .."', ");
table.insert(sql, "'".. message_length .."' ");
--table.insert(sql, "'".. message_status .."', ");
--table.insert(sql, "'".. message_priority .."' ");
table.insert(sql, ") ");
sql = table.concat(sql, "\n");
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
dbh:query(sql);
--set the message waiting event
local event = freeswitch.Event("message_waiting");
event:addHeader("MWI-Messages-Waiting", "yes");
event:addHeader("MWI-Message-Account", "sip:"..forward_voicemail_id.."@"..domain_name);
event:fire();
--if local after email is true then copy the recording file
mkdir(voicemail_dir.."/"..forward_voicemail_id);
os.execute("cp "..voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext.." "..voicemail_dir.."/"..forward_voicemail_id.."/msg_"..uuid.."."..vm_message_ext);
--send the email with the voicemail recording attached
send_email(forward_voicemail_id, uuid);
end
@@ -1,43 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--get the voicemail id
function get_voicemail_id()
session:flushDigits();
dtmf_digits = '';
voicemail_id = macro(session, "voicemail_id", 20, 5000, '');
if (string.len(voicemail_id) == 0) then
if (session:ready()) then
timeouts = timeouts + 1;
if (timeouts < max_timeouts) then
voicemail_id = get_voicemail_id();
else
macro(session, "goodbye", 1, 1000, '');
session:hangup();
end
end
end
return voicemail_id;
end
@@ -1,137 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define function to listen to the recording
function listen_to_recording (message_number, uuid, created_epoch, caller_id_name, caller_id_number)
--set default values
dtmf_digits = '';
max_digits = 1;
--flush dtmf digits from the input buffer
session:flushDigits();
--set the display
if (session:ready()) then
reply = api:executeString("uuid_display "..session:get_uuid().." "..caller_id_number);
end
--say the message number
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "message_number", 1, 100, '');
end
end
--say the number
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
session:say(message_number, default_language, "NUMBER", "pronounced");
end
end
--say the message date
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
session:say(created_epoch, default_language, "CURRENT_DATE_TIME", "pronounced");
end
end
--play the message
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
session:streamFile(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext);
session:streamFile("silence_stream://1000");
end
end
--to listen to the recording press 1
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "listen_to_recording", 1, 100, '');
end
end
--to save the recording press 2
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "save_recording", 1, 100, '');
end
end
--to return the call now press 5
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "return_call", 1, 100, '');
end
end
--to delete the recording press 7
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "delete_recording", 1, 100, '');
end
end
--to forward this message press 8
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "to_forward_message", 1, 100, '');
end
end
--to forward this recording to your email press 9
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "forward_to_email", 1, 3000, '');
end
end
--wait for more digits
--if (session:ready()) then
-- if (string.len(dtmf_digits) == 0) then
-- dtmf_digits = session:getDigits(max_digits, "#", 1, 3000);
-- end
--end
--process the dtmf
if (session:ready()) then
if (dtmf_digits == "1") then
listen_to_recording(message_number, uuid, created_epoch, caller_id_name, caller_id_number);
elseif (dtmf_digits == "2") then
message_saved(voicemail_id, uuid);
macro(session, "message_saved", 1, 100, '');
elseif (dtmf_digits == "5") then
message_saved(voicemail_id, uuid);
return_call(caller_id_number);
elseif (dtmf_digits == "7") then
delete_recording(voicemail_id, uuid);
message_waiting(voicemail_id, domain_uuid);
elseif (dtmf_digits == "8") then
forward_to_extension(voicemail_id, uuid);
dtmf_digits = '';
macro(session, "message_saved", 1, 100, '');
elseif (dtmf_digits == "9") then
send_email(voicemail_id, uuid);
dtmf_digits = '';
macro(session, "emailed", 1, 100, '');
elseif (dtmf_digits == "*") then
timeouts = 0;
main_menu();
elseif (dtmf_digits == "0") then
message_saved(voicemail_id, uuid);
session:transfer("0", "XML", context);
else
message_saved(voicemail_id, uuid);
macro(session, "message_saved", 1, 100, '');
end
end
end
@@ -1,319 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define the macro function
function macro(session, name, max_digits, max_timeout, param)
if (session:ready()) then
--create an empty table
actions = {}
--Please enter your id followed by
if (name == "voicemail_id") then
table.insert(actions, {app="streamFile",data="voicemail/vm-enter_id.wav"});
table.insert(actions, {app="streamFile",data="digits/pound.wav"});
end
--Please enter your id followed by
if (name == "voicemail_password") then
table.insert(actions, {app="streamFile",data="voicemail/vm-enter_pass.wav"});
table.insert(actions, {app="streamFile",data="digits/pound.wav"});
end
--the person at extension 101 is not available record your message at the tone press any key or stop talking to end the recording
if (name == "person_not_available_record_message") then
table.insert(actions, {app="streamFile",data="voicemail/vm-person.wav"});
--pronounce the voicemail_id
table.insert(actions, {app="say.number.iterated",data=voicemail_id});
table.insert(actions, {app="streamFile",data="voicemail/vm-not_available.wav"});
end
--record your message at the tone press any key or stop talking to end the recording
if (name == "record_message") then
table.insert(actions, {app="streamFile",data="voicemail/vm-record_message.wav"});
end
--beep
if (name == "record_beep") then
table.insert(actions, {app="tone_stream",data="L=1;%(1000, 0, 640)"});
end
--to listen to the recording press 1
if (name == "to_listen_to_recording") then
table.insert(actions, {app="streamFile",data="voicemail/vm-listen_to_recording.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/1.wav"});
end
--to save the recording press 2
if (name == "to_save_recording") then
table.insert(actions, {app="streamFile",data="voicemail/vm-save_recording.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/2.wav"});
end
--to rerecord press 3
if (name == "to_rerecord") then
table.insert(actions, {app="streamFile",data="voicemail/vm-rerecord.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/3.wav"});
end
--You have zero new messages
if (name == "new_messages") then
table.insert(actions, {app="streamFile",data="voicemail/vm-you_have.wav"});
table.insert(actions, {app="say.number.pronounced",data=param});
table.insert(actions, {app="streamFile",data="voicemail/vm-new.wav"});
if (param == "1") then
table.insert(actions, {app="streamFile",data="voicemail/vm-message.wav"});
else
table.insert(actions, {app="streamFile",data="voicemail/vm-messages.wav"});
end
end
--You have zero saved messages
if (name == "saved_messages") then
table.insert(actions, {app="streamFile",data="voicemail/vm-you_have.wav"});
table.insert(actions, {app="say.number.pronounced",data=param});
table.insert(actions, {app="streamFile",data="voicemail/vm-saved.wav"});
if (param == "1") then
table.insert(actions, {app="streamFile",data="voicemail/vm-message.wav"});
else
table.insert(actions, {app="streamFile",data="voicemail/vm-messages.wav"});
end
end
--To listen to new messages press 1
if (name == "listen_to_new_messages") then
table.insert(actions, {app="streamFile",data="voicemail/vm-listen_new.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/1.wav"});
end
--To listen to saved messages press 2
if (name == "listen_to_saved_messages") then
table.insert(actions, {app="streamFile",data="voicemail/vm-listen_saved.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/2.wav"});
end
--For advanced options press 5
if (name == "advanced") then
table.insert(actions, {app="streamFile",data="voicemail/vm-advanced.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/5.wav"});
end
--Advanced Options Menu
--To record a greeting press 1
if (name == "to_record_greeting") then
table.insert(actions, {app="streamFile",data="voicemail/vm-to_record_greeting.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/1.wav"});
end
--Choose a greeting between 1 and 9
if (name == "choose_greeting_choose") then
table.insert(actions, {app="streamFile",data="voicemail/vm-choose_greeting_choose.wav"});
end
--Greeting invalid value
if (name == "choose_greeting_fail") then
table.insert(actions, {app="streamFile",data="voicemail/vm-choose_greeting_fail.wav"});
end
--Record your greeting at the tone press any key or stop talking to end the recording
if (name == "record_greeting") then
table.insert(actions, {app="streamFile",data="voicemail/vm-record_greeting.wav"});
table.insert(actions, {app="tone_stream",data="L=1;%(1000, 0, 640)"});
end
--To choose greeting press 2
if (name == "choose_greeting") then
table.insert(actions, {app="streamFile",data="voicemail/vm-choose_greeting.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/2.wav"});
end
--Greeting 1 selected
if (name == "greeting_selected") then
table.insert(actions, {app="streamFile",data="voicemail/vm-greeting.wav"});
table.insert(actions, {app="streamFile",data="digits/"..param..".wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-selected.wav"});
end
--To record your name 3
if (name == "to_record_name") then
table.insert(actions, {app="streamFile",data="voicemail/vm-record_name2.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/3.wav"});
end
--At the tone please record your name press any key or stop talking to end the recording
if (name == "record_name") then
table.insert(actions, {app="streamFile",data="voicemail/vm-record_name1.wav"});
table.insert(actions, {app="tone_stream",data="L=1;%(1000, 0, 640)"});
end
--To change your password press 6
if (name == "change_password") then
table.insert(actions, {app="streamFile",data="voicemail/vm-change_password.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/6.wav"});
end
--For the main menu press 0
if (name == "main_menu") then
table.insert(actions, {app="streamFile",data="voicemail/vm-main_menu.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/0.wav"});
end
--To exit press *
if (name == "to_exit_press") then
table.insert(actions, {app="streamFile",data="voicemail/vm-to_exit.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/star.wav"});
end
--Additional Macros
--Please enter your new password then press the # key #
if (name == "password_new") then
table.insert(actions, {app="streamFile",data="voicemail/vm-enter_new_pin.wav"});
end
--Has been changed to
if (name == "password_changed") then
table.insert(actions, {app="streamFile",data="voicemail/vm-has_been_changed_to.wav"});
table.insert(actions, {app="say.number.iterated",data=param});
end
--Login Incorrect
--if (name == "password_not_valid") then
-- table.insert(actions, {app="streamFile",data="voicemail/vm-password_not_valid.wav"});
--end
--Login Incorrect
if (name == "password_not_valid") then
table.insert(actions, {app="streamFile",data="voicemail/vm-fail_auth.wav"});
end
--Too many failed attempts
if (name == "too_many_failed_attempts") then
table.insert(actions, {app="streamFile",data="voicemail/vm-abort.wav"});
end
--Message number
if (name == "message_number") then
table.insert(actions, {app="streamFile",data="voicemail/vm-message_number.wav"});
end
--To listen to the recording press 1
if (name == "listen_to_recording") then
table.insert(actions, {app="streamFile",data="voicemail/vm-listen_to_recording.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/1.wav"});
end
--To save the recording press 2
if (name == "save_recording") then
table.insert(actions, {app="streamFile",data="voicemail/vm-save_recording.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/2.wav"});
end
--To delete the recording press 7
if (name == "delete_recording") then
table.insert(actions, {app="streamFile",data="voicemail/vm-delete_recording.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/7.wav"});
end
--Message deleted
if (name == "message_deleted") then
table.insert(actions, {app="streamFile",data="voicemail/vm-message.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-deleted.wav"});
end
--To return the call now press 5
if (name == "return_call") then
table.insert(actions, {app="streamFile",data="voicemail/vm-return_call.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/5.wav"});
end
--To forward this message press 8
if (name == "to_forward_message") then
table.insert(actions, {app="streamFile",data="voicemail/vm-to_forward.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/8.wav"});
end
--Please enter the extension to forward this message to followed by #
if (name == "forward_enter_extension") then
table.insert(actions, {app="streamFile",data="voicemail/vm-forward_enter_ext.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-followed_by_pound.wav"});
end
--To forward this recording to your email press 9
if (name == "forward_to_email") then
table.insert(actions, {app="streamFile",data="voicemail/vm-forward_to_email.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-press.wav"});
table.insert(actions, {app="streamFile",data="digits/9.wav"});
end
--Emailed
if (name == "emailed") then
table.insert(actions, {app="streamFile",data="voicemail/vm-emailed.wav"});
end
--Please enter the extension to send this message to followed by #
--if (name == "send_message_to_extension") then
-- table.insert(actions, {app="streamFile",data="voicemail/vm-zzz.wav"});
--end
--Message saved
if (name == "message_saved") then
table.insert(actions, {app="streamFile",data="voicemail/vm-message.wav"});
table.insert(actions, {app="streamFile",data="voicemail/vm-saved.wav"});
end
--Your recording is below the minimal acceptable length, please try again.
if (name == "too_small") then
table.insert(actions, {app="streamFile",data="voicemail/vm-too-small.wav"});
end
--Goodbye
if (name == "goodbye") then
table.insert(actions, {app="streamFile",data="voicemail/vm-goodbye.wav"});
end
--if actions table exists then process it
if (actions) then
--set default values
tries = 1;
timeout = 100;
--loop through the action and data
for key, row in pairs(actions) do
--freeswitch.consoleLog("notice", "[voicemail] app: " .. row.app .. " data: " .. row.data .. "\n");
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
if (row.app == "streamFile") then
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..row.data);
elseif (row.app == "playback") then
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..row.data);
elseif (row.app == "tone_stream") then
session:streamFile("tone_stream://"..row.data);
elseif (row.app == "silence_stream") then
session:streamFile("silence_stream://100"..row.data);
elseif (row.app == "playAndGetDigits") then
--playAndGetDigits <min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp> <digit_timeout>
if (not file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..row.data)) then
dtmf_digits = session:playAndGetDigits(min_digits, max_digits, tries, timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..row.data, "", "\\d+", max_timeout);
else
dtmf_digits = session:playAndGetDigits(min_digits, max_digits, tries, timeout, "#", row.data, "", "\\d+", max_timeout);
end
elseif (row.app == "say.number.pronounced") then
session:say(row.data, default_language, "number", "pronounced");
elseif (row.app == "say.number.iterated") then
session:say(row.data, default_language, "number", "iterated");
end
session:streamFile("silence_stream://100");
end --if
end --session:ready
end --for
--get the remaining digits
if (session:ready()) then
if (string.len(dtmf_digits) < max_digits) then
dtmf_digits = dtmf_digits .. session:getDigits(max_digits, "#", max_timeout);
end
end
--return dtmf the digits
return dtmf_digits;
else
--no dtmf digits to return
return '';
end
end
end
@@ -1,115 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define function main menu
function main_menu ()
if (voicemail_uuid) then
--clear the value
dtmf_digits = '';
--flush dtmf digits from the input buffer
session:flushDigits();
--new voicemail count
if (session:ready()) then
sql = [[SELECT count(*) as new_messages FROM v_voicemail_messages
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_uuid = ']] .. voicemail_uuid ..[['
AND (message_status is null or message_status = '') ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
new_messages = row["new_messages"];
end);
dtmf_digits = macro(session, "new_messages", 1, 100, new_messages);
end
--saved voicemail count
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
sql = [[SELECT count(*) as saved_messages FROM v_voicemail_messages
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_uuid = ']] .. voicemail_uuid ..[['
AND message_status = 'saved' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
saved_messages = row["saved_messages"];
end);
dtmf_digits = macro(session, "saved_messages", 1, 100, saved_messages);
end
end
--to listen to new message
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "listen_to_new_messages", 1, 100, '');
end
end
--to listen to saved message
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "listen_to_saved_messages", 1, 100, '');
end
end
--for advanced options
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "advanced", 1, 100, '');
end
end
--to exit press #
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "to_exit_press", 1, 3000, '');
end
end
--process the dtmf
if (session:ready()) then
if (dtmf_digits == "1") then
menu_messages("new");
elseif (dtmf_digits == "2") then
menu_messages("saved");
elseif (dtmf_digits == "5") then
timeouts = 0;
advanced();
elseif (dtmf_digits == "0") then
main_menu();
elseif (dtmf_digits == "*") then
dtmf_digits = '';
macro(session, "goodbye", 1, 100, '');
session:hangup();
else
if (session:ready()) then
timeouts = timeouts + 1;
if (timeouts < max_timeouts) then
main_menu();
else
macro(session, "goodbye", 1, 1000, '');
session:hangup();
end
end
end
end
end
end
@@ -1,111 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define function for messages menu
function menu_messages (message_status)
--set default values
max_timeout = 2000;
min_digits = 1;
max_digits = 1;
tries = 1;
timeout = 2000;
--clear the dtmf
dtmf_digits = '';
--flush dtmf digits from the input buffer
--session:flushDigits();
--set the message number
message_number = 0;
--message_status new,saved
if (session:ready()) then
if (voicemail_id ~= nil) then
sql = [[SELECT * FROM v_voicemail_messages
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_uuid = ']] .. voicemail_uuid ..[[']]
if (message_status == "new") then
sql = sql .. [[AND (message_status is null or message_status = '') ]];
elseif (message_status == "saved") then
sql = sql .. [[AND message_status = 'saved' ]];
end
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
--get the values from the database
--row["voicemail_message_uuid"];
--row["created_epoch"];
--row["caller_id_name"];
--row["caller_id_number"];
--row["message_length"];
--row["message_status"];
--row["message_priority"];
--increment the message count
message_number = message_number + 1;
--listen to the message
if (session:ready()) then
if (debug["info"]) then
freeswitch.consoleLog("notice", message_number.." "..string.lower(row["voicemail_message_uuid"]).." "..row["created_epoch"]);
end
listen_to_recording(message_number, string.lower(row["voicemail_message_uuid"]), row["created_epoch"], row["caller_id_name"], row["caller_id_number"]);
end
end);
end
end
--voicemail count if zero new messages set the mwi to no
if (session:ready()) then
if (voicemail_id ~= nil) then
sql = [[SELECT count(*) as new_messages FROM v_voicemail_messages
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_uuid = ']] .. voicemail_uuid ..[['
AND (message_status is null or message_status = '') ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
--send the message waiting event
local event = freeswitch.Event("message_waiting");
if (row["new_messages"] == "0") then
event:addHeader("MWI-Messages-Waiting", "no");
else
event:addHeader("MWI-Messages-Waiting", "yes");
end
event:addHeader("MWI-Message-Account", "sip:"..voicemail_id.."@"..domain_name);
event:fire();
end);
end
end
--set the display
if (session:ready()) then
reply = api:executeString("uuid_display "..session:get_uuid().." "..destination_number);
end
--send back to the main menu
if (session:ready()) then
timeouts = 0;
main_menu();
end
end
@@ -1,56 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--save the message
function message_saved(voicemail_id, uuid)
--clear the dtmf
dtmf_digits = '';
--flush dtmf digits from the input buffer
session:flushDigits();
--get the voicemail_uuid
sql = [[SELECT * FROM v_voicemails
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_id = ']] .. voicemail_id ..[[']];
status = dbh:query(sql, function(row)
db_voicemail_uuid = row["voicemail_uuid"];
end);
--delete from the database
sql = [[UPDATE v_voicemail_messages SET message_status = 'saved'
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_uuid = ']] .. db_voicemail_uuid ..[['
AND voicemail_message_uuid = ']] .. uuid ..[[']];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
dbh:query(sql);
--log to console
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail][saved] id: " .. voicemail_id .. " message: "..uuid.."\n");
end
--check the message waiting status
message_waiting(voicemail_id, domain_uuid);
--clear the variable
db_voicemail_uuid = '';
end
@@ -1,52 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--voicemail count if zero new messages set the mwi to no
function message_waiting(voicemail_id, domain_uuid)
sql = [[SELECT count(*) as message_count FROM v_voicemail_messages as m, v_voicemails as v
WHERE v.domain_uuid = ']] .. domain_uuid ..[['
AND v.voicemail_uuid = m.voicemail_uuid
AND v.voicemail_id = ']] .. voicemail_id ..[['
AND (m.message_status is null or m.message_status = '') ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
--send the message waiting event
local event = freeswitch.Event("message_waiting");
if (row["message_count"] == "0") then
--freeswitch.consoleLog("notice", "[voicemail] mailbox: "..voicemail_id.."@"..domain_name.." messages: " .. row["message_count"] .. " no messages\n");
event:addHeader("MWI-Messages-Waiting", "no");
else
event:addHeader("MWI-Messages-Waiting", "yes");
end
event:addHeader("MWI-Message-Account", "sip:"..voicemail_id.."@"..domain_name);
event:fire();
--log to console
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail] mailbox: "..voicemail_id.."@"..domain_name.." messages: " .. row["message_count"] .. " \n");
end
end);
end
@@ -1,46 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define on_dtmf call back function
function on_dtmf(s, type, obj, arg)
if (type == "dtmf") then
freeswitch.console_log("info", "[voicemail] dtmf digit: " .. obj['digit'] .. ", duration: " .. obj['duration'] .. "\n");
if (obj['digit'] == "#") then
return 0;
else
dtmf_digits = dtmf_digits .. obj['digit'];
if (debug["info"]) then
freeswitch.console_log("info", "[voicemail] dtmf digits: " .. dtmf_digits .. ", length: ".. string.len(dtmf_digits) .." max_digits: " .. max_digits .. "\n");
end
if (string.len(dtmf_digits) >= max_digits) then
if (debug["info"]) then
freeswitch.console_log("info", "[voicemail] max_digits reached\n");
end
return 0;
end
end
end
return 0;
end
@@ -1,44 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--play the greeting
function play_greeting()
--voicemail prompt
if (skip_greeting == "true") then
--skip the greeting
else
if (session:ready()) then
dtmf_digits = '';
if (string.len(greeting_id) > 0) then
--play the custom greeting
session:streamFile(voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav");
session:streamFile("silence_stream://200");
else
--play the default greeting
dtmf_digits = macro(session, "person_not_available_record_message", 1, 200);
end
end
end
end
@@ -1,96 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define a function to record the greeting
function record_greeting()
--flush dtmf digits from the input buffer
session:flushDigits();
--Choose a greeting between 1 and 9
if (session:ready()) then
dtmf_digits = '';
greeting_id = macro(session, "choose_greeting_choose", 1, 5000, '');
freeswitch.consoleLog("notice", "[voicemail] greeting_id: " .. greeting_id .. "\n");
end
--validate the greeting_id
if (greeting_id == "1"
or greeting_id == "2"
or greeting_id == "3"
or greeting_id == "4"
or greeting_id == "5"
or greeting_id == "6"
or greeting_id == "7"
or greeting_id == "8"
or greeting_id == "9") then
--record your greeting at the tone press any key or stop talking to end the recording
if (session:ready()) then
dtmf_digits = '';
macro(session, "record_greeting", 1, 100, '');
end
--record the greeting
if (session:ready()) then
max_len_seconds = 30;
silence_threshold = 30;
silence_seconds = 5;
mkdir(voicemail_dir.."/"..voicemail_id);
-- syntax is session:recordFile(file_name, max_len_secs, silence_threshold, silence_secs)
result = session:recordFile(voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav", max_len_seconds, silence_threshold, silence_seconds);
--session:execute("record", voicemail_dir.."/"..uuid.." 180 200");
end
--play the greeting
--if (session:ready()) then
-- if (file_exists(voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav")) then
-- session:streamFile(voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav");
-- end
--end
--option to play, save, and re-record the greeting
if (session:ready()) then
timeouts = 0;
record_menu("greeting", voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav");
end
else
--invalid greeting_id
if (session:ready()) then
dtmf_digits = '';
macro(session, "choose_greeting_fail", 1, 100, '');
end
--send back to choose the greeting
if (session:ready()) then
timeouts = timeouts + 1;
if (timeouts < max_timeouts) then
record_greeting();
else
timeouts = 0;
advanced();
end
end
end
end
@@ -1,116 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--record message menu
function record_menu(type, file)
if (session:ready()) then
--clear the dtmf digits variable
dtmf_digits = '';
--flush dtmf digits from the input buffer
session:flushDigits();
--to listen to the recording press 1
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "to_listen_to_recording", 1, 100, '');
end
end
--to save the recording press 2
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "to_save_recording", 1, 100, '');
end
end
--to re-record press 3
if (session:ready()) then
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "to_rerecord", 1, 3000, '');
end
end
--process the dtmf
if (session:ready()) then
if (dtmf_digits == "1") then
--listen to the recording
session:streamFile(file);
--session:streamFile(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext);
--record menu 1 listen to the recording, 2 save the recording, 3 re-record
record_menu(type, file);
elseif (dtmf_digits == "2") then
--save the message
dtmf_digits = '';
macro(session, "message_saved", 1, 100, '');
if (type == "message") then
--goodbye
macro(session, "goodbye", 1, 100, '');
--hangup the call
session:hangup();
end
if (type == "greeting") then
advanced();
end
if (type == "name") then
advanced();
end
elseif (dtmf_digits == "3") then
--re-record the message
timeouts = 0;
dtmf_digits = '';
if (type == "message") then
record_message();
end
if (type == "greeting") then
record_greeting();
end
if (type == "name") then
record_name();
end
elseif (dtmf_digits == "*") then
--hangup
if (session:ready()) then
dtmf_digits = '';
macro(session, "goodbye", 1, 100, '');
session:hangup();
end
else
if (session:ready()) then
timeouts = timeouts + 1;
if (timeouts < max_timeouts) then
record_menu(type, file);
else
if (type == "message") then
macro(session, "goodbye", 1, 1000, '');
session:hangup();
end
if (type == "greeting") then
advanced();
end
if (type == "name") then
advanced();
end
end
end
end
end
end
end
@@ -1,122 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--save the recording
function record_message()
--record your message at the tone press any key or stop talking to end the recording
if (skip_greeting == "true") then
--skip the greeting
else
if (string.len(dtmf_digits) == 0) then
dtmf_digits = macro(session, "record_message", 1, 100);
end
end
--direct dial
if (dtmf_digits) then
if (string.len(dtmf_digits) > 0) then
if (session:ready()) then
if (direct_dial["enabled"] == "true") then
if (string.len(dtmf_digits) < max_digits) then
dtmf_digits = dtmf_digits .. session:getDigits(direct_dial["max_digits"], "#", 5000);
end
end
end
if (session:ready()) then
freeswitch.consoleLog("notice", "[voicemail] dtmf_digits: " .. string.sub(dtmf_digits, 0, 1) .. "\n");
if (dtmf_digits == "*") then
--check the voicemail password
check_password(voicemail_id, password_tries);
--send to the main menu
timeouts = 0;
main_menu();
elseif (string.sub(dtmf_digits, 0, 1) == "*") then
--do not allow dialing numbers prefixed with *
session:hangup();
else
session:transfer(dtmf_digits, "XML", context);
end
end
end
end
--play the beep
dtmf_digits = '';
result = macro(session, "record_beep", 1, 100);
--start epoch
start_epoch = os.time();
--save the recording
-- syntax is session:recordFile(file_name, max_len_secs, silence_threshold, silence_secs)
max_len_seconds = 300;
silence_threshold = 30;
silence_seconds = 5;
mkdir(voicemail_dir.."/"..voicemail_id);
result = session:recordFile(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext, max_len_seconds, silence_threshold, silence_seconds);
--session:execute("record", voicemail_dir.."/"..uuid.." 180 200");
--stop epoch
stop_epoch = os.time();
--calculate the message length
message_length = stop_epoch - start_epoch;
message_length_formatted = format_seconds(message_length);
--if the recording is below the minimal length then re-record the message
if (message_length > 2) then
--continue
else
if (session:ready()) then
--your recording is below the minimal acceptable length, please try again
dtmf_digits = '';
macro(session, "too_small", 1, 100);
--record your message at the tone
timeouts = timeouts + 1;
if (timeouts < max_timeouts) then
record_message();
else
timeouts = 0;
record_menu("message", voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext);
end
end
end
--instructions press 1 to listen to the recording, press 2 to save the recording, press 3 to re-record
if (session:ready()) then
if (skip_instructions == "true") then
--save the message
dtmf_digits = '';
macro(session, "message_saved", 1, 100, '');
macro(session, "goodbye", 1, 100, '');
--hangup the call
session:hangup();
else
timeouts = 0;
record_menu("message", voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext);
end
end
end
@@ -1,55 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define a function to record the name
function record_name()
if (session:ready()) then
--flush dtmf digits from the input buffer
session:flushDigits();
--play the name record
dtmf_digits = '';
macro(session, "record_name", 1, 100, '');
--save the recording
-- syntax is session:recordFile(file_name, max_len_secs, silence_threshold, silence_secs)
max_len_seconds = 30;
silence_threshold = 30;
silence_seconds = 5;
mkdir(voicemail_dir.."/"..voicemail_id);
result = session:recordFile(voicemail_dir.."/"..voicemail_id.."/recorded_name.wav", max_len_seconds, silence_threshold, silence_seconds);
--session:execute("record", voicemail_dir.."/"..uuid.." 180 200");
--play the name
--session:streamFile(voicemail_dir.."/"..voicemail_id.."/recorded_name.wav");
--option to play, save, and re-record the name
if (session:ready()) then
timeouts = 0;
record_menu("name", voicemail_dir.."/"..voicemail_id.."/recorded_name.wav");
end
end
end
@@ -1,36 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define a function to return the call
function return_call(destination)
if (session:ready()) then
--clear the dtmf
dtmf_digits = '';
--flush dtmf digits from the input buffer
session:flushDigits();
--transfer the call
session:transfer(destination, "XML", context);
end
end
@@ -1,156 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define a function to send email
function send_email(id, uuid)
--get voicemail message details
sql = [[SELECT * FROM v_voicemails
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_id = ']] .. id ..[[']]
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
db_voicemail_uuid = string.lower(row["voicemail_uuid"]);
--voicemail_password = row["voicemail_password"];
--greeting_id = row["greeting_id"];
voicemail_mail_to = row["voicemail_mail_to"];
voicemail_attach_file = row["voicemail_attach_file"];
voicemail_local_after_email = row["voicemail_local_after_email"];
end);
--set default values
if (voicemail_local_after_email == nil) then
voicemail_local_after_email = "true";
end
if (voicemail_attach_file == nil) then
voicemail_attach_file = "true";
end
--require the email address to send the email
if (string.len(voicemail_mail_to) > 2) then
--get voicemail message details
sql = [[SELECT * FROM v_voicemail_messages
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_message_uuid = ']] .. uuid ..[[']]
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
--get the values from the database
--uuid = row["voicemail_message_uuid"];
created_epoch = row["created_epoch"];
caller_id_name = row["caller_id_name"];
caller_id_number = row["caller_id_number"];
message_length = row["message_length"];
--message_status = row["message_status"];
--message_priority = row["message_priority"];
end);
--format the message length and date
message_length_formatted = format_seconds(message_length);
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail] message length: " .. message_length .. "\n");
end
local message_date = os.date("%A, %d %b %Y %I:%M %p", created_epoch)
--prepare the files
file_subject = scripts_dir.."/app/voicemail/resources/templates/"..default_language.."/"..default_dialect.."email_subject.tpl";
file_body = scripts_dir.."/app/voicemail/resources/templates/"..default_language.."/"..default_dialect.."/email_body.tpl";
if (not file_exists(file_subject)) then
file_subject = scripts_dir.."/app/voicemail/resources/templates/en/us/email_subject.tpl";
file_body = scripts_dir.."/app/voicemail/resources/templates/en/us/email_body.tpl";
end
--prepare the subject
local f = io.open(file_subject, "r");
local subject = f:read("*all");
f:close();
subject = subject:gsub("${caller_id_name}", caller_id_name);
subject = subject:gsub("${caller_id_number}", caller_id_number);
subject = subject:gsub("${message_date}", message_date);
subject = subject:gsub("${message_duration}", message_length_formatted);
subject = subject:gsub("${account}", id);
subject = subject:gsub("${domain_name}", domain_name);
subject = trim(subject);
subject = '=?utf-8?B?'..base64.enc(subject)..'?=';
--prepare the body
local f = io.open(file_body, "r");
body = f:read("*all");
f:close();
body = body:gsub("${caller_id_name}", caller_id_name);
body = body:gsub("${caller_id_number}", caller_id_number);
body = body:gsub("${message_date}", message_date);
body = body:gsub("${message_duration}", message_length_formatted);
body = body:gsub("${account}", id);
body = body:gsub("${domain_name}", domain_name);
body = body:gsub(" ", "&nbsp;");
body = body:gsub("%s+", "");
body = body:gsub("&nbsp;", " ");
body = body:gsub("\n", "");
body = body:gsub("\n", "");
body = body:gsub("'", "&#39;");
body = body:gsub([["]], "&#34;");
body = trim(body);
--send the email
if (voicemail_attach_file == "true") then
if (voicemail_local_after_email == "false") then
delete = "true";
else
delete = "false";
end
file = voicemail_dir.."/"..id.."/msg_"..uuid.."."..vm_message_ext;
cmd = "luarun email.lua "..voicemail_mail_to.." "..voicemail_mail_to.." '"..subject.."' '"..body.."' '"..file.."' "..delete;
else
cmd = "luarun email.lua "..voicemail_mail_to.." "..voicemail_mail_to.." '"..subject.."' '"..body.."'";
end
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail] cmd: " .. cmd .. "\n");
end
result = api:executeString(cmd);
end
--whether to keep the voicemail message and details local after email
if (voicemail_mail_to) then
if (voicemail_local_after_email == "false" and string.len(voicemail_mail_to) > 0) then
--delete the voicemail message details
sql = [[DELETE FROM v_voicemail_messages
WHERE domain_uuid = ']] .. domain_uuid ..[['
AND voicemail_uuid = ']] .. db_voicemail_uuid ..[['
AND voicemail_message_uuid = ']] .. uuid ..[[']]
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql);
--set message waiting indicator
message_waiting(id, domain_uuid);
--clear the variable
db_voicemail_uuid = '';
end
end
end
@@ -1,100 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--include the lua script
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--define general settings
tmp_file = "/usr/local/freeswitch/log/mwi.tmp";
sleep = 300;
--debug
debug["sql"] = false;
debug["info"] = false;
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--used to stop the lua service
local file = assert(io.open(tmp_file, "w"));
file:write("remove this file to stop the script");
--add the trim function
function trim(s)
return s:gsub("^%s+", ""):gsub("%s+$", "")
end
--check if a file exists
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
--create the api object
api = freeswitch.API();
--run lua as a service
while true do
--exit the loop when the file does not exist
if (not file_exists(tmp_file)) then
freeswitch.consoleLog("NOTICE", tmp_file.." not found\n");
break;
end
--Send MWI events for voicemail boxes with messages
sql = [[SELECT v.voicemail_id, v.voicemail_uuid, v.domain_uuid, d.domain_name, COUNT(*) AS message_count
FROM v_voicemail_messages as m, v_voicemails as v, v_domains as d
WHERE v.voicemail_uuid = m.voicemail_uuid
AND v.domain_uuid = d.domain_uuid
GROUP BY v.voicemail_id, v.voicemail_uuid, v.domain_uuid, d.domain_name;]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
--send the message waiting event
local event = freeswitch.Event("message_waiting");
if (row["message_count"] == "0") then
event:addHeader("MWI-Messages-Waiting", "no");
else
event:addHeader("MWI-Messages-Waiting", "yes");
end
event:addHeader("MWI-Message-Account", "sip:"..row["voicemail_id"].."@"..row["domain_name"]);
event:fire();
--log to console
if (debug["info"]) then
freeswitch.consoleLog("notice", "[voicemail] mailbox: "..row["voicemail_id"].."@"..row["domain_name"].." messages: " .. row["message_count"] .. " \n");
end
end);
--slow the loop down
os.execute("sleep "..sleep);
--testing exit immediately
--break;
end
@@ -1,7 +0,0 @@
<font face="arial">
<b>Message From "${caller_id_name}" <a href="tel:${caller_id_number}">${caller_id_number}</a></b><br/>
<hr noshade="noshade" size="1"/>
Created: ${message_date}<br/>
Duration: ${message_duration}<br/>
Account: ${account}@${domain_name}<br/>
</font>
@@ -1 +0,0 @@
Voicemail from ${caller_id_name} <${caller_id_number}> ${message_duration}
@@ -1,7 +0,0 @@
<font face="arial">
<b>Message From "${caller_id_name}" <a href="tel:${caller_id_number}">${caller_id_number}</a></b><br/>
<hr noshade="noshade" size="1"/>
Created: ${message_date}<br/>
Duration: ${message_duration}<br/>
Account: ${account}@${domain_name}<br/>
</font>
@@ -1 +0,0 @@
Voicemail from ${caller_id_name} <${caller_id_number}> ${message_duration}
@@ -1,138 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set defaults
expire = {}
expire["directory"] = "3600";
expire["dialplan"] = "300";
expire["sofia.conf"] = "3600";
--set the debug options
debug["params"] = false;
debug["sql"] = false;
debug["xml_request"] = false;
debug["xml_string"] = false;
debug["cache"] = false;
--general functions
dofile(scripts_dir.."/resources/functions/trim.lua");
dofile(scripts_dir.."/resources/functions/file_exists.lua");
dofile(scripts_dir.."/resources/functions/explode.lua");
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--exits the script if we didn't connect properly
assert(dbh:connected());
--if the params class and methods do not exist then add them to prevent errors
if (not params) then
params = {}
function params:getHeader(name)
self.name = name;
end
function params:serialize(name)
self.name = name;
end
end
--show the params in the console
if (debug["params"]) then
if (params:serialize() ~= nil) then
freeswitch.consoleLog("notice", "[xml_handler] Params:\n" .. params:serialize() .. "\n");
end
end
--show the xml request in the console
if (debug["xml_request"]) then
freeswitch.consoleLog("notice", "[xml_handler] Section: " .. XML_REQUEST["section"] .. "\n");
freeswitch.consoleLog("notice", "[xml_handler] Tag Name: " .. XML_REQUEST["tag_name"] .. "\n");
freeswitch.consoleLog("notice", "[xml_handler] Key Name: " .. XML_REQUEST["key_name"] .. "\n");
freeswitch.consoleLog("notice", "[xml_handler] Key Value: " .. XML_REQUEST["key_value"] .. "\n");
end
--get the params and set them as variables
domain_name = params:getHeader("sip_from_host");
if (domain_uuid == nil) then
domain_uuid = params:getHeader("domain_uuid");
end
domain_name = params:getHeader("domain");
if (domain_name == nil) then
domain_name = params:getHeader("domain_name");
end
if (domain_name == nil) then
domain_name = params:getHeader("variable_domain_name");
end
purpose = params:getHeader("purpose");
profile = params:getHeader("profile");
key = params:getHeader("key");
user = params:getHeader("user");
user_context = params:getHeader("variable_user_context");
call_context = params:getHeader("Caller-Context");
destination_number = params:getHeader("Caller-Destination-Number");
caller_id_number = params:getHeader("Caller-Caller-ID-Number");
hunt_context = params:getHeader("Hunt-Context");
if (hunt_context ~= nil) then
call_context = hunt_context;
end
--prepare the api object
api = freeswitch.API();
--get the domain_uuid
if (domain_uuid == nil) then
--get the domain_uuid
if (domain_name ~= nil) then
sql = "SELECT domain_uuid FROM v_domains ";
sql = sql .. "WHERE domain_name = '" .. domain_name .."' ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(rows)
domain_uuid = rows["domain_uuid"];
end);
end
end
--process the sections
if (XML_REQUEST["section"] == "configuration") then
configuration = scripts_dir.."/app/xml_handler/resources/scripts/configuration/"..XML_REQUEST["key_value"]..".lua";
if (debug["xml_request"]) then
freeswitch.consoleLog("notice", "[xml_handler] " .. configuration .. "\n");
end
if (file_exists(configuration)) then
dofile(configuration);
end
end
if (XML_REQUEST["section"] == "directory") then
dofile(scripts_dir.."/app/xml_handler/resources/scripts/directory/directory.lua");
end
if (XML_REQUEST["section"] == "dialplan") then
dofile(scripts_dir.."/app/xml_handler/resources/scripts/dialplan/dialplan.lua");
end
--close the database connection
dbh:release();
@@ -1,103 +0,0 @@
-- xml_handler.lua
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set the xml array
local xml = {}
table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
table.insert(xml, [[<document type="freeswitch/xml">]]);
table.insert(xml, [[ <section name="configuration">]]);
table.insert(xml, [[ <configuration name="conference.conf" description="Audio Conference">]]);
table.insert(xml, [[ <caller-controls>]]);
table.insert(xml, [[ <group name="default">]]);
table.insert(xml, [[ <control action="mute" digits=""/>]]);
table.insert(xml, [[ <control action="deaf mute" digits=""/>]]);
table.insert(xml, [[ <control action="energy up" digits="9"/>]]);
table.insert(xml, [[ <control action="energy equ" digits="8"/>]]);
table.insert(xml, [[ <control action="energy dn" digits="7"/>]]);
table.insert(xml, [[ <control action="vol talk up" digits="3"/>]]);
table.insert(xml, [[ <control action="vol talk zero" digits="2"/>]]);
table.insert(xml, [[ <control action="vol talk dn" digits="1"/>]]);
table.insert(xml, [[ <control action="vol listen up" digits="6"/>]]);
table.insert(xml, [[ <control action="vol listen zero" digits="5"/>]]);
table.insert(xml, [[ <control action="vol listen dn" digits="4"/>]]);
table.insert(xml, [[ <control action="hangup" digits=""/>]]);
table.insert(xml, [[ </group>]]);
table.insert(xml, [[ <group name="moderator">]]);
table.insert(xml, [[ <control action="mute" digits="#"/>]]);
table.insert(xml, [[ <control action="deaf mute" digits=""/>]]);
table.insert(xml, [[ <control action="energy up" digits="9"/>]]);
table.insert(xml, [[ <control action="energy equ" digits="8"/>]]);
table.insert(xml, [[ <control action="energy dn" digits="7"/>]]);
table.insert(xml, [[ <control action="vol talk up" digits="3"/>]]);
table.insert(xml, [[ <control action="vol talk zero" digits="2"/>]]);
table.insert(xml, [[ <control action="vol talk dn" digits="1"/>]]);
table.insert(xml, [[ <control action="vol listen up" digits="6"/>]]);
table.insert(xml, [[ <control action="vol listen zero" digits="5"/>]]);
table.insert(xml, [[ <control action="vol listen dn" digits="4"/>]]);
table.insert(xml, [[ <control action="hangup" digits=""/>]]);
table.insert(xml, [[ </group>]]);
table.insert(xml, [[ </caller-controls>]]);
table.insert(xml, "");
table.insert(xml, [[ <profile name="default">]]);
table.insert(xml, [[ <param name="cdr-log-dir" value="auto"/>]]);
table.insert(xml, [[ <param name="conference-flags" value="wait-mod" />]]);
table.insert(xml, [[ <param name="domain" value="$${domain}"/>]]);
table.insert(xml, [[ <param name="rate" value="16000"/>]]);
table.insert(xml, [[ <param name="interval" value="20"/>]]);
table.insert(xml, [[ <param name="energy-level" value="15"/>]]);
table.insert(xml, [[ <param name="auto-gain-level" value="50"/>]]);
table.insert(xml, [[ <param name="caller-controls" value="default"/>]]);
table.insert(xml, [[ <param name="moderator-controls" value="default"/>]]);
table.insert(xml, [[ <param name="muted-sound" value="conference/conf-muted.wav"/>]]);
table.insert(xml, [[ <param name="unmuted-sound" value="conference/conf-unmuted.wav"/>]]);
table.insert(xml, [[ <param name="alone-sound" value="conference/conf-alone.wav"/>]]);
table.insert(xml, [[ <param name="moh-sound" value="$${hold_music}"/>]]);
table.insert(xml, [[ <param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>]]);
table.insert(xml, [[ <param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>]]);
table.insert(xml, [[ <param name="kicked-sound" value="conference/conf-kicked.wav"/>]]);
table.insert(xml, [[ <param name="locked-sound" value="conference/conf-locked.wav"/>]]);
table.insert(xml, [[ <param name="is-locked-sound" value="conference/conf-is-locked.wav"/>]]);
table.insert(xml, [[ <param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>]]);
table.insert(xml, [[ <param name="pin-sound" value="conference/conf-pin.wav"/>]]);
table.insert(xml, [[ <param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>]]);
table.insert(xml, [[ <param name="caller-id-name" value="$${outbound_caller_name}"/>]]);
table.insert(xml, [[ <param name="caller-id-number" value="$${outbound_caller_id}"/>]]);
table.insert(xml, [[ <param name="comfort-noise" value="true"/>]]);
table.insert(xml, [[ <param name="auto-record" value="/tmp/test.wav"/>]]);
table.insert(xml, [[ </profile>]]);
--set the xml array and then concatenate the array to a string
table.insert(xml, [[ </configuration>]]);
table.insert(xml, [[ </section>]]);
table.insert(xml, [[</document>]]);
XML_STRING = table.concat(xml, "\n");
--send the xml to the console
if (debug["xml_string"]) then
local file = assert(io.open("/tmp/conference.conf.xml", "w"));
file:write(XML_STRING);
file:close();
end
@@ -1,265 +0,0 @@
-- xml_handler.lua
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--get the cache
if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
XML_STRING = trim(api:execute("memcache", "get configuration:sofia.conf"));
else
XML_STRING = "-ERR NOT FOUND";
end
--set the cache
if (XML_STRING == "-ERR NOT FOUND") then
--get the variables
vars = trim(api:execute("global_getvar", ""));
--start the xml array
local xml = {}
table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
table.insert(xml, [[<document type="freeswitch/xml">]]);
table.insert(xml, [[ <section name="configuration">]]);
table.insert(xml, [[ <configuration name="sofia.conf" description="sofia Endpoint">]]);
table.insert(xml, [[ <global_settings>]]);
table.insert(xml, [[ <param name="log-level" value="0"/>]]);
--table.insert(xml, [[ <param name="auto-restart" value="false"/>]]);
table.insert(xml, [[ <param name="debug-presence" value="0"/>]]);
--table.insert(xml, [[ <param name="capture-server" value="udp:homer.domain.com:5060"/>]]);
table.insert(xml, [[ </global_settings>]]);
table.insert(xml, [[ <profiles>]]);
--set defaults
previous_sip_profile_name = "";
profile_tag_status = "closed";
--run the query
sql = "select p.sip_profile_name, p.sip_profile_description, s.sip_profile_setting_name, s.sip_profile_setting_value ";
sql = sql .. "from v_sip_profiles as p, v_sip_profile_settings as s ";
sql = sql .. "where p.sip_profile_uuid = s.sip_profile_uuid ";
sql = sql .. "and s.sip_profile_setting_enabled = 'true' ";
sql = sql .. "order by p.sip_profile_name asc ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
end
x = 0;
dbh:query(sql, function(row)
--set as variables
sip_profile_name = row.sip_profile_name;
--sip_profile_description = row.sip_profile_description;
sip_profile_setting_name = row.sip_profile_setting_name;
sip_profile_setting_value = row.sip_profile_setting_value;
--open xml tag
if (sip_profile_name ~= previous_sip_profile_name) then
if (x > 1) then
table.insert(xml, [[ </settings>]]);
table.insert(xml, [[ </profile>]]);
end
table.insert(xml, [[ <profile name="]]..sip_profile_name..[[">]]);
table.insert(xml, [[ <aliases>]]);
table.insert(xml, [[ </aliases>]]);
table.insert(xml, [[ <gateways>]]);
--table.insert(xml, [[ <X-PRE-PROCESS cmd="include" data="]]..sip_profile_name..[[/*.xml"/>]]);
--get the gateways
if (domain_count > 1) then
sql = "select * from v_gateways as g, v_domains as d ";
sql = sql .. "where g.profile = '"..sip_profile_name.."' ";
sql = sql .. "and g.enabled = 'true' ";
sql = sql .. "and g.domain_uuid = d.domain_uuid ";
else
sql = "select * from v_gateways ";
sql = sql .. "where profile = '"..sip_profile_name.."' and enabled = 'true' ";
end
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
end
x = 0;
dbh:query(sql, function(field)
--set as variables
gateway = field.gateway;
gateway = gateway:gsub(" ", "_");
if (domain_count > 1) then
table.insert(xml, [[ <gateway name="]] .. field.domain_name .."-".. gateway .. [[">]]);
else
table.insert(xml, [[ <gateway name="]] .. gateway .. [[">]]);
end
if (string.len(field.username) > 0) then
table.insert(xml, [[ <param name="username" value="]] .. field.username .. [["/>]]);
else
table.insert(xml, [[ <param name="username" value="register:false"/>]]);
end
if (string.len(field.distinct_to) > 0) then
table.insert(xml, [[ <param name="distinct-to" value="]] .. field.distinct_to .. [["/>]]);
end
if (string.len(field.auth_username) > 0) then
table.insert(xml, [[ <param name="auth-username" value="]] .. field.auth_username .. [["/>]]);
end
if (string.len(field.password) > 0) then
table.insert(xml, [[ <param name="password" value="]] .. field.password .. [["/>]]);
else
table.insert(xml, [[ <param name="password" value="register:false"/>]]);
end
if (string.len(field.realm) > 0) then
table.insert(xml, [[ <param name="realm" value="]] .. field.realm .. [["/>]]);
end
if (string.len(field.from_user) > 0) then
table.insert(xml, [[ <param name="from-user" value="]] .. field.from_user .. [["/>]]);
end
if (string.len(field.from_domain) > 0) then
table.insert(xml, [[ <param name="from-domain" value="]] .. field.from_domain .. [["/>]]);
end
if (string.len(field.proxy) > 0) then
table.insert(xml, [[ <param name="proxy" value="]] .. field.proxy .. [["/>]]);
end
if (string.len(field.register_proxy) > 0) then
table.insert(xml, [[ <param name="register-proxy" value="]] .. field.register_proxy .. [["/>]]);
end
if (string.len(field.outbound_proxy) > 0) then
table.insert(xml, [[ <param name="outbound-proxy" value="]] .. field.outbound_proxy .. [["/>]]);
end
if (string.len(field.expire_seconds) > 0) then
table.insert(xml, [[ <param name="expire-seconds" value="]] .. field.expire_seconds .. [["/>]]);
end
if (string.len(field.register) > 0) then
table.insert(xml, [[ <param name="register" value="]] .. field.register .. [["/>]]);
end
if (field.register_transport) then
if (field.register_transport == "udp") then
table.insert(xml, [[ <param name="register-transport" value="udp"/>]]);
elseif (field.register_transport == "tcp") then
table.insert(xml, [[ <param name="register-transport" value="tcp"/>]]);
elseif (field.register_transport == "tls") then
table.insert(xml, [[ <param name="register-transport" value="tls"/>]]);
table.insert(xml, [[ <param name="contact-params" value="transport=tls"/>]]);
else
table.insert(xml, [[ <param name="register-transport" value="udp"/>]]);
end
end
if (string.len(field.retry_seconds) > 0) then
table.insert(xml, [[ <param name="retry-seconds" value="]] .. field.retry_seconds .. [["/>]]);
end
if (string.len(field.extension) > 0) then
table.insert(xml, [[ <param name="extension" value="]] .. field.extension .. [["/>]]);
end
if (string.len(field.ping) > 0) then
table.insert(xml, [[ <param name="ping" value="]] .. field.ping .. [["/>]]);
end
if (string.len(field.context) > 0) then
table.insert(xml, [[ <param name="context" value="]] .. field.context .. [["/>]]);
end
if (string.len(field.caller_id_in_from) > 0) then
table.insert(xml, [[ <param name="caller-id-in-from" value="]] .. field.caller_id_in_from .. [["/>]]);
end
if (string.len(field.supress_cng) > 0) then
table.insert(xml, [[ <param name="supress-cng" value="]] .. field.supress_cng .. [["/>]]);
end
if (string.len(field.sip_cid_type) > 0) then
table.insert(xml, [[ <param name="sip_cid_type" value="]] .. field.sip_cid_type .. [["/>]]);
end
if (string.len(field.extension_in_contact) > 0) then
table.insert(xml, [[ <param name="extension-in-contact" value="]] .. field.extension_in_contact .. [["/>]]);
end
table.insert(xml, [[ </gateway>]]);
end)
table.insert(xml, [[ </gateways>]]);
table.insert(xml, [[ <domains>]]);
table.insert(xml, [[ <domain name="all" alias="false" parse="true"/>]]);
table.insert(xml, [[ </domains>]]);
table.insert(xml, [[ <settings>]]);
profile_tag_status = "open";
end
--loop through the var array
for line in (vars.."\n"):gmatch"(.-)\n" do
if (line) then
pos = string.find(line, "=", 0, true);
--name = string.sub( line, 0, pos-1);
--value = string.sub( line, pos+1);
sip_profile_setting_value = sip_profile_setting_value:gsub("%$%${"..string.sub( line, 0, pos-1).."}", string.sub( line, pos+1));
end
end
--remove $ and replace with ""
--if (sip_profile_setting_value) then
-- sip_profile_setting_value = sip_profile_setting_value:gsub("%$", "");
--end
--set the parameters
if (sip_profile_setting_name) then
table.insert(xml, [[ <param name="]]..sip_profile_setting_name..[[" value="]]..sip_profile_setting_value..[["/>]]);
end
--set the previous value
previous_sip_profile_name = sip_profile_name;
--increment the value of x
x = x + 1;
end)
--close the extension tag if it was left open
if (profile_tag_status == "open") then
table.insert(xml, [[ </settings>]]);
table.insert(xml, [[ </profile>]]);
profile_tag_status = "close";
end
table.insert(xml, [[ </profiles>]]);
table.insert(xml, [[ </configuration>]]);
table.insert(xml, [[ </section>]]);
table.insert(xml, [[</document>]]);
XML_STRING = table.concat(xml, "\n");
if (debug["xml_string"]) then
freeswitch.consoleLog("notice", "[xml_handler] XML_STRING: " .. XML_STRING .. "\n");
end
--set the cache
result = trim(api:execute("memcache", "set configuration:sofia.conf '"..XML_STRING:gsub("'", "&#39;").."' "..expire["sofia.conf"]));
--send the xml to the console
if (debug["xml_string"]) then
local file = assert(io.open("/tmp/sofia.conf.xml", "w"));
file:write(XML_STRING);
file:close();
end
--send to the console
if (debug["cache"]) then
freeswitch.consoleLog("notice", "[xml_handler] configuration:sofia.conf source: database\n");
end
else
--replace the &#39 back to a single quote
XML_STRING = XML_STRING:gsub("&#39;", "'");
--send to the console
if (debug["cache"]) then
freeswitch.consoleLog("notice", "[xml_handler] configuration:sofia.conf source: memcache\n");
end
end --if XML_STRING
@@ -1,264 +0,0 @@
-- xml_handler.lua
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--get the cache
if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
XML_STRING = trim(api:execute("memcache", "get dialplan:" .. call_context));
else
XML_STRING = "-ERR NOT FOUND";
end
--set the cache
if (XML_STRING == "-ERR NOT FOUND") then
--set the xml array and then concatenate the array to a string
local xml = {}
table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
table.insert(xml, [[<document type="freeswitch/xml">]]);
table.insert(xml, [[ <section name="dialplan" description="">]]);
table.insert(xml, [[ <context name="]] .. call_context .. [[">]]);
--set defaults
previous_dialplan_uuid = "";
previous_dialplan_detail_group = "";
previous_dialplan_detail_tag = "";
previous_dialplan_detail_type = "";
previous_dialplan_detail_data = "";
dialplan_tag_status = "closed";
condition_tag_status = "closed";
--get the dialplan and related details
sql = "select * from v_dialplans as d, v_dialplan_details as s ";
sql = sql .. "where d.dialplan_context = '" .. call_context .. "' ";
sql = sql .. "and d.dialplan_enabled = 'true' ";
sql = sql .. "and d.dialplan_uuid = s.dialplan_uuid ";
--if (call_context ~= "public") then
-- sql = sql .. "and d.domain_uuid = '" .. domain_uuid .. "' ";
--end
sql = sql .. "order by ";
sql = sql .. "d.dialplan_order asc, ";
sql = sql .. "d.dialplan_name asc, ";
sql = sql .. "d.dialplan_uuid asc, ";
sql = sql .. "s.dialplan_detail_group asc, ";
sql = sql .. "CASE s.dialplan_detail_tag ";
sql = sql .. "WHEN 'condition' THEN 1 ";
sql = sql .. "WHEN 'action' THEN 2 ";
sql = sql .. "WHEN 'anti-action' THEN 3 ";
sql = sql .. "ELSE 100 END, ";
sql = sql .. "s.dialplan_detail_order asc ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
end
x = 0;
dbh:query(sql, function(row)
--get the dialplan
--domain_uuid = row.domain_uuid;
dialplan_uuid = row.dialplan_uuid;
--app_uuid = row.app_uuid;
--dialplan_context = row.dialplan_context;
dialplan_name = row.dialplan_name;
--dialplan_number = row.dialplan_number;
dialplan_continue = row.dialplan_continue;
--dialplan_order = row.dialplan_order;
--dialplan_enabled = row.dialplan_enabled;
--dialplan_description = row.dialplan_description;
--get the dialplan details
--dialplan_detail_uuid = row.dialplan_detail_uuid;
dialplan_detail_tag = row.dialplan_detail_tag;
dialplan_detail_type = row.dialplan_detail_type;
dialplan_detail_data = row.dialplan_detail_data;
dialplan_detail_break = row.dialplan_detail_break;
dialplan_detail_inline = row.dialplan_detail_inline;
dialplan_detail_group = row.dialplan_detail_group;
--dialplan_detail_order = row.dialplan_detail_order;
--remove $$ and replace with $
dialplan_detail_data = dialplan_detail_data:gsub("%$%$", "$");
--get the dialplan detail inline
detail_inline = "";
if (dialplan_detail_inline) then
if (string.len(dialplan_detail_inline) > 0) then
detail_inline = [[ inline="]] .. dialplan_detail_inline .. [["]];
end
end
--close the tags
if (condition_tag_status ~= "closed") then
if (previous_dialplan_uuid ~= dialplan_uuid) then
table.insert(xml, [[ </condition>]]);
table.insert(xml, [[ </extension>]]);
dialplan_tag_status = "closed";
condition_tag_status = "closed";
else
if (previous_dialplan_detail_group ~= dialplan_detail_group and previous_dialplan_detail_tag == "condition") then
table.insert(xml, [[ </condition>]]);
condition_tag_status = "closed";
end
end
end
--open the tags
if (dialplan_tag_status == "closed") then
table.insert(xml, [[ <extension name="]] .. dialplan_name .. [[" continue="]] .. dialplan_continue .. [[" uuid="]] .. dialplan_uuid .. [[">]]);
dialplan_tag_status = "open";
end
if (dialplan_detail_tag == "condition") then
--determine the type of condition
if (dialplan_detail_type == "hour") then
condition_type = 'time';
elseif (dialplan_detail_type == "minute") then
condition_type = 'time';
elseif (dialplan_detail_type == "minute-of-day") then
condition_type = 'time';
elseif (dialplan_detail_type == "mday") then
condition_type = 'time';
elseif (dialplan_detail_type == "mweek") then
condition_type = 'time';
elseif (dialplan_detail_type == "mon") then
condition_type = 'time';
elseif (dialplan_detail_type == "yday") then
condition_type = 'time';
elseif (dialplan_detail_type == "year") then
condition_type = 'time';
elseif (dialplan_detail_type == "wday") then
condition_type = 'time';
elseif (dialplan_detail_type == "week") then
condition_type = 'time';
else
condition_type = 'default';
end
--get the condition break attribute
condition_break = "";
if (dialplan_detail_break) then
if (string.len(dialplan_detail_break) > 0) then
condition_break = [[ break="]] .. dialplan_detail_break .. [["]];
end
end
if (condition_tag_status == "open") then
if (previous_dialplan_detail_tag == "condition") then
--add the condition self closing tag
if (condition) then
if (string.len(condition) > 0) then
table.insert(xml, condition .. [[/>]]);
end
end
end
if (previous_dialplan_detail_tag == "action" or previous_dialplan_detail_tag == "anti-action") then
table.insert(xml, [[ </condition>]]);
condition_tag_status = "closed";
condition_type = "";
condition_attribute = "";
condition_expression = "";
end
end
--condition tag but leave off the ending
if (condition_type == "default") then
condition = [[ <condition field="]] .. dialplan_detail_type .. [[" expression="]] .. dialplan_detail_data .. [["]] .. condition_break;
elseif (condition_type == "time") then
if (condition_attribute) then
condition_attribute = condition_attribute .. dialplan_detail_type .. [[="]] .. dialplan_detail_data .. [[" ]];
else
condition_attribute = dialplan_detail_type .. [[="]] .. dialplan_detail_data .. [[" ]];
end
condition_expression = "";
condition = ""; --prevents a duplicate time condition
else
condition = [[ <condition field="]] .. dialplan_detail_type .. [[" expression="]] .. dialplan_detail_data .. [["]] .. condition_break;
end
condition_tag_status = "open";
end
if (dialplan_detail_tag == "action" or dialplan_detail_tag == "anti-action") then
if (previous_dialplan_detail_tag == "condition") then
--add the condition ending
if (condition_type == "time") then
condition = [[ <condition ]] .. condition_attribute .. condition_break;
condition_attribute = ""; --prevents the condition attribute from being used on every condition
else
if (previous_dialplan_detail_type) then
condition = [[ <condition field="]] .. previous_dialplan_detail_type .. [[" expression="]] .. previous_dialplan_detail_data .. [["]] .. condition_break;
end
end
table.insert(xml, condition .. [[>]]);
condition = ""; --prevents duplicate time conditions
end
end
if (dialplan_detail_tag == "action") then
table.insert(xml, [[ <action application="]] .. dialplan_detail_type .. [[" data="]] .. dialplan_detail_data .. [["]] .. detail_inline .. [[/>]]);
end
if (dialplan_detail_tag == "anti-action") then
table.insert(xml, [[ <anti-action application="]] .. dialplan_detail_type .. [[" data="]] .. dialplan_detail_data .. [["]] .. detail_inline .. [[/>]]);
end
--save the previous values
previous_dialplan_uuid = dialplan_uuid;
previous_dialplan_detail_group = dialplan_detail_group;
previous_dialplan_detail_tag = dialplan_detail_tag;
previous_dialplan_detail_type = dialplan_detail_type;
previous_dialplan_detail_data = dialplan_detail_data;
--increment the x
x = x + 1;
end);
--close the extension tag if it was left open
if (dialplan_tag_status == "open") then
table.insert(xml, [[ </condition>]]);
table.insert(xml, [[ </extension>]]);
end
--set the xml array and then concatenate the array to a string
table.insert(xml, [[ </context>]]);
table.insert(xml, [[ </section>]]);
table.insert(xml, [[</document>]]);
XML_STRING = table.concat(xml, "\n");
--set the cache
tmp = XML_STRING:gsub("\\", "\\\\");
result = trim(api:execute("memcache", "set dialplan:" .. call_context .. " '"..tmp:gsub("'", "&#39;").."' "..expire["dialplan"]));
--send the xml to the console
if (debug["xml_string"]) then
local file = assert(io.open("/tmp/dialplan-" .. call_context .. ".xml", "w"));
file:write(XML_STRING);
file:close();
end
--send to the console
if (debug["cache"]) then
freeswitch.consoleLog("notice", "[xml_handler] dialplan:"..call_context.." source: database\n");
end
else
--replace the &#39 back to a single quote
XML_STRING = XML_STRING:gsub("&#39;", "'");
--send to the console
if (debug["cache"]) then
freeswitch.consoleLog("notice", "[xml_handler] dialplan:"..call_context.." source: memcache\n");
end
end
@@ -1,124 +0,0 @@
-- xml_handler.lua
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--get the cache
if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
XML_STRING = trim(api:execute("memcache", "get directory:groups:"..domain_name));
else
XML_STRING = "-ERR NOT FOUND";
end
--set the cache
if (XML_STRING == "-ERR NOT FOUND") then
--build the call group array
sql = [[
select * from v_extensions
where domain_uuid = ']]..domain_uuid..[['
order by call_group asc
]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
end
call_group_array = {};
status = dbh:query(sql, function(row)
call_group = row['call_group'];
--call_group = str_replace(";", ",", call_group);
tmp_array = explode(",", call_group);
for key,value in pairs(tmp_array) do
value = trim(value);
--freeswitch.consoleLog("notice", "[directory] Key: " .. key .. " Value: " .. value .. " " ..row['extension'] .."\n");
if (string.len(value) == 0) then
--do nothing
else
if (call_group_array[value] == nil) then
call_group_array[value] = row['extension'];
else
call_group_array[value] = call_group_array[value]..','..row['extension'];
end
end
end
end);
--for key,value in pairs(call_group_array) do
-- freeswitch.consoleLog("notice", "[directory] Key: " .. key .. " Value: " .. value .. "\n");
--end
--build the xml array
local xml = {}
table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
table.insert(xml, [[<document type="freeswitch/xml">]]);
table.insert(xml, [[ <section name="directory">]]);
table.insert(xml, [[ <domain name="]] .. domain_name .. [[">]]);
table.insert(xml, [[ <groups>]]);
previous_call_group = "";
for key, value in pairs(call_group_array) do
call_group = trim(key);
extension_list = trim(value);
if (string.len(call_group) > 0) then
freeswitch.consoleLog("notice", "[directory] call_group: " .. call_group .. "\n");
freeswitch.consoleLog("notice", "[directory] extension_list: " .. extension_list .. "\n");
if (previous_call_group ~= call_group) then
table.insert(xml, [[ <group name="]]..call_group..[[">]]);
table.insert(xml, [[ <users>]]);
extension_array = explode(",", extension_list);
for index,tmp_extension in pairs(extension_array) do
table.insert(xml, [[ <user id="]]..tmp_extension..[[" type="pointer"/>]]);
end
table.insert(xml, [[ </users>]]);
table.insert(xml, [[ </group>]]);
end
previous_call_group = call_group;
end
end
table.insert(xml, [[ </groups>]]);
table.insert(xml, [[ </domain>]]);
table.insert(xml, [[ </section>]]);
table.insert(xml, [[</document>]]);
XML_STRING = table.concat(xml, "\n");
--set the cache
result = trim(api:execute("memcache", "set directory:groups:"..domain_name.." '"..XML_STRING:gsub("'", "&#39;").."' "..expire["directory"]));
--send to the console
if (debug["cache"]) then
freeswitch.consoleLog("notice", "[xml_handler] directory:groups:"..domain_name.." source: database\n");
end
else
--replace the &#39 back to a single quote
XML_STRING = XML_STRING:gsub("&#39;", "'");
--send to the console
if (debug["cache"]) then
if (XML_STRING) then
freeswitch.consoleLog("notice", "[xml_handler] directory:groups:"..domain_name.." source: memcache\n");
end
end
end
--send the xml to the console
if (debug["xml_string"]) then
freeswitch.consoleLog("notice", "[xml_handler] directory:groups:"..domain_name.." XML_STRING: \n" .. XML_STRING .. "\n");
end
@@ -1,8 +0,0 @@
--params
--Event-Calling-Line-Number: 102
--Event-Sequence: 4173
--action: message-count
--key: id
--user: *98
--domain: example.com
@@ -1,379 +0,0 @@
-- xml_handler.lua
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set the default
continue = true;
--get the action
action = params:getHeader("action");
purpose = params:getHeader("purpose");
--sip_auth - registration
--group_call - call group has been called
--user_call - user has been called
--additional information
--event_calling_function = params:getHeader("Event-Calling-Function");
--determine the correction action to perform
if (purpose == "gateways") then
if (params:getHeader("profile") == "internal") then
--process when the sip profile is rescanned or sofia is reloaded
local xml = {}
table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
table.insert(xml, [[<document type="freeswitch/xml">]]);
table.insert(xml, [[ <section name="directory">]]);
sql = "SELECT * FROM v_domains ";
dbh:query(sql, function(row)
table.insert(xml, [[ <domain name="]]..row.domain_name..[[" />]]);
end);
table.insert(xml, [[ </section>]]);
table.insert(xml, [[</document>]]);
XML_STRING = table.concat(xml, "\n");
end
elseif (action == "message-count") then
dofile(scripts_dir.."/app/xml_handler/resources/scripts/directory/action/message-count.lua");
elseif (action == "group_call") then
dofile(scripts_dir.."/app/xml_handler/resources/scripts/directory/action/group_call.lua");
else
--handle action
--all other directory actions: sip_auth, user_call
--except for the action: group_call
--get the cache
if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
if (user == nil) then
user = "";
end
if (domain_name) then
XML_STRING = trim(api:execute("memcache", "get directory:" .. user .. "@" .. domain_name));
end
if (XML_STRING == "-ERR NOT FOUND") then
continue = true;
else
continue = false;
end
else
XML_STRING = "";
continue = true;
end
--prevent processing for invalid user
if (user == "*97") then
continue = false;
end
--prevent processing for invalid domains
if (domain_uuid == nil) then
continue = false;
end
--get the extension from the database
if (continue) then
sql = "SELECT * FROM v_extensions WHERE domain_uuid = '" .. domain_uuid .. "' and extension = '" .. user .. "' and enabled = 'true' ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
end
dbh:query(sql, function(row)
--general
domain_uuid = row.domain_uuid;
extension_uuid = row.extension_uuid;
extension = row.extension;
cidr = "";
if (string.len(row.cidr) > 0) then
cidr = [[ cidr="]] .. row.cidr .. [["]];
end
number_alias = "";
if (string.len(row.number_alias) > 0) then
number_alias = [[ number-alias="]] .. row.number_alias .. [["]];
end
--params
password = row.password;
vm_enabled = "true";
if (string.len(row.vm_enabled) > 0) then
vm_enabled = row.vm_enabled;
end
vm_password = row.vm_password;
vm_attach_file = "true";
if (string.len(row.vm_attach_file) > 0) then
vm_attach_file = row.vm_attach_file;
end
vm_keep_local_after_email = "true";
if (string.len(row.vm_keep_local_after_email) > 0) then
vm_keep_local_after_email = row.vm_keep_local_after_email;
end
if (string.len(row.vm_mailto) > 0) then
vm_mailto = row.vm_mailto;
else
vm_mailto = "";
end
mwi_account = row.mwi_account;
auth_acl = row.auth_acl;
--variables
sip_from_user = row.extension;
call_group = row.call_group;
hold_music = row.hold_music;
toll_allow = row.toll_allow;
accountcode = row.accountcode;
user_context = row.user_context;
effective_caller_id_name = row.effective_caller_id_name;
effective_caller_id_number = row.effective_caller_id_number;
outbound_caller_id_name = row.outbound_caller_id_name;
outbound_caller_id_number = row.outbound_caller_id_number;
emergency_caller_id_number = row.emergency_caller_id_number;
directory_full_name = row.directory_full_name;
directory_visible = row.directory_visible;
directory_exten_visible = row.directory_exten_visible;
limit_max = row.limit_max;
call_timeout = row.call_timeout;
limit_destination = row.limit_destination;
sip_force_contact = row.sip_force_contact;
sip_force_expires = row.sip_force_expires;
nibble_account = row.nibble_account;
sip_bypass_media = row.sip_bypass_media;
--set the dial_string
if (string.len(row.dial_string) > 0) then
dial_string = row.dial_string;
else
dial_string = "{sip_invite_domain=" .. domain_name .. ",leg_timeout=" .. call_timeout .. ",presence_id=" .. user .. "@" .. domain_name .. "}${sofia_contact(" .. user .. "@" .. domain_name .. ")}";
end
end);
end
--if the extension does not exist set continue to false;
if (extension_uuid == nil) then
continue = false;
end
--outbound hot desking - get the extension variables
if (continue) then
sql = "SELECT * FROM v_extensions WHERE dial_domain = '" .. domain_name .. "' and dial_user = '" .. user .. "' and enabled = 'true' ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n");
end
dbh:query(sql, function(row)
--get the values from the database
extension_uuid = row.extension_uuid;
domain_uuid = row.domain_uuid;
sip_from_user = row.extension;
call_group = row.call_group;
hold_music = row.hold_music;
toll_allow = row.toll_allow;
accountcode = row.accountcode;
user_context = row.user_context;
effective_caller_id_name = row.effective_caller_id_name;
effective_caller_id_number = row.effective_caller_id_number;
outbound_caller_id_name = row.outbound_caller_id_name;
outbound_caller_id_number = row.outbound_caller_id_number;
emergency_caller_id_number = row.emergency_caller_id_number;
directory_full_name = row.directory_full_name;
directory_visible = row.directory_visible;
directory_exten_visible = row.directory_exten_visible;
limit_max = row.limit_max;
--call_timeout = row.call_timeout;
limit_destination = row.limit_destination;
sip_force_contact = row.sip_force_contact;
sip_force_expires = row.sip_force_expires;
nibble_account = row.nibble_account;
sip_bypass_media = row.sip_bypass_media;
end);
end
--set the xml array and then concatenate the array to a string
if (continue and password) then
--build the xml
local xml = {}
table.insert(xml, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
table.insert(xml, [[<document type="freeswitch/xml">]]);
table.insert(xml, [[ <section name="directory">]]);
table.insert(xml, [[ <domain name="]] .. domain_name .. [[" alias="true">]]);
table.insert(xml, [[ <groups>]]);
table.insert(xml, [[ <group name="default">]]);
table.insert(xml, [[ <users>]]);
if (number_alias) then
if (cidr) then
table.insert(xml, [[ <user id="]] .. extension .. [["]] .. cidr .. number_alias .. [[ type=>]]);
else
table.insert(xml, [[ <user id="]] .. extension .. [["]] .. number_alias .. [[>]]);
end
else
if (cidr) then
table.insert(xml, [[ <user id="]] .. extension .. [["]] .. cidr .. [[>]]);
else
table.insert(xml, [[ <user id="]] .. extension .. [[">]]);
end
end
table.insert(xml, [[ <params>]]);
table.insert(xml, [[ <param name="password" value="]] .. password .. [["/>]]);
table.insert(xml, [[ <param name="vm-enabled" value="]] .. vm_enabled .. [["/>]]);
if (string.len(vm_mailto) > 0) then
table.insert(xml, [[ <param name="vm-password" value="]] .. vm_password .. [["/>]]);
table.insert(xml, [[ <param name="vm-email-all-messages" value="]] .. vm_enabled ..[["/>]]);
table.insert(xml, [[ <param name="vm-attach-file" value="]] .. vm_attach_file .. [["/>]]);
table.insert(xml, [[ <param name="vm-keep-local-after-email" value="]] .. vm_keep_local_after_email .. [["/>]]);
table.insert(xml, [[ <param name="vm-mailto" value="]] .. vm_mailto .. [["/>]]);
end
if (string.len(mwi_account) > 0) then
table.insert(xml, [[ <param name="MWI-Account" value="]] .. mwi_account .. [["/>]]);
end
if (string.len(auth_acl) > 0) then
table.insert(xml, [[ <param name="auth-acl" value="]] .. auth_acl .. [["/>]]);
end
table.insert(xml, [[ <param name="dial-string" value="]] .. dial_string .. [["/>]]);
table.insert(xml, [[ </params>]]);
table.insert(xml, [[ <variables>]]);
table.insert(xml, [[ <variable name="domain_uuid" value="]] .. domain_uuid .. [["/>]]);
table.insert(xml, [[ <variable name="domain_name" value="]] .. domain_name .. [["/>]]);
table.insert(xml, [[ <variable name="extension_uuid" value="]] .. extension_uuid .. [["/>]]);
--table.insert(xml, [[ <variable name="call_timeout" value="]] .. call_timeout .. [["/>]]);
table.insert(xml, [[ <variable name="caller_id_name" value="]] .. sip_from_user .. [["/>]]);
table.insert(xml, [[ <variable name="caller_id_number" value="]] .. sip_from_user .. [["/>]]);
if (string.len(call_group) > 0) then
table.insert(xml, [[ <variable name="call_group" value="]] .. call_group .. [["/>]]);
end
if (string.len(hold_music) > 0) then
table.insert(xml, [[ <variable name="hold_music" value="]] .. hold_music .. [["/>]]);
end
if (string.len(toll_allow) > 0) then
table.insert(xml, [[ <variable name="toll_allow" value="]] .. toll_allow .. [["/>]]);
end
if (string.len(accountcode) > 0) then
table.insert(xml, [[ <variable name="accountcode" value="]] .. accountcode .. [["/>]]);
end
table.insert(xml, [[ <variable name="user_context" value="]] .. user_context .. [["/>]]);
if (string.len(effective_caller_id_name) > 0) then
table.insert(xml, [[ <variable name="effective_caller_id_name" value="]] .. effective_caller_id_name.. [["/>]]);
end
if (string.len(effective_caller_id_number) > 0) then
table.insert(xml, [[ <variable name="effective_caller_id_number" value="]] .. effective_caller_id_number.. [["/>]]);
end
if (string.len(outbound_caller_id_name) > 0) then
table.insert(xml, [[ <variable name="outbound_caller_id_name" value="]] .. outbound_caller_id_name .. [["/>]]);
end
if (string.len(outbound_caller_id_number) > 0) then
table.insert(xml, [[ <variable name="outbound_caller_id_number" value="]] .. outbound_caller_id_number .. [["/>]]);
end
if (string.len(emergency_caller_id_number) > 0) then
table.insert(xml, [[ <variable name="emergency_caller_id_number" value="]] .. emergency_caller_id_number .. [["/>]]);
end
if (string.len(directory_full_name) > 0) then
table.insert(xml, [[ <variable name="directory_full_name" value="]] .. directory_full_name .. [["/>]]);
end
if (string.len(directory_visible) > 0) then
table.insert(xml, [[ <variable name="directory-visible" value="]] .. directory_visible .. [["/>]]);
end
if (string.len(directory_exten_visible) > 0) then
table.insert(xml, [[ <variable name="directory-exten-visible" value="]] .. directory_exten_visible .. [["/>]]);
end
if (string.len(limit_max) > 0) then
table.insert(xml, [[ <variable name="limit_max" value="]] .. limit_max .. [["/>]]);
else
table.insert(xml, [[ <variable name="limit_max" value="5"/>]]);
end
if (string.len(limit_destination) > 0) then
table.insert(xml, [[ <variable name="limit_destination" value="]] .. limit_destination .. [["/>]]);
end
if (string.len(sip_force_contact) > 0) then
table.insert(xml, [[ <variable name="sip_force_contact" value="]] .. sip_force_contact .. [["/>]]);
end
if (string.len(sip_force_expires) > 0) then
table.insert(xml, [[ <variable name="sip-force-expires" value="]] .. sip_force_expires .. [["/>]]);
end
if (string.len(nibble_account) > 0) then
table.insert(xml, [[ <variable name="nibble_account" value="]] .. nibble_account .. [["/>]]);
end
if (sip_bypass_media == "bypass-media") then
table.insert(xml, [[ <variable name="bypass_media" value="true"/>]]);
end
if (sip_bypass_media == "bypass-media-after-bridge") then
table.insert(xml, [[ <variable name="bypass_media_after_bridge" value="true"/>]]);
end
if (sip_bypass_media == "proxy-media") then
table.insert(xml, [[ <variable name="proxy_media" value="true"/>]]);
end
table.insert(xml, [[ <variable name="record_stereo" value="true"/>]]);
table.insert(xml, [[ <variable name="transfer_fallback_extension" value="operator"/>]]);
table.insert(xml, [[ <variable name="export_vars" value="domain_name"/>]]);
table.insert(xml, [[ </variables>]]);
table.insert(xml, [[ </user>]]);
table.insert(xml, [[ </users>]]);
table.insert(xml, [[ </group>]]);
table.insert(xml, [[ </groups>]]);
table.insert(xml, [[ </domain>]]);
table.insert(xml, [[ </section>]]);
table.insert(xml, [[</document>]]);
XML_STRING = table.concat(xml, "\n");
--set the cache
if (user and domain_name) then
result = trim(api:execute("memcache", "set directory:" .. user .. "@" .. domain_name .. " '"..XML_STRING:gsub("'", "&#39;").."' "..expire["directory"]));
end
--send the xml to the console
if (debug["xml_string"]) then
local file = assert(io.open("/tmp/" .. user .. "@" .. domain_name .. ".xml", "w"));
file:write(XML_STRING);
file:close();
end
--send to the console
if (debug["cache"]) then
freeswitch.consoleLog("notice", "[xml_handler] directory:" .. user .. "@" .. domain_name .. " source: database\n");
end
else
--replace the &#39 back to a single quote
if (XML_STRING) then
XML_STRING = XML_STRING:gsub("&#39;", "'");
end
--send to the console
if (debug["cache"]) then
if (XML_STRING) then
freeswitch.consoleLog("notice", "[xml_handler] directory:" .. user .. "@" .. domain_name .. " source: memcache \n");
end
end
end
end --if action
--if the extension does not exist send "not found"
if (trim(XML_STRING) == "-ERR NOT FOUND" or XML_STRING == nil) then
--send not found
XML_STRING = [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="freeswitch/xml">
<section name="result">
<result status="not found" />
</section>
</document>]];
--set the cache
if (user and domain_name) then
result = trim(api:execute("memcache", "set directory:" .. user .. "@" .. domain_name .. " '"..XML_STRING:gsub("'", "&#39;").."' "..expire["directory"]));
end
end
--send the xml to the console
if (debug["xml_string"]) then
freeswitch.consoleLog("notice", "[xml_handler] XML_STRING: \n" .. XML_STRING .. "\n");
end
-174
View File
@@ -1,174 +0,0 @@
-- intercom.lua
-- Part of FusionPBX
-- Copyright (C) 2010 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set the variables
max_tries = "3";
digit_timeout = "5000";
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
if (session:ready()) then
--get the variables
domain_name = session:getVariable("domain_name");
call_flow_uuid = session:getVariable("call_flow_uuid");
sounds_dir = session:getVariable("sounds_dir");
feature_code = session:getVariable("feature_code");
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--get the extension list
sql = [[SELECT * FROM v_call_flows
where call_flow_uuid = ']]..call_flow_uuid..[[']]
--and call_flow_enabled = 'true'
--freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n");
app_data = "";
x = 0;
dbh:query(sql, function(row)
call_flow_name = row.call_flow_name;
call_flow_extension = row.call_flow_extension;
call_flow_feature_code = row.call_flow_feature_code;
--call_flow_context = row.call_flow_context;
call_flow_status = row.call_flow_status;
pin_number = row.call_flow_pin_number;
call_flow_label = row.call_flow_label;
call_flow_anti_label = row.call_flow_anti_label;
if (string.len(call_flow_status) == 0) then
app = row.call_flow_app;
data = row.call_flow_data
else
if (call_flow_status == "true") then
app = row.call_flow_app;
data = row.call_flow_data
else
app = row.call_flow_anti_app;
data = row.call_flow_anti_data
end
end
end);
if (feature_code == "true") then
--if the pin number is provided then require it
if (string.len(pin_number) > 0) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
session:answer();
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:voicemail_enter_pass:#", "", "\\d+");
if (digits == pin_number) then
--pin is correct
else
session:streamFile("phrase:voicemail_fail_auth:#");
session:hangup("NORMAL_CLEARING");
return;
end
end
--feature code - toggle the status
if (string.len(call_flow_status) == 0) then
toggle = "false";
else
if (call_flow_status == "true") then
toggle = "false";
else
toggle = "true";
end
end
if (toggle == "true") then
--set the presence to terminated - turn the lamp off:
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("Presence-Call-Direction", "outbound");
event:addHeader("state", "Active (1 waiting)");
event:addHeader("from", call_flow_feature_code.."@"..domain_name);
event:addHeader("login", call_flow_feature_code.."@"..domain_name);
event:addHeader("unique-id", call_flow_uuid);
event:addHeader("answer-state", "terminated");
event:fire();
--answer and play a tone
session:answer();
if (string.len(call_flow_label) > 0) then
api = freeswitch.API();
reply = api:executeString("uuid_display "..session:get_uuid().." "..call_flow_label);
end
session:execute("sleep", "2000");
session:execute("playback", "tone_stream://%(200,0,500,600,700)");
--show in the console
freeswitch.consoleLog("notice", "Call Flow: label="..call_flow_label..",status=true,uuid="..call_flow_uuid.."\n");
else
--set presence in - turn lamp on
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("login", call_flow_feature_code.."@"..domain_name);
event:addHeader("from", call_flow_feature_code.."@"..domain_name);
event:addHeader("status", "Active (1 waiting)");
event:addHeader("rpid", "unknown");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("event_count", "1");
event:addHeader("unique-id", call_flow_uuid);
event:addHeader("Presence-Call-Direction", "outbound")
event:addHeader("answer-state", "confirmed");
event:fire();
--answer and play a tone
session:answer();
if (string.len(call_flow_anti_label) > 0) then
api = freeswitch.API();
reply = api:executeString("uuid_display "..session:get_uuid().." "..call_flow_anti_label);
end
session:execute("sleep", "2000");
session:execute("playback", "tone_stream://%(500,0,300,200,100,50,25)");
--show in the console
freeswitch.consoleLog("notice", "Call Flow: label="..call_flow_anti_label..",status=false,uuid="..call_flow_uuid.."\n");
end
dbh:query("UPDATE v_call_flows SET call_flow_status = '"..toggle.."' WHERE call_flow_uuid = '"..call_flow_uuid.."'");
else
--app_data
freeswitch.consoleLog("notice", "Call Flow: " .. app .. " " .. data .. "\n");
--exucute the application
session:execute(app, data);
--timeout application
--if (not session:answered()) then
-- session:execute(ring_group_timeout_app, ring_group_timeout_data);
--end
end
end
@@ -1,137 +0,0 @@
-- call_flow_monitor.lua
-- Part of FusionPBX
-- Copyright (C) 2010 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set the time between loops in seconds
sleep = 300;
--set the debug level
debug["log"] = false;
debug["sql"] = false;
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--general functions
dofile(scripts_dir.."/resources/functions/file_exists.lua");
dofile(scripts_dir.."/resources/functions/mkdir.lua");
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--make sure the scripts/run dir exists
mkdir(scripts_dir .. "/run");
--define the run file
run_file = scripts_dir .. "/run/call_flow_monitor.tmp";
--define the functions
--shell return results
function shell(c)
local o, h
h = assert(io.popen(c,"r"))
o = h:read("*all")
h:close()
return o
end
--used to stop the lua service
local file = assert(io.open(run_file, "w"));
file:write("remove this file to stop the script");
--monitor the call flows status
x = 0
while true do
--get the extension list
sql = [[select d.domain_name, f.call_flow_uuid, f.call_flow_extension, f.call_flow_feature_code, f.call_flow_status, f.call_flow_label, f.call_flow_anti_label
from v_call_flows as f, v_domains as d
where f.domain_uuid = d.domain_uuid]]
--and call_flow_enabled = 'true'
if (debug["sql"]) then
freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n");
end
x = 0;
dbh:query(sql, function(row)
domain_name = row.domain_name;
call_flow_uuid = row.call_flow_uuid;
--call_flow_name = row.call_flow_name;
call_flow_extension = row.call_flow_extension;
call_flow_feature_code = row.call_flow_feature_code;
--call_flow_context = row.call_flow_context;
call_flow_status = row.call_flow_status;
--pin_number = row.call_flow_pin_number;
call_flow_label = row.call_flow_label;
call_flow_anti_label = row.call_flow_anti_label;
if (call_flow_status == "true") then
--set the presence to terminated - turn the lamp off:
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("Presence-Call-Direction", "outbound");
event:addHeader("state", "Active (1 waiting)");
event:addHeader("from", call_flow_feature_code.."@"..domain_name);
event:addHeader("login", call_flow_feature_code.."@"..domain_name);
event:addHeader("unique-id", call_flow_uuid);
event:addHeader("answer-state", "terminated");
event:fire();
--show in the console
if (debug["log"]) then
freeswitch.consoleLog("notice", "Call Flow: label="..call_flow_label..",status=true,uuid="..call_flow_uuid.."\n");
end
else
--set presence in - turn lamp on
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("login", call_flow_feature_code.."@"..domain_name);
event:addHeader("from", call_flow_feature_code.."@"..domain_name);
event:addHeader("status", "Active (1 waiting)");
event:addHeader("rpid", "unknown");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("event_count", "1");
event:addHeader("unique-id", call_flow_uuid);
event:addHeader("Presence-Call-Direction", "outbound");
event:addHeader("answer-state", "confirmed");
event:fire();
--show in the console
if (debug["log"]) then
freeswitch.consoleLog("notice", "Call Flow: label="..call_flow_anti_label..",status=false,uuid="..call_flow_uuid.."\n");
end
end
end);
--exit the loop when the file does not exist
if (not file_exists(run_file)) then
break;
end
--sleep a moment to prevent using unecessary resources
freeswitch.msleep(sleep*1000);
end
-127
View File
@@ -1,127 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
pin_number = "";
max_tries = "3";
digit_timeout = "3000";
function file_exists(fname)
local f = io.open(fname, "r")
if (f and f:read()) then return true end
end
if ( session:ready() ) then
session:answer();
--session:execute("info", "");
extension = session:getVariable("user_name");
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
dialplan_default_dir = session:getVariable("dialplan_default_dir");
call_forward_number = session:getVariable("call_forward_number");
extension_required = session:getVariable("extension_required");
context = session:getVariable("context");
if (not context ) then context = 'default'; end
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--if the pin number is provided then require it
if (pin_number) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_pin_number.wav", "", "\\d+");
if (digits == pin_number) then
--pin is correct
else
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/your_pin_number_is_incorect_goodbye.wav");
session:hangup("NORMAL_CLEARING");
return;
end
end
--if extension_requires is true then get the extension number
if (extension_required) then
if (extension_required == "true") then
extension = session:playAndGetDigits(3, 6, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_extension_number.wav", "", "\\d+");
end
end
if (file_exists(dialplan_default_dir.."/000_call_forward_"..extension..".xml")) then
--file exists
--remove the call forward dialplan entry
os.remove (dialplan_default_dir.."/000_call_forward_"..extension..".xml");
--stream file
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/call_forward_has_been_deleted.wav");
--wait for the file to be written before proceeding
session:sleep(1000);
else
--file does not exist
dtmf = ""; --clear dtmf digits to prepare for next dtmf request
if (call_forward_number) then
-- do nothing
else
-- get the call forward number
call_forward_number = session:playAndGetDigits(3, 15, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_phone_number.wav", "", "\\d+");
end
if (string.len(call_forward_number) > 0) then
--write the xml file
xml = "<extension name=\"call_forward_"..extension.."\" >\n";
xml = xml .. " <condition field=\"destination_number\" expression=\"^"..extension.."$\">\n";
xml = xml .. " <action application=\"transfer\" data=\""..call_forward_number.." XML "..context.."\"/>\n";
xml = xml .. " </condition>\n";
xml = xml .. "</extension>\n";
session:execute("log", xml);
local file = assert(io.open(dialplan_default_dir.."/000_call_forward_"..extension..".xml", "w"));
file:write(xml);
file:close();
--wait for the file to be written before proceeding
--session:sleep(20000);
--stream file
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/call_forward_has_been_set.wav");
end
end
--reloadxml
api = freeswitch.API();
reply = api:executeString("reloadxml");
--wait for the file to be written before proceeding
session:sleep(1000);
session:hangup();
end
-78
View File
@@ -1,78 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
max_tries = "3";
digit_timeout = "5000";
if ( session:ready() ) then
session:answer();
context = session:getVariable("context");
sounds_dir = session:getVariable("sounds_dir");
destination_number = session:getVariable("destination_number");
--prepare the api
api = freeswitch.API();
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--confirm the calls
--set the default
prompt_for_digits = true;
--if an extension answer the call
-- user_exists id 1005 voip.fusionpbx.com
cmd = "user_exists id ".. destination_number .." "..context;
result = api:executeString(cmd);
freeswitch.consoleLog("NOTICE", "[confirm] "..cmd.." --"..result.."--\n");
if (result == "true") then
prompt_for_digits = false;
end
--prompt for digits
if (prompt_for_digits) then
--get the digit
min_digits = 1;
max_digits = 1;
digit = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-accept_reject_voicemail.wav", "", "\\d+");
--process the response
if (digit == "1") then
--freeswitch.consoleLog("NOTICE", "[confirm] accept\n");
elseif (digit == "2") then
--freeswitch.consoleLog("NOTICE", "[confirm] reject\n");
session:hangup("CALL_REJECTED"); --LOSE_RACE
elseif (digit == "3") then
--freeswitch.consoleLog("NOTICE", "[confirm] voicemail\n");
session:hangup("NO_ANSWER");
else
--freeswitch.consoleLog("NOTICE", "[confirm] no answer\n");
session:hangup("NO_ANSWER");
end
else
--freeswitch.consoleLog("NOTICE", "[confirm] automatically accepted\n");
end
end
@@ -1,70 +0,0 @@
-- intercom.lua
-- Part of FusionPBX
-- Copyright (C) 2010 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--add a trim function
function trim (s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
--get the variables
domain_name = session:getVariable("domain_name");
outbound_number = session:getVariable("destination_number");
freeswitch.consoleLog("notice", "outbound_number: --" .. outbound_number .. "--\n");
outbound_area_code = string.sub(outbound_number,3,5);
freeswitch.consoleLog("notice", "Area Code: " .. outbound_area_code .. "\n");
--caller_id_name = session:getVariable("caller_id_name");
--caller_id_number = session:getVariable("caller_id_number");
--get the destination_number
sql = [[ SELECT * FROM v_destinations
where destination_number like '1]].. outbound_area_code ..[[%']]
freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n");
x = 0;
dbh:query(sql, function(row)
destination_number = row.destination_number;
--destination_caller_id_name = row.destination_caller_id_name;
--destination_caller_id_number = row.destination_caller_id_number;
x = x + 1;
end);
--session actions
if (session:ready()) then
if (destination_number) then
freeswitch.consoleLog("notice", "effective_caller_id_number="..destination_number.."\n");
session:execute("set", "effective_caller_id_number="..destination_number);
end
--session:hangup();
end
-201
View File
@@ -1,201 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
--set default variables
max_tries = "3";
digit_timeout = "5000";
--set the debug level
debug["sql"] = false;
debug["var"] = false;
db_dial_string = "";
db_extension_uuid = "";
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
if ( session:ready() ) then
session:answer();
domain_uuid = session:getVariable("domain_uuid");
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
sip_from_user = session:getVariable("sip_from_user");
sip_from_host = session:getVariable("sip_from_host");
direction = session:getVariable("direction"); --in, out, both
extension = tostring(session:getVariable("extension")); --true, false
dial_string = tostring(session:getVariable("dial_string"));
if (dial_string == "nil") then dial_string = ""; end
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--get the unique_id
min_digits = 1;
max_digits = 15;
unique_id = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:voicemail_enter_id:#", "", "\\d+");
--add the unique_id value to the dial_string
if (string.len(dial_string) > 0) then
dial_string = string.gsub(dial_string, '{v_unique_id}', unique_id);
end
--authenticate the user
if (pin_number) then
--get the pin number from the caller
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
caller_pin_number = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:voicemail_enter_pass:#", "", "\\d+");
else
--get the vm_password
min_digits = 1;
max_digits = 12;
vm_password = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:voicemail_enter_pass:#", "", "\\d+");
if (debug["sql"]) then
freeswitch.consoleLog("NOTICE", "unique_id ".. unique_id .. " vm_password " .. vm_password .. "\n");
end
end
--get the dial_string, and extension_uuid
sql = "SELECT * FROM v_extensions as e, v_domains as d ";
sql = sql .. "WHERE e.domain_uuid = d.domain_uuid ";
if (extension == "true") then
sql = sql .. "AND e.extension = '" .. unique_id .."' ";
sql = sql .. "AND e.domain_uuid = '" .. domain_uuid .."' ";
else
sql = sql .. "AND e.unique_id = '" .. unique_id .."' ";
end
if (pin_number) then
--do nothing
else
sql = sql .. "AND e.vm_password = '" .. vm_password .."' ";
end
if (debug["sql"]) then
freeswitch.consoleLog("NOTICE", "sql: ".. sql .. "\n");
end
dbh:query(sql, function(row)
db_domain_uuid = row.domain_uuid;
db_extension_uuid = row.extension_uuid;
db_dial_string = row.dial_string;
db_dial_user = row.dial_user;
db_dial_domain = row.dial_domain;
end);
--check to see if the pin number is correct
if (pin_number) then
if (pin_number ~= caller_pin_number) then
--access denied
db_extension_uuid = "";
end
end
if (string.len(db_extension_uuid) > 0) then
--add the dial string
if (direction == "in") then
if (string.len(dial_string) == 0) then
dial_string = [[{sip_invite_domain=]] .. sip_from_host .. [[,presence_id=]] .. sip_from_user .. [[@]] .. sip_from_host .. [[}${sofia_contact(]] .. sip_from_user .. [[@]] .. sip_from_host .. [[)}]];
end
sql = "UPDATE v_extensions SET ";
sql = sql .. "dial_string = '" .. dial_string .."', ";
sql = sql .. "dial_user = '" .. sip_from_user .."', ";
sql = sql .. "dial_domain = '" .. sip_from_host .."' ";
sql = sql .. "WHERE extension_uuid = '" .. db_extension_uuid .."' ";
if (debug["sql"]) then
freeswitch.consoleLog("NOTICE", "[dial_string] sql: ".. sql .. "\n");
end
dbh:query(sql);
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-saved.wav");
end
--remove the dialstring
if (direction == "out") then
--if the the dial_string has a value then clear the dial string
sql = "UPDATE v_extensions SET ";
sql = sql .. "dial_string = null, ";
sql = sql .. "dial_user = null, ";
sql = sql .. "dial_domain = null ";
sql = sql .. "WHERE extension_uuid = '" .. db_extension_uuid .."' ";
if (debug["sql"]) then
freeswitch.consoleLog("NOTICE", "[dial_string] sql: ".. sql .. "\n");
end
dbh:query(sql);
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-deleted.wav");
end
--toggle the dial string
if (direction == "both") then
if (string.len(db_dial_string) > 1) then
--if the the dial_string has a value then clear the dial string
sql = "UPDATE v_extensions SET ";
sql = sql .. "dial_string = null, ";
sql = sql .. "dial_user = null, ";
sql = sql .. "dial_domain = null ";
sql = sql .. "WHERE extension_uuid = '" .. db_extension_uuid .."' ";
if (debug["sql"]) then
freeswitch.consoleLog("NOTICE", "[dial_string] sql: ".. sql .. "\n");
end
dbh:query(sql);
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-deleted.wav");
else
--if the dial string is empty then set the dial string
if (string.len(dial_string) == 0) then
dial_string = [[{sip_invite_domain=]] .. sip_from_host .. [[,presence_id=]] .. sip_from_user .. [[@]] .. sip_from_host .. [[}${sofia_contact(]] .. sip_from_user .. [[@]] .. sip_from_host .. [[)}]];
end
sql = "UPDATE v_extensions SET ";
sql = sql .. "dial_string = '" .. dial_string .."', ";
sql = sql .. "dial_user = '" .. sip_from_user .."', ";
sql = sql .. "dial_domain = '" .. sip_from_host .."' ";
sql = sql .. "WHERE extension_uuid = '" .. db_extension_uuid .."' ";
if (debug["sql"]) then
freeswitch.consoleLog("NOTICE", "[dial_string] sql: ".. sql .. "\n");
end
dbh:query(sql);
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-saved.wav");
end
end
else
session:streamFile("phrase:voicemail_fail_auth:#");
session:hangup("NORMAL_CLEARING");
return;
end
--log to the console
if (debug["var"]) then
freeswitch.consoleLog("NOTICE", "sip_from_host: ".. sip_from_host .. "\n");
freeswitch.consoleLog("NOTICE", "extension_uuid: ".. extension_uuid .. "\n");
freeswitch.consoleLog("NOTICE", "dial_string: ".. dial_string .. "\n");
end
--show call variables
--session:execute("info", "");
end
-330
View File
@@ -1,330 +0,0 @@
-- directory.lua
-- Part of FusionPBX
-- Copyright (C) 2012 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set the defaults
digit_max_length = 3;
timeout_pin = 5000;
timeout_transfer = 5000;
max_tries = 3;
digit_timeout = 5000;
search_limit = 3;
search_count = 0;
--debug
debug["info"] = false;
debug["sql"] = false;
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--prepare the api object
api = freeswitch.API();
--get the session variables
if ( session:ready() ) then
--answer the session
session:answer();
--give time for the call to be ready
session:streamFile("silence_stream://1000");
--get the domain info
domain_name = session:getVariable("domain_name");
domain_uuid = session:getVariable("domain_uuid");
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--set the sounds path for the language, dialect and voice
ringback = session:getVariable("ringback");
if (ringback) then
ringback = ringback:gsub("$", "");
ringback = ringback:gsub("{", "");
ringback = ringback:gsub("}", "");
end
session:setVariable("instant_ringback", "true");
session:setVariable("ignore_early_media", "true");
if (not ringback) then
session:execute("set", "ringback=local_stream://default"); --set to ringtone
session:execute("set", "transfer_ringback=local_stream://default"); --set to ringtone
elseif (ringback == "uk-ring") then
session:setVariable("ringback", "%(400,200,400,450);%(400,2200,400,450)");
session:setVariable("transfer_ringback", "%(400,200,400,450);%(400,2200,400,450)");
elseif (ringback == "us-ring") then
session:setVariable("ringback", "%(2000, 4000, 440.0, 480.0)");
session:setVariable("transfer_ringback", "%(2000, 4000, 440.0, 480.0)");
elseif (ringback == "fr-ring") then
session:setVariable("ringback", "%(1500, 3500, 440.0, 0.0)");
session:setVariable("transfer_ringback", "%(1500, 3500, 440.0, 0.0)");
elseif (ringback == "rs-ring") then
session:setVariable("ringback", "%(1000, 4000, 425.0, 0.0)");
session:setVariable("transfer_ringback", "%(1000, 4000, 425.0, 0.0)");
else
session:execute("set", "ringback=local_stream://default"); --set to ringtone
session:execute("set", "transfer_ringback=local_stream://default"); --set to ringtone
end
--define the sounds directory
sounds_dir = session:getVariable("sounds_dir");
sounds_dir = sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice;
end
--get session variables
base_dir = session:getVariable("base_dir");
--set the voicemail_dir
voicemail_dir = base_dir.."/storage/voicemail/default/"..domain_name;
if (debug["info"]) then
freeswitch.consoleLog("notice", "[directory] voicemail_dir: " .. voicemail_dir .. "\n");
end
--get the domain_uuid
if (domain_uuid == nil) then
if (domain_name ~= nil) then
sql = "SELECT domain_uuid FROM v_domains ";
sql = sql .. "WHERE domain_name = '" .. domain_name .."' ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[conference] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(rows)
domain_uuid = string.lower(rows["domain_uuid"]);
end);
end
end
--define explode
function explode ( seperator, str )
local pos, arr = 0, {}
for st, sp in function() return string.find( str, seperator, pos, true ) end do -- for each divider found
table.insert( arr, string.sub( str, pos, st-1 ) ) -- attach chars left of current divider
pos = sp + 1 -- jump past current divider
end
table.insert( arr, string.sub( str, pos ) ) -- attach chars right of last divider
return arr
end
--define a function to convert dialpad letters to numbers
function dialpad_to_digit(letter)
letter = string.lower(letter);
if (letter == "a" or letter == "b" or letter == "c") then
digit = "2";
elseif (letter == "d" or letter == "e" or letter == "f") then
digit = "3";
elseif (letter == "g" or letter == "h" or letter == "i") then
digit = "4";
elseif (letter == "j" or letter == "k" or letter == "l") then
digit = "5";
elseif (letter == "m" or letter == "n" or letter == "o") then
digit = "6";
elseif (letter == "p" or letter == "q" or letter == "r" or letter == "s") then
digit = "7";
elseif (letter == "t" or letter == "u" or letter == "v") then
digit = "8";
elseif (letter == "w" or letter == "x" or letter == "y" or letter == "z") then
digit = "9";
end
return digit;
end
--print(dialpad_to_digit("m"));
--define table_count
function table_count(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
--define trim
function trim (s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
--check if a file exists
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
--define select_entry function
function select_entry()
dtmf_digits = "";
digit_timeout = "500";
max_digits = 1;
max_tries = 1;
dtmf_digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/directory/dir-to_select_entry.wav", "", "\\d+");
if (string.len(dtmf_digits) == 0) then
dtmf_digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/voicemail/vm-press.wav", "", "\\d+");
end
if (string.len(dtmf_digits) == 0) then
digit_timeout = "3000";
dtmf_digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/digits/1.wav", "", "\\d+");
end
return dtmf_digits;
end
--define prompt_for_name function
function prompt_for_name()
dtmf_digits = "";
min_digits=0; max_digits=3; max_tries=3; digit_timeout = "5000";
dtmf_digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/directory/dir-enter_person_first_or_last.wav", "", "\\d+");
return dtmf_digits;
end
--define the directory_search function
function directory_search()
--get the digits for the name
dtmf_digits = prompt_for_name();
--show the dtmf digits
freeswitch.consoleLog("notice", "[directory] first 3 letters of first or last name: " .. dtmf_digits .. "\n");
--loop through the extensions to find matches
search_dtmf_digits = dtmf_digits;
found = false;
for key,row in pairs(directory) do
--if (row.first_name and row.last_name) then
-- freeswitch.consoleLog("notice", "[directory] ext: " .. row.extension .. " context " .. row.context .. " name " .. row.first_name .. " "..row.first_name_digits.." ".. row.last_name .. " "..row.last_name_digits.." "..row.directory_exten_visible.."\n");
--else
-- freeswitch.consoleLog("notice", "[directory] ext: " .. row.extension .. " context " .. row.context .. "\n");
--end
if (search_dtmf_digits == row.last_name_digits) or (search_dtmf_digits == row.first_name_digits) then
if (row.first_name and row.last_name) then
if (debug["info"]) then
freeswitch.consoleLog("notice", "[directory] path: "..voicemail_dir.."/"..row.extension.."/recorded_name.wav\n");
end
if (file_exists(voicemail_dir.."/"..row.extension.."/recorded_name.wav")) then
session:streamFile(voicemail_dir.."/"..row.extension.."/recorded_name.wav");
else
--announce the first and last names
session:execute("say", "en name_spelled iterated "..row.first_name);
--session:execute("sleep", "500");
session:execute("say", "en name_spelled iterated "..row.last_name);
end
--announce the extension number
if (row.directory_exten_visible == "false") then
--invisible extension number
else
session:streamFile(sounds_dir.."/directory/dir-at_extension.wav");
session:execute("say", "en number iterated "..row.extension);
end
--select this entry press 1
dtmf_digits = select_entry();
--if 1 is pressed then transfer the call
if (dtmf_digits == "1") then
session:execute("transfer", row.extension.." XML "..row.context);
end
end
found = true;
end
end
if (found ~= true) then
session:streamFile(sounds_dir.."/directory/dir-no_matching_results.wav");
end
search_count = search_count + 1;
if (search_count < search_limit) then
directory_search();
end
end
--get the extensions from the database
sql = "SELECT * FROM v_extensions WHERE domain_uuid = '" .. domain_uuid .. "' AND enabled = 'true' AND (directory_visible is null or directory_visible = 'true'); ";
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[directory] SQL: " .. sql .. "\n");
end
x = 1;
directory = {}
dbh:query(sql, function(row)
--show all key value pairs
--for key, val in pairs(row) do
-- freeswitch.consoleLog("notice", "[directory] Key: " .. key .. " Value: " .. val .. "\n");
--end
--add the entire row to the directory table array
--directory[x] = row;
--variables
effective_caller_id_name = row.effective_caller_id_name;
if (row.directory_full_name) then
name = row.directory_full_name;
else
if (row.directory_full_name) then
name = row.effective_caller_id_name;
end
end
if (name) then
name_table = explode(" ",name);
first_name = name_table[1];
last_name = name_table[2];
if (first_name) then
if (string.len(first_name) > 0) then
--freeswitch.consoleLog("notice", "[directory] first_name: --" .. first_name .. "--\n");
first_name_digits = dialpad_to_digit(string.sub(first_name, 1, 1))..dialpad_to_digit(string.sub(first_name, 2, 2))..dialpad_to_digit(string.sub(first_name, 3, 3));
end
end
if (last_name) then
if (string.len(last_name) > 0) then
--freeswitch.consoleLog("notice", "[directory] last_name: --" .. last_name .. "--\n");
last_name_digits = dialpad_to_digit(string.sub(last_name, 1, 1))..dialpad_to_digit(string.sub(last_name, 2, 2))..dialpad_to_digit(string.sub(last_name, 3, 3));
end
end
end
--add the row to the array
table.insert(directory, {extension=row.extension,context=row.user_context,first_name=name_table[1],last_name=name_table[2],first_name_digits=first_name_digits,last_name_digits=last_name_digits,directory_exten_visible=row.directory_exten_visible});
--increment x
x = x + 1;
end);
--call the directory search function
if (session:ready()) then
directory_search();
end
--notes
--session:execute("say", "en name_spelled pronounced mark");
--<action application="say" data="en name_spelled iterated ${destination_number}"/>
--session:execute("say", "en number iterated 12345");
--session:execute("say", "en number pronounced 1001");
--session:execute("say", "en short_date_time pronounced [timestamp]");
--session:execute("say", "en CURRENT_TIME pronounced CURRENT_TIME");
--session:execute("say", "en CURRENT_DATE pronounced CURRENT_DATE");
--session:execute("say", "en CURRENT_DATE_TIME pronounced CURRENT_DATE_TIME");
-155
View File
@@ -1,155 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
predefined_destination = "";
max_tries = "3";
digit_timeout = "5000";
function trim (s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
function explode ( seperator, str )
local pos, arr = 0, {}
for st, sp in function() return string.find( str, seperator, pos, true ) end do -- for each divider found
table.insert( arr, string.sub( str, pos, st-1 ) ) -- attach chars left of current divider
pos = sp + 1 -- jump past current divider
end
table.insert( arr, string.sub( str, pos ) ) -- attach chars right of last divider
return arr
end
if ( session:ready() ) then
session:answer( );
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
caller_id_name = session:getVariable("caller_id_name");
caller_id_number = session:getVariable("caller_id_number");
predefined_destination = session:getVariable("predefined_destination");
digit_min_length = session:getVariable("digit_min_length");
digit_max_length = session:getVariable("digit_max_length");
gateway = session:getVariable("gateway");
context = session:getVariable("context");
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--set defaults
if (digit_min_length) then
--do nothing
else
digit_min_length = "2";
end
if (digit_max_length) then
--do nothing
else
digit_max_length = "11";
end
--if the pin number is provided then require it
if (pin_number) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-please_enter_pin_followed_by_pound.wav", "", "\\d+");
if (digits == pin_number) then
--pin is correct
else
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-pin_or_extension_is-invalid.wav");
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-im_sorry.wav");
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-goodbye.wav");
session:hangup("NORMAL_CLEARING");
return;
end
end
--if a predefined_destination is provided then set the number to the predefined_destination
if (predefined_destination) then
destination_number = predefined_destination;
else
dtmf = ""; --clear dtmf digits to prepare for next dtmf request
destination_number = session:playAndGetDigits(digit_min_length, digit_max_length, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-enter_destination_telephone_number.wav", "", "\\d+");
--if (string.len(destination_number) == 10) then destination_number = "1"..destination_number; end
end
--set the caller id anme and number
if (string.len(destination_number) < 7) then
if (caller_id_name) then
--caller id name provided do nothing
else
caller_id_number = session:getVariable("effective_caller_id_name");
end
if (caller_id_number) then
--caller id number provided do nothing
else
caller_id_number = session:getVariable("effective_caller_id_number");
end
else
if (caller_id_name) then
--caller id name provided do nothing
else
caller_id_number = session:getVariable("outbound_caller_id_name");
end
if (caller_id_number) then
--caller id number provided do nothing
else
caller_id_number = session:getVariable("outbound_caller_id_number");
end
end
--transfer or bridge the call
if (string.len(destination_number) < 7) then
--local call
session:execute("transfer", destination_number .. " XML " .. context);
else
--remote call
if (gateway) then
gateway_table = explode(",",gateway);
for index,value in pairs(gateway_table) do
session:execute("bridge", "{continue_on_fail=true,hangup_after_bridge=true,origination_caller_id_name="..caller_id_name..",origination_caller_id_number="..caller_id_number.."}sofia/gateway/"..value.."/"..destination_number);
end
else
session:execute("set", "effective_caller_id_name="..caller_id_name);
session:execute("set", "effective_caller_id_number="..caller_id_number);
session:execute("transfer", destination_number .. " XML " .. context);
end
end
--alternate method
--local session2 = freeswitch.Session("{ignore_early_media=true}sofia/gateway/flowroute.com/"..destination_number);
--t1 = os.date('*t');
--call_start_time = os.time(t1);
--freeswitch.bridge(session, session2);
end
--function HangupHook(s, status, arg)
--session:execute("info", "");
--freeswitch.consoleLog("NOTICE", "HangupHook: " .. status .. "\n");
--end
--session:setHangupHook("HangupHook", "");
-113
View File
@@ -1,113 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
max_tries = "3";
digit_timeout = "5000";
extension = argv[1];
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--add the file_exists function
dofile(scripts_dir.."/resources/functions/file_exists.lua");
--connect to the database
if (file_exists(database_dir.."/core.db")) then
--dbh = freeswitch.Dbh("core:core"); -- when using sqlite
dbh = freeswitch.Dbh("sqlite://"..database_dir.."/core.db");
else
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('switch');
end
--exits the script if we didn't connect properly
assert(dbh:connected());
if ( session:ready() ) then
session:answer( );
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
domain_name = session:getVariable("domain_name");
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--set defaults
if (digit_min_length) then
--do nothing
else
digit_min_length = "2";
end
if (digit_max_length) then
--do nothing
else
digit_max_length = "11";
end
--if the pin number is provided then require it
if (pin_number) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_pin_number.wav", "", "\\d+");
if (digits == pin_number) then
--pin is correct
else
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/your_pin_number_is_incorect_goodbye.wav");
session:hangup("NORMAL_CLEARING");
return;
end
end
--check the database to get the uuid
--eavesdrop
sql = "select uuid from channels where presence_id = '"..extension.."@"..domain_name.."' ";
dbh:query(sql, function(result)
for key, val in pairs(result) do
freeswitch.consoleLog("NOTICE", "result "..key.." "..val.."\n");
end
uuid = result.uuid;
end);
end
--eavesdrop
if (uuid) then
session:execute("eavesdrop", uuid); --call barge
end
--notes
--originate a call
--cmd = "originate user/1007@voip.example.com &eavesdrop("..uuid..")";
--cmd = "uuid_bridge "..caller_uuid.." "..uuid;
--api = freeswitch.API();
--result = api:executeString(cmd);
-88
View File
@@ -1,88 +0,0 @@
-- email.lua
-- Part of FusionPBX
-- Copyright (C) 2010 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--Description:
--purpose: send an email
--freeswitch.email(to, from, headers, body, file, convert_cmd, convert_ext)
--to (mandatory) a valid email address
--from (mandatory) a valid email address
--headers (mandatory) for example "subject: you've got mail!\n"
--body (optional) your regular mail body
--file (optional) a file to attach to your mail
--convert_cmd (optional) convert file to a different format before sending
--convert_ext (optional) to replace the file's extension
--Example
--luarun email.lua to@domain.com from@domain.com 'subject' 'body'
--get the argv values
script_name = argv[0];
to = argv[1];
from = argv[2];
subject = argv[3];
body = argv[4];
file = argv[5];
delete = argv[6];
--convert_cmd = argv[7];
--convert_ext = argv[8];
--replace the &#39 with a single quote
body = body:gsub("&#39;", "'");
--replace the &#34 with double quote
body = body:gsub("&#34;", [["]]);
--send the email
if (file == nil) then
freeswitch.email("",
"",
"To: "..to.."\nFrom: "..from.."\nSubject: "..subject,
body
);
else
if (convert_cmd == nil) then
freeswitch.email("",
"",
"To: "..to.."\nFrom: "..from.."\nSubject: "..subject,
body,
file
);
else
freeswitch.email("",
"",
"To: "..to.."\nFrom: "..from.."\nSubject: "..subject,
body,
file,
convert_cmd,
convert_ext
);
end
end
--delete the file
if (delete == "true") then
os.remove(file);
end
-186
View File
@@ -1,186 +0,0 @@
--contribtors: Mark J. Crane, James O. Rose
--set default variables
fax_retry_sleep = 30;
fax_retry_limit = 4;
fax_busy_limit = 3;
api = freeswitch.API();
-- show all channel variables
--dat = env:serialize()
--freeswitch.consoleLog("INFO","info:\n" .. dat .. "\n")
-- example channel variables relating to fax
--variable_fax_success: 0
--variable_fax_result_code: 49
--variable_fax_result_text: The%20call%20dropped%20prematurely
--variable_fax_ecm_used: off
--variable_fax_local_station_id: SpanDSP%20Fax%20Ident
--variable_fax_document_transferred_pages: 0
--variable_fax_document_total_pages: 0
--variable_fax_image_resolution: 0x0
--variable_fax_image_size: 0
--variable_fax_bad_rows: 0
--variable_fax_transfer_rate: 14400
-- set channel variables to lua variables
uuid = env:getHeader("uuid");
fax_success = env:getHeader("fax_success");
fax_result_text = env:getHeader("fax_result_text");
fax_ecm_used = env:getHeader("fax_ecm_used");
fax_retry_attempts = tonumber(env:getHeader("fax_retry_attempts"));
fax_retry_limit = tonumber(env:getHeader("fax_retry_limit"));
--fax_retry_sleep = tonumber(env:getHeader("fax_retry_sleep"));
fax_uri = env:getHeader("fax_uri");
fax_file = env:getHeader("fax_file");
fax_extension_number = env:getHeader("fax_extension_number");
origination_caller_id_name = env:getHeader("origination_caller_id_name");
origination_caller_id_number = env:getHeader("origination_caller_id_number");
bridge_hangup_cause = env:getHeader("bridge_hangup_cause");
fax_result_code = env:getHeader("fax_result_code");
fax_busy_attempts = tonumber(env:getHeader("fax_busy_attempts"));
--set default values
if (not origination_caller_id_name) then
origination_caller_id_name = '000000000000000';
end
if (not origination_caller_id_number) then
origination_caller_id_number = '000000000000000';
end
if (not fax_busy_attempts) then
fax_busy_attempts = 0;
end
--for email
email_address = env:getHeader("mailto_address");
--email_address = api:execute("system", "/bin/echo -n "..email_address.." | /bin/sed -e s/\,/\\\\,/g");
email_address = email_address:gsub(",", "\\,");
from_address = env:getHeader("mailfrom_address");
--needs to be fixed on lesser operating systems that do not have GNU utils.
number_dialed = api:execute("system", "/bin/echo -n "..fax_uri.." | sed -e s,.*/,,g");
--do not use apostrophies in message, they are not excaped and the mail will fail.
email_message_fail = "We are sorry the fax failed to go through. It has been attached. Please check the number "..number_dialed..", and if it was correct you might consider emailing it instead."
email_message_success = "We are happy to report the fax was sent successfully. It has been attached for your records."
-- send the selected variables to the console
freeswitch.consoleLog("INFO","fax_success: '" .. fax_success .. "'\n");
freeswitch.consoleLog("INFO","fax_result_text: '" .. fax_result_text .. "'\n");
freeswitch.consoleLog("INFO","fax_file: '" .. fax_file .. "'\n");
freeswitch.consoleLog("INFO","uuid: '" .. uuid .. "'\n");
freeswitch.consoleLog("INFO","fax_ecm_used: '" .. fax_ecm_used .. "'\n");
freeswitch.consoleLog("INFO","fax_retry_attempts: " .. fax_retry_attempts.. "\n");
freeswitch.consoleLog("INFO","fax_retry_limit: " .. fax_retry_limit.. "\n");
freeswitch.consoleLog("INFO","fax_retry_sleep: " .. fax_retry_sleep.. "\n");
freeswitch.consoleLog("INFO","fax_uri: '" .. fax_uri.. "'\n");
freeswitch.consoleLog("INFO","origination_caller_id_name: " .. origination_caller_id_name .. "\n");
freeswitch.consoleLog("INFO","origination_caller_id_number: " .. origination_caller_id_number .. "\n");
freeswitch.consoleLog("INFO","fax_result_code: ".. fax_result_code .."\n");
freeswitch.consoleLog("INFO","mailfrom_address: ".. from_address .."\n");
freeswitch.consoleLog("INFO","mailto_address: ".. email_address .."\n");
-- if the fax failed then try again
if (fax_success == "0") then
--DEBUG
--email_cmd = "/bin/echo '"..email_message_fail.."' | /usr/bin/mail -s 'Fax to: "..number_dialed.." FAILED' -r "..from_address.." -a "..fax_file.." "..email_address;
--to keep the originate command shorter these are things we always send. One place to adjust for all.
originate_same = "mailto_address='"..email_address.."',mailfrom_address='"..from_address.."',origination_caller_id_name='"..origination_caller_id_name.. "',origination_caller_id_number="..origination_caller_id_number..",fax_uri="..fax_uri..",fax_retry_limit="..fax_retry_limit..",fax_retry_sleep="..fax_retry_sleep..",fax_verbose=true,fax_file='"..fax_file.."'";
if (fax_retry_attempts < fax_retry_limit) then
--timed out waitng for comm or on first message (busy code?)
if (fax_result_code == "2" or fax_result_code == "3" ) then
--do nothing. don't want to increment
freeswitch.consoleLog("INFO","Last Fax was probably Busy, don't increment retry_attempts. \n");
fax_busy_attempts = fax_busy_attempts + 1;
freeswitch.msleep(fax_retry_sleep * 1000);
elseif (fax_retry_attempts < 5 ) then
freeswitch.consoleLog("INFO","Last Fax Failed, try a different way. Wait first.\n");
freeswitch.msleep(fax_retry_sleep * 500);
else
freeswitch.consoleLog("INFO","All attempts to send fax to "..number_dialed.."FAILED\n");
end
if (fax_retry_attempts == 1) then
--send t38 on ECM on
freeswitch.consoleLog("INFO","FAX TRYING ["..fax_retry_attempts.."] of [4] to: "..number_dialed.." with: t38 ON ECM ON, Fast\n");
fax_retry_attempts = fax_retry_attempts + 1;
cmd = "originate {fax_retry_attempts="..fax_retry_attempts..","..originate_same..",fax_use_ecm=true,fax_enable_t38=true,fax_enable_t38_request=true,fax_disable_v17=false,fax_busy_attempts='"..fax_busy_attempts.."',api_hangup_hook='lua fax_retry.lua'}"..fax_uri.." &txfax('"..fax_file.."')";
elseif (fax_retry_attempts == 2) then
--send t38 off, ECM on
freeswitch.consoleLog("INFO","FAX TRYING ["..fax_retry_attempts.."] of [4] to: "..number_dialed.." with: t38 OFF ECM ON, Fast\n");
fax_retry_attempts = fax_retry_attempts + 1;
cmd = "originate {fax_retry_attempts="..fax_retry_attempts..","..originate_same..",fax_use_ecm=true,fax_enable_t38=false,fax_enable_t38_request=false,fax_disable_v17=false,fax_busy_attempts='"..fax_busy_attempts.."',api_hangup_hook='lua fax_retry.lua'}"..fax_uri.." &txfax('"..fax_file.."')";
elseif (fax_retry_attempts == 3) then
--send t38 on v17 [slow] on ECM off
freeswitch.consoleLog("INFO","FAX TRYING ["..fax_retry_attempts.."] of [4] to: "..number_dialed.." with: t38 ON ECM OFF, SLOW\n");
fax_retry_attempts = fax_retry_attempts + 1;
cmd = "originate {fax_retry_attempts="..fax_retry_attempts..","..originate_same..",fax_use_ecm=false,fax_enable_t38=true,fax_enable_t38_request=true,fax_disable_v17=true,fax_busy_attempts='"..fax_busy_attempts.."',api_hangup_hook='lua fax_retry.lua'}"..fax_uri.." &txfax('"..fax_file.."')";
elseif (fax_retry_attempts == 4) then
--send t38 off v17 [slow] on ECM off
freeswitch.consoleLog("INFO","FAX TRYING ["..fax_retry_attempts.."] of [4] to: "..number_dialed.." with: t38 OFF ECM OFF, SLOW\n");
fax_retry_attempts = fax_retry_attempts + 1;
cmd = "originate {fax_retry_attempts="..fax_retry_attempts..","..originate_same..",fax_use_ecm=false,fax_enable_t38=false,fax_enable_t38_request=false,fax_disable_v17=true,fax_busy_attempts='"..fax_busy_attempts.."',api_hangup_hook='lua fax_retry.lua'}"..fax_uri.." &txfax('"..fax_file.."')";
else
--the fax failed completely. send a message
freeswitch.consoleLog("INFO","FAX_RETRY FAILED: TRIED ["..fax_retry_attempts.."] of [4]: GIVING UP\n");
freeswitch.consoleLog("INFO", "FAX_RETRY_STATS FAILURE: GATEWAY[".. fax_uri .."], tried 5 combinations without success\n");
email_address = email_address:gsub("\\,", ",");
freeswitch.email("",
"",
"To: "..email_address.."\nFrom: "..from_address.."\nSubject: Fax to: "..number_dialed.." FAILED",
email_message_fail ,
fax_file
);
fax_retry_attempts = fax_retry_attempts + 1;
end
api = freeswitch.API();
if ( not cmd ) then
freeswitch.consoleLog("INFO","Last Fallthrough (5th) of FAX_RETRY.lua: \n");
else
freeswitch.consoleLog("INFO","retry cmd: " .. cmd .. "\n");
reply = api:executeString(cmd);
end
end
else
--Huzah! Success!
if (fax_retry_attempts == 0) then
fax_trial = "fax_use_ecm=false,fax_enable_t38=true,fax_enable_t38_request=true,fax_disable_v17=default";
elseif (fax_retry_attempts == 1) then
fax_trial = "fax_use_ecm=true,fax_enable_t38=true,fax_enable_t38_request=true,fax_disable_v17=false";
elseif (fax_retry_attempts == 2) then
fax_trial = "fax_use_ecm=true,fax_enable_t38=false,fax_enable_t38_request=false,fax_disable_v17=false";
elseif (fax_retry_attempts == 3) then
fax_trial = "fax_use_ecm=true,fax_enable_t38=true,fax_enable_t38_request=true,fax_disable_v17=true";
elseif (fax_retry_attempts == 4) then
fax_trial = "fax_use_ecm=false,fax_enable_t38=false,fax_enable_t38_request=false,fax_disable_v17=false";
else
fax_trial = "fax_retry had an issue and tried more than 5 times"
end
freeswitch.consoleLog("INFO", "FAX_RETRY_STATS SUCCESS: GATEWAY[".. fax_uri .."] VARS[" .. fax_trial .. "]\n");
email_address = email_address:gsub("\\,", ",");
freeswitch.email("",
"",
"To: "..email_address.."\nFrom: "..from_address.."\nSubject: Fax to: "..number_dialed.." SENT",
email_message_success ,
fax_file
);
end
-99
View File
@@ -1,99 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
sounds_dir = "";
recordings_dir = "";
pin_number = "";
max_tries = "3";
digit_timeout = "3000";
if ( session:ready() ) then
session:answer();
--session:execute("info", "");
user_name = session:getVariable("user_name");
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
queue_name = session:getVariable("queue_name");
fifo_simo = session:getVariable("fifo_simo");
fifo_timeout = session:getVariable("fifo_timeout");
fifo_lag = session:getVariable("fifo_lag");
--pin_number = "1234"; --for testing
--queue_name = "5900@voip.fusionpbx.com";
--fifo_simo = 1;
--fifo_timeout = 10;
--fifo_lag = 10;
if (pin_number) then
digits = session:playAndGetDigits(3, 8, 3, digit_timeout, "#", sounds_dir.."/custom/please_enter_the_pin_number.wav", "", "\\d+");
if (digits == pin_number) then
--pin is correct
--press 1 to login and 2 to logout
menu_selection = session:playAndGetDigits(1, 1, max_tries, digit_timeout, "#", sounds_dir.."/custom/please_enter_the_phone_number.wav", "", "\\d+");
freeswitch.consoleLog("NOTICE", "menu_selection: "..menu_selection.."\n");
if (menu_selection == "1") then
session:execute("set", "fifo_member_add_result=${fifo_member(add "..queue_name.." {fifo_member_wait=nowait}user/"..user_name.." "..fifo_simo.." "..fifo_timeout.." "..fifo_lag.."} )"); --simo timeout lag
fifo_member_add_result = session:getVariable("fifo_member_add_result");
freeswitch.consoleLog("NOTICE", "fifo_member_add_result: "..fifo_member_add_result.."\n");
session:streamFile("ivr/ivr-you_are_now_logged_in.wav");
end
if (menu_selection == "2") then
session:execute("set", "fifo_member_del_result=${fifo_member(del "..queue_name.." {fifo_member_wait=nowait}user/"..user_name.."} )");
session:streamFile("ivr/ivr-you_are_now_logged_out.wav");
end
--wait for the file to be written before proceeding
-- session:sleep(1000);
session:hangup();
else
session:streamFile(sounds_dir.."/custom/your_pin_number_is_incorect_goodbye.wav");
end
else
--pin number is not required
--press 1 to login and 2 to logout
menu_selection = session:playAndGetDigits(1, 1, max_tries, digit_timeout, "#", sounds_dir.."/custom/please_enter_the_phone_number.wav", "", "\\d+");
freeswitch.consoleLog("NOTICE", "menu_selection: "..menu_selection.."\n");
if (menu_selection == "1") then
session:execute("set", "fifo_member_add_result=${fifo_member(add "..queue_name.." {fifo_member_wait=nowait}user/"..user_name.." "..fifo_simo.." "..fifo_timeout.." "..fifo_lag.."} )"); --simo timeout lag
fifo_member_add_result = session:getVariable("fifo_member_add_result");
freeswitch.consoleLog("NOTICE", "fifo_member_add_result: "..fifo_member_add_result.."\n");
session:streamFile("ivr/ivr-you_are_now_logged_in.wav");
end
if (menu_selection == "2") then
session:execute("set", "fifo_member_del_result=${fifo_member(del "..queue_name.." {fifo_member_wait=nowait}user/"..user_name.."} )");
session:streamFile("ivr/ivr-you_are_now_logged_out.wav");
end
--wait for the file to be written before proceeding
-- session:sleep(1000);
session:hangup();
end
end
@@ -1,108 +0,0 @@
--get the argv values
domain_name = argv[1];
uuid = argv[2];
sipuri = argv[3];
extension = argv[4];
caller_id_name = argv[5];
caller_id_number = argv[6];
caller_announce = argv[7];
--variable preparation
tmp_sipuri = '';
caller_id_name = string.gsub(caller_id_name, "+", " ");
function explode ( seperator, str )
local pos, arr = 0, {}
for st, sp in function() return string.find( str, seperator, pos, true ) end do -- for each divider found
table.insert( arr, string.sub( str, pos, st-1 ) ) -- attach chars left of current divider
pos = sp + 1 -- jump past current divider
end
table.insert( arr, string.sub( str, pos ) ) -- attach chars right of last divider
return arr
end
function originate (domain_name, session, sipuri, extension, caller_announce, caller_id_name, caller_id_number)
cid = ",origination_caller_id_name="..caller_id_name..",origination_caller_id_number="..caller_id_number;
local new_session = freeswitch.Session("{ignore_early_media=true"..cid.."}"..sipuri);
new_session:execute("set", "call_timeout=60");
new_session:execute("sleep", "1000");
--if the session is not ready wait longer
if ( new_session:ready() ) then
--do nothing
else
new_session:execute("sleep", "1000");
end
if ( new_session:ready() ) then
--get the session id
uuid = new_session:getVariable("uuid");
--set the sounds path for the language, dialect and voice
default_language = new_session:getVariable("default_language");
default_dialect = new_session:getVariable("default_dialect");
default_voice = new_session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--caller announce
if (caller_announce) then
new_session:streamFile(caller_announce);
end
--set the sounds directory
sounds_dir = new_session:getVariable("sounds_dir");
--check the fifo status if it is empty hangup the call
api = freeswitch.API();
cmd = "fifo count "..extension.."@"..domain_name;
result = api:executeString(cmd);
--freeswitch.consoleLog("notice", "result " .. result .. "\n");
result_table = explode(":",result);
if (result_table[3] == "0") then
--session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/your_pin_number_is_incorect_goodbye.wav");
new_session:hangup("NORMAL_CLEARING");
return;
end
--prompt user for action
dtmf_digits = new_session:playAndGetDigits(1, 1, 2, 3000, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/8000/press_1_to_accept_2_to_reject_or_3_for_voicemail.wav", "", "\\d+");
freeswitch.consoleLog("NOTICE", "followme: "..dtmf_digits.."\n");
if ( dtmf_digits == "1" ) then
freeswitch.consoleLog("NOTICE", "followme: call accepted\n");
freeswitch.consoleLog("NOTICE", extension.."@"..domain_name.." out nowait\n");
new_session:execute("fifo", extension.."@"..domain_name.." out nowait");
return true;
end
if ( dtmf_digits == "2" ) then
freeswitch.consoleLog("NOTICE", "followme: call rejected\n");
new_session:hangup();
return false;
end
if ( dtmf_digits == "3" ) then
freeswitch.consoleLog("NOTICE", "followme: call sent to voicemail\n");
cmd = "uuid_transfer "..uuid.." *99"..extension;
api = freeswitch.API();
reply = api:executeString(cmd);
return true;
end
if ( dtmf_digits == "" ) then
freeswitch.consoleLog("NOTICE", "followme: no dtmf detected\n");
return false;
end
else
freeswitch.consoleLog("err", "followme: session not ready\n");
end
end
sipuri_table = explode(",",sipuri);
for index,tmp_sip_uri in pairs(sipuri_table) do
freeswitch.consoleLog("NOTICE", "sip_uri: "..tmp_sip_uri.."\n");
result = originate (domain_name, session, tmp_sip_uri, extension, caller_announce, caller_id_name, caller_id_number);
if (result) then
break;
--exit;
end
end
-127
View File
@@ -1,127 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
--user defined variables
max_tries = "3";
digit_timeout = "5000";
extension = argv[1];
--set the debug options
debug["sql"] = false;
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
if (file_exists(database_dir.."/core.db")) then
--dbh = freeswitch.Dbh("core:core"); -- when using sqlite
dbh = freeswitch.Dbh("sqlite://"..database_dir.."/core.db");
else
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('switch');
end
--exits the script if we didn't connect properly
assert(dbh:connected());
if ( session:ready() ) then
--answer the session
session:answer();
--get session variables
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
domain_name = session:getVariable("domain_name");
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--set defaults
if (digit_min_length) then
--do nothing
else
digit_min_length = "2";
end
if (digit_max_length) then
--do nothing
else
digit_max_length = "11";
end
--if the pin number is provided then require it
if (pin_number) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
--digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_pin_number.wav", "", "\\d+");
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:voicemail_enter_pass:#", "", "\\d+");
if (digits == pin_number) then
--pin is correct
else
--session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/your_pin_number_is_incorect_goodbye.wav");
session:streamFile("phrase:voicemail_fail_auth:#");
session:hangup("NORMAL_CLEARING");
return;
end
end
--check the database to get the uuid of a ringing call
sql = "select call_uuid as uuid from channels ";
sql = sql .. "where callstate = 'RINGING' ";
if (extension) then
sql = sql .. "and presence_id = '"..extension.."@"..domain_name.."' ";
else
if (domain_count > 1) then
sql = sql .. "and context = '"..domain_name.."' ";
end
end
if (debug["sql"]) then
freeswitch.consoleLog("NOTICE", "sql "..sql.."\n");
end
dbh:query(sql, function(result)
--for key, val in pairs(result) do
-- freeswitch.consoleLog("NOTICE", "result "..key.." "..val.."\n");
--end
uuid = result.uuid;
end);
end
--intercept a call that is ringing
if (uuid) then
session:execute("intercept", uuid);
end
--notes
--originate a call
--cmd = "originate user/1007@voip.example.com &intercept("..uuid..")";
--api = freeswitch.API();
--result = api:executeString(cmd);
-254
View File
@@ -1,254 +0,0 @@
-- ivr_menu.lua
-- Part of FusionPBX
-- Copyright (C) 2012 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--set the debug options
debug["action"] = false;
debug["sql"] = false;
debug["regex"] = false;
debug["dtmf"] = false;
debug["tries"] = false;
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--get the variables
domain_name = session:getVariable("domain_name");
context = session:getVariable("context");
ivr_menu_uuid = session:getVariable("ivr_menu_uuid");
caller_id_name = session:getVariable("caller_id_name");
caller_id_number = session:getVariable("caller_id_number");
--set default variable(s)
tries = 0;
--add the trim function
function trim(s)
return s:gsub("^%s+", ""):gsub("%s+$", "")
end
--check if a file exists
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
--get the ivr menu from the database
sql = [[SELECT * FROM v_ivr_menus
WHERE ivr_menu_uuid = ']] .. ivr_menu_uuid ..[['
AND ivr_menu_enabled = 'true' ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
ivr_menu_name = row["ivr_menu_name"];
--ivr_menu_extension = row["ivr_menu_extension"];
ivr_menu_greet_long = row["ivr_menu_greet_long"];
ivr_menu_greet_short = row["ivr_menu_greet_short"];
ivr_menu_invalid_sound = row["ivr_menu_invalid_sound"];
ivr_menu_exit_sound = row["ivr_menu_exit_sound"];
ivr_menu_confirm_macro = row["ivr_menu_confirm_macro"];
ivr_menu_confirm_key = row["ivr_menu_confirm_key"];
ivr_menu_tts_engine = row["ivr_menu_tts_engine"];
ivr_menu_tts_voice = row["ivr_menu_tts_voice"];
ivr_menu_confirm_attempts = row["ivr_menu_confirm_attempts"];
ivr_menu_timeout = row["ivr_menu_timeout"];
--ivr_menu_exit_app = row["ivr_menu_exit_app"];
--ivr_menu_exit_data = row["ivr_menu_exit_data"];
ivr_menu_inter_digit_timeout = row["ivr_menu_inter_digit_timeout"];
ivr_menu_max_failures = row["ivr_menu_max_failures"];
ivr_menu_max_timeouts = row["ivr_menu_max_timeouts"];
ivr_menu_digit_len = row["ivr_menu_digit_len"];
ivr_menu_direct_dial = row["ivr_menu_direct_dial"];
--ivr_menu_description = row["ivr_menu_description"];
ivr_menu_ringback = row["ivr_menu_ringback"];
ivr_menu_cid_prefix = row["ivr_menu_cid_prefix"];
end);
--set the caller id name
if (caller_id_name) then
if (string.len(ivr_menu_cid_prefix) > 0) then
caller_id_name = ivr_menu_cid_prefix .. "#" .. caller_id_name;
session:setVariable("caller_id_name", caller_id_name);
session:setVariable("effective_caller_id_name", caller_id_name);
end
end
--get the sounds dir, language, dialect and voice
sounds_dir = session:getVariable("sounds_dir");
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--make the path relative
if (string.sub(ivr_menu_greet_long,0,71) == "$${sounds_dir}/${default_language}/${default_dialect}/${default_voice}/") then
ivr_menu_greet_long = string.sub(ivr_menu_greet_long,72);
end
if (string.sub(ivr_menu_greet_short,0,71) == "$${sounds_dir}/${default_language}/${default_dialect}/${default_voice}/") then
ivr_menu_greet_short = string.sub(ivr_menu_greet_short,72);
end
--adjust the file path
if (ivr_menu_greet_short) then
--do nothing
else
ivr_menu_greet_short = ivr_menu_greet_long;
end
if (not file_exists(ivr_menu_greet_long)) then
if (file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..ivr_menu_greet_long)) then
ivr_menu_greet_long = sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..ivr_menu_greet_long;
end
end
if (not file_exists(ivr_menu_greet_short)) then
if (file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..ivr_menu_greet_short)) then
ivr_menu_greet_short = sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..ivr_menu_greet_short;
end
end
ivr_menu_invalid_entry = sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/ivr/ivr-that_was_an_invalid_entry.wav";
--prepare the api object
api = freeswitch.API();
--define the ivr menu
function menu()
--increment the tries
tries = tries + 1;
dtmf_digits = "";
min_digits = 1;
if (tries == 1) then
freeswitch.consoleLog("notice", "[ivr_menu] greet long: " .. ivr_menu_greet_long .. "\n");
dtmf_digits = session:playAndGetDigits(min_digits, ivr_menu_digit_len, 1, ivr_menu_timeout, ivr_menu_confirm_key, ivr_menu_greet_long, "", ".*");
else
freeswitch.consoleLog("notice", "[ivr_menu] greet long: " .. ivr_menu_greet_short .. "\n");
dtmf_digits = session:playAndGetDigits(min_digits, ivr_menu_digit_len, ivr_menu_max_timeouts, ivr_menu_timeout, ivr_menu_confirm_key, ivr_menu_greet_short, "", ".*");
end
if (string.len(dtmf_digits) > 0) then
freeswitch.consoleLog("notice", "[ivr_menu] dtmf_digits: " .. dtmf_digits .. "\n");
menu_options(session, dtmf_digits);
else
if (tries <= tonumber(ivr_menu_max_failures)) then
--log the dtmf digits
if (debug["tries"]) then
freeswitch.consoleLog("notice", "[ivr_menu] tries: " .. tries .. "\n");
end
--run the menu again
menu();
end
end
end
function menu_options(session, digits)
--log the dtmf digits
if (debug["dtmf"]) then
freeswitch.consoleLog("notice", "[ivr_menu] dtmf: " .. digits .. "\n");
end
--get the ivr menu options
sql = [[SELECT * FROM v_ivr_menu_options WHERE ivr_menu_uuid = ']] .. ivr_menu_uuid ..[[' ORDER BY ivr_menu_option_order asc ]];
if (debug["sql"]) then
freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "\n");
end
status = dbh:query(sql, function(row)
--check for matching options
if (tonumber(row.ivr_menu_option_digits) ~= nil) then
row.ivr_menu_option_digits = "^"..row.ivr_menu_option_digits.."$";
end
if (api:execute("regex", digits.."|"..row.ivr_menu_option_digits) == "true") then
if (row.ivr_menu_option_action == "menu-exec-app") then
--get the action and data
pos = string.find(row.ivr_menu_option_param, " ", 0, true);
action = string.sub( row.ivr_menu_option_param, 0, pos-1);
data = string.sub( row.ivr_menu_option_param, pos+1);
--check if the option uses a regex
regex = string.find(row.ivr_menu_option_digits, "(", 0, true);
if (regex) then
--get the regex result
result = trim(api:execute("regex", digits.."|"..row.ivr_menu_option_digits.."|\$1"));
if (debug["regex"]) then
freeswitch.consoleLog("notice", "[ivr_menu] regex "..digits.."|"..row.ivr_menu_option_digits.."|\$1\n");
freeswitch.consoleLog("notice", "[ivr_menu] result: "..result.."\n");
end
--replace the $1 and the domain name
data = data:gsub("$1", result);
data = data:gsub("${domain_name}", domain_name);
end --if regex
end --if menu-exex-app
end --if regex match
--execute
if (action) then
if (string.len(action) > 0) then
--send to the log
if (debug["action"]) then
freeswitch.consoleLog("notice", "[ivr_menu] action: " .. action .. " data: ".. data .. "\n");
end
--run the action
session:execute(action, data);
end
else
if (ivr_menu_direct_dial == "true") then
if (string.len(digits) < 6) then
--replace the $1 and the domain name
digits = digits:gsub("*", "");
--run the action
session:execute("transfer", digits.." XML "..context);
end
end
end
--clear the variables
action = "";
data = "";
end); --end results
--execute
if (action) then
if (string.len(action) == 0) then
session:streamFile(ivr_menu_invalid_entry);
menu();
end
else
session:streamFile(ivr_menu_invalid_entry);
menu();
end
end --end function
--answer the session
if ( session:ready() ) then
session:answer();
menu();
end
-92
View File
@@ -1,92 +0,0 @@
-- monitor.lua
-- Part of FusionPBX
-- Copyright (C) 2010 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--define general settings
tmp_file = "/usr/local/freeswitch/log/monitor.tmp";
--used to stop the lua service
local file = assert(io.open(tmp_file, "w"));
file:write("remove this file to stop the script");
--add the trim function
function trim(s)
return s:gsub("^%s+", ""):gsub("%s+$", "")
end
--check if a file exists
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
--create the api object
api = freeswitch.API();
--run lua as a service
while true do
--exit the loop when the file does not exist
if (not file_exists(tmp_file)) then
break;
end
--check to see if the sip profile is running
sip_profile = "internal";
result = trim(api:execute("sofia", "status profile "..sip_profile));
if (result == "Invalid Profile!") then
--start the sip profile
result = trim(api:execute("sofia", "profile "..sip_profile.." start"));
freeswitch.consoleLog("NOTICE", "monitor.lua: "..sip_profile.." is not running starting the sip profile.\n");
--run sofia recover
api = freeswitch.API();
result = api:execute("sofia", "recover");
freeswitch.consoleLog("NOTICE", "monitor.lua - sofia recover\n");
end
result = "";
--check to see if the sip profile is running
sip_profile = "external";
result = trim(api:execute("sofia", "status profile "..sip_profile));
if (result == "Invalid Profile!") then
--start the sip profile
result = trim(api:execute("sofia", "profile "..sip_profile.." start"));
freeswitch.consoleLog("NOTICE", "monitor.lua: "..sip_profile.." is not running starting the sip profile.\n");
--run sofia recover
api = freeswitch.API();
result = api:execute("sofia", "recover");
freeswitch.consoleLog("NOTICE", "monitor.lua - sofia recover\n");
end
result = "";
--send a message to the log
--freeswitch.consoleLog("NOTICE", "monitor.lua "..result.."\n");
--slow the loop down
os.execute("sleep 3");
--testing exit immediately
--break;
end
-157
View File
@@ -1,157 +0,0 @@
-- page.lua
-- Part of FusionPBX
-- Copyright (C) 2010 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
pin_number = "";
max_tries = "3";
digit_timeout = "3000";
function trim (s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
function explode ( seperator, str )
local pos, arr = 0, {}
for st, sp in function() return string.find( str, seperator, pos, true ) end do -- for each divider found
table.insert( arr, string.sub( str, pos, st-1 ) ) -- attach chars left of current divider
pos = sp + 1 -- jump past current divider
end
table.insert( arr, string.sub( str, pos ) ) -- attach chars right of last divider
return arr
end
if ( session:ready() ) then
session:answer();
--get the dialplan variables and set them as local variables
destination_number = session:getVariable("destination_number");
pin_number = session:getVariable("pin_number");
domain_name = session:getVariable("domain_name");
sounds_dir = session:getVariable("sounds_dir");
extension_list = session:getVariable("extension_list");
caller_id_name = session:getVariable("caller_id_name");
caller_id_number = session:getVariable("caller_id_number");
extension_table = explode(",",extension_list);
sip_from_user = session:getVariable("sip_from_user");
mute = session:getVariable("mute");
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
if (caller_id_name) then
--caller id name provided do nothing
else
effective_caller_id_name = session:getVariable("effective_caller_id_name");
caller_id_number = effective_caller_id_name;
end
if (caller_id_number) then
--caller id number provided do nothing
else
effective_caller_id_number = session:getVariable("effective_caller_id_number");
caller_id_number = effective_caller_id_number;
end
--set conference flags
if (mute) then
if (mute == "false") then
flags = "flags{}";
else
flags = "flags{mute}";
end
else
flags = "flags{mute}";
end
--if the pin number is provided then require it
if (pin_number) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_pin_number.wav", "", "\\d+");
if (digits == pin_number) then
--pin is correct
else
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/your_pin_number_is_incorect_goodbye.wav");
session:hangup("NORMAL_CLEARING");
return;
end
end
destination_count = 0;
api = freeswitch.API();
for index,value in pairs(extension_table) do
if (string.find(value, "-") == nill) then
value = value..'-'..value;
end
sub_table = explode("-",value);
for extension=sub_table[1],sub_table[2] do
--extension_exists = "username_exists id "..extension.."@"..domain_name;
--reply = trim(api:executeString(extension_exists));
--if (reply == "true") then
extension_status = "show channels like "..extension.."@";
reply = trim(api:executeString(extension_status));
if (reply == "0 total.") then
--freeswitch.consoleLog("NOTICE", "extension "..extension.." available\n");
if (extension == tonumber(sip_from_user)) then
--this extension is the caller that initated the page
else
--originate the call
cmd_string = "bgapi originate {sip_auto_answer=true,sip_h_Alert-Info='Ring Answer',hangup_after_bridge=false,origination_caller_id_name='"..caller_id_name.."',origination_caller_id_number="..caller_id_number.."}user/"..extension.."@"..domain_name.." conference:page-"..destination_number.."@page+"..flags.." inline";
api:executeString(cmd_string);
destination_count = destination_count + 1;
end
--freeswitch.consoleLog("NOTICE", "cmd_string "..cmd_string.."\n");
else
--look inside the reply to check for the correct domain_name
if string.find(reply, domain_name) then
--found: extension number is busy
else
--not found
if (extension == tonumber(sip_from_user)) then
--this extension is the caller that initated the page
else
--originate the call
cmd_string = "bgapi originate {sip_auto_answer=true,hangup_after_bridge=false,origination_caller_id_name='"..caller_id_name.."',origination_caller_id_number="..caller_id_number.."}user/"..extension.."@"..domain_name.." conference:page-"..destination_number.."@page+"..flags.." inline";
api:executeString(cmd_string);
destination_count = destination_count + 1;
end
end
end
--end
end
end
--send main call to the conference room
if (destination_count > 0) then
session:execute("conference", "page-"..destination_number.."@page+flags{endconf}");
else
session:execute("playback", "tone_stream://%(500,500,480,620);loops=3");
end
end
-233
View File
@@ -1,233 +0,0 @@
--example usage
--basic
--condition destination_number 5900
--action set park_extension=5901
--advanced
--condition destination_number ^59(\d{2})$
--action set park_extension=$1
--additional settings
--action set park_range=5
--action set park_direction=in (in/out/both)
--action set park_announce=true (not implemented yet)
--action set park_timeout_seconds=30 (not implemented yet)
--action set park_timeout_extension=1001 (not implemented yet)
--action set park_music=$${hold_music}
--action lua park.lua
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
--dbh = freeswitch.Dbh("core:core"); -- when using sqlite
dbh = freeswitch.Dbh("sqlite://"..database_dir.."/park.db");
--dofile(scripts_dir.."/resources/functions/database_handle.lua");
--dbh = database_handle('system');
--exits the script if we didn't connect properly
assert(dbh:connected());
--get the session variables
sounds_dir = session:getVariable("sounds_dir");
park_direction = session:getVariable("park_direction");
uuid = session:getVariable("uuid");
domain_name = session:getVariable("domain_name");
park_extension = session:getVariable("park_extension");
park_range = session:getVariable("park_range");
park_announce = session:getVariable("park_announce");
park_timeout_type = session:getVariable("park_timeout_type");
park_timeout_destination = session:getVariable("park_timeout_destination");
park_timeout_seconds = session:getVariable("park_timeout_seconds");
park_music = session:getVariable("park_music");
--add the explode function
function explode ( seperator, str )
local pos, arr = 0, {}
for st, sp in function() return string.find( str, seperator, pos, true ) end do -- for each divider found
table.insert( arr, string.sub( str, pos, st-1 ) ) -- attach chars left of current divider
pos = sp + 1 -- jump past current divider
end
table.insert( arr, string.sub( str, pos ) ) -- attach chars right of last divider
return arr
end
--add the trim function
function trim(s)
return s:gsub("^%s+", ""):gsub("%s+$", "")
end
--if park_timeout_seconds is not defined set the timeout to 5 minutes
if (not park_timeout_seconds) then
park_timeout_seconds = 300;
end
--if park_timeout_type is not defined set to transfer
if (not park_timeout_type) then
park_timeout_type = "transfer";
end
--prepare the api
api = freeswitch.API();
--answer the call
session:answer();
--database
--exits the script if we didn't connect properly
assert(dbh:connected());
--create the table if it doesn't exist
--pgsql
dbh:test_reactive("SELECT * FROM park", "", "CREATE TABLE park (id SERIAL, lot TEXT, domain TEXT, uuid TEXT, CONSTRAINT park_pk PRIMARY KEY(id))");
--sqlite
dbh:test_reactive("SELECT * FROM park", "", "CREATE TABLE park (id INTEGER PRIMARY KEY, lot TEXT, domain TEXT, uuid TEXT)");
--mysql
dbh:test_reactive("SELECT * FROM park", "", "CREATE TABLE park (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, lot TEXT, domain TEXT, uuid TEXT)");
--if park_range is defined then loop through the range to find an available parking lot
if (park_range) then
park_extension_start = park_extension;
park_extension_end = ((park_extension+park_range)-1);
extension = park_extension_start;
while true do
--exit the loop at the end of the range
if (tonumber(extension) > park_extension_end) then
break;
end
--check the database for an available slot
lot_status = "available";
sql = "SELECT count(*) as count FROM park WHERE lot = '"..extension.."' and domain = '"..domain_name.."' ";
dbh:query(sql, function(result)
--for key, val in pairs(result) do
-- freeswitch.consoleLog("NOTICE", "parking result "..key.." "..val.."\n");
--end
count = result.count;
end);
--if count is 0 then the parking lot is available end the loop
if (count == "0") then
lot_status = "available";
park_extension = ""..extension;
break;
end
--increment the value
extension = extension + 1;
end
end
--check the database to see if the slot is available or unavailable
lot_status = "available";
sql = "SELECT id, lot, uuid FROM park WHERE lot = '"..park_extension.."' and domain = '"..domain_name.."' ";
dbh:query(sql, function(row)
lot_uuid = row.uuid;
lot_status = "unavailable";
end);
--if park direction is set to out then unpark by bridging it to the caller
if (park_direction == "out") then
if (lot_uuid) then
--set the park status
cmd = "uuid_setvar "..lot_uuid.." park_status unparked";
result = trim(api:executeString(cmd));
freeswitch.consoleLog("NOTICE", "Park Status: unparked "..park_extension.."\n");
--unpark the call with bridge
cmd = "uuid_bridge "..uuid.." "..lot_uuid;
result = trim(api:executeString(cmd));
end
else
--check if the uuid_exists, if it does not exist then delete the uuid from the db and set presence to terminated
if (lot_uuid) then
cmd = "uuid_exists "..lot_uuid;
result = trim(api:executeString(cmd));
if (result == "false") then
--set presence out
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("Presence-Call-Direction", "outbound");
event:addHeader("state", "Active (1 waiting)");
event:addHeader("from", park_extension.."@"..domain_name);
event:addHeader("login", park_extension.."@"..domain_name);
event:addHeader("unique-id", lot_uuid);
event:addHeader("answer-state", "terminated");
event:fire();
--delete from the database
dbh:query("DELETE from park WHERE lot = '"..park_extension.."' and domain = '"..domain_name.."' ");
--freeswitch.consoleLog("NOTICE", "Park - Affected rows: " .. dbh:affected_rows() .. "\n");
--set the status to available
lot_status = "available";
end
end
--check if the parking lot is available, if it is then add it to the db, set presenence to confirmed and park the call
if (lot_status == "available") then
--park the call
cmd = "uuid_park "..uuid;
result = trim(api:executeString(cmd));
if (park_music) then
cmd = "uuid_broadcast "..uuid.." "..park_music.." aleg";
result = trim(api:executeString(cmd));
end
--set the park status
cmd = "uuid_setvar "..uuid.." park_status parked";
result = trim(api:executeString(cmd));
freeswitch.consoleLog("NOTICE", "Park Status: parked "..park_extension.."\n");
--add to the database
dbh:query("INSERT INTO park (lot, domain, uuid) VALUES ('"..park_extension.."', '"..domain_name.."', '"..uuid.."')");
--set presence in
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip"); --park
event:addHeader("login", park_extension.."@"..domain_name);
event:addHeader("from", park_extension.."@"..domain_name);
event:addHeader("status", "Active (1 waiting)");
event:addHeader("rpid", "unknown");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("event_count", "1");
event:addHeader("unique-id", uuid);
--event:addHeader("Presence-Call-Direction", "outbound")
event:addHeader("answer-state", "confirmed");
event:fire();
else
--bridge the current call to the call that is parked
--set the presence to terminated
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("Presence-Call-Direction", "outbound");
--event:addHeader("state", "Active (1 waiting)");
event:addHeader("from", park_extension.."@"..domain_name);
event:addHeader("login", park_extension.."@"..domain_name);
event:addHeader("unique-id", uuid);
event:addHeader("answer-state", "terminated");
event:fire();
--delete the lot from the database
dbh:query("DELETE from park WHERE lot = '"..park_extension.."' and domain = '"..domain_name.."' ");
--freeswitch.consoleLog("NOTICE", "Park 200- Affected rows: " .. dbh:affected_rows() .. "\n");
--set the park status
cmd = "uuid_setvar "..lot_uuid.." park_status unparked";
result = trim(api:executeString(cmd));
freeswitch.consoleLog("NOTICE", "Park Status: unparked "..park_extension.."\n");
--connect the calls
cmd = "uuid_bridge "..uuid.." "..lot_uuid;
result = trim(api:executeString(cmd));
end
--continue running when the session ends
session:setAutoHangup(false);
--start the fifo monitor on its own so that it doesn't block the script execution
api = freeswitch.API();
cmd = "luarun park_monitor.lua "..uuid.." "..domain_name.." "..park_extension.." "..park_timeout_type.." "..park_timeout_seconds.." "..park_timeout_destination;
result = api:executeString(cmd);
end
-188
View File
@@ -1,188 +0,0 @@
-- park_monitor.lua
-- Part of FusionPBX
-- Copyright (C) 2010 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--Description:
--if the call has been answered
--then send presence terminate, and delete from the database
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
--dbh = freeswitch.Dbh("core:core"); -- when using sqlite
dbh = freeswitch.Dbh("sqlite://"..database_dir.."/park.db");
--dofile(scripts_dir.."/resources/functions/database_handle.lua");
--get the argv values
script_name = argv[0];
uuid = argv[1];
domain_name = argv[2];
park_extension = argv[3];
park_timeout_type = argv[4];
park_timeout_seconds = argv[5];
park_timeout_destination = argv[6];
--prepare the api
api = freeswitch.API();
--add a trim function
function trim (s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
--monitor the parking lot if the call has hungup send a terminated event, and delete from the db
x = 0
while true do
--sleep a moment to prevent using unecessary resources
freeswitch.msleep(1000);
if (api:executeString("uuid_exists "..uuid) == "false") then
--set the presence to terminated
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("Presence-Call-Direction", "outbound");
event:addHeader("state", "Active (1 waiting)");
event:addHeader("from", park_extension.."@"..domain_name);
event:addHeader("login", park_extension.."@"..domain_name);
event:addHeader("unique-id", uuid);
event:addHeader("answer-state", "terminated");
event:fire();
--set the park status
cmd = "uuid_setvar "..uuid.." park_status cancelled";
result = trim(api:executeString(cmd));
freeswitch.consoleLog("NOTICE", "Park Status: cancelled\n");
--delete the lot from the database
dbh:query("DELETE from park WHERE lot = '"..park_extension.."' and domain = '"..domain_name.."' ");
--end the loop
break;
else
cmd = "uuid_getvar "..uuid.." park_status";
result = trim(api:executeString(cmd));
--freeswitch.consoleLog("notice", "" .. result .. "\n");
if (result == "parked") then --_undef_
--set presence in
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip"); --park
event:addHeader("login", park_extension.."@"..domain_name);
event:addHeader("from", park_extension.."@"..domain_name);
event:addHeader("status", "Active (1 waiting)");
event:addHeader("rpid", "unknown");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("event_count", "1");
event:addHeader("unique-id", uuid);
--event:addHeader("Presence-Call-Direction", "outbound")
event:addHeader("answer-state", "confirmed");
event:fire();
else
--set the presence to terminated
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("Presence-Call-Direction", "outbound");
event:addHeader("state", "Active (1 waiting)");
event:addHeader("from", park_extension.."@"..domain_name);
event:addHeader("login", park_extension.."@"..domain_name);
event:addHeader("unique-id", uuid);
event:addHeader("answer-state", "terminated");
event:fire();
--delete the lot from the database
dbh:query("DELETE from park WHERE lot = '"..park_extension.."' and domain = '"..domain_name.."' ");
--freeswitch.consoleLog("NOTICE", "Affected rows: park ext "..park_extension.." " .. dbh:affected_rows() .. "\n");
--set the park status
cmd = "uuid_setvar "..uuid.." park_status unparked";
result = trim(api:executeString(cmd));
freeswitch.consoleLog("NOTICE", "Park Status: unparked "..park_extension.."\n");
--end the loop
break;
end
end
--limit the monitor to watching 60 seconds
x = x + 1;
if (x > tonumber(park_timeout_seconds)) then
--set the presence to terminated
event = freeswitch.Event("PRESENCE_IN");
event:addHeader("proto", "sip");
event:addHeader("event_type", "presence");
event:addHeader("alt_event_type", "dialog");
event:addHeader("Presence-Call-Direction", "outbound");
event:addHeader("state", "Active (1 waiting)");
event:addHeader("from", park_extension.."@"..domain_name);
event:addHeader("login", park_extension.."@"..domain_name);
event:addHeader("unique-id", uuid);
event:addHeader("answer-state", "terminated");
event:fire();
--delete the lot from the database
dbh:query("DELETE from park WHERE lot = '"..park_extension.."' and domain = '"..domain_name.."' ");
--set the park status
cmd = "uuid_setvar "..uuid.." park_status timeout";
result = trim(api:executeString(cmd));
freeswitch.consoleLog("NOTICE", "Park Status: timeout\n");
--end the loop
break;
end
end
--if the timeout was reached transfer the call
--get the park status
cmd = "uuid_getvar "..uuid.." park_status";
park_status = trim(api:executeString(cmd));
--get and set the the caller id prefix
cmd = "uuid_getvar "..uuid.." park_caller_id_prefix";
park_caller_id_prefix = trim(api:executeString(cmd));
if (park_caller_id_prefix) then
--get the caller id name
cmd = "uuid_getvar "..uuid.." effective_caller_id_name";
caller_id_name = trim(api:executeString(cmd));
--set the caller id name and prefix
cmd = "uuid_setvar "..uuid.." effective_caller_id_name '"..park_caller_id_prefix.."#"..caller_id_name.."'";
result = trim(api:executeString(cmd));
end
--transfer the call to the timeout destination
if (park_timeout_type == "transfer" and park_status == "timeout") then
--set the park status
cmd = "uuid_setvar "..uuid.." park_status unparked";
result = trim(api:executeString(cmd));
freeswitch.consoleLog("NOTICE", "Park Status: unparked\n");
--transfer the call when it has timed out
cmd = "uuid_transfer "..uuid.." "..park_timeout_destination;
result = trim(api:executeString(cmd));
end
-67
View File
@@ -1,67 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
max_tries = "3";
digit_timeout = "5000";
if ( session:ready() ) then
session:answer( );
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--set defaults
if (digit_min_length) then
--do nothing
else
digit_min_length = "2";
end
if (digit_max_length) then
--do nothing
else
digit_max_length = "11";
end
--if the pin number is provided then require it
if (pin_number) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:voicemail_enter_pass:#", "", "\\d+");
if (digits == pin_number) then
--pin is correct
else
session:streamFile("phrase:voicemail_fail_auth:#");
session:hangup("NORMAL_CLEARING");
return;
end
end
end
-183
View File
@@ -1,183 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
--set the variables
pin_number = "";
max_tries = "3";
digit_timeout = "3000";
sounds_dir = "";
recordings_dir = "";
file_name = "";
recording_number = "";
recording_slots = "";
recording_prefix = "";
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--dtmf call back function detects the "#" and ends the call
function onInput(s, type, obj)
if (type == "dtmf" and obj['digit'] == '#') then
return "break";
end
end
--start the recording
function begin_record(session, sounds_dir, recordings_dir)
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
recording_slots = session:getVariable("recording_slots");
recording_prefix = session:getVariable("recording_prefix");
recording_name = session:getVariable("recording_name");
--select the recording number
if (recording_slots) then
min_digits = 1;
max_digits = 20;
recording_number = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_recording_number.wav", "", "\\d+");
recording_name = recording_prefix..recording_number..".wav";
end
--set the default recording name if one was not provided
if (recording_name) then
--recording name is provided do nothing
else
--set a default recording_name
recording_name = "temp_"..session:get_uuid()..".wav";
end
--prompt for the recording
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/begin_recording.wav");
session:execute("set", "playback_terminators=#");
--begin recording
session:execute("record", "'"..recordings_dir.."/"..recording_name.."' 180 200");
--preview the recording
session:streamFile(recordings_dir.."/"..recording_name);
--approve the recording, to save the recording press 1 to re-record press 2
min_digits="0" max_digits="1" max_tries = "1"; digit_timeout = "100";
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "voicemail/vm-save_recording.wav", "", "\\d+");
if (string.len(digits) == 0) then
min_digits="0" max_digits="1" max_tries = "1"; digit_timeout = "100";
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "voicemail/vm-press.wav", "", "\\d+");
end
if (string.len(digits) == 0) then
min_digits="0" max_digits="1" max_tries = "1"; digit_timeout = "100";
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "digits/1.wav", "", "\\d+");
end
if (string.len(digits) == 0) then
min_digits="0" max_digits="1" max_tries = "1"; digit_timeout = "100";
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "voicemail/vm-rerecord.wav", "", "\\d+");
end
if (string.len(digits) == 0) then
min_digits="0" max_digits="1" max_tries = "1"; digit_timeout = "100";
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "voicemail/vm-press.wav", "", "\\d+");
end
if (string.len(digits) == 0) then
min_digits="1" max_digits="1" max_tries = "1"; digit_timeout = "5000";
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "digits/2.wav", "", "\\d+");
end
if (digits == "1") then
--recording saved, hangup
session:streamFile("voicemail/vm-saved.wav");
return;
elseif (digits == "2") then
--delete the old recording
os.remove (recordings_dir.."/"..recording_name);
--session:execute("system", "rm "..);
--make a new recording
begin_record(session, sounds_dir, recordings_dir);
else
--recording saved, hangup
session:streamFile("voicemail/vm-saved.wav");
return;
end
end
if ( session:ready() ) then
session:answer();
--get the dialplan variables and set them as local variables
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
domain_name = session:getVariable("domain_name");
--set the base recordings dir
base_recordings_dir = recordings_dir;
--get the recordings from the config.lua and append the domain_name if the system is multi-tenant
if (domain_count > 1) then
recordings_dir = recordings_dir .. "/" .. domain_name;
end
--use the recording_dir when the variable is set
if (session:getVariable("recordings_dir")) then
if (base_recordings_dir ~= session:getVariable("recordings_dir")) then
recordings_dir = session:getVariable("recordings_dir");
end
end
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (not default_language) then default_language = 'en'; end
if (not default_dialect) then default_dialect = 'us'; end
if (not default_voice) then default_voice = 'callie'; end
--if the pin number is provided then require it
if (pin_number) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_pin_number.wav", "", "\\d+");
if (digits == pin_number) then
--pin is correct
else
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/your_pin_number_is_incorect_goodbye.wav");
session:hangup("NORMAL_CLEARING");
return;
end
end
--start recording
begin_record(session, sounds_dir, recordings_dir);
session:hangup();
end
@@ -1,36 +0,0 @@
-- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss <alexthkloss@web.de>
-- licensed under the terms of the LGPL2
base64={}
-- character table string
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
-- encoding
function base64.enc(data)
return ((data:gsub('.', function(x)
local r,b='',x:byte()
for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
return r;
end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
if (#x < 6) then return '' end
local c=0
for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
return b:sub(c+1,c+1)
end)..({ '', '==', '=' })[#data%3+1])
end
-- decoding
function base64.dec(data)
data = string.gsub(data, '[^'..b..'=]', '')
return (data:gsub('.', function(x)
if (x == '=') then return '' end
local r,f='',(b:find(x)-1)
for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
return r;
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
if (#x ~= 8) then return '' end
local c=0
for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
return string.char(c)
end))
end
@@ -1,12 +0,0 @@
--find and return path to the config.lua
function config()
dofile(scripts_dir.."/resources/functions/file_exists.lua");
if (file_exists("/etc/fusionpbx/config.lua")) then
return "/etc/fusionpbx/config.lua";
elseif (file_exists("/usr/local/etc/fusionpbx/config.lua")) then
return "/usr/local/etc/fusionpbx/config.lua";
else
return scripts_dir.."/resources/config.lua";
end
end
@@ -1,9 +0,0 @@
--connect to the database
function database_handle(t)
if (t == "system") then
return freeswitch.Dbh(database["system"]);
elseif (t == "switch") then
return freeswitch.Dbh(database["switch"]);
end
end
@@ -1,11 +0,0 @@
--add the explode function
function explode ( seperator, str )
local pos, arr = 0, {}
for st, sp in function() return string.find( str, seperator, pos, true ) end do -- for each divider found
table.insert( arr, string.sub( str, pos, st-1 ) ) -- attach chars left of current divider
pos = sp + 1 -- jump past current divider
end
table.insert( arr, string.sub( str, pos ) ) -- attach chars right of last divider
return arr
end
@@ -1,6 +0,0 @@
--check if a file exists
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
@@ -1,37 +0,0 @@
-- Part of FusionPBX
-- Copyright (C) 2013 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--format seconds to 00:00:00
function format_seconds(seconds)
local seconds = tonumber(seconds);
if seconds == 0 then
return "00:00:00";
else
hours = string.format("%02.f", math.floor(seconds/3600));
minutes = string.format("%02.f", math.floor(seconds/60 - (hours*60)));
seconds = string.format("%02.f", math.floor(seconds - hours*3600 - minutes *60));
return string.format("%02d:%02d:%02d", hours, minutes, seconds);
end
end
@@ -1,14 +0,0 @@
--add the mkdir function
function mkdir(dir)
dir = dir:gsub([[\]], "/");
if (package.config:sub(1,1) == "/") then
--unix
cmd = [[mkdir -p "]] .. dir .. [["]];
elseif (package.config:sub(1,1) == [[\]]) then
--windows
cmd = [[mkdir "]] .. dir .. [["]];
end
os.execute(cmd);
return cmd;
end
@@ -1,7 +0,0 @@
--add the trim function
function trim(s)
if (s) then
return s:gsub("^%s+", ""):gsub("%s+$", "")
end
end
-145
View File
@@ -1,145 +0,0 @@
-- ring_groups.lua
-- Part of FusionPBX
-- Copyright (C) 2010 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--include config.lua
scripts_dir = string.sub(debug.getinfo(1).source,2,string.len(debug.getinfo(1).source)-(string.len(argv[0])+1));
dofile(scripts_dir.."/resources/functions/config.lua");
dofile(config());
--connect to the database
dofile(scripts_dir.."/resources/functions/database_handle.lua");
dbh = database_handle('system');
--get the variables
if (session:ready()) then
domain_name = session:getVariable("domain_name");
ring_group_uuid = session:getVariable("ring_group_uuid");
caller_id_name = session:getVariable("caller_id_name");
caller_id_number = session:getVariable("caller_id_number");
recordings_dir = session:getVariable("recordings_dir");
uuid = session:getVariable("uuid");
end
--get the extension list
sql =
[[ SELECT g.ring_group_extension_uuid, e.extension_uuid, e.extension,
r.ring_group_strategy, r.ring_group_timeout_sec, r.ring_group_timeout_app, g.extension_delay, g.extension_timeout, r.ring_group_timeout_data, r.ring_group_cid_name_prefix, r.ring_group_ringback
FROM v_ring_groups as r, v_ring_group_extensions as g, v_extensions as e
where g.ring_group_uuid = r.ring_group_uuid
and g.ring_group_uuid = ']]..ring_group_uuid..[['
and e.extension_uuid = g.extension_uuid
and r.ring_group_enabled = 'true'
order by g.extension_delay, e.extension asc ]]
--freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n");
x = 0;
dbh:query(sql, function(row)
ring_group_timeout_sec = row.ring_group_timeout_sec;
ring_group_timeout_app = row.ring_group_timeout_app;
ring_group_timeout_data = row.ring_group_timeout_data;
ring_group_cid_name_prefix = row.ring_group_cid_name_prefix;
ring_group_ringback = row.ring_group_ringback;
extension_delay = row.extension_delay;
extension_timeout = row.extension_timeout;
if (ring_group_ringback == "${uk-ring}") then
ring_group_ringback = "%(400,200,400,450);%(400,2200,400,450)";
end
if (ring_group_ringback == "${us-ring}") then
ring_group_ringback = "%(2000, 4000, 440.0, 480.0)";
end
if (ring_group_ringback == "${fr-ring}") then
ring_group_ringback = "%(1500, 3500, 440.0, 0.0)";
end
if (ring_group_ringback == "${rs-ring}") then
ring_group_ringback = "%(1000, 4000, 425.0, 0.0)";
end
session:setVariable("ringback", ring_group_ringback);
session:setVariable("transfer_ringback", ring_group_ringback);
if (string.len(ring_group_cid_name_prefix) > 0) then
origination_caller_id_name = ring_group_cid_name_prefix .. "#" .. caller_id_name;
else
origination_caller_id_name = caller_id_name;
end
delimiter = ",";
if (row.ring_group_strategy == "sequence") then
delimiter = "|";
end
if (row.ring_group_strategy == "simultaneous") then
delimiter = ",";
end
if (row.ring_group_strategy == "enterprise") then
delimiter = ":_:";
end
if (x == 0) then
app_data = ""; --{originate_timeout="..ring_group_timeout_sec.."}";
app_data = app_data .. "[sip_invite_domain="..domain_name..",leg_timeout="..extension_timeout..",leg_delay_start="..extension_delay..",origination_caller_id_name="..origination_caller_id_name.."]user/" .. row.extension .. "@" .. domain_name;
else
app_data = app_data .. delimiter .. "[sip_invite_domain="..domain_name..",leg_timeout="..extension_timeout..",leg_delay_start="..extension_delay..",origination_caller_id_name="..origination_caller_id_name.."]user/" .. row.extension .. "@" .. domain_name;
end
x = x + 1;
end);
--app_data
--freeswitch.consoleLog("notice", "[ring group] app_data: " .. app_data .. "\n");
--session actions
if (session:ready()) then
session:preAnswer();
session:execute("set", "hangup_after_bridge=true");
session:execute("set", "continue_on_fail=true");
session:execute("bind_meta_app", "1 ab s execute_extension::dx XML features");
session:execute("bind_meta_app", "2 ab s record_session::"..recordings_dir.."}/archive/"..os.date("%Y").."/"..os.date("%m").."/"..os.date("%d").."}/"..uuid..".wav");
session:execute("bind_meta_app", "3 ab s execute_extension::cf XML features");
session:execute("bind_meta_app", "4 ab s execute_extension::att_xfer XML features");
if (app_data) then
session:execute("bridge", app_data);
else
--get the timeout app and data
sql = [[SELECT ring_group_timeout_app, ring_group_timeout_data FROM v_ring_groups
where ring_group_uuid = ']]..ring_group_uuid..[['
and ring_group_enabled = 'true' ]];
--freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n");
dbh:query(sql, function(row)
ring_group_timeout_app = row.ring_group_timeout_app;
ring_group_timeout_data = row.ring_group_timeout_data;
end);
end
if (session:getVariable("originate_disposition") == "ALLOTTED_TIMEOUT") then
session:execute(ring_group_timeout_app, ring_group_timeout_data);
end
end
--actions
--ACTIONS = {}
--table.insert(ACTIONS, {"set", "hangup_after_bridge=true"});
--table.insert(ACTIONS, {"set", "continue_on_fail=true"});
--table.insert(ACTIONS, {"bridge", app_data});
--table.insert(ACTIONS, {ring_group_timeout_app, ring_group_timeout_data});
-91
View File
@@ -1,91 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
predefined_destination = "";
max_tries = "3";
digit_timeout = "5000";
port = "8080";
if ( session:ready() ) then
session:answer( );
pin_number = session:getVariable("pin_number");
sounds_dir = session:getVariable("sounds_dir");
host = session:getVariable("host");
--set the sounds path for the language, dialect and voice
default_language = session:getVariable("default_language");
default_dialect = session:getVariable("default_dialect");
default_voice = session:getVariable("default_voice");
if (default_language) then else default_language = 'en'; end
if (default_dialect) then else default_dialect = 'us'; end
if (default_voice) then else default_voice = 'callie'; end
digitmaxlength = 0;
timeoutpin = 7500;
timeouttransfer = 7500;
--if the pin number is provided then require it
if (pin_number) then
min_digits = string.len(pin_number);
max_digits = string.len(pin_number)+1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_pin_number.wav", "", "\\d+");
if (digits == pin_number) then
--pin is correct
digits = "";
else
session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/your_pin_number_is_incorect_goodbye.wav");
session:hangup("NORMAL_CLEARING");
return;
end
end
if (session:ready()) then
session:answer();
min_digits = 1;
max_digits = 1;
digitmaxlength = 1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/custom/please_enter_the_phone_number.wav", "", "\\d+");
x = 0;
while (session:ready() == true) do
if (string.len(digits) == 0) then
--getDigits(length, terminators, timeout, digit_timeout, abs_timeout)
digits = session:getDigits(1, "#", 40000);
end
if (string.len(digits) > 0) then
--press star to exit
if (digits == "*") then
break;
end
--send the command to php
session:execute("system","/usr/local/bin/php /usr/local/www/fusionpbx/mod/roku/roku.php "..digits.." "..host.." "..port);
end
digits = "";
if (x > 17500) then
break;
end
end
session:hangup("NORMAL_CLEARING");
end
end
-203
View File
@@ -1,203 +0,0 @@
--
-- FusionPBX
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL/
--
-- Software distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License.
--
-- The Original Code is FusionPBX
--
-- The Initial Developer of the Original Code is
-- Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2010
-- the Initial Developer. All Rights Reserved.
--
-- Contributor(s):
-- Mark J Crane <markjcrane@fusionpbx.com>
--get the argv values
script_name = argv[0];
domain_name = argv[1];
wakeup_number = argv[2];
--add the trim function
function trim(s)
return s:gsub("^%s+", ""):gsub("%s+$", "")
end
--add is_numeric
function is_numeric(text)
if type(text)~="string" and type(text)~="number" then return false end
return tonumber(text) and true or false
end
--set the default values for the variables
pin_number = "";
max_tries = "3";
digit_timeout = "3000";
sounds_dir = "";
extension_type = ""; --number,caller_id_number,prompt
extension_number = "";
if (wakeup_number) then
--begin the wakeup call
if ( session:ready() ) then
--prepare the api object
api = freeswitch.API();
--set session settings
session:answer();
session:setAutoHangup(false);
--wakeup confirm press 1 to 3
min_digits = 1;
max_digits = 1;
digits = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:wakeup-call", "", "\\d+");
--reschedule the call for snooze
if (digits == "2") then
freeswitch.consoleLog("NOTICE", "wakeup call: snooze selected - rescheduled the call\n");
api = freeswitch.API();
caller_id_name = "wakeup call";
caller_id_number = wakeup_number;
sched_api_time = "600";
cmd_string = "sched_api +"..sched_api_time.." wakeup-call-"..wakeup_number.." originate {hangup_after_bridge=false,origination_caller_id_name='"..caller_id_name.."',origination_caller_id_number="..caller_id_number.."}user/"..wakeup_number.."@"..domain_name.." &lua('wakeup.lua "..domain_name.." "..wakeup_number.."') ";
freeswitch.consoleLog("NOTICE", "wakeup: "..cmd_string.."\n");
reply = api:executeString(cmd_string);
end
end
else
--prompt for the wakeup call information
if ( session:ready() ) then
session:answer();
session:setAutoHangup(false);
--get the dialplan variables and set them as local variables
sounds_dir = session:getVariable("sounds_dir");
domain_name = session:getVariable("domain_name");
extension_number = session:getVariable("extension_number");
extension_type = session:getVariable("extension_type");
time_zone_offset = session:getVariable("time_zone_offset");
sip_number_alias = session:getVariable("sip_number_alias");
sip_from_user = session:getVariable("sip_from_user");
if (is_numeric(sip_number_alias)) then
wakeup_number = sip_number_alias;
else
wakeup_number = sip_from_user;
end
--get the extension number
if (extension_type == "prompt") then
min_digits = 1;
max_digits = 11;
wakeup_time = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:wakeup-get-extension", "", "\\d+");
end
--get the wakeup time
min_digits = 4;
max_digits = 4;
wakeup_time = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:wakeup-greeting", "", "\\d+");
freeswitch.consoleLog("NOTICE", "wakeup time: "..wakeup_time.."\n");
--get the current time
current_hours = tonumber(os.date("%H"));
current_minutes = tonumber(os.date("%M"));
current_seconds = tonumber(os.date("%S"));
--adjust the time zone offset
if (time_zone_offset) then
current_hours = time_zone_offset + current_hours;
if (current_hours < 0) then
current_hours = current_hours + 24;
end
if (current_hours > 23) then
current_hours = current_hours - 24;
end
end
--show the current hours minutes and seconds to the log
--freeswitch.consoleLog("NOTICE", "Hours: " .. current_hours .. "\n");
--freeswitch.consoleLog("NOTICE", "Mins: " .. current_minutes .. "\n");
--freeswitch.consoleLog("NOTICE", "Seconds: " .. current_seconds .. "\n");
--prepare the current time
current_time = (current_hours * 100) + current_minutes;
--get the wakeup hours and minutes
wakeup_hours = string.sub(wakeup_time, 1, 2);
wakeup_minutes = string.sub(wakeup_time, 3);
--show the wakeup time, hours, and minutes to the log
--freeswitch.consoleLog("NOTICE", "wakeup_time "..wakeup_time.."\n");
--freeswitch.consoleLog("NOTICE", "wakeup_hours "..wakeup_hours.."\n");
--freeswitch.consoleLog("NOTICE", "wakeup_minutes "..wakeup_minutes.."\n");
--convert the time, hours and minutes to numbers
wakeup_time = tonumber(wakeup_time);
wakeup_hours = tonumber(wakeup_hours);
wakeup_minutes = tonumber(wakeup_minutes);
if (current_time > wakeup_time) then
--get the current_time_in_seconds
current_time_in_seconds = (current_hours * 3600) + (current_minutes * 60);
--freeswitch.consoleLog("NOTICE", "sched_api_time = ("..current_hours.." * 3600) + ("..current_minutes.." * 60)\n");
--get the seconds until midnight
seconds_until_midnight = (24 * 3600) - current_time_in_seconds;
--freeswitch.consoleLog("NOTICE", "sched_api_time = (24 * 3600) - "..current_time_in_seconds.."\n");
--get the wakeup_time_in_seconds
wakeup_time_in_seconds = (wakeup_hours * 3600) + (wakeup_minutes * 60);
--freeswitch.consoleLog("NOTICE", "sched_api_time = ("..wakeup_hours.." * 3600) + ("..wakeup_minutes.." * 60)\n");
--add the seconds_until_midnight to the wakeup_time_in_seconds
sched_api_time = wakeup_time_in_seconds + seconds_until_midnight;
--freeswitch.consoleLog("NOTICE", "sched_api_time = "..wakeup_time_in_seconds.." + "..seconds_until_midnight.."\n");
else
--get the current_time_in_seconds
current_time_in_seconds = (current_hours * 3600) + (current_minutes * 60);
--freeswitch.consoleLog("NOTICE", "current_time_in_seconds = ("..current_hours.." * 3600) + ("..current_minutes.." * 60);\n");
--get the wakeup_time_in_seconds
wakeup_time_in_seconds = (wakeup_hours * 3600) + (wakeup_minutes * 60);
--freeswitch.consoleLog("NOTICE", "wakeup_time_in_seconds = ("..wakeup_hours.." * 3600) + ("..wakeup_minutes.." * 60);\n");
--subtract the current time from wakeup_time_in_seconds
sched_api_time = wakeup_time_in_seconds - current_time_in_seconds;
--freeswitch.consoleLog("NOTICE", "sched_api_time = "..wakeup_time_in_seconds.." - "..current_time_in_seconds.."\n");
end
--freeswitch.consoleLog("NOTICE", "sched_api_time "..sched_api_time.."\n");
--wakeup call has been scheduled
session:streamFile("phrase:wakeup-scheduled");
session:say(wakeup_time, "en", "number", "ITERATED");
--wakeup confirm press 1 to 3
min_digits = 1;
max_digits = 1;
wakeup_accept = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", "phrase:wakeup-accept", "", "\\d+");
--accept
if (wakeup_accept == "1") then
--send a message to the console
freeswitch.consoleLog("NOTICE", "wakeup: accepted\n");
--schedule the wakeup call
caller_id_name = "wakeup call";
caller_id_number = wakeup_number;
cmd_string = "sched_api +"..sched_api_time.." wakeup-call-"..wakeup_number.." originate {hangup_after_bridge=false,origination_caller_id_name='"..caller_id_name.."',origination_caller_id_number="..caller_id_number.."}user/"..wakeup_number.."@"..domain_name.." &lua('wakeup.lua "..domain_name.." "..wakeup_number.."') ";
freeswitch.consoleLog("NOTICE", "wakeup: "..cmd_string.."\n");
api = freeswitch.API();
reply = api:executeString(cmd_string);
--hangup
session:hangup();
end
--cancel
if (wakeup_accept == "2") then
--send a message to the console
freeswitch.consoleLog("NOTICE", "wakeup: cancelled\n");
--hangup
session:hangup();
end
end
end

Some files were not shown because too many files have changed in this diff Show More