diff options
Diffstat (limited to 'misc/freeswitch/scripts/common')
-rw-r--r-- | misc/freeswitch/scripts/common/call_forwarding.lua | 185 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/database.lua | 2 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/group.lua | 84 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/log.lua | 16 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/object.lua | 106 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/sip_account.lua | 36 |
6 files changed, 409 insertions, 20 deletions
diff --git a/misc/freeswitch/scripts/common/call_forwarding.lua b/misc/freeswitch/scripts/common/call_forwarding.lua index 192c694..3429dc9 100644 --- a/misc/freeswitch/scripts/common/call_forwarding.lua +++ b/misc/freeswitch/scripts/common/call_forwarding.lua @@ -16,6 +16,7 @@ function CallForwarding.new(self, arg, object) self.database = arg.database; self.record = arg.record; self.domain = arg.domain; + self.parent = arg.parent; return object; end @@ -92,11 +93,191 @@ function CallForwarding.list_by_owner(self, call_forwardable_id, call_forwardabl end -function CallForwarding.presence_set(self, presence_state) +function CallForwarding.presence_set(self, presence_state, id) + id = id or self.record.id; + + if not id or not presence_state then + return; + end + require 'dialplan.presence' local presence = dialplan.presence.Presence:new(); - presence:init{log = self.log, accounts = { 'f-cftg-' .. tostring(self.record.id) }, domain = self.domain, uuid = 'call_forwarding_' .. tostring(self.record.id)}; + presence:init{log = self.log, accounts = { 'f-cftg-' .. id }, domain = self.domain, uuid = 'call_forwarding_' .. id}; return presence:set(presence_state); end + + +function CallForwarding.service_id_by_name(self, service_name) + local service_id = nil; + sql_query = 'SELECT `id` FROM `call_forward_cases` WHERE `value` = ' .. self.database:escape(service_name, '"'); + self.database:query(sql_query, function(record) + service_id = tonumber(record.id); + end); + + return service_id; +end + + +function CallForwarding.camelize_type(self, account_type) + ACCOUNT_TYPES = { + sipaccount = 'SipAccount', + conference = 'Conference', + faxaccount = 'FaxAccount', + callthrough = 'Callthrough', + huntgroup = 'HuntGroup', + automaticcalldistributor = 'AutomaticCallDistributor', + } + + return ACCOUNT_TYPES[account_type] or account_type; +end + +function CallForwarding.call_forwarding_on(self, service, destination, destination_type, timeout, source) + require 'common.str' + + if source then + sql_query = 'SELECT `id`, `destination`, `destinationable_type`, `destinationable_id`, `call_forward_case_id`, `position`, `timeout` FROM `call_forwards` \ + WHERE `call_forwardable_id` = ' .. self.parent.id .. ' \ + AND `call_forwardable_type` = "' .. self.parent.class .. '" \ + AND `call_forward_case_id` IN (SELECT `id` FROM `call_forward_cases` WHERE `value` = "' .. service .. '") \ + AND `source` = "' .. source .. '" ORDER BY `active` DESC LIMIT 1'; + else + sql_query = 'SELECT `id`, `destination`, `destinationable_type`, `destinationable_id`, `call_forward_case_id`, `position`, `timeout` FROM `call_forwards` \ + WHERE `call_forwardable_id` = ' .. self.parent.id .. ' \ + AND `call_forwardable_type` = "' .. self.parent.class .. '" \ + AND `call_forward_case_id` IN (SELECT `id` FROM `call_forward_cases` WHERE `value` = "' .. service .. '") \ + AND (`source` = "" OR `source` IS NULL) ORDER BY `active` DESC LIMIT 1'; + end + + destination_type = destination_type or 'PhoneNumber'; + local destination_id = nil; + destination = destination or ''; + local service_id = nil; + local entry_id = nil; + + self.database:query(sql_query, function(record) + entry_id = tonumber(record.id); + service_id = record.call_forward_case_id; + timeout = tonumber(timeout) or tonumber(record.timeout); + if common.str.blank(destination) then + if not common.str.blank(record.destinationable_type) then + destination_type = common.str.downcase(record.destinationable_type); + end + if not common.str.blank(record.destination) then + destination = record.destination; + end + destination_id = tonumber(record.destinationable_id); + end + end) + + if service == 'noanswer' then + timeout = tonumber(timeout) or '30'; + else + timeout = nil; + end + + if destination == '' and not estination_id and destination_type:lower() ~= 'voicemail' then + self.log:notice('CALL_FORWARDING_ON ', service, ' - for: ', self.parent.class, '=', self.parent.id, '/', self.parent.uuid,' - destination not specified: ', destination_type, '=', destination_id); + return false; + end + + if not tonumber(service_id) then + service_id = self:service_id_by_name(service); + end + + local call_forwarding_record = { + id = entry_id, + active = true, + uuid = { 'UUID()', raw = true }, + updated_at = { 'NOW()', raw = true }, + created_at = { 'NOW()', raw = true }, + call_forwardable_id = self.parent.id, + call_forwardable_type = self:camelize_type(self.parent.class), + call_forward_case_id = service_id, + destination = destination, + destinationable_type = self:camelize_type(destination_type), + destinationable_id = destination_id, + timeout = timeout, + position = 1, + }; + + local result = self.database:insert_or_update('call_forwards', call_forwarding_record, { created_at = false, position = false }); + + if not result then + self.log:notice('CALL_FORWARDING_ON ', service, ' - could not be activated for: ', self.parent.class, '=', self.parent.id, '/', self.parent.uuid,' - destination: ', destination_type, '=', destination_id, '|', destination); + return false; + end + + entry_id = entry_id or self.database:last_insert_id(); + + self.log:info('CALL_FORWARDING_ON ', service, ' - callforwarding=', entry_id, ', for: ', self.parent.class, '=', self.parent.id, '/', self.parent.uuid, ', destination: ', destination_type, '=', destination_id, '|', destination, ', timeout: ', timeout); + + if tonumber(entry_id) then + if destination_type:lower() == 'voicemail' then + self:presence_set('early', entry_id); + else + self:presence_set('confirmed', entry_id); + end + end + + return result; +end + + +function CallForwarding.call_forwarding_off(self, service, source, delete) + local conditions = {} + table.insert(conditions, '`call_forwardable_id` = ' .. self.parent.id); + table.insert(conditions, '`call_forwardable_type` = "' .. self.parent.class .. '"'); + + if source then + table.insert(conditions, '`source` = "' .. source); + else + table.insert(conditions, '(`source` = "" OR `source` IS NULL)'); + end + + if service then + table.insert(conditions, '`call_forward_case_id` IN (SELECT `id` FROM `call_forward_cases` WHERE `value` = "' .. service .. '")'); + end + + local call_forwarding_ids = {} + local sql_query = 'SELECT `id` FROM `call_forwards` WHERE ' .. table.concat(conditions, ' AND '); + self.database:query(sql_query, function(record) + table.insert(call_forwarding_ids, record.id); + end) + + -- set call forwarding entry inactive + local sql_query = 'UPDATE `call_forwards` SET `active` = FALSE, `updated_at` = NOW() WHERE ' .. table.concat(conditions, ' AND '); + local call_forwards = {}; + + -- or delete call forwarding entry + if delete then + sql_query = 'SELECT * FROM `call_forwards` WHERE ' .. table.concat(conditions, ' AND '); + self.database:query(sql_query, function(forwarding_entry) + table.insert(call_forwards, forwarding_entry) + end) + sql_query = 'DELETE FROM `call_forwards` WHERE ' .. table.concat(conditions, ' AND '); + end + + if not self.database:query(sql_query) then + self.log:notice('CALL_FORWARDING_OFF ', (service or 'any'), ' - could not be deactivated for: ', self.parent.class, '=', self.parent.id, '/', self.parent.uuid); + return false; + end + + if delete then + require 'common.sync_log' + local sync_log_class = common.sync_log.SyncLog:new{ log = self.log, database = self.database, homebase_ip_address = '' } + + for index, call_forward in ipairs(call_forwards) do + sync_log_class:insert('CallForward', call_forward, 'destroy', nil); + end + end + + for index, entry_id in ipairs(call_forwarding_ids) do + if tonumber(entry_id) then + self:presence_set('terminated', entry_id); + end + end + + return true; +end diff --git a/misc/freeswitch/scripts/common/database.lua b/misc/freeswitch/scripts/common/database.lua index 345f69d..8aed1ac 100644 --- a/misc/freeswitch/scripts/common/database.lua +++ b/misc/freeswitch/scripts/common/database.lua @@ -72,7 +72,7 @@ function Database.last_insert_id(self) end -function Database.insert_or_update(self, db_table, record, use_on_update) +function Database.insert_or_update(self, db_table, record, ignore_on_update) ignore_on_update = ignore_on_update or self.ignore_on_update; local record_sql_create = {}; local record_sql_update = {}; diff --git a/misc/freeswitch/scripts/common/group.lua b/misc/freeswitch/scripts/common/group.lua index c4125bc..b9cae61 100644 --- a/misc/freeswitch/scripts/common/group.lua +++ b/misc/freeswitch/scripts/common/group.lua @@ -86,3 +86,87 @@ function Group.name_id_by_member(self, member_id, member_type) return group_names, group_ids; end + + +function Group.permission_targets(self, group_ids, permission) + if not group_ids or #group_ids == 0 or not permission then + return {}; + end + + local sql_query = 'SELECT DISTINCT `b`.`id`, `b`.`name` \ + FROM `group_permissions` `a` \ + JOIN `groups` `b` ON `b`.`id` = `a`.`target_group_id` \ + WHERE `a`.`permission` = ' .. self.database:escape(permission, '"') .. ' \ + AND `a`.`group_id` IN (' .. table.concat(group_ids, ',') .. ') \ + AND `b`.`active` IS TRUE \ + GROUP BY `a`.`target_group_id` LIMIT ' .. MAX_GROUP_MEMBERSHIPS; + + local group_names = {}; + local group_ids = {}; + + self.database:query(sql_query, function(account_entry) + table.insert(group_names, account_entry.name); + table.insert(group_ids, tonumber(account_entry.id)); + end); + + return group_names, group_ids; +end + + +function Group.is_target(self, group_id, permission) + if not group_id or not permission then + return nil; + end + + local sql_query = 'SELECT `b`.`name` \ + FROM `group_permissions` `a` \ + JOIN `groups` `b` ON `b`.`id` = `a`.`target_group_id` \ + WHERE `a`.`permission` = ' .. self.database:escape(permission, '"') .. ' \ + AND `a`.`group_id` = ' .. tonumber(group_id) .. ' \ + AND `b`.`active` IS TRUE \ + LIMIT 1'; + + return self.database:query_return_value(sql_query); +end + + +function Group.union(self, ...) + local groups = {}; + local group_sets = {...}; + for set_index=1, #group_sets do + if type(group_sets[set_index]) == 'table' then + local group_ids = group_sets[set_index]; + for index=1, #group_ids do + groups[tonumber(group_ids[index])] = true; + end + end + end + + local group_ids = {}; + for group_id, status in pairs(groups) do + table.insert(group_ids, group_id); + end + + return group_ids; +end + + +function Group.intersection(self, set_one, set_two) + if not set_one or not set_two then + return {}; + end + + local basic_set = {}; + for index=1, #set_one do + basic_set[set_one[index]] = true; + end + + local final_set = {}; + for index=1, #set_two do + if basic_set[set_two[index]] then + table.insert(final_set, set_two[index]); + end + end + + return final_set; +end diff --git a/misc/freeswitch/scripts/common/log.lua b/misc/freeswitch/scripts/common/log.lua index 5aff2b8..b7c8d09 100644 --- a/misc/freeswitch/scripts/common/log.lua +++ b/misc/freeswitch/scripts/common/log.lua @@ -37,33 +37,33 @@ function Log.message(self, log_level, message_arguments ) end function Log.console(self, ...) - self:message(self.level_console, arg); + self:message(self.level_console, {...}); end function Log.alert(self, ...) - self:message(self.level_alert, arg); + self:message(self.level_alert, {...}); end function Log.critical(self, ...) - self:message(self.level_critical, arg); + self:message(self.level_critical, {...}); end function Log.error(self, ...) - self:message(self.level_error, arg); + self:message(self.level_error, {...}); end function Log.warning(self, ...) - self:message(self.level_warning, arg); + self:message(self.level_warning, {...}); end function Log.notice(self, ...) - self:message(self.level_notice, arg); + self:message(self.level_notice, {...}); end function Log.info(self, ...) - self:message(self.level_info, arg); + self:message(self.level_info, {...}); end function Log.debug(self, ...) - self:message(self.level_debug, arg); + self:message(self.level_debug, {...}); end diff --git a/misc/freeswitch/scripts/common/object.lua b/misc/freeswitch/scripts/common/object.lua new file mode 100644 index 0000000..8c195e5 --- /dev/null +++ b/misc/freeswitch/scripts/common/object.lua @@ -0,0 +1,106 @@ +-- Gemeinschaft 5 module: object class +-- (c) AMOOMA GmbH 2013 +-- + +module(...,package.seeall) + +Object = {} + +-- create object object ;) +function Object.new(self, arg) + arg = arg or {} + object = arg.object or {} + setmetatable(object, self); + self.__index = self; + self.class = 'object'; + self.log = arg.log; + self.database = arg.database; + return object; +end + +-- find object +function Object.find(self, attributes) + if not attributes.class then + return nil; + end + + local object = nil; + + require 'common.str'; + local class = common.str.downcase(attributes.class); + + if class == 'user' then + require 'dialplan.user'; + if tonumber(attributes.id) then + object = dialplan.user.User:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.user.User:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + + if object then + object.user_groups = object:list_groups(); + end + elseif class == 'tenant' then + require 'dialplan.tenant'; + if tonumber(attributes.id) then + object = dialplan.tenant.Tenant:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.tenant.Tenant:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + elseif class == 'sipaccount' then + require 'common.sip_account'; + if not common.str.blank(attributes.auth_name) then + object = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_auth_name(attributes.auth_name, attributes.domain); + elseif tonumber(attributes.id) then + object = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + + if object then + object.owner = self:find{class = object.record.sip_accountable_type, id = tonumber(object.record.sip_accountable_id)}; + end + elseif class == 'huntgroup' then + require 'dialplan.hunt_group'; + + if tonumber(attributes.id) then + object = dialplan.hunt_group.HuntGroup:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.hunt_group.HuntGroup:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + + if object then + object.owner = self:find{class = 'tenant', id = tonumber(object.record.tenant_id)}; + end + elseif class == 'automaticcalldistributor' then + require 'dialplan.acd'; + + if tonumber(attributes.id) then + object = dialplan.acd.AutomaticCallDistributor:new{ log = self.log, database = self.database, domain = self.domain }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.acd.AutomaticCallDistributor:new{ log = self.log, database = self.database, domain = self.domain }:find_by_uuid(attributes.uuid); + end + + if object then + object.owner = self:find{class = object.record.automatic_call_distributorable_type, id = tonumber(object.record.automatic_call_distributorable_id)}; + end + elseif class == 'faxaccount' then + require 'dialplan.fax'; + if tonumber(attributes.id) then + object = dialplan.fax.Fax:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.fax.Fax:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + + if object then + object.owner = self:find{class = object.record.fax_accountable_type, id = tonumber(object.record.fax_accountable_id)}; + end + end + + if object then + require 'common.group'; + object.groups, object.group_ids = common.group.Group:new{ log = self.log, database = self.database }:name_id_by_member(object.id, object.class); + end + + return object; +end diff --git a/misc/freeswitch/scripts/common/sip_account.lua b/misc/freeswitch/scripts/common/sip_account.lua index 5b1ea56..6cc7d25 100644 --- a/misc/freeswitch/scripts/common/sip_account.lua +++ b/misc/freeswitch/scripts/common/sip_account.lua @@ -16,6 +16,7 @@ function SipAccount.new(self, arg) self.log = arg.log; self.database = arg.database; self.record = arg.record; + self.domain = arg.domain; return object; end @@ -128,15 +129,32 @@ function SipAccount.send_text(self, text) end -function SipAccount.call_state(self) - local state = nil - local sql_query = "SELECT `callstate` FROM `channels` \ - WHERE `name` LIKE (\"\%" .. self.record.auth_name .. "@%\") \ - OR `name` LIKE (\"\%" .. self.record.auth_name .. "@%\") LIMIT 1"; +function SipAccount.call_state(self) + local sql_query = 'SELECT `callstate` FROM `detailed_calls` \ + WHERE `presence_id` LIKE "' .. self.record.auth_name .. '@%" \ + OR `b_presence_id` LIKE "' .. self.record.auth_name .. '@%" \ + LIMIT 1'; - self.database:query(sql_query, function(channel_entry) - state = channel_entry.callstate; - end) + return self.database:query_return_value(sql_query); +end + + +function SipAccount.call_forwarding_on(self, service, destination, destination_type, timeout, source) + + if not self.call_forwarding then + require 'common.call_forwarding'; + self.call_forwarding = common.call_forwarding.CallForwarding:new{ log = self.log, database = self.database, parent = self, domain = self.domain }; + end + + return self.call_forwarding:call_forwarding_on(service, destination, destination_type, timeout, source) +end + + +function SipAccount.call_forwarding_off(self, service, source, delete) + if not self.call_forwarding then + require 'common.call_forwarding'; + self.call_forwarding = common.call_forwarding.CallForwarding:new{ log = self.log, database = self.database, parent = self, domain = self.domain }; + end - return state; + return self.call_forwarding:call_forwarding_off(service, source, delete) end |