2012-11-08 20:16:32 +00:00
-- 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.
2012-11-08 21:07:36 +00:00
--set the defaults
2012-11-08 20:16:32 +00:00
digit_max_length = 3 ;
timeout_pin = 5000 ;
timeout_transfer = 5000 ;
max_tries = 3 ;
digit_timeout = 5000 ;
2013-01-17 01:11:43 +00:00
search_limit = 3 ;
2012-11-08 21:07:36 +00:00
search_count = 0 ;
2012-11-08 20:16:32 +00:00
2013-01-14 19:37:50 +00:00
--debug
debug [ "info" ] = false ;
debug [ "sql" ] = false ;
2013-03-31 08:18:41 +00:00
--include config.lua
2012-11-08 20:16:32 +00:00
scripts_dir = string.sub ( debug.getinfo ( 1 ). source , 2 , string.len ( debug.getinfo ( 1 ). source ) - ( string.len ( argv [ 0 ]) + 1 ));
2013-05-02 01:10:45 +00:00
dofile ( scripts_dir .. "/resources/functions/config.lua" );
dofile ( config ());
2012-11-08 20:16:32 +00:00
--connect to the database
2013-04-29 23:29:46 +00:00
dofile ( scripts_dir .. "/resources/functions/database_handle.lua" );
dbh = database_handle ( 'system' );
2012-11-08 20:16:32 +00:00
--prepare the api object
api = freeswitch.API ();
--get the session variables
if ( session : ready () ) then
--answer the session
session : answer ();
2013-01-17 01:11:43 +00:00
--give time for the call to be ready
session : streamFile ( "silence_stream://1000" );
2013-04-10 07:52:17 +00:00
--get the domain info
2012-11-08 20:16:32 +00:00
domain_name = session : getVariable ( "domain_name" );
2013-04-10 07:52:17 +00:00
domain_uuid = session : getVariable ( "domain_uuid" );
2012-11-08 20:16:32 +00:00
--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
2013-01-17 01:11:43 +00:00
2013-01-26 22:15:41 +00:00
--set the sounds path for the language, dialect and voice
ringback = session : getVariable ( "ringback" );
2013-01-27 03:33:34 +00:00
if ( ringback ) then
ringback = ringback : gsub ( "$" , "" );
ringback = ringback : gsub ( "{" , "" );
ringback = ringback : gsub ( "}" , "" );
end
2013-01-26 22:15:41 +00:00
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
2013-01-17 01:11:43 +00:00
--define the sounds directory
sounds_dir = session : getVariable ( "sounds_dir" );
sounds_dir = sounds_dir .. "/" .. default_language .. "/" .. default_dialect .. "/" .. default_voice ;
2012-11-08 20:16:32 +00:00
end
2013-01-14 19:37:50 +00:00
--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
2012-11-08 20:16:32 +00:00
--get the domain_uuid
2013-04-10 07:52:17 +00:00
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 );
2012-11-08 20:16:32 +00:00
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
2013-01-14 19:37:50 +00:00
--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
2012-11-08 21:07:36 +00:00
--define select_entry function
function select_entry ()
2012-11-08 20:16:32 +00:00
dtmf_digits = "" ;
digit_timeout = "500" ;
max_digits = 1 ;
max_tries = 1 ;
2013-01-17 01:11:43 +00:00
dtmf_digits = session : playAndGetDigits ( min_digits , max_digits , max_tries , digit_timeout , "#" , sounds_dir .. "/directory/dir-to_select_entry.wav" , "" , " \\ d+" );
2012-11-08 20:16:32 +00:00
if ( string.len ( dtmf_digits ) == 0 ) then
2013-01-17 01:11:43 +00:00
dtmf_digits = session : playAndGetDigits ( min_digits , max_digits , max_tries , digit_timeout , "#" , sounds_dir .. "/voicemail/vm-press.wav" , "" , " \\ d+" );
2012-11-08 20:16:32 +00:00
end
if ( string.len ( dtmf_digits ) == 0 ) then
digit_timeout = "3000" ;
2013-01-17 01:11:43 +00:00
dtmf_digits = session : playAndGetDigits ( min_digits , max_digits , max_tries , digit_timeout , "#" , sounds_dir .. "/digits/1.wav" , "" , " \\ d+" );
2012-11-08 20:16:32 +00:00
end
return dtmf_digits ;
end
2012-11-08 21:07:36 +00:00
--define prompt_for_name function
function prompt_for_name ()
2012-11-08 20:26:15 +00:00
dtmf_digits = "" ;
min_digits = 0 ; max_digits = 3 ; max_tries = 3 ; digit_timeout = "5000" ;
2013-01-17 01:11:43 +00:00
dtmf_digits = session : playAndGetDigits ( min_digits , max_digits , max_tries , digit_timeout , "#" , sounds_dir .. "/directory/dir-enter_person_first_or_last.wav" , "" , " \\ d+" );
2012-11-08 20:16:32 +00:00
return dtmf_digits ;
end
--define the directory_search function
2012-11-08 21:07:36 +00:00
function directory_search ()
2012-11-08 20:16:32 +00:00
2012-11-08 21:07:36 +00:00
--get the digits for the name
dtmf_digits = prompt_for_name ();
2012-11-08 20:16:32 +00:00
2012-11-08 21:07:36 +00:00
--show the dtmf digits
freeswitch.consoleLog ( "notice" , "[directory] first 3 letters of first or last name: " .. dtmf_digits .. " \n " );
2012-11-08 20:16:32 +00:00
2012-11-08 21:07:36 +00:00
--loop through the extensions to find matches
search_dtmf_digits = dtmf_digits ;
found = false ;
for key , row in pairs ( directory ) do
2012-11-08 20:16:32 +00:00
2012-11-08 21:07:36 +00:00
--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");
2012-11-08 20:16:32 +00:00
--end
2012-11-08 21:07:36 +00:00
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
2013-01-14 19:37:50 +00:00
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
2012-11-08 21:07:36 +00:00
--announce the extension number
if ( row.directory_exten_visible == "false" ) then
--invisible extension number
else
2013-01-17 01:11:43 +00:00
session : streamFile ( sounds_dir .. "/directory/dir-at_extension.wav" );
2013-01-14 19:37:50 +00:00
session : execute ( "say" , "en number iterated " .. row.extension );
2012-11-08 21:07:36 +00:00
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
2012-11-08 20:16:32 +00:00
end
2012-11-08 21:07:36 +00:00
found = true ;
2012-11-08 20:16:32 +00:00
end
2012-11-08 21:07:36 +00:00
end
if ( found ~= true ) then
2013-01-17 01:11:43 +00:00
session : streamFile ( sounds_dir .. "/directory/dir-no_matching_results.wav" );
end
search_count = search_count + 1 ;
if ( search_count < search_limit ) then
directory_search ();
2012-11-08 21:07:36 +00:00
end
end
2012-11-08 20:16:32 +00:00
2012-11-08 21:07:36 +00:00
--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 ;
2012-11-08 20:16:32 +00:00
else
2012-11-08 21:07:36 +00:00
if ( row.directory_full_name ) then
name = row.effective_caller_id_name ;
end
2012-11-08 20:16:32 +00:00
end
2012-11-08 21:07:36 +00:00
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 ));
2012-11-08 20:16:32 +00:00
end
2012-11-08 21:07:36 +00:00
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 ));
2012-11-08 20:16:32 +00:00
end
2012-11-08 21:07:36 +00:00
end
2012-11-08 20:16:32 +00:00
end
2012-11-08 21:07:36 +00:00
--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 });
2012-11-08 20:16:32 +00:00
2012-11-08 21:07:36 +00:00
--increment x
x = x + 1 ;
end );
--call the directory search function
if ( session : ready ()) then
directory_search ();
end
2012-11-08 20:16:32 +00:00
2012-11-08 21:07:36 +00:00
--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");