salix/back/methods/osticket/closeTicket.js

156 lines
5.9 KiB
JavaScript

const jsdom = require('jsdom');
const mysql = require('mysql');
const FormData = require('form-data');
module.exports = Self => {
Self.remoteMethodCtx('closeTicket', {
description: 'Close tickets without response from the user',
accessType: 'READ',
returns: {
type: 'object',
root: true
},
http: {
path: `/closeTicket`,
verb: 'POST'
}
});
Self.closeTicket = async ctx => {
const models = Self.app.models;
const config = await models.OsTicketConfig.findOne();
const ostUri = `${config.host}/login.php`;
if (!config.user || !config.password || !config.userDb || !config.passwordDb)
return false;
const con = mysql.createConnection({
host: config.hostDb,
user: config.userDb,
password: config.passwordDb,
port: config.portDb
});
const sql = `SELECT ot.ticket_id, ot.number
FROM osticket.ost_ticket ot
JOIN osticket.ost_ticket_status ots ON ots.id = ot.status_id
JOIN osticket.ost_thread ot2 ON ot2.object_id = ot.ticket_id AND ot2.object_type = 'T'
JOIN (
SELECT sub2.thread_id, sub2.type, sub2.updated, sub2.created
FROM (
SELECT ote.thread_id, ote.created, ote.updated, ote.type
FROM osticket.ost_thread_entry ote
WHERE ote.staff_id
ORDER BY ote.id DESC
LIMIT 10000000000000000000) sub2
GROUP BY sub2.thread_id
) sub ON sub.thread_id = ot2.id
WHERE ot.isanswered
AND ots.id IN (?)
AND sub.type = 'R'
AND IF(sub.updated > sub.created, sub.updated, sub.created) < DATE_SUB(CURDATE(), INTERVAL ? DAY);`;
const ticketsId = [];
const statusIdToClose = config.oldStatus.split(',');
con.connect(err => {
if (err) throw err;
con.query(sql, [statusIdToClose, config.day],
(err, results) => {
if (err) throw err;
for (const result of results)
ticketsId.push(result.ticket_id);
});
});
await getRequestToken();
async function getRequestToken() {
const response = await fetch(ostUri);
const result = response.headers.get('set-cookie');
const [firtHeader] = result.split(' ');
const cookie = firtHeader.substring(0, firtHeader.length - 1);
const body = await response.text();
const dom = new jsdom.JSDOM(body);
const token = dom.window.document.querySelector('[name="__CSRFToken__"]').value;
await login(token, cookie);
}
async function login(token, cookie) {
const data = {
__CSRFToken__: token,
do: 'scplogin',
userid: config.user,
passwd: config.password,
ajax: 1
};
const params = {
method: 'POST',
body: new URLSearchParams(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': cookie
}
};
await fetch(ostUri, params);
await close(token, cookie);
}
async function close(token, cookie) {
for (const ticketId of ticketsId) {
try {
const lock = await getLockCode(token, cookie, ticketId);
if (!lock.code) {
let error = `Can't get lock code`;
if (lock.msg) error += `: ${lock.msg}`;
throw new Error(error);
}
let form = new FormData();
form.append('__CSRFToken__', token);
form.append('id', ticketId);
form.append('a', config.responseType);
form.append('lockCode', lock.code);
form.append('from_email_id', config.fromEmailId);
form.append('reply-to', config.replyTo);
form.append('cannedResp', 0);
form.append('response', config.comment);
form.append('signature', 'none');
form.append('reply_status_id', config.newStatusId);
const ostUri = `${config.host}/tickets.php?id=${ticketId}`;
const params = {
method: 'POST',
body: form,
headers: {
'Cookie': cookie
}
};
await fetch(ostUri, params);
} catch (e) {
const err = new Error(`${ticketId} Ticket close failed: ${e.message}`);
err.stack += e.stack;
console.error(err);
}
}
}
async function getLockCode(token, cookie, ticketId) {
const ostUri = `${config.host}/ajax.php/lock/ticket/${ticketId}`;
const params = {
method: 'POST',
headers: {
'X-CSRFToken': token,
'Cookie': cookie
}
};
const response = await fetch(ostUri, params);
const body = await response.text();
const json = JSON.parse(body);
return json;
}
};
};