Files
fusionpbx/resources/install/scripts/app/follow_me/index.lua
Stephen Forster d72718ea9f Fix table name, variables and syntax Follow me Lua (#4609)
* Fix table name, variables and syntax Follow me Lua

Correct the wrong table name on line 123. Correct the param on line 126 and correct the syntax on line 347.

* Update index.lua

Missing AND in where clause.

* Change order of preference Caller ID

Changed order of preference for Caller ID. If user exists should take preference over Follow Me override select caller ID.

This is my preference and my opinion only. May not be the desired effect of others. Perhaps a select option to choose a preference like the following options: Set caller ID override all, Local user else Caller ID
2019-09-30 17:18:27 -07:00

458 lines
18 KiB
Lua

-- 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>
-- Portions created by the Initial Developer are Copyright (C) 2019
-- the Initial Developer. All Rights Reserved.
--includes
local Database = require "resources.functions.database";
local route_to_bridge = require "resources.functions.route_to_bridge"
require "resources.functions.trim";
--get the variables
if (session:ready()) then
domain_name = session:getVariable("domain_name");
domain_uuid = session:getVariable("domain_uuid");
destination_number = session:getVariable("destination_number");
caller_id_name = session:getVariable("caller_id_name");
caller_id_number = session:getVariable("caller_id_number");
outbound_caller_id_name = session:getVariable("outbound_caller_id_name");
outbound_caller_id_number = session:getVariable("outbound_caller_id_number");
call_direction = session:getVariable("call_direction");
original_destination_number = session:getVariable("destination_number");
end
--set caller id
if (effective_caller_id_name ~= nil) then
caller_id_name = effective_caller_id_name;
end
if (effective_caller_id_number ~= nil) then
caller_id_number = effective_caller_id_number;
end
--default to local if nil
if (call_direction == nil) then
call_direction = "local";
end
--set the strategy
follow_me_strategy = 'simultaneous'; --simultaneous, enterprise
--include json library
debug["sql"] = false;
local json
if (debug["sql"]) then
json = require "resources.functions.lunajson";
end
--prepare the api object
api = freeswitch.API();
--get the destination and follow the forward
function get_forward_all(count, destination_number, domain_name)
cmd = "user_exists id ".. destination_number .." "..domain_name;
--freeswitch.consoleLog("notice", "[follow me][call forward all] " .. cmd .. "\n");
user_exists = api:executeString(cmd);
if (user_exists == "true") then
---check to see if the new destination is forwarded
cmd = "user_data ".. destination_number .."@" ..domain_name.." var forward_all_enabled";
if (api:executeString(cmd) == "true") then
--get the toll_allow var
cmd = "user_data ".. destination_number .."@" ..domain_name.." var toll_allow";
toll_allow = api:executeString(cmd);
--freeswitch.consoleLog("notice", "[follow me][call forward all] " .. destination_number .. " toll_allow is ".. toll_allow .."\n");
--get the new destination
cmd = "user_data ".. destination_number .."@" ..domain_name.." var forward_all_destination";
destination_number = api:executeString(cmd);
--freeswitch.consoleLog("notice", "[follow me][call forward all] " .. count .. " " .. cmd .. " ".. destination_number .."\n");
count = count + 1;
if (count < 5) then
count, destination_number = get_forward_all(count, destination_number, domain_name);
end
end
end
return count, destination_number, toll_allow;
end
--connect to the database
local dbh = Database.new('system');
--get the forward busy
--cmd = "user_data ".. destination_number .."@"..domain_name.." var forward_busy_enabled=";
--forward_busy_enabled = trim(api:executeString(cmd));
--cmd = "user_data ".. destination_number .."@"..domain_name.." var forward_busy_destination=";
--forward_busy_destination = trim(api:executeString(cmd));
--select data from the database
local sql = "select follow_me_uuid, toll_allow ";
sql = sql .. "from v_extensions ";
sql = sql .. "where domain_uuid = :domain_uuid ";
sql = sql .. "and ( ";
sql = sql .. " extension = :destination_number ";
sql = sql .. " OR number_alias = :destination_number ";
sql = sql .. ") ";
local params = {domain_uuid = domain_uuid,destination_number = destination_number};
if (debug["sql"]) then
freeswitch.consoleLog("notice", "SQL:" .. sql .. "; params: " .. json.encode(params) .. "\n");
end
status = dbh:query(sql, params, function(row)
follow_me_uuid = row["follow_me_uuid"];
extension_toll_allow = row["toll_allow"];
end);
--dbh:query(sql, params, function(row);
--get the follow me data
if (follow_me_uuid ~= nil) then
local sql = "select cid_name_prefix, cid_number_prefix, ";
sql = sql .. "follow_me_enabled, follow_me_caller_id_uuid, follow_me_ignore_busy ";
sql = sql .. "from v_follow_me ";
sql = sql .. "where domain_uuid = :domain_uuid ";
sql = sql .. "and follow_me_uuid = :follow_me_uuid; ";
local params = {domain_uuid = domain_uuid,follow_me_uuid = follow_me_uuid};
if (debug["sql"]) then
freeswitch.consoleLog("notice", "SQL:" .. sql .. "; params: " .. json.encode(params) .. "\n");
end
status = dbh:query(sql, params, function(row)
caller_id_name_prefix = row["cid_name_prefix"];
caller_id_number_prefix = row["cid_number_prefix"];
follow_me_enabled = row["follow_me_enabled"];
follow_me_caller_id_uuid = row["follow_me_caller_id_uuid"];
follow_me_ignore_busy = row["follow_me_ignore_busy"];
end);
--dbh:query(sql, params, function(row);
end
--get the follow me destinations
if (follow_me_uuid ~= nil) then
sql = "select d.domain_uuid, d.domain_name, f.follow_me_destination as destination_number, ";
sql = sql .. "f.follow_me_delay as destination_delay, f.follow_me_timeout as destination_timeout, ";
sql = sql .. "f.follow_me_prompt as destination_prompt ";
sql = sql .. "from v_follow_me_destinations as f, v_domains as d ";
sql = sql .. "where f.follow_me_uuid = :follow_me_uuid ";
sql = sql .. "and f.domain_uuid = d.domain_uuid ";
sql = sql .. "order by f.follow_me_order; ";
local params = {follow_me_uuid = follow_me_uuid};
destinations = {};
destination_count = 0;
x = 1;
dbh:query(sql, params, function(row)
domain_uuid = row["domain_uuid"];
domain_name = row["domain_name"];
if (row.destination_prompt == "1" or row.destination_prompt == "2") then
prompt = "true";
end
--follow the forwards
count, destination_number, toll_allow = get_forward_all(0, row.destination_number, domain_name);
--update values
row['destination_number'] = destination_number
--row['toll_allow'] = toll_allow;
--check if the user exists
cmd = "user_exists id ".. destination_number .." "..domain_name;
user_exists = api:executeString(cmd);
--cmd = "user_exists id ".. destination_number .." "..domain_name;
if (user_exists == "true") then
--add user_exists true or false to the row array
row['user_exists'] = "true";
--handle do_not_disturb
cmd = "user_data ".. destination_number .."@" ..domain_name.." var do_not_disturb";
if (api:executeString(cmd) ~= "true") then
--add the row to the destinations array
destinations[x] = row;
end
else
--set the values
external = "true";
row['user_exists'] = "false";
--add the row to the destinations array
destinations[x] = row;
end
row['domain_name'] = domain_name;
destination_count = destination_count + 1;
x = x + 1;
end);
end
--get the dialplan data and save it to a table
if (external == "true") then
dialplans = route_to_bridge.preload_dialplan(
dbh, domain_uuid, {hostname = hostname, context = context}
)
end
--prepare the array of destinations
x = 1;
for key, row in pairs(destinations) do
--set the values from the database as variables
destination_number = row.destination_number;
--determine if the user is registered if not registered then lookup
if (user_exists == "true") then
cmd = "sofia_contact */".. destination_number .."@" ..domain_name;
if (api:executeString(cmd) == "error/user_not_registered") then
freeswitch.consoleLog("NOTICE", "[follow_me] "..cmd.."\n");
cmd = "user_data ".. destination_number .."@" ..domain_name.." var forward_user_not_registered_enabled";
freeswitch.consoleLog("NOTICE", "[follow_me] "..cmd.."\n");
if (api:executeString(cmd) == "true") then
--get the new destination number
cmd = "user_data ".. destination_number .."@" ..domain_name.." var forward_user_not_registered_destination";
freeswitch.consoleLog("NOTICE", "[follow_me] "..cmd.."\n");
not_registered_destination_number = api:executeString(cmd);
freeswitch.consoleLog("NOTICE", "[follow_me] "..not_registered_destination_number.."\n");
if (not_registered_destination_number ~= nil) then
destination_number = not_registered_destination_number;
destinations[key]['destination_number'] = destination_number;
end
end
end
end
end
--process the destinations
x = 1;
for key, row in pairs(destinations) do
freeswitch.consoleLog("NOTICE", "[follow me] destination_number: "..row.destination_number.."\n");
end
--process the destinations
x = 1;
for key, row in pairs(destinations) do
--set the values from the database as variables
domain_uuid = row.domain_uuid;
destination_number = row.destination_number;
destination_delay = row.destination_delay;
destination_timeout = row.destination_timeout;
destination_prompt = row.destination_prompt;
group_confirm_key = row.group_confirm_key;
group_confirm_file = row.group_confirm_file;
toll_allow = row.toll_allow;
user_exists = row.user_exists;
--follow the forwards
count, destination_number = get_forward_all(0, destination_number, domain_name);
--check if the user exists
cmd = "user_exists id ".. destination_number .." "..domain_name;
user_exists = api:executeString(cmd);
--set ringback
--follow_me_ringback = format_ringback(follow_me_ringback);
--session:setVariable("ringback", follow_me_ringback);
--session:setVariable("transfer_ringback", follow_me_ringback);
--set the timeout if there is only one destination
if (session:ready() and destination_count == 1) then
session:execute("set", "call_timeout="..row.destination_timeout);
end
--setup the delimiter
delimiter = ",";
if (follow_me_strategy == "simultaneous") then
delimiter = ",";
end
if (follow_me_strategy == "enterprise") then
delimiter = ":_:";
end
--leg delay settings
if (follow_me_strategy == "enterprise") then
timeout_name = "originate_timeout";
delay_name = "originate_delay_start";
destination_delay = destination_delay * 500;
else
timeout_name = "leg_timeout";
delay_name = "leg_delay_start";
end
--set confirm
if (session:ready() and follow_me_strategy == "simultaneous") then
session:execute("set", "group_confirm_key=exec");
session:execute("set", "group_confirm_file=lua ".. scripts_dir:gsub('\\','/') .."/confirm.lua");
end
--determine confirm prompt
if (destination_prompt == nil) then
group_confirm = "confirm=false,";
elseif (destination_prompt == "1") then
group_confirm = "group_confirm_key=exec,group_confirm_file=lua ".. scripts_dir:gsub('\\','/') .."/confirm.lua,confirm=true";
elseif (destination_prompt == "2") then
group_confirm = "group_confirm_key=exec,group_confirm_file=lua ".. scripts_dir:gsub('\\','/') .."/confirm.lua,confirm=true";
else
group_confirm = "confirm=false";
end
--process according to user_exists, sip_uri, external number
if (user_exists == "true") then
--get the extension_uuid
cmd = "user_data ".. destination_number .."@"..domain_name.." var extension_uuid";
extension_uuid = trim(api:executeString(cmd));
--send to user
local dial_string_to_user = "[sip_invite_domain="..domain_name..",call_direction="..call_direction..","..group_confirm..","..timeout_name.."="..destination_timeout..","..delay_name.."="..destination_delay..",dialed_extension=" .. row.destination_number .. ",extension_uuid="..extension_uuid .. "]user/" .. row.destination_number .. "@" .. domain_name;
dial_string = dial_string_to_user;
elseif (tonumber(destination_number) == nil) then
--sip uri
dial_string = "[sip_invite_domain="..domain_name..",call_direction="..call_direction..","..group_confirm..","..timeout_name.."="..destination_timeout..","..delay_name.."="..destination_delay.."]" .. row.destination_number;
else
--external number
route_bridge = 'loopback/'..destination_number;
if (extension_toll_allow ~= nil) then
toll_allow = extension_toll_allow:gsub(",", ":");
end
--set the toll allow to an empty string
if (toll_allow == nil) then
toll_allow = '';
end
--get the destination caller id name and number
if (follow_me_caller_id_uuid ~= nil) then
local sql = "select destination_uuid, destination_number, destination_description, destination_caller_id_name, destination_caller_id_number ";
sql = sql .. "from v_destinations ";
sql = sql .. "where domain_uuid = :domain_uuid ";
sql = sql .. "and destination_uuid = :destination_uuid ";
sql = sql .. "order by destination_number asc ";
local params = {domain_uuid = domain_uuid, destination_uuid = follow_me_caller_id_uuid};
if (debug["sql"]) then
freeswitch.consoleLog("notice", "SQL:" .. sql .. "; params: " .. json.encode(params) .. "\n");
end
status = dbh:query(sql, params, function(field)
caller_id_name = field["destination_caller_id_name"];
caller_id_number = field["destination_caller_id_number"];
end);
end
--check if the user exists
if tonumber(caller_id_number) ~= nil then
cmd = "user_exists id ".. caller_id_number .." "..domain_name;
caller_is_local = api:executeString(cmd);
end
--set the outbound caller id
if (session:ready() and caller_is_local) then
if (outbound_caller_id_name ~= nil) then
caller_id_name = outbound_caller_id_name;
end
if (outbound_caller_id_number ~= nil) then
caller_id_number = outbound_caller_id_number;
end
end
--set the caller id
caller_id = '';
if (caller_id_name ~= nil) then
caller_id = "origination_caller_id_name='"..caller_id_name.."'"
end
if (caller_id_number ~= nil) then
caller_id = caller_id .. ",origination_caller_id_number="..caller_id_number;
end
--set the destination dial string
dial_string = "[ignore_early_media=true,toll_allow=".. toll_allow ..",".. caller_id ..",sip_invite_domain="..domain_name..",call_direction="..call_direction..","..group_confirm..","..timeout_name.."="..destination_timeout..","..delay_name.."="..destination_delay.."]"..route_bridge
end
--add a delimiter between destinations
if (dial_string ~= nil) then
--freeswitch.consoleLog("notice", "[follow me] dial_string: " .. dial_string .. "\n");
if (x == 1) then
if (follow_me_strategy == "enterprise") then
app_data = dial_string;
else
app_data = "{ignore_early_media=true}"..dial_string;
end
else
if (app_data == nil) then
if (follow_me_strategy == "enterprise") then
app_data = dial_string;
else
app_data = "{ignore_early_media=true}"..dial_string;
end
else
app_data = app_data .. delimiter .. dial_string;
end
end
end
--increment the value of x
x = x + 1;
end
--set ring ready
if (session:ready()) then
session:execute("ring_ready", "");
end
--send to the console
freeswitch.consoleLog("notice", "[app:follow_me] " .. destination_number .. "\n");
--session execute
if (session:ready()) then
--set the variables
session:execute("set", "hangup_after_bridge=true");
session:execute("set", "continue_on_fail=true");
--execute the bridge
if (app_data ~= nil) then
if (follow_me_strategy == "enterprise") then
app_data = app_data:gsub("%[", "{");
app_data = app_data:gsub("%]", "}");
end
freeswitch.consoleLog("NOTICE", "[follow me] app_data: "..app_data.."\n");
session:execute("bridge", app_data);
end
--timeout destination
if (app_data ~= nil) then
if session:ready() and (
session:getVariable("originate_disposition") == "ALLOTTED_TIMEOUT"
or session:getVariable("originate_disposition") == "NO_ANSWER"
or session:getVariable("originate_disposition") == "NO_USER_RESPONSE"
or session:getVariable("originate_disposition") == "USER_NOT_REGISTERED"
or session:getVariable("originate_disposition") == "NORMAL_TEMPORARY_FAILURE"
or session:getVariable("originate_disposition") == "NO_ROUTE_DESTINATION"
or session:getVariable("originate_disposition") == "USER_BUSY"
or session:getVariable("originate_disposition") == "RECOVERY_ON_TIMER_EXPIRE"
or session:getVariable("originate_disposition") == "failure"
) then
--get the forward no answer
cmd = "user_data ".. original_destination_number .."@"..domain_name.." var forward_no_answer_enabled";
forward_no_answer_enabled = trim(api:executeString(cmd));
cmd = "user_data ".. original_destination_number .."@"..domain_name.." var forward_no_answer_destination";
forward_no_answer_destination = trim(api:executeString(cmd));
cmd = "user_data ".. original_destination_number .."@"..domain_name.." var user_context";
user_context = trim(api:executeString(cmd));
--execute the time out action
if (forward_no_answer_enabled == 'true') then
session:transfer(forward_no_answer_destination, 'XML', user_context);
else
session:transfer('*99' .. original_destination_number, 'XML', user_context);
end
--check and report missed call
--missed();
end
end
end