diff options
Diffstat (limited to 'misc/freeswitch')
-rw-r--r-- | misc/freeswitch/scripts/common/call_forwarding.lua | 185 |
1 files changed, 183 insertions, 2 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 |