printnatura/print-server.js

159 lines
5.1 KiB
JavaScript
Raw Normal View History

2022-11-04 13:41:36 +00:00
const mysql = require('mysql2/promise');
const exec = require('child_process').exec;
const fs = require('fs-extra');
const path = require('path');
const colors = require('colors');
const axios = require('axios');
const yml = require('require-yml');
const selectQuery = fs.readFileSync(`sql/selectQueued.sql`).toString();
const jobArgsQuery = fs.readFileSync(`sql/jobArgs.sql`).toString();
const updateQuery = fs.readFileSync(`sql/updateState.sql`).toString();
const appDir = path.dirname(require.main.filename);
class PrintServer {
async start() {
let conf = yml(path.join(__dirname, 'config.yml'));
const localConfFile = path.join(__dirname, 'config.local.yml');
if (fs.existsSync(localConfFile))
conf = Object.assign({}, conf, yml(localConfFile));
this.conf = conf;
2022-11-07 09:24:16 +00:00
let decoration = '△▽△▽△▽△▽△▽△▽△▽△▽△▽△▽'
2022-11-04 13:41:36 +00:00
console.clear();
2022-11-07 09:24:16 +00:00
console.log(decoration, `${colors.bgBlack.white.bold(' Print')}${colors.bgBlack.green.bold('Natura ')}`, decoration, '\n')
2022-11-04 13:41:36 +00:00
await this.init();
}
async init() {
this.conn = await mysql.createConnection(this.conf.db);
this.conn.on('error', err => this.onDbError(err));
await this.getToken();
await this.poll();
}
async stop() {
await this.end();
}
async end() {
clearTimeout(this.pollTimeout);
await this.conn.end();
if (this.reconnectTimeout) {
clearTimeout(this.reconnectTimeout);
this.reconnectTimeout = null;
}
}
async getToken() {
let response = await axios.post(`${this.conf.salix.url}/api/Accounts/login`, {
user: this.conf.salix.user,
password: this.conf.salix.password
});
this.token = response.data.token
}
async onDbError(err) {
switch(err.code) {
case 'CONNECTION_CLOSE':
try {
await this.end();
} catch(e) {}
await this.reconnect();
break;
}
}
async reconnect() {
this.reconnectTimeout = null;
try {
await this.init();
} catch (err) {
this.reconnectTimeout = setTimeout(reconnect, this.conf.reconnectTimeout * 1000);
}
}
async poll() {
try {
await this.printJob();
} catch (err) {
console.error(err)
this.reconnect();
}
this.pollTimeout = setTimeout(() => this.poll(), this.conf.refreshRate);
}
async printJob() {
const conn = this.conn;
const conf = this.conf;
let printJob;
let jobId;
try {
await conn.beginTransaction();
[[printJob]] = await conn.query(selectQuery, 'LabelCollection');
if (!printJob) return;
jobId = printJob.id;
await conn.query(updateQuery, ['printing', null, jobId]);
await conn.commit();
} catch (err) {
conn.rollback();
throw err;
}
try {
const args = {};
const res = await conn.query(jobArgsQuery, jobId);
for (const row of res[0])
args[row.name] = row.value;
const response = await axios({
method: 'get',
url: `${conf.salix.url}/api/Tickets/${args.param}/collection-label?access_token=${this.token}`,
responseType: 'arraybuffer',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/pdf'
}
});
const printer = printJob.printer;
2022-11-04 13:53:18 +00:00
if (!fs.existsSync(path.join(appDir, 'tmp')))
fs.mkdirSync(path.join(appDir, 'tmp'))
2022-11-04 13:41:36 +00:00
const tmpFilePath = path.join(appDir, 'tmp', `${Math.random().toString(36).substring(7)}.pdf`);
await fs.writeFile(tmpFilePath, response.data, 'binary');
try {
await pExec(`lp -d "${printer}" "${tmpFilePath}"`);
} catch(err) {
await fs.unlink(tmpFilePath);
throw new Error(`The printer could not be accessed: ${printer}: ${err.message}`);
}
await conn.query(updateQuery, ['printed', null, jobId]);
if (conf.debug)
2022-11-07 09:24:16 +00:00
console.debug(`(${colors.yellow(jobId)}) Document has been printed`, `[${printer}, ${printJob.report}]`.green);
2022-11-04 13:41:36 +00:00
await fs.unlink(tmpFilePath);
} catch (err) {
switch(err.code) {
case 'ERR_BAD_REQUEST':
try {
await this.getToken();
} catch(err) {
console.error(err);
}
break;
}
await this.conn.query(updateQuery, ['error', err.message, jobId]);
throw new Error(`(${jobId}) ${err.message}`);
}
}
}
module.exports = PrintServer;
function pExec(command) {
return new Promise(function(resolve, reject) {
exec(command, function(err, stdout, stderr) {
if (err) return reject(err);
resolve({stdout, stderr})
});
});
}