summaryrefslogtreecommitdiff
path: root/misc/freeswitch/scripts/dialplan/hunt_group.lua
diff options
context:
space:
mode:
Diffstat (limited to 'misc/freeswitch/scripts/dialplan/hunt_group.lua')
-rw-r--r--misc/freeswitch/scripts/dialplan/hunt_group.lua202
1 files changed, 202 insertions, 0 deletions
diff --git a/misc/freeswitch/scripts/dialplan/hunt_group.lua b/misc/freeswitch/scripts/dialplan/hunt_group.lua
new file mode 100644
index 0000000..87f86f1
--- /dev/null
+++ b/misc/freeswitch/scripts/dialplan/hunt_group.lua
@@ -0,0 +1,202 @@
+-- Gemeinschaft 5 module: hunt group class
+-- (c) AMOOMA GmbH 2012
+--
+
+module(...,package.seeall)
+
+HuntGroup = {}
+
+local DEFAULT_MEMBER_TIMEOUT = 20;
+
+-- Create HuntGroup object
+function HuntGroup.new(self, arg)
+ arg = arg or {}
+ object = arg.object or {}
+ setmetatable(object, self);
+ self.__index = self;
+ self.class = 'huntgroup';
+ self.log = arg.log;
+ self.database = arg.database;
+ self.record = arg.record;
+ return object;
+end
+
+
+function HuntGroup.find_by_id(self, id)
+ local sql_query = 'SELECT * FROM `hunt_groups` WHERE `id`= '.. tonumber(id) .. ' LIMIT 1';
+ local hunt_group = nil;
+
+ self.database:query(sql_query, function(entry)
+ hunt_group = HuntGroup:new(self);
+ hunt_group.record = entry;
+ hunt_group.id = tonumber(entry.id);
+ hunt_group.uuid = entry.uuid;
+ end)
+
+ return hunt_group;
+end
+
+
+function HuntGroup.find_by_uuid(self, uuid)
+ local sql_query = 'SELECT * FROM `hunt_groups` WHERE `id`= "'.. uuid .. '" LIMIT 1';
+ local hunt_group = nil;
+
+ self.database:query(sql_query, function(entry)
+ hunt_group = HuntGroup:new(self);
+ hunt_group.record = entry;
+ hunt_group.id = tonumber(entry.id);
+ hunt_group.uuid = entry.uuid;
+ end)
+
+ return hunt_group;
+end
+
+
+function HuntGroup.list_active_members(self)
+ local sql_query = 'SELECT `a`.`number`, `b`.`name` \
+ FROM `phone_numbers` `a` \
+ LEFT JOIN `hunt_group_members` `b` ON `a`.`phone_numberable_type` = "huntgroupmember" AND `a`.`phone_numberable_id` = `b`.`id` \
+ WHERE `a`.`phone_numberable_type` = "huntgroupmember" \
+ AND `b`.`active` IS TRUE \
+ AND `b`.`hunt_group_id` = ' .. self.record.id;
+
+ local hunt_group_members = {}
+
+ self.database:query(sql_query, function(hunt_group_members_entry)
+ table.insert(hunt_group_members, hunt_group_members_entry);
+ end)
+
+ return hunt_group_members;
+end
+
+
+function HuntGroup.is_member_by_numbers(self, numbers)
+ local sql_query = 'SELECT `a`.`number`, `b`.`name` \
+ FROM `phone_numbers` `a` \
+ LEFT JOIN `hunt_group_members` `b` ON `a`.`phone_numberable_type` = "huntgroupmember" AND `a`.`phone_numberable_id` = `b`.`id` \
+ WHERE `a`.`phone_numberable_type` = "huntgroupmember" \
+ AND `b`.`active` IS TRUE \
+ AND `b`.`hunt_group_id` = ' .. self.record.id .. '\
+ AND `a`.`number` IN ("' .. table.concat( numbers, '","') .. '") LIMIT 1';
+
+ local hunt_group_member = false;
+
+ self.database:query(sql_query, function(hunt_group_members_entry)
+ hunt_group_member = true;
+ end)
+
+ return hunt_group_member;
+end
+
+
+function HuntGroup.run(self, dialplan_object, caller, destination)
+ local hunt_group_members = self:list_active_members();
+
+ if #hunt_group_members == 0 then
+ return { disposition = 'HUNT_GROUP_EMPTY', code = 480, phrase = 'No active users' }
+ end
+
+ self.log:info('HUNTGROUP ', self.record.id, ' - name: ', self.record.name, ', strategy: ', self.record.strategy,', members: ', #hunt_group_members);
+
+ local destinations = {}
+ for index, hunt_group_member in ipairs(hunt_group_members) do
+ local destination = dialplan_object:destination_new{ number = hunt_group_member.number };
+ if destination.type == 'unknown' then
+ require 'dialplan.route'
+ local routes = dialplan.route.Route:new{ log = self.log, database = self.database, routing_table = dialplan_object.routes }:outbound(caller, destination.number);
+ if routes and #routes > 0 then
+ destination.callee_id_number = destination.number;
+ destination.callee_id_name = nil;
+ local route = routes[1];
+ destination.gateway = route.endpoint;
+ destination.type = route.class;
+ destination.number = route.value;
+ destination.caller_id_number = route.caller_id_number;
+ destination.caller_id_name = route.caller_id_name;
+ table.insert(destinations, destination);
+ end
+ else
+ table.insert(destinations, destination);
+ end
+ end
+
+ local forwarding_destination = nil;
+ if caller.forwarding_service == 'assistant' and caller.auth_account then
+ forwarding_destination = dialplan_object:destination_new{ type = caller.auth_account.class, id = caller.auth_account.id, number = forwarding_number }
+ forwarding_destination.alert_info = 'http://amooma.com;info=Ringer0;x-line-id=0';
+ end
+
+ local result = { continue = false };
+ local start_time = os.time();
+ if self.record.strategy == 'ring_recursively' then
+ local member_timeout = tonumber(self.record.seconds_between_jumps) or DEFAULT_MEMBER_TIMEOUT;
+ local run_queue = true;
+ while run_queue do
+ for index, member_destination in ipairs(destinations) do
+ local recursive_destinations = { member_destination }
+ if forwarding_destination then
+ table.insert(recursive_destinations, forwarding_destination);
+ end
+ require 'dialplan.sip_call'
+ result = dialplan.sip_call.SipCall:new{ log = self.log, database = self.database, caller = caller }:fork( recursive_destinations, { callee_id_number = destination.number, timeout = member_timeout });
+ if result.disposition == 'SUCCESS' then
+ if result.fork_index then
+ result.destination = recursive_destinations[result.fork_index];
+ end
+ run_queue = false;
+ break;
+ elseif os.time() > start_time + dialplan_object.dial_timeout_active then
+ run_queue = false;
+ break;
+ elseif not caller:ready() then
+ run_queue = false;
+ break;
+ end
+ end
+ if tostring(result.code) == '486' then
+ self.log:info('HUNTGROUP ', self.record.id, ' - all members busy');
+ run_queue = false;
+ end
+ end
+ else
+ if forwarding_destination then
+ table.insert(destinations, forwarding_destination);
+ end
+
+ require 'dialplan.sip_call'
+ result = dialplan.sip_call.SipCall:new{ log = self.log, database = self.database, caller = caller }:fork( destinations,
+ {
+ callee_id_number = destination.number,
+ timeout = dialplan_object.dial_timeout_active,
+ send_ringing = ( dialplan_object.send_ringing_to_gateways and caller.from_gateway ),
+ });
+ if result.fork_index then
+ result.destination = destinations[result.fork_index];
+ end
+
+ return result;
+ end
+
+ return result;
+end
+
+
+function HuntGroup.list_destination_numbers(self)
+ require "common.phone_number"
+ local phone_number_class = common.phone_number.PhoneNumber:new(defaults)
+
+ local sql_query = string.format("SELECT * FROM `phone_numbers` WHERE `state`='active' AND `phone_numberable_type` = 'HuntGroupMember' AND `phone_numberable_id` IN ( \
+ SELECT `id` FROM `hunt_group_members` WHERE `active` IS TRUE AND `hunt_group_id`=%d ) ORDER BY `position` ASC", tonumber(self.record.id));
+ local phone_numbers = {}
+
+ self.database:query(sql_query, function(hunt_group_number_entry)
+ local number_object = phone_number_class:find_by_number(hunt_group_number_entry.number)
+ if number_object and number_object.record then
+ table.insert(phone_numbers, {number = hunt_group_number_entry.number, destination_type = number_object.record.phone_numberable_type, destination_id = number_object.record.phone_numberable_id});
+ else
+ table.insert(phone_numbers, {number = hunt_group_number_entry.number});
+ end
+ end)
+
+ return phone_numbers ;
+end