2012-11-08 20:16:32 +00:00
-- directory.lua
-- Part of FusionPBX
2017-06-17 11:38:24 -06:00
-- Copyright (C) 2012-2017 Mark J Crane <markjcrane@fusionpbx.com>
2012-11-08 20:16:32 +00:00
-- 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.
--
2017-02-07 18:56:21 -07:00
-- THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
2012-11-08 20:16:32 +00:00
-- 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 ;
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
2015-04-18 22:39:14 +00:00
--include config.lua
2015-08-11 05:06:33 +03:00
require "resources.functions.config" ;
2015-04-18 22:41:45 +00:00
--connect to the database
2016-11-23 12:01:29 +03:00
local Database = require "resources.functions.database" ;
dbh = Database.new ( 'system' );
--include json library
local json
if ( debug [ "sql" ]) then
json = require "resources.functions.lunajson"
end
2015-04-18 22:41:45 +00:00
2016-01-28 15:47:31 +00:00
--include functions
require "resources.functions.format_ringback"
2015-04-18 22:36:26 +00:00
--settings
2015-08-11 05:06:33 +03:00
require "resources.functions.settings" ;
2015-04-18 22:36:26 +00:00
settings = settings ( domain_uuid );
storage_type = "" ;
storage_path = "" ;
if ( settings [ 'voicemail' ] ~= nil ) then
if ( settings [ 'voicemail' ][ 'storage_type' ] ~= nil ) then
if ( settings [ 'voicemail' ][ 'storage_type' ][ 'text' ] ~= nil ) then
storage_type = settings [ 'voicemail' ][ 'storage_type' ][ 'text' ];
end
end
2016-06-10 15:07:11 -07:00
if ( settings [ 'voicemail' ][ 'speak_mod' ] ~= nil ) then
if ( settings [ 'voicemail' ][ 'speak_mod' ][ 'text' ] ~= nil ) then
speak_mod = settings [ 'voicemail' ][ 'speak_mod' ][ 'text' ];
end
end
if ( settings [ 'voicemail' ][ 'speak_voice' ] ~= nil ) then
if ( settings [ 'voicemail' ][ 'speak_voice' ][ 'text' ] ~= nil ) then
speak_voice = settings [ 'voicemail' ][ 'speak_voice' ][ 'text' ];
end
end
2015-04-18 22:36:26 +00:00
if ( settings [ 'voicemail' ][ 'storage_path' ] ~= nil ) then
if ( settings [ 'voicemail' ][ 'storage_path' ][ 'text' ] ~= nil ) then
storage_path = settings [ 'voicemail' ][ 'storage_path' ][ 'text' ];
storage_path = storage_path : gsub ( "${domain_name}" , domain_name );
storage_path = storage_path : gsub ( "${voicemail_id}" , voicemail_id );
storage_path = storage_path : gsub ( "${voicemail_dir}" , voicemail_dir );
end
end
end
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" );
2016-11-23 12:01:29 +03:00
2016-07-22 11:48:29 -06:00
--get the timeout destination
timeout_destination = session : getVariable ( "timeout_destination" );
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
2016-01-28 15:47:31 +00:00
--set ringback
directory_ringback = format_ringback ( session : getVariable ( "ringback" ));
session : setVariable ( "ringback" , directory_ringback );
session : setVariable ( "transfer_ringback" , directory_ringback );
2013-01-26 22:15:41 +00:00
--set the sounds path for the language, dialect and voice
session : setVariable ( "instant_ringback" , "true" );
session : setVariable ( "ignore_early_media" , "true" );
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
--set the voicemail_dir
2015-08-12 23:45:27 -06:00
voicemail_dir = settings [ 'switch' ][ 'voicemail' ][ 'dir' ] .. "/default/" .. domain_name ;
2013-01-14 19:37:50 +00:00
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
2016-11-23 12:01:29 +03:00
local sql = "SELECT domain_uuid FROM v_domains " ;
sql = sql .. "WHERE domain_name = :domain_name" ;
local params = { domain_name = domain_name };
2013-04-10 07:52:17 +00:00
if ( debug [ "sql" ]) then
2016-11-23 12:01:29 +03:00
freeswitch.consoleLog ( "notice" , "[directory] SQL: " .. sql .. "; params: " .. json.encode ( params ) .. " \n " );
2013-04-10 07:52:17 +00:00
end
2016-11-23 12:01:29 +03:00
dbh : query ( sql , params , function ( rows )
2013-04-10 07:52:17 +00:00
domain_uuid = string.lower ( rows [ "domain_uuid" ]);
2016-09-04 22:05:47 +03:00
end );
2012-11-08 20:16:32 +00:00
end
end
2015-08-11 05:06:33 +03:00
--define the explode function
require "resources.functions.explode"
2012-11-08 20:16:32 +00:00
--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
2015-08-11 05:06:33 +03:00
--define the trim function
require "resources.functions.trim"
2012-11-08 20:16:32 +00:00
2013-01-14 19:37:50 +00:00
--check if a file exists
2015-08-11 05:06:33 +03:00
require "resources.functions.file_exists"
2013-01-14 19:37:50 +00:00
2016-03-11 13:21:52 +00:00
--define select_entry function
2012-11-08 21:07:36 +00:00
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
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
2017-02-07 18:56:21 -07:00
if ( string.len ( dtmf_digits ) == 0 ) then
dtmf_digits = session : playAndGetDigits ( min_digits , max_digits , max_tries , digit_timeout , "#" , sounds_dir .. "/directory/dir-for_next.wav" , "" , " \\ d+" );
end
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 = "5000" ;
dtmf_digits = session : playAndGetDigits ( min_digits , max_digits , max_tries , digit_timeout , "#" , sounds_dir .. "/digits/6.wav" , "" , " \\ d+" );
end
2012-11-08 20:16:32 +00:00
return dtmf_digits ;
end
2016-03-11 13:21:52 +00:00
--define prompt_for_name function
2012-11-08 21:07:36 +00:00
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
2016-03-11 13:21:52 +00:00
--show the dtmf digits
2012-11-08 21:07:36 +00:00
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
2016-02-16 13:05:25 -07:00
if ( row.first_name ) then
2015-04-18 22:36:26 +00:00
--play the recorded name
if ( storage_type == "base64" ) then
2016-09-04 22:05:47 +03:00
local dbh = Database.new ( 'system' , 'base64/read' )
2016-11-23 12:01:29 +03:00
local sql = [[SELECT * FROM v_voicemails
WHERE domain_uuid = :domain_uuid
AND voicemail_id = :voicemail_id]] ;
local params = { domain_uuid = domain_uuid , voicemail_id = row.extension };
2015-04-18 22:51:43 +00:00
if ( debug [ "sql" ]) then
2016-11-23 12:01:29 +03:00
freeswitch.consoleLog ( "notice" , "[directory] SQL: " .. sql .. "; params: " .. json.encode ( params ) .. " \n " );
2015-04-18 22:51:43 +00:00
end
2016-11-23 12:01:29 +03:00
dbh : query ( sql , params , function ( field )
2015-04-18 22:36:26 +00:00
--set the voicemail message path
file_location = voicemail_dir .. "/" .. row.extension .. "/recorded_name.wav" ;
--save the recording to the file system
2015-04-18 22:49:09 +00:00
if ( string.len ( field [ "voicemail_name_base64" ]) > 32 ) then
2016-09-04 22:05:47 +03:00
--include the file io
local file = require "resources.functions.file"
--write decoded string to file
file.write_base64 ( file_location , field [ "voicemail_name_base64" ]);
2015-04-18 22:36:26 +00:00
end
--play the recorded name
if ( file_exists ( file_location )) then
session : streamFile ( file_location );
else
--announce the first and last names
2017-02-07 18:56:21 -07:00
if ( row.first_name ~= nil and row.first_name ~= '' ) then
if ( speak_mod ~= nil and speak_voice ~= nil ) then
session : execute ( "speak" , speak_mod .. "|" .. speak_voice .. "|" .. row.first_name );
else
session : execute ( "say" , default_language .. " name_spelled iterated " .. row.first_name );
end
2016-06-10 15:07:11 -07:00
end
2015-04-18 22:36:26 +00:00
--session:execute("sleep", "500");
2017-02-07 18:56:21 -07:00
if ( row.last_name ~= nil and row.last_name ~= '' ) then
2016-06-10 15:07:11 -07:00
if ( speak_mod ~= nil and speak_voice ~= nil ) then
2017-02-07 18:56:21 -07:00
session : execute ( "speak" , speak_mod .. "|" .. speak_voice .. "|" .. row.last_name );
2016-06-10 15:07:11 -07:00
else
2017-02-07 18:56:21 -07:00
session : execute ( "say" , default_language .. " name_spelled iterated " .. row.last_name );
2016-06-10 15:07:11 -07:00
end
2016-02-16 13:05:25 -07:00
end
2015-04-18 22:36:26 +00:00
end
end );
2016-09-04 22:05:47 +03:00
dbh : release ()
2015-04-18 22:36:26 +00:00
elseif ( storage_type == "http_cache" ) then
file_location = storage_path .. "/" .. row.extension .. "/recorded_name.wav" ;
if ( file_exists ( file_location )) then
session : streamFile ( file_location );
end
else
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
2017-02-07 18:56:21 -07:00
if ( row.first_name ~= nil and row.first_name ~= '' ) then
if ( speak_mod ~= nil and speak_voice ~= nil ) then
session : execute ( "speak" , speak_mod .. "|" .. speak_voice .. "|" .. row.first_name );
else
session : execute ( "say" , default_language .. " name_spelled iterated " .. row.first_name );
end
2016-06-10 15:07:11 -07:00
end
2017-02-07 18:56:21 -07:00
if ( row.last_name ~= nil and row.last_name ~= '' ) then
2016-02-16 13:05:25 -07:00
--session:execute("sleep", "500");
2016-06-10 15:07:11 -07:00
if ( speak_mod ~= nil and speak_voice ~= nil ) then
session : execute ( "speak" , speak_mod .. "|" .. speak_voice .. "|" .. row.last_name );
else
2017-02-07 18:56:21 -07:00
session : execute ( "say" , default_language .. " name_spelled iterated " .. row.last_name );
2016-06-10 15:07:11 -07:00
end
2016-02-16 13:05:25 -07:00
end
2015-04-18 22:36:26 +00:00
end
end
2012-11-08 21:07:36 +00:00
--announce the extension number
2017-02-07 18:56:21 -07:00
--if (row.directory_exten_visible == "false") then
2012-11-08 21:07:36 +00:00
--invisible extension number
2017-02-07 18:56:21 -07:00
if ( row.extension ~= nil and row.extension ~= '' and row.directory_exten_visible == "true" ) then
2013-01-17 01:11:43 +00:00
session : streamFile ( sounds_dir .. "/directory/dir-at_extension.wav" );
2017-02-07 18:56:21 -07:00
session : execute ( "say" , default_language .. " NAME_SPELLED 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
2016-11-23 12:01:29 +03:00
local sql = "SELECT * FROM v_extensions WHERE domain_uuid = :domain_uuid AND enabled = 'true' AND (directory_visible is null or directory_visible = 'true'); " ;
local params = { domain_uuid = domain_uuid };
2012-11-08 21:07:36 +00:00
if ( debug [ "sql" ]) then
2016-11-23 12:01:29 +03:00
freeswitch.consoleLog ( "notice" , "[directory] SQL: " .. sql .. "; params: " .. json.encode ( params ) .. " \n " );
2012-11-08 21:07:36 +00:00
end
x = 1 ;
directory = {}
2016-11-23 12:01:29 +03:00
dbh : query ( sql , params , function ( row )
2012-11-08 21:07:36 +00:00
--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 ;
2017-06-17 11:38:24 -06:00
if ( row.directory_first_name ) then
first_name = row.directory_first_name ;
last_name = row.directory_last_name ;
2012-11-08 20:16:32 +00:00
else
2014-02-09 09:12:05 +00:00
if ( string.len ( effective_caller_id_name ) > 0 ) then
name = effective_caller_id_name ;
2017-06-17 11:38:24 -06:00
name_table = explode ( " " , name );
first_name = name_table [ 1 ];
last_name = name_table [ 2 ];
2012-11-08 21:07:36 +00:00
end
2012-11-08 20:16:32 +00:00
end
2017-06-17 11:38:24 -06:00
--get the digits
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 21:07:36 +00:00
end
2017-06-17 11:38:24 -06: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 21:07:36 +00:00
end
2012-11-08 20:16:32 +00:00
end
2017-06-17 11:38:24 -06:00
2012-11-08 21:07:36 +00:00
--add the row to the array
2014-02-09 09:12:05 +00:00
--freeswitch.consoleLog("notice", "[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.."\n");
2017-06-17 11:38:24 -06:00
table.insert ( directory , { extension = row.extension , context = row.user_context , first_name = first_name , last_name = last_name , 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
2016-07-22 11:48:29 -06:00
--timeout action
if ( timeout_destination == nil ) then
session : streamFile ( sounds_dir .. "/voicemail/vm-goodbye.wav" );
else
session : execute ( "transfer" , timeout_destination .. " XML " .. row.context );
end
2015-03-23 05:35:41 +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");