mirror of
https://github.com/fusionpbx/fusionpbx.git
synced 2026-01-06 11:43:50 +00:00
Add. Use route_to_bridge module to build routes for ring groups. (#2907)
* Add. Use `route_to_bridge` module to build routes fro ring groups. This commit has several improvements 1. Select only needed fields. (do not select quite big XML text strings) 2. Filter routes also by context name 3. Filter dialplans also by hostname 4. Handle conditions based not only `destination_number` 5. Handle `break` and `continue` attributes for extensions 6. Escape vars inside dial-string 7. Add log messages similar as FS dialplan do * Add. `route_to_bridge` set inline vars so it possible use then in next conditions. Add. `route_to_bridge` can execute basic api commands from allowed lists. `route_to_bridge` expand all known vars. If var is unknown then it pass as is. Fix. `export nolocal:` action. * Fix. Short variable names * Add. some comments * Fix. Do not try execute empty string This produce error messages `[ERR] switch_cpp.cpp:759 No application specified` * Fix. Export nolocal values.
This commit is contained in:
committed by
FusionPBX
parent
8e0cf6ae12
commit
679d4e1fb5
@@ -30,6 +30,9 @@
|
||||
--include the log
|
||||
local log = require "resources.functions.log".ring_group
|
||||
|
||||
-- include libs
|
||||
local route_to_bridge = require "resources.functions.route_to_bridge"
|
||||
|
||||
--connect to the database
|
||||
local Database = require "resources.functions.database";
|
||||
dbh = Database.new('system');
|
||||
@@ -118,6 +121,7 @@
|
||||
uuid = session:getVariable("uuid");
|
||||
context = session:getVariable("context");
|
||||
call_direction = session:getVariable("call_direction");
|
||||
accountcode = session:getVariable("accountcode");
|
||||
end
|
||||
|
||||
--default to local if nil
|
||||
@@ -170,6 +174,9 @@
|
||||
-- error();
|
||||
--end
|
||||
|
||||
--get current switchname
|
||||
hostname = trim(api:execute("switchname", ""))
|
||||
|
||||
--get the ring group
|
||||
ring_group_forward_enabled = "";
|
||||
ring_group_forward_destination = "";
|
||||
@@ -187,7 +194,7 @@
|
||||
missed_call_app = row["ring_group_missed_call_app"];
|
||||
missed_call_data = row["ring_group_missed_call_data"];
|
||||
end);
|
||||
|
||||
|
||||
--get the ring group user
|
||||
sql = "SELECT r.*, u.user_uuid FROM v_ring_groups as r, v_ring_group_users as u ";
|
||||
sql = sql .. "where r.ring_group_uuid = :ring_group_uuid ";
|
||||
@@ -304,7 +311,7 @@
|
||||
--process the ring group
|
||||
if (ring_group_forward_enabled == "true" and string.len(ring_group_forward_destination) > 0) then
|
||||
--forward the ring group
|
||||
session:setVariable("toll_allow",ring_group_forward_toll_allow);
|
||||
session:setVariable("toll_allow",ring_group_forward_toll_allow);
|
||||
session:execute("transfer", ring_group_forward_destination.." XML "..context);
|
||||
else
|
||||
--get the strategy of the ring group, if random, we use random() to order the destinations
|
||||
@@ -422,33 +429,9 @@
|
||||
|
||||
--get the dialplan data and save it to a table
|
||||
if (external) then
|
||||
sql = [[select * from v_dialplans as d, v_dialplan_details as s
|
||||
where (d.domain_uuid = :domain_uuid or d.domain_uuid is null)
|
||||
and d.app_uuid = '8c914ec3-9fc0-8ab5-4cda-6c9288bdc9a3'
|
||||
and d.dialplan_enabled = 'true'
|
||||
and d.dialplan_uuid = s.dialplan_uuid
|
||||
order by
|
||||
d.dialplan_order asc,
|
||||
d.dialplan_name asc,
|
||||
d.dialplan_uuid asc,
|
||||
s.dialplan_detail_group asc,
|
||||
CASE s.dialplan_detail_tag
|
||||
WHEN 'condition' THEN 1
|
||||
WHEN 'action' THEN 2
|
||||
WHEN 'anti-action' THEN 3
|
||||
ELSE 100 END,
|
||||
s.dialplan_detail_order asc
|
||||
]];
|
||||
params = {domain_uuid = domain_uuid};
|
||||
if debug["sql"] then
|
||||
freeswitch.consoleLog("notice", "[ring group] SQL:" .. sql .. "; params:" .. json.encode(params) .. "\n");
|
||||
end
|
||||
dialplans = {};
|
||||
x = 1;
|
||||
assert(dbh:query(sql, params, function(row)
|
||||
dialplans[x] = row;
|
||||
x = x + 1;
|
||||
end));
|
||||
dialplans = route_to_bridge.preload_dialplan(
|
||||
dbh, domain_uuid, {hostname = hostname, context = context}
|
||||
)
|
||||
end
|
||||
|
||||
--process the destinations
|
||||
@@ -580,77 +563,65 @@
|
||||
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.."leg_timeout="..destination_timeout..","..delay_name.."="..destination_delay..",dialed_extension=" .. row.destination_number .. ",extension_uuid="..extension_uuid .. row.record_session .. "]user/" .. row.destination_number .. "@" .. domain_name;
|
||||
dial_string = dial_string_to_user;
|
||||
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.."leg_timeout="..destination_timeout..","..delay_name.."="..destination_delay.."]" .. row.destination_number;
|
||||
else
|
||||
--external number
|
||||
y = 0;
|
||||
dial_string = '';
|
||||
previous_dialplan_uuid = '';
|
||||
regex_match = false;
|
||||
for k, r in pairs(dialplans) do
|
||||
if (y > 0) then
|
||||
if (previous_dialplan_uuid ~= r.dialplan_uuid) then
|
||||
regex_match = false;
|
||||
bridge_match = false;
|
||||
square = square .. "]";
|
||||
y = 0;
|
||||
dial_string = nil
|
||||
|
||||
local session_mt = {__index = function(_, k) return session:getVariable(k) end}
|
||||
local params = setmetatable({
|
||||
__api__ = api,
|
||||
destination_number = destination_number,
|
||||
user_exists = 'false',
|
||||
call_direction = 'outbound',
|
||||
domain_name = domain_name,
|
||||
domain_uuid = domain_uuid,
|
||||
destination_timeout = destination_timeout,
|
||||
destination_delay = destination_delay,
|
||||
}, session_mt)
|
||||
|
||||
local confirm = string.gsub(group_confirm, ',$', '') -- remove `,` from end of string
|
||||
local route = route_to_bridge.apply_vars({ -- predefined actions
|
||||
"domain_name=${domain_name}",
|
||||
"domain_uuid=${domain_uuid}",
|
||||
"sip_invite_domain=${domain_name}",
|
||||
"leg_timeout=${destination_timeout}",
|
||||
delay_name .. "=${destination_delay}",
|
||||
"ignore_early_media=true",
|
||||
confirm,
|
||||
}, params)
|
||||
|
||||
route = route_to_bridge(dialplans, domain_uuid, params, route)
|
||||
|
||||
if route and route.bridge then
|
||||
local remove_actions = {
|
||||
["effective_caller_id_name="] = true;
|
||||
["effective_caller_id_number="] = true;
|
||||
['sip_h_X-accountcode='] = true;
|
||||
}
|
||||
|
||||
-- cleanup variables
|
||||
local i = 1 while i < #route do
|
||||
-- remove vars from prev variant
|
||||
if remove_actions[ route[i] ] then
|
||||
table.remove(route, i)
|
||||
i = i - 1
|
||||
-- remove vars with unresolved vars
|
||||
elseif string.find(route[i], '%${.+}') then
|
||||
table.remove(route, i)
|
||||
i = i - 1
|
||||
-- remove vars with empty values
|
||||
elseif string.find(route[i], '=$') then
|
||||
table.remove(route, i)
|
||||
i = i - 1
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
if (r.dialplan_detail_tag == "condition") then
|
||||
if (r.dialplan_detail_type == "destination_number") then
|
||||
dial_string = "regex m:~"..destination_number.."~"..r.dialplan_detail_data
|
||||
if (api:execute("regex", "m:~"..destination_number.."~"..r.dialplan_detail_data) == "true") then
|
||||
--get the regex result
|
||||
destination_result = trim(api:execute("regex", "m:~"..destination_number.."~"..r.dialplan_detail_data.."~$1"));
|
||||
--set match equal to true
|
||||
regex_match = true;
|
||||
end
|
||||
end
|
||||
end
|
||||
--regex_match = true;
|
||||
--dial_string = r.dialplan_detail_data;
|
||||
if (r.dialplan_detail_tag == "action") then
|
||||
if (regex_match) then
|
||||
--dial_string = 'match';
|
||||
--replace $1
|
||||
dialplan_detail_data = r.dialplan_detail_data:gsub("$1", destination_result);
|
||||
--if the session is set then process the actions
|
||||
if (y == 0) then
|
||||
square = "[domain_name="..domain_name..",domain_uuid="..domain_uuid..",sip_invite_domain="..domain_name..",call_direction=outbound,"..group_confirm.."leg_timeout="..destination_timeout..","..delay_name.."="..destination_delay..",ignore_early_media=true,";
|
||||
end
|
||||
if (r.dialplan_detail_type == "set") then
|
||||
--session:execute("eval", dialplan_detail_data);
|
||||
if (dialplan_detail_data == "sip_h_X-accountcode=${accountcode}") then
|
||||
if (session) then
|
||||
accountcode = session:getVariable("accountcode");
|
||||
if (accountcode) then
|
||||
square = square .. "sip_h_X-accountcode="..accountcode..",";
|
||||
end
|
||||
end
|
||||
elseif (dialplan_detail_data == "effective_caller_id_name=${outbound_caller_id_name}") then
|
||||
elseif (dialplan_detail_data == "effective_caller_id_number=${outbound_caller_id_number}") then
|
||||
else
|
||||
square = square .. dialplan_detail_data..",";
|
||||
end
|
||||
elseif (r.dialplan_detail_type == "bridge") then
|
||||
if (bridge_match) then
|
||||
dial_string = dial_string .. delimiter .. square .."]"..dialplan_detail_data;
|
||||
square = "[";
|
||||
else
|
||||
dial_string = square .."]"..dialplan_detail_data;
|
||||
end
|
||||
bridge_match = true;
|
||||
break;
|
||||
end
|
||||
--increment the value
|
||||
y = y + 1;
|
||||
end
|
||||
end
|
||||
previous_dialplan_uuid = r.dialplan_uuid;
|
||||
|
||||
dial_string = '[' .. table.concat(route, ',') .. ']' .. route.bridge
|
||||
end
|
||||
end
|
||||
|
||||
@@ -776,12 +747,16 @@
|
||||
or session:getVariable("originate_disposition") == "failure"
|
||||
) then
|
||||
--execute the time out action
|
||||
session:execute(ring_group_timeout_app, ring_group_timeout_data);
|
||||
if ring_group_timeout_app and #ring_group_timeout_app > 0 then
|
||||
session:execute(ring_group_timeout_app, ring_group_timeout_data);
|
||||
end
|
||||
end
|
||||
else
|
||||
if (ring_group_timeout_app ~= nil) then
|
||||
--execute the time out action
|
||||
session:execute(ring_group_timeout_app, ring_group_timeout_data);
|
||||
if ring_group_timeout_app and #ring_group_timeout_app > 0 then
|
||||
session:execute(ring_group_timeout_app, ring_group_timeout_data);
|
||||
end
|
||||
else
|
||||
local sql = "SELECT ring_group_timeout_app, ring_group_timeout_data FROM v_ring_groups ";
|
||||
sql = sql .. "where ring_group_uuid = :ring_group_uuid";
|
||||
@@ -791,7 +766,9 @@
|
||||
end
|
||||
dbh:query(sql, params, function(row)
|
||||
--execute the time out action
|
||||
session:execute(row.ring_group_timeout_app, row.ring_group_timeout_data);
|
||||
if row.ring_group_timeout_app and #row.ring_group_timeout_app > 0 then
|
||||
session:execute(row.ring_group_timeout_app, row.ring_group_timeout_data);
|
||||
end
|
||||
end);
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user