- -- post_hangup_handler.lua
- -- runs after hangup to end CDRs and do cleanup
- local log = require "lua.modules.logger.main"
- local config = require "lua.modules.config.main".load()
- local Phone = require "lua.modules.phone.main"
- local rex = require "rex_pcre"
- local json = require "json"
- local call_log = require "lua.modules.call_log.main"
- local function send_mobile_forward_hangup_push(env, status)
- local uuid = env:getHeader('uuid')
- local sip_from_user = env:getHeader('sip_from_user') or ""
- local mobile_forward_voip_phone_id = env:getHeader('mobile_forward_voip_phone_id') or ""
- local linked_uuid = env:getHeader('linked_uuid')
- local hostname = env:getHeader('hostname') or env:getHeader('mobile_forward_hostname')
- local sip_from_display = env:getHeader('sip_from_display') or env:getHeader('caller_id_name') or ""
- local original_called_number = env:getHeader('original_called_number') or ""
- local api = freeswitch.API()
- api:executeString("luarun lua/api/http_push_request.lua webcom "
- .. uuid .. " "
- .. sip_from_user .. " "
- .. mobile_forward_voip_phone_id .. " "
- .. linked_uuid .. " "
- .. hostname .. " "
- .. "'" .. sip_from_display .. "' "
- .. original_called_number .. " "
- .. status
- )
- end
- local function check_queue_tmp(env)
- local dbh_unified = assert(freeswitch.Dbh(config.mysql.database.unified.name,
- config.mysql.user,
- config.mysql.password),
- "Could not connect to database")
- local dbh = assert(freeswitch.Dbh(config.mysql.database.fs_unified.name,
- config.mysql.user,
- config.mysql.password),
- "Could not connect to database")
- -- check table
- local linked_uuid = env:getHeader('linked_uuid')
- local new_linked_uuid = string.gsub(linked_uuid, "-", "_")
- local queue_tmp_check_sql = string.format([[
- SELECT queue_uuid, queue_id, member, queue_hold_time
- FROM asterisk_queue_tmp
- WHERE queue_uuid = '%s'
- ]], new_linked_uuid)
- log.console(queue_tmp_check_sql)
- local queue_uuid
- local queue_id
- local member
- local queue_hold_time
- dbh_unified:query(queue_tmp_check_sql, function(row)
- queue_uuid = row.queue_uuid
- queue_id = row.queue_id
- member = row.member
- queue_hold_time = row.queue_hold_time
- end)
- if queue_uuid == nil then log.console("check_queue_tmp() - No queue_uuid") return end
- if queue_id == nil then log.console("check_queue_tmp() - No queue_id") return end
- if member == nil then log.console("check_queue_tmp() - No member") return end
- if queue_hold_time == nil then log.console("check_queue_tmp() - No queue_hold_time") return end
- if string.match(member, "^PJSIP/%+1%d+") then
- log.console("check_queue_tmp() - The queue was answered by an external number")
- local called_number = string.match(member, "^PJSIP/(%+1%d+)")
- local call_log_object = {
- called_number = called_number,
- caller_id = env:getHeader('queue_caller_id_number'),
- type = 'dial_out',
- voip_id = env:getHeader('voip_id'),
- queue_hold_time = queue_hold_time,
- }
- call_log.post_hangup_buffered_update(env, call_log_object)
- else
- log.console("check_queue_tmp() - The queue was answered by a voip_device_id")
- local queue_voip_device_id = string.match(member, "^PJSIP/(%d+)")
- local phone, err = Phone.new(dbh, nil, queue_voip_device_id)
- if not phone then
- log.err(err)
- dbh:release()
- dbh_unified:release()
- return
- end
- local call_log_object = {
- voip_phone_id = phone.variables.voip_phone_id,
- caller_id = env:getHeader('queue_caller_id_number'),
- called_number = phone.variables.extension,
- type = 'phone',
- voip_id = phone.variables.voip_id,
- queue_hold_time = queue_hold_time,
- }
- call_log.post_hangup_buffered_update(env, call_log_object)
- end
- -- delete row from table
- local queue_tmp_delete_sql = string.format([[
- DELETE FROM asterisk_queue_tmp
- WHERE queue_uuid='%s'
- AND queue_id=%s
- AND member='%s'
- AND queue_hold_time=%s
- ]], queue_uuid, queue_id, member, queue_hold_time)
- log.console(queue_tmp_delete_sql)
- dbh_unified:query(queue_tmp_delete_sql)
- if dbh_unified:affected_rows() ~= 1 then
- log.err("check_queue_tmp() - Could not delete \n"
- .. queue_tmp_delete_sql .. "\n from database.")
- end
- dbh:release()
- dbh_unified:release()
- return
- end
- local function handle_queue_member_answer_call_log(env)
- local last_sent_callee_id_number = env:getHeader('last_sent_callee_id_number')
- if string.match(last_sent_callee_id_number, "^%d?%d?%d?%d?%d?%d?%+1%d+") then
- log.console("handle_queue_member_answer_call_log() - "
- .. "last_sent_callee_id_number is an external number. "
- .. "Doing dial_out buffered_insert")
- local called_number = string.match(last_sent_callee_id_number, "^%d?%d?%d?%d?%d?%d?(%+1%d+)")
- local call_log_object = {
- called_number = called_number,
- caller_id = env:getHeader('queue_caller_id_number'),
- type = 'dial_out',
- voip_id = env:getHeader('voip_id'),
- }
- call_log.post_hangup_buffered_update(env, call_log_object)
- else
- log.console("last_sent_callee_id_number is a voip_device_id. Doing phone buffered_insert")
- local dbh = assert(freeswitch.Dbh(config.mysql.database.fs_unified.name,config.mysql.user,config.mysql.password),
- "Could not connect to database")
- local phone, err = Phone.new(dbh, nil, last_sent_callee_id_number)
- if not phone then
- log.err("Could not get the voip_phone_id for the agent: " .. err)
- dbh:release()
- return
- end
- local call_log_object = {
- voip_phone_id = phone.variables.voip_phone_id,
- caller_id = env:getHeader('queue_caller_id_number'),
- called_number = phone.variables.extension,
- type = 'phone',
- voip_id = phone.variables.voip_id,
- }
- call_log.post_hangup_buffered_update(env, call_log_object)
- dbh:release()
- end
- end
- local function cleanup_mobile_push(env)
- local usecs = tonumber( env:getHeader("answerusec") )
- if usecs == 0 then
- local from = env:getHeader("sip_from_user")
- local voip_phone_id = env:getHeader("voip_phone_id")
- local uuid = env:getHeader("uuid")
- local linked_uuid = env:getHeader("linked_uuid")
- local hostname = env:getHeader("hostname")
- local caller_contact_name = env:getHeader("sip_from_display") or env:getHeader("original_caller_number") or ""
- local original_called_number = env:getHeader('original_called_number') or ""
- log.console("Inside hangup hook, sending cancel push\n")
- local mobile_voip_phone_ids = env:getHeader('mobile_voip_phone_ids')
- if not mobile_voip_phone_ids then
- return
- end
- local mobile_voip_phone_ids_table = json.decode(mobile_voip_phone_ids)
- for _, voip_phone in ipairs(mobile_voip_phone_ids_table) do
- local api = freeswitch.API()
- api:executeString("luarun lua/api/http_push_request.lua basic "
- .. uuid .. " "
- .. from .. " "
- .. voip_phone .. " "
- .. linked_uuid .. " "
- .. hostname .. " '"
- .. caller_contact_name .. "' "
- .. original_called_number
- .. " canceled")
- end
- else
- log.console("Inside hangup hook, not sending cancel push\n")
- end
- end
- -----------------------------------------------------------------------------
- --
- --
- -- @param
- -- @return N/A
- -----------------------------------------------------------------------------
- local function parked_calls_cleanup(uuid, valet_lot_extension)
- local dbh_unified = assert(freeswitch.Dbh(config.mysql.database.unified.name,config.mysql.user,config.mysql.password), "Could not connect to database")
- local delete_voip_parked_call_sql
- if uuid ~= nil then
- delete_voip_parked_call_sql = string.format([[
- DELETE FROM voip_parked_calls
- WHERE linked_uuid='%s'
- ]], uuid)
- else
- delete_voip_parked_call_sql = string.format([[
- DELETE FROM voip_parked_calls
- WHERE voip_phone_id=%s
- ]], valet_lot_extension)
- end
- log.console("post_hangup_handler.lua - parked_calls_cleanup(): " .. delete_voip_parked_call_sql)
- dbh_unified:query(delete_voip_parked_call_sql)
- dbh_unified:release()
- end
- -----------------------------------------------------------------------------
- --
- -- https://freeswitch.org/confluence/display/FREESWITCH/api_hangup_hook
- --
- -- @param
- -- @return N/A
- -----------------------------------------------------------------------------
- local function post_hangup_handler(env)
- if not env then
- return
- end
- -- See everything
- -- local dat = env:serialize()
- -- log.console("Here's everything:\n" .. dat .. "\n")
- if env:getHeader('is_loopback') == "true" then
- -- we want to skip loopback hangups
- return
- end
- if env:getHeader('cc_cause') == "answered" then
- if env:getHeader('is_external_queue_call') == "true" then
- log.console("post_hangup_handler() - This was an external queue call that got answered. "
- .. "So, we did an insert into asterisk_queue_tmp table for the original server "
- .. " to use in a final buffered_update.")
- return
- end
- log.console("post_hangup_handler() - This was a queue call that got answered on the original "
- .. "server that received the call. So, we are just going to make a buffered_update "
- .. "file with the answered agents information because we do the final buffered_insert "
- .. " to complete the call logs.")
- handle_queue_member_answer_call_log(env)
- end
- if env:getHeader('is_queue_call') == "Y" then
- log.console("post_hangup_handler() - This was a queue call that got sent to another server. "
- .. "So, we need to check the asterisk_queue_tmp table to see if an agent answered "
- .. " so we can do a final buffered_update before the final buffered_insert to end the call logs.")
- check_queue_tmp(env)
- end
- if env:getHeader('is_external_queue_call') == "true" then
- log.console("post_hangup_handler() - This is an external queue call that did not get answered. "
- .. "Returning without doing anything.")
- return
- end
- if env:getHeader('is_mobile_dial') == "Y" then
- cleanup_mobile_push(env)
- end
- local callee_number = env:getHeader('last_sent_callee_id_number')
- if callee_number then
- local voip_device_id, line = rex.match(callee_number, "^(\\d{2,10})x?(\\d{1,2})?$")
- if voip_device_id then
- local dbh = assert(freeswitch.Dbh(config.mysql.database.fs_unified.name,
- config.mysql.user,
- config.mysql.password),
- "Could not connect to database")
- local callee_phone = Phone.new(dbh, nil, voip_device_id, line)
- if callee_phone then
- env:addHeader('voip_phone_id', callee_phone.variables.voip_phone_id)
- end
- dbh:release()
- end
- end
- -- final buffered call log update
- call_log.final_buffered_insert(env)
- if env:getHeader('is_live_answer') == "Y" then
- -- live_answer_cdr_update(env) -- what is this?
- end
- if env:getHeader('transfer_disposition') == 'replaced' and env:getHeader('endpoint_disposition') == 'ATTENDED_TRANSFER' then
- local other_uuid = env:getHeader('other_uuid')
- if other_uuid ~= "" and other_uuid ~= nil then
- local channel = require "lua.modules.channel.main"
- if other_uuid then
- channel.set_var(other_uuid, "transfer_destination_id")
- end
- end
- end
- if env:getHeader('mobile_forward_voip_phone_id') then
- -- This call had a mobile_forward push
- -- check that is was answered by the mobile device number
- local mobile_forward_number = env:getHeader('mobile_forward_number')
- if callee_number then
- local _, number = rex.match(callee_number, "^(\\d{1,6})(\\+\\d+)$")
- if number == mobile_forward_number then
- send_mobile_forward_hangup_push(env, 'disconnect')
- end
- else
- local usecs = tonumber( env:getHeader("answerusec") )
- if usecs == 0 then
- send_mobile_forward_hangup_push(env, 'cancelled')
- end
- end
- return
- end
- local linked_uuid = env:getHeader('linked_uuid')
- local original_parked_linked_uuid = env:getHeader('original_parked_linked_uuid')
- local valet_lot_extension = env:getHeader('valet_lot_extension')
- local parker_leg = env:getHeader('parker_leg')
- if parker_leg then log.console("post_hangup_handler.lua - parker_leg: " .. parker_leg) end
- local check = env:getHeader('valet_lot_extension')
- if check then
- log.console("post_hangup_handler.lua - valet_lot_extension: " .. check)
- else
- log.console("No valet_lot_extension found.")
- end
- local direction = env:getHeader('sip_h_X-Call-Direction')
- if direction then
- log.console("post_hangup_handler.lua - direction: " .. direction)
- end
- if valet_lot_extension then valet_lot_extension = string.match(valet_lot_extension, "^%d+$") end
- if original_parked_linked_uuid ~= nil then
- log.console("post_hangup_handler.lua - linked_uuid: " .. linked_uuid ..
- " and original_parked_linked_uuid: " .. original_parked_linked_uuid)
- end
- if linked_uuid == original_parked_linked_uuid then
- log.console("post_hangup_handler.lua - linked_uuid: " .. linked_uuid ..
- " and original_parked_linked_uuid: " .. original_parked_linked_uuid)
- parked_calls_cleanup(linked_uuid)
- elseif valet_lot_extension ~= nil then
- log.console("post_hangup_handler.lua - parked caller hungup"
- .. " using valet_lot_extension " .. valet_lot_extension
- .. " to clear voip_parked_calls")
- parked_calls_cleanup(nil, valet_lot_extension)
- return
- end
- end
- post_hangup_handler(env)