Remove Fax tasks as replaced with the fax queue

This commit is contained in:
markjcrane
2023-06-06 10:33:59 -06:00
parent 28ebdbc722
commit 047824cad7
4 changed files with 0 additions and 1033 deletions

View File

@@ -1,187 +0,0 @@
-- @usage without queue
-- api: originate {fax_file='',wav_file='',fax_dtmf=''}user/108@domain.local &lua(app/fax/resources/scripts/queue/exec.lua)
-- @usage with queue task
-- api: originate {fax_task_uuid=''}user/108@domain.local &lua(app/fax/resources/scripts/queue/exec.lua)
-- @fax_dtmf
-- 0-9*# - dtmf symbols
-- @200 - dtmf duration in ms
-- p - pause 500 ms
-- P - pause 1000 ms
--
-- example: pause 5 sec dial 008 pause 2 sec play greeting
-- PPPPP008@300PP
--
require "resources.functions.config"
local log = require "resources.functions.log".fax_task
-- If we handle queue task
local fax_task_uuid = session:getVariable('fax_task_uuid')
local task if fax_task_uuid then
local Tasks = require "app.fax.resources.scripts.queue.tasks"
task = Tasks.select_task(fax_task_uuid)
if not task then
log.warningf("Can not found fax task: %q", tostring(fax_task_uuid))
return
end
end
if task then
local str = 'Queue task :'
for k, v in pairs(task) do
str = str .. ('\n %q = %q'):format(k, v)
end
log.info(str)
else
log.info('Not queued task')
end
local function empty(t) return (not t) or (#t == 0) end
local function not_empty(t) if not empty(t) then return t end end
local dtmf, wav_file, fax_file
if task then
dtmf = not_empty(task.dtmf)
wav_file = not_empty(task.wav_file) or not_empty(task.greeting)
fax_file = not_empty(task.fax_file)
else
dtmf = not_empty(session:getVariable('fax_dtmf'))
wav_file = not_empty(session:getVariable('wav_file'))
fax_file = not_empty(session:getVariable('fax_file'))
end
if not (wav_file or fax_file) then
log.warning("No fax or wav file")
return
end
local function decode_dtmf(dtmf)
local r, sleep, seq = {}
dtmf:gsub('P', 'pp'):gsub('.', function(ch)
if ch == ';' or ch == ',' then
r[#r + 1] = sleep or seq
sleep, seq = nil
elseif ch == 'p' then
r[#r + 1] = seq
sleep = (sleep or 0) + 500
seq = nil
else
r[#r + 1] = sleep
seq = (seq or '') .. ch
sleep = nil
end
end)
r[#r + 1] = sleep or seq
return r
end
local function send_fax()
session:execute("txfax", fax_file)
end
local function start_fax_detect(detect_duration)
if not tone_detect_cb then
function tone_detect_cb(s, type, obj, arg)
if type == "event" then
if obj:getHeader('Event-Name') == 'DETECTED_TONE' then
return "false"
end
end
end
end
log.notice("Start detecting fax")
detect_duration = detect_duration or 60000
session:setInputCallback("tone_detect_cb")
session:execute("tone_detect", "txfax 2100 r +" .. tostring(detect_duration) .. " set remote_fax_detected=txfax")
session:execute("tone_detect", "rxfax 1100 r +" .. tostring(detect_duration) .. " set remote_fax_detected=rxfax")
session:setVariable("sip_api_on_image", "uuid_break " .. session:getVariable("uuid") .. " all")
end
local function stop_fax_detect()
session:unsetInputCallback()
session:execute("stop_tone_detect")
session:setVariable("sip_api_on_image", "")
end
local function fax_deteced()
if session:getVariable('has_t38') == 'true' then
log.noticef('Detected t38')
session:setVariable('remote_fax_detected', 'txfax')
end
if fax_file and session:getVariable('remote_fax_detected') then
log.noticef("Detected %s", session:getVariable('remote_fax_detected'))
if session:getVariable('remote_fax_detected') == 'txfax' then
send_fax()
else
log.warning('Remote fax try send fax')
end
return true
end
end
local function check()
if not session:ready() then return false end
if fax_deteced() then return false end
return true
end
local function task()
local session_uuid = session:getVariable('uuid')
session:setVariable('fax_queue_task_session', session_uuid)
log.infof("SESSION UUID: %s", session_uuid)
session:waitForAnswer(session)
while not session:answered() do
if not session:ready() then return end
session:sleep(500)
end
if not (session:ready() and session:answered()) then return end
if fax_file and wav_file then
start_fax_detect()
end
if dtmf then
dtmf = decode_dtmf(dtmf)
for _, element in ipairs(dtmf) do
if type(element) == 'number' then
session:streamFile("silence_stream://" .. tostring(element))
else
session:execute("send_dtmf", element)
end
if not check() then return end
end
end
if wav_file then
session:streamFile(wav_file)
if not check() then return end
end
if fax_file then
if wav_file then
stop_fax_detect()
end
send_fax()
end
end
log.noticef("START TASK")
log.notice("Fax:" .. tostring(fax_file))
log.notice("Wav:" .. tostring(wav_file))
task()
log.noticef("STOP TASK")
log.notice("Ready: " .. tostring(session:ready()))
log.notice("Answered: " .. tostring(session:answered()))

View File

@@ -1,98 +0,0 @@
require "resources.functions.config"
require "resources.functions.sleep"
require "resources.functions.file_exists"
local log = require "resources.functions.log".next_fax_task
local Tasks = require "app.fax.resources.scripts.queue.tasks"
local Esl = require "resources.functions.esl"
local FAX_OPTIONS = {
"fax_use_ecm=false,fax_enable_t38=true,fax_enable_t38_request=true,fax_disable_v17=default";
"fax_use_ecm=true,fax_enable_t38=true,fax_enable_t38_request=true,fax_disable_v17=false";
"fax_use_ecm=true,fax_enable_t38=false,fax_enable_t38_request=false,fax_disable_v17=false";
"fax_use_ecm=true,fax_enable_t38=true,fax_enable_t38_request=true,fax_disable_v17=true";
"fax_use_ecm=false,fax_enable_t38=false,fax_enable_t38_request=false,fax_disable_v17=false";
}
local function task_send_mail(task, err)
local number_dialed = task.uri:match("/([^/]-)%s*$")
local Text = require "resources.functions.text"
local text = Text.new("app.fax.app_languages")
local env = {
destination_number = number_dialed:match("^([^@]*)");
hangup_cause = err;
message = text['message-send_fail'];
}
local body = Tasks.build_template(task, 'outbound/fail/body', env)
local subject = Tasks.build_template(task, 'outbound/fail/subject', env)
if not subject then
log.warning("Can not find template for email")
subject = "Fax to: " .. number_dialed .. " FAILED"
end
Tasks.send_mail_task(task, {subject, body}, nil, file_exists(task.fax_file))
end
local function next_task()
local task, err = Tasks.next_task()
if not task then
if err then
log.noticef('Can not select next task: %s', tostring(err))
else
log.notice("No task")
end
return
end
local esl
local ok, err = pcall(function()
local mode = (task.retry_counter % #FAX_OPTIONS) + 1
local dial_string = '{' ..
task.dial_string .. "api_hangup_hook='lua app/fax/resources/scripts/queue/retry.lua'," ..
FAX_OPTIONS[mode] ..
'}' .. task.uri
local originate = 'originate ' .. dial_string .. ' &lua(app/fax/resources/scripts/queue/exec.lua)'
log.notice(originate)
esl = assert(Esl.new())
local ok, status, info = esl:api(originate)
if not ok then
Tasks.wait_task(task, false, info)
if task.status ~= 0 then
Tasks.remove_task(task)
task_send_mail(task, tostring(info))
end
log.noticef('Can not originate to `%s` cause: %s: %s ', task.uri, tostring(status), tostring(info))
else
log.noticef("originate successfuly: %s", tostring(info))
end
end)
if esl then esl:close() end
if not ok then
Tasks.release_task(task)
log.noticef("Error execute task: %s", tostring(err))
end
return true
end
local function poll_once()
Tasks.cleanup_tasks()
while next_task() do
sleep(5000)
end
Tasks.release_db()
end
return {
poll_once = poll_once;
}

View File

@@ -1,418 +0,0 @@
-- include libraries
require "resources.functions.config";
require "resources.functions.split";
require "resources.functions.file_exists";
local log = require "resources.functions.log".fax_retry
local Database = require "resources.functions.database"
local Settings = require "resources.functions.lazy_settings"
local Tasks = require "app.fax.resources.scripts.queue.tasks"
local send_mail = require "resources.functions.send_mail"
--include json library
local json
if (debug["sql"]) then
json = require "resources.functions.lunajson"
end
local fax_task_uuid = env:getHeader('fax_task_uuid')
if not fax_task_uuid then
log.warning("No [fax_task_uuid] channel variable")
return
end
local task = Tasks.select_task(fax_task_uuid)
if not task then
log.warningf("Can not find fax task: %q", tostring(fax_task_uuid))
return
end
-- show all channel variables
if debug["fax_serialize"] then
log.noticef("info:\n%s", env:serialize())
end
local dbh = Database.new('system')
-- Global environment
default_language = env:getHeader("default_language")
default_dialect = env:getHeader("default_dialect")
-- Channel/FusionPBX variables
local uuid = env:getHeader("uuid")
local fax_queue_task_session = env:getHeader('fax_queue_task_session')
local domain_uuid = env:getHeader("domain_uuid") or task.domain_uuid
local domain_name = env:getHeader("domain_name") or task.domain_name
local origination_caller_id_name = env:getHeader("origination_caller_id_name") or '000000000000000'
local origination_caller_id_number = env:getHeader("origination_caller_id_number") or '000000000000000'
local accountcode = env:getHeader("accountcode") or domain_name
local duration = tonumber(env:getHeader("billmsec")) or 0
local sip_to_user = env:getHeader("sip_to_user")
local bridge_hangup_cause = env:getHeader("bridge_hangup_cause")
local hangup_cause_q850 = tonumber(env:getHeader("hangup_cause_q850"))
local answered = duration > 0
-- fax variables
local fax_success = env:getHeader('fax_success')
local has_t38 = env:getHeader('has_t38') or 'false'
local t38_broken_boolean = env:getHeader('t38_broken_boolean') or ''
local fax_result_code = tonumber(env:getHeader('fax_result_code')) or 2
local fax_result_text = env:getHeader('fax_result_text') or 'FS_NOT_SET'
local fax_ecm_used = env:getHeader('fax_ecm_used') or ''
local fax_local_station_id = env:getHeader('fax_local_station_id') or ''
local fax_document_transferred_pages = env:getHeader('fax_document_transferred_pages') or nil
local fax_document_total_pages = env:getHeader('fax_document_total_pages') or nil
local fax_image_resolution = env:getHeader('fax_image_resolution') or ''
local fax_image_size = env:getHeader('fax_image_size') or nil
local fax_bad_rows = env:getHeader('fax_bad_rows') or nil
local fax_transfer_rate = env:getHeader('fax_transfer_rate') or nil
local fax_v17_disabled = env:getHeader('fax_v17_disabled') or ''
local fax_ecm_requested = env:getHeader('fax_ecm_requested') or ''
local fax_remote_station_id = env:getHeader('fax_remote_station_id') or ''
local fax_options = ("fax_use_ecm=%s,fax_enable_t38=%s,fax_enable_t38_request=%s,fax_disable_v17=%s"):format(
env:getHeader('fax_use_ecm') or '',
env:getHeader('fax_enable_t38') or '',
env:getHeader('fax_enable_t38_request') or '',
env:getHeader('fax_disable_v17') or ''
)
-- Fax task params
local fax_uri = env:getHeader("fax_uri") or task.uri
local fax_file = env:getHeader("fax_file") or task.fax_file
local wav_file = env:getHeader("wav_file") or task.wav_file
local fax_uuid = task.fax_uuid
local pdf_file = fax_file and string.gsub(fax_file, '(%.[^\\/]+)$', '.pdf')
-- Email variables
local number_dialed = fax_uri:match("/([^/]-)%s*$")
log.noticef([[<<< CALL RESULT >>>
uuid: = '%s'
task_session_uuid: = '%s'
answered: = '%s'
fax_file: = '%s'
wav_file: = '%s'
fax_uri: = '%s'
sip_to_user: = '%s'
accountcode: = '%s'
origination_caller_id_name: = '%s'
origination_caller_id_number: = '%s'
mailto_address: = '%s'
hangup_cause_q850: = '%s'
fax_options = '%s'
]],
tostring(uuid) ,
tostring(fax_queue_task_session) ,
tostring(answered) ,
tostring(fax_file) ,
tostring(wav_file) ,
tostring(fax_uri) ,
tostring(sip_to_user) ,
tostring(accountcode) ,
tostring(origination_caller_id_name) ,
tostring(origination_caller_id_number) ,
tostring(task.reply_address) ,
tostring(hangup_cause_q850) ,
fax_options
)
if fax_success then
log.noticef([[<<< FAX RESULT >>>
fax_success = '%s'
has_t38 = '%s'
t38_broken_boolean = '%s'
fax_result_code = '%s'
fax_result_text = '%s'
fax_ecm_used = '%s'
fax_local_station_id = '%s'
fax_document_transferred_pages = '%s'
fax_document_total_pages = '%s'
fax_image_resolution = '%s'
fax_image_size = '%s'
fax_bad_rows = '%s'
fax_transfer_rate = '%s'
fax_v17_disabled = '%s'
fax_ecm_requested = '%s'
fax_remote_station_id = '%s'
'%s'
]],
fax_success ,
has_t38 ,
t38_broken_boolean ,
fax_result_code ,
fax_result_text ,
fax_ecm_used ,
fax_local_station_id ,
fax_document_transferred_pages ,
fax_document_total_pages ,
fax_image_resolution ,
fax_image_size ,
fax_bad_rows ,
fax_transfer_rate ,
fax_v17_disabled ,
fax_ecm_requested ,
fax_remote_station_id ,
'---------------------------------'
)
end
log.debug([[<<< DEBUG >>>
domain_name = '%s'
domain_uuid = '%s'
task.domain_name = '%s'
task.domain_uuid = '%s'
]],
tostring(domain_name ),
tostring(domain_uuid ),
tostring(task.domain_name ),
tostring(task.domain_uuid )
)
assert(fax_uuid, 'no fax server uuid')
assert(domain_name, 'no domain name')
assert(domain_uuid, 'no domain uuid')
assert(domain_uuid:lower() == task.domain_uuid:lower(), 'invalid domain uuid')
assert(domain_name:lower() == task.domain_name:lower(), 'invalid domain name')
--settings
local settings = Settings.new(dbh, domain_name, domain_uuid)
local keep_local = settings:get('fax', 'keep_local', 'boolean')
local storage_type = (keep_local == "false") and "" or settings:get('fax', 'storage_type', 'text')
local function opt(v, default)
if v then return "'" .. v .. "'" end
return default or 'NULL'
end
local function now_sql()
return (database["type"] == "sqlite") and "'"..os.date("%Y-%m-%d %X").."'" or "now()";
end
--add to fax logs
do
local fields = {
"fax_log_uuid";
"domain_uuid";
"fax_uuid";
"fax_success";
"fax_result_code";
"fax_result_text";
"fax_file";
"fax_ecm_used";
"fax_local_station_id";
"fax_document_transferred_pages";
"fax_document_total_pages";
"fax_image_resolution";
"fax_image_size";
"fax_bad_rows";
"fax_transfer_rate";
"fax_retry_attempts";
"fax_retry_limit";
"fax_retry_sleep";
"fax_uri";
"fax_epoch";
}
local params = {
fax_log_uuid = uuid;
domain_uuid = domain_uuid;
fax_uuid = fax_uuid or dbh.NULL;
fax_success = fax_success or dbh.NULL;
fax_result_code = fax_result_code or dbh.NULL;
fax_result_text = fax_result_text or dbh.NULL;
fax_file = fax_file or dbh.NULL;
fax_ecm_used = fax_ecm_used or dbh.NULL;
fax_local_station_id = fax_local_station_id or dbh.NULL;
fax_document_transferred_pages = fax_document_transferred_pages or '0';
fax_document_total_pages = fax_document_total_pages or '0';
fax_image_resolution = fax_image_resolution or dbh.NULL;
fax_image_size = fax_image_size or dbh.NULL;
fax_bad_rows = fax_bad_rows or dbh.NULL;
fax_transfer_rate = fax_transfer_rate or dbh.NULL;
fax_retry_attempts = fax_retry_attempts or dbh.NULL;
fax_retry_limit = fax_retry_limit or dbh.NULL;
fax_retry_sleep = fax_retry_sleep or dbh.NULL;
fax_uri = fax_uri or dbh.NULL;
fax_epoch = os.time();
}
local values = ":" .. table.concat(fields, ",:")
fields = table.concat(fields, ",") .. ",fax_date"
if database["type"] == "sqlite" then
params.fax_date = os.date("%Y-%m-%d %X");
values = values .. ",:fax_date"
else
values = values .. ",now()"
end
local sql = "insert into v_fax_logs(" .. fields .. ")values(" .. values .. ")"
if (debug["sql"]) then
log.noticef("SQL: %s; params: %s", sql, json.encode(params, dbh.NULL));
end
dbh:query(sql, params);
end
-- add the fax files
if fax_success == "1" then
if storage_type == "base64" then
--include the file io
local file = require "resources.functions.file"
--read file content as base64 string
fax_base64 = file.read_base64(fax_file);
if not fax_base64 then
log.waitng("Can not find file %s", fax_file)
storage_type = nil
end
end
-- build SQL
local sql do
local fields = {
"fax_file_uuid";
"fax_uuid";
"fax_mode";
"fax_destination";
"fax_file_type";
"fax_file_path";
"fax_caller_id_name";
"fax_caller_id_number";
"fax_epoch";
"fax_base64";
"domain_uuid";
}
local params = {
fax_file_uuid = uuid;
fax_uuid = fax_uuid or dbh.NULL;
fax_mode = "tx";
fax_destination = sip_to_user or dbh.NULL;
fax_file_type = "tif";
fax_file_path = fax_file or dbh.NULL;
fax_caller_id_name = origination_caller_id_name or dbh.NULL;
fax_caller_id_number = origination_caller_id_number or dbh.NULL;
fax_epoch = os.time();
fax_base64 = fax_base64 or dbh.NULL;
domain_uuid = domain_uuid or dbh.NULL;
}
local values = ":" .. table.concat(fields, ",:")
fields = table.concat(fields, ",") .. ",fax_date"
if database["type"] == "sqlite" then
params.fax_date = os.date("%Y-%m-%d %X");
values = values .. ",:fax_date"
else
values = values .. ",now()"
end
local sql = "insert into v_fax_files(" .. fields .. ")values(" .. values .. ")"
if (debug["sql"]) then
log.noticef("SQL: %s; params: %s", sql, json.encode(params, dbh.NULL));
end
if storage_type == "base64" then
local dbh = Database.new('system', 'base64');
dbh:query(sql, params);
dbh:release();
else
dbh:query(sql, params)
end
end
end
if fax_success == "1" then
--Success
log.infof("RETRY STATS SUCCESS: GATEWAY[%s]", fax_options);
Tasks.remove_task(task)
local Text = require "resources.functions.text"
local text = Text.new("app.fax.app_languages")
local env = {
fax_options = fax_options;
destination_number = number_dialed:match("^([^@]*)");
document_transferred_pages = fax_document_transferred_pages;
document_total_pages = fax_document_total_pages;
message = text['message-send_success'];
}
local body = Tasks.build_template(task, 'outbound/success/body', env)
local subject = Tasks.build_template(task, 'outbound/success/subject', env)
if not subject then
log.warning("Can not find template for email")
subject = "Fax to: " .. number_dialed .. " SENT"
end
local attachment = pdf_file and file_exists(pdf_file) or fax_file and file_exists(fax_file)
Tasks.send_mail_task(task, {subject, body}, uuid, attachment)
if keep_local == "false" then
os.remove(pdf_file);
os.remove(fax_file);
end
end
if fax_success ~= "1" then
if not answered then
log.noticef("no answer: %d", hangup_cause_q850)
else
if not fax_success then
log.noticef("Fax not detected: %s", fax_options)
else
log.noticef("fax fail %s", fax_options)
end
end
-- if task use group call then retry.lua will be called multiple times
-- here we check eathre that channel which execute `exec.lua`
-- Note that if there no one execute `exec.lua` we do not need call this
-- becase it should deal in `next.lua`
if fax_queue_task_session == uuid then
Tasks.wait_task(task, answered, hangup_cause_q850)
if task.status ~= 0 then
Tasks.remove_task(task)
local Text = require "resources.functions.text"
local text = Text.new("app.fax.app_languages")
local env = {
fax_options = fax_options;
destination_number = number_dialed:match("^([^@]*)");
document_transferred_pages = fax_document_transferred_pages;
document_total_pages = fax_document_total_pages;
hangup_cause = hangup_cause;
hangup_cause_q850 = hangup_cause_q850;
fax_result_code = fax_result_code;
fax_result_text = fax_result_text;
message = text['message-send_fail'];
}
local body = Tasks.build_template(task, 'outbound/fail/body', env)
local subject = Tasks.build_template(task, 'outbound/fail/subject', env)
if not subject then
log.warning("Can not find template for email")
subject = "Fax to: " .. number_dialed .. " FAILED"
end
local attachment = pdf_file and file_exists(pdf_file) or fax_file and file_exists(fax_file)
Tasks.send_mail_task(task, {subject, body}, uuid, attachment)
if keep_local == "false" then
os.remove(pdf_file);
os.remove(fax_file);
end
end
end
end

View File

@@ -1,330 +0,0 @@
local Database = require "resources.functions.database"
local Settings = require "resources.functions.lazy_settings"
local send_mail = require "resources.functions.send_mail"
local db
local date_utc_now_sql
local now_add_sec_sql
if database.type == 'pgsql' then
date_utc_now_sql = "NOW() at time zone 'utc'"
now_add_sec_sql = "NOW() at time zone 'utc' + interval '%s second'"
elseif database.type == 'mysql' then
date_utc_now_sql = "UTC_TIMESTAMP()"
now_add_sec_sql = "DATE_ADD(UTC_TIMESTAMP(), INTERVAL %s SECOND)"
elseif database.type == 'sqlite' then
date_utc_now_sql = "datetime('now')"
now_add_sec_sql = "datetime('now', '%s seconds')"
else
error("unsupported database type: " .. database.type)
end
-- Broken on FS 1.4 with native postgresql
-- Fixed on 1.6.0
-- Also works with ODBC
local ignore_affected_rows = true
if dbh_affected_rows_broken ~= nil then
ignore_affected_rows = dbh_affected_rows_broken
end
local Q850_TIMEOUT = {
[17] = 60;
}
local select_task_common_sql = [[
select
t1.fax_task_uuid as uuid,
t1.fax_uuid as fax_uuid,
t3.domain_name,
t3.domain_uuid,
t1.task_status as status,
t1.task_uri as uri,
t1.task_dial_string as dial_string,
t1.task_dtmf as dtmf,
t1.task_fax_file as fax_file,
t1.task_wav_file as wav_file,
t1.task_reply_address as reply_address,
t1.task_no_answer_counter as no_answer_counter,
t1.task_no_answer_retry_counter as no_answer_retry_counter,
t1.task_retry_counter as retry_counter,
t2.fax_send_greeting as greeting
from v_fax_tasks t1
inner join v_fax t2 on t2.fax_uuid = t1.fax_uuid
inner join v_domains t3 on t2.domain_uuid = t3.domain_uuid
where t1.task_interrupted <> 'true'
]]
local next_task_sql = select_task_common_sql .. [[
and t1.task_status = 0 and t1.task_next_time < ]] .. date_utc_now_sql .. [[
and t2.fax_send_channels > (select count(*) from v_fax_tasks as tasks
where tasks.fax_uuid = t1.fax_uuid and
tasks.task_status > 0 and tasks.task_status <= 2
)
order by t1.task_next_time
]]
local select_task_sql = select_task_common_sql .. "and t1.fax_task_uuid='%s'"
local aquire_task_sql = [[
update v_fax_tasks set task_status = 1, task_lock_time = ]] .. date_utc_now_sql .. [[
where fax_task_uuid = '%s' and task_status = 0
]]
local wait_task_sql = [[
update v_fax_tasks
set task_status = %s,
task_lock_time = NULL,
task_no_answer_counter = %s,
task_no_answer_retry_counter = %s,
task_retry_counter = %s,
task_next_time = ]] .. now_add_sec_sql .. [[
where fax_task_uuid = '%s'
]]
local remove_task_task_sql = [[
delete from v_fax_tasks
where fax_task_uuid = '%s'
]]
local release_task_sql = [[
update v_fax_tasks
set task_status = 0, task_lock_time = NULL,
task_next_time = ]] .. now_add_sec_sql .. [[
where fax_task_uuid = '%s'
]]
local release_stuck_tasks_sql = [[
update v_fax_tasks
set task_status = 0, task_lock_time = NULL,
task_next_time = ]] .. date_utc_now_sql .. [[
where task_lock_time < ]] .. now_add_sec_sql:format('-3600') .. [[
]]
local remove_finished_tasks_sql = [[
delete from v_fax_tasks where task_status > 3
]]
local function serialize(task, header)
local str = header or ''
for k, v in pairs(task) do
str = str .. ('\n %q = %q'):format(tostring(k), tostring(v))
end
return str
end
local function get_db()
if not db then
db = assert(Database.new('system'))
end
return db
end
local function next_task()
local db = get_db()
while true do
local task, err = db:first_row(next_task_sql)
if not task then return nil, err end
local ok, err = db:query( aquire_task_sql:format(task.uuid) )
if not ok then return nil, err end
local rows = db:affected_rows()
if ignore_affected_rows then
rows = 1
end
if rows == 1 then
task.no_answer_counter = tonumber(task.no_answer_counter)
task.no_answer_retry_counter = tonumber(task.no_answer_retry_counter)
task.retry_counter = tonumber(task.retry_counter)
return task
end
end
end
local function select_task(fax_task_uuid)
local db = get_db()
local task, err = db:first_row(select_task_sql:format(fax_task_uuid))
if not task then return nil, err end
task.no_answer_counter = tonumber(task.no_answer_counter)
task.no_answer_retry_counter = tonumber(task.no_answer_retry_counter)
task.retry_counter = tonumber(task.retry_counter)
return task
end
local function wait_task(task, answered, q850)
local db = get_db()
local interval = 30
local settings = Settings.new(db, task.domain_name, task.domain_uuid)
task.status = 0
if not answered then
interval = Q850_TIMEOUT[q850 or 17] or interval
end
if not answered then
local fax_send_no_answer_retry_limit = tonumber(settings:get('fax', 'send_no_answer_retry_limit', 'numeric')) or 0
task.no_answer_retry_counter = task.no_answer_retry_counter + 1
if task.no_answer_retry_counter >= fax_send_no_answer_retry_limit then
task.no_answer_retry_counter = 0
task.no_answer_counter = task.no_answer_counter + 1
local fax_send_no_answer_limit = tonumber(settings:get('fax', 'send_no_answer_limit', 'numeric')) or 0
if task.no_answer_counter >= fax_send_no_answer_limit then
task.status = 4
else
interval = tonumber(settings:get('fax', 'send_no_answer_interval', 'numeric')) or interval
end
else
interval = tonumber(settings:get('fax', 'send_no_answer_retry_interval', 'numeric')) or interval
end
else
task.retry_counter = task.retry_counter + 1
local fax_send_retry_limit = tonumber(settings:get('fax', 'send_retry_limit', 'numeric')) or 0
if task.retry_counter >= fax_send_retry_limit then
task.status = 4
else
interval = tonumber(settings:get('fax', 'send_retry_interval', 'numeric')) or interval
task.task_seq_call_counter = 0
end
end
local sql = wait_task_sql:format(
tostring(task.status),
tostring(task.no_answer_counter),
tostring(task.no_answer_retry_counter),
tostring(task.retry_counter),
tostring(interval),
task.uuid
)
local ok, err = db:query( sql )
if not ok then return nil, err end
return task
end
local function remove_task(task)
local db = get_db()
local sql = remove_task_task_sql:format(task.uuid)
local ok, err = db:query( sql )
if not ok then return nil, err end
return db:affected_rows()
end
local function release_task(task)
local db = get_db()
local interval = 30
local sql = release_task_sql:format(
tostring(interval),
task.uuid
)
local ok, err = db:query( sql )
if not ok then return nil, err end
return task
end
local function cleanup_tasks()
local db = get_db()
db:query(release_stuck_tasks_sql)
db:query(remove_finished_tasks_sql)
end
local function send_mail_task(task, message, call_uuid, file)
if not task.reply_address or #task.reply_address == 0 then
return
end
local mail_x_headers = {
["X-FusionPBX-Domain-UUID"] = task.domain_uuid;
["X-FusionPBX-Domain-Name"] = task.domain_name;
["X-FusionPBX-Call-UUID"] = call_uuid;
["X-FusionPBX-Email-Type"] = 'email2fax';
}
return send_mail(mail_x_headers, nil, task.reply_address, message, file)
end
local function read_file(name, mode)
local f, err, code = io.open(name, mode or 'rb')
if not f then return nil, err, code end
local data = f:read("*all")
f:close()
return data
end
local function read_template(app, name, lang)
local default_language_path = 'en/us'
local full_path_tpl = scripts_dir .. '/app/' .. app .. '/resources/templates/{lang}/' .. name .. '.tpl'
local path
if lang then
path = file_exists((full_path_tpl:gsub('{lang}', lang)))
end
if (not path) and (lang ~= default_language_path) then
path = file_exists((full_path_tpl:gsub('{lang}', default_language_path)))
end
if path then
return read_file(path)
end
end
local function build_template(task, templ, env)
local lang
if default_language and default_dialect then
lang = (default_language .. '/' .. default_dialect):lower()
else
local settings = Settings.new(get_db(), task.domain_name, task.domain_uuid)
lang = settings:get('domain', 'language', 'code')
if lang then lang = lang:gsub('%-', '/'):lower() end
end
local body = read_template('fax', templ, lang)
body = body:gsub("[^\\](${.-})", function(name)
name = name:sub(3, -2)
if type(env) == 'table' then
return env[name] or ''
end
if type(env) == 'function' then
return env(name) or ''
end
end)
return body
end
return {
release_db = function()
if db then
db:release()
db = nil
end
end;
next_task = next_task;
wait_task = wait_task;
select_task = select_task;
remove_task = remove_task;
release_task = release_task;
cleanup_tasks = cleanup_tasks;
send_mail_task = send_mail_task;
build_template = build_template;
}