refs #4550 Solved bugs
gitea/printnatura/pipeline/head This commit looks good Details

This commit is contained in:
Guillermo Bonet 2022-12-15 15:04:36 +01:00
parent 9156b45c30
commit f54c8ba9c7
6 changed files with 66 additions and 54 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules node_modules
config.local.yml config.local.yml
tmp

View File

@ -14,6 +14,16 @@ RUN curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - \
&& apt install -y nodejs \ && apt install -y nodejs \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Cups
RUN useradd admin && usermod -g lpadmin admin
COPY ctzcls-cups_1.1.0-0_amd64.deb /tmp/
RUN chmod a+x /tmp/ctzcls-cups_1.1.0-0_amd64.deb \
&& dpkg -i /tmp/ctzcls-cups_1.1.0-0_amd64.deb
# Printnatura
WORKDIR /printnatura WORKDIR /printnatura
COPY \ COPY \
@ -22,9 +32,6 @@ COPY \
./ ./
RUN npm install RUN npm install
COPY cupsd.conf /etc/cups/
RUN useradd admin && usermod -g lpadmin admin
COPY \ COPY \
main.js \ main.js \
print-server.js \ print-server.js \
@ -33,9 +40,5 @@ COPY \
./ ./
COPY sql sql COPY sql sql
COPY ctzcls-cups_1.1.0-0_amd64.deb /tmp/
RUN chmod a+x /tmp/ctzcls-cups_1.1.0-0_amd64.deb \
&& dpkg -i /tmp/ctzcls-cups_1.1.0-0_amd64.deb
ENTRYPOINT ["/printnatura/entrypoint.sh"] ENTRYPOINT ["/printnatura/entrypoint.sh"]
CMD ["node", "main.js"] CMD ["node", "main.js"]

View File

@ -8,12 +8,13 @@ This project is used to print pdf, it acts as a print server.
## Installaton ## Installaton
Clone the repository Clone the repository
``` ```
$ git clone https://gitea.verdnatura.es/verdnatura/printnatura.git > git clone https://gitea.verdnatura.es/verdnatura/printnatura.git
``` ```
Build Build
``` ```
$ docker build -t printnatura . > $CUPS_PASSWORD = 1234
> docker build --build-arg CUPS_PASSWORD -t printnatura .
``` ```
Create file named "config.local.yml" and put your private configuration: Create file named "config.local.yml" and put your private configuration:
@ -35,12 +36,13 @@ refreshRate: 1000
Exec Exec
``` ```
$ docker run --name printnatura -it --rm -v $PWD/config.local.yml:/printnatura/config.local.yml:ro -p 80:631 printnatura > docker run --name printnatura -it --rm -v $PWD/config.local.yml:/printnatura/config.local.yml:ro -v $PWD/cupsd.conf:/etc/cups/cupsd.conf:ro -p 80:631 printnatura
``` ```
Bash Bash
``` ```
$ docker exec -i -t printnatura bash > docker exec -i -t printnatura bash
``` ```
Has a graphical web interface (cupsd.conf) Has a graphical web interface (cupsd.conf)

View File

@ -7,6 +7,7 @@ const axios = require('axios');
const yml = require('require-yml'); const yml = require('require-yml');
const selectQuery = fs.readFileSync(`sql/selectQueued.sql`).toString(); const selectQuery = fs.readFileSync(`sql/selectQueued.sql`).toString();
const jobDataQuery = fs.readFileSync(`sql/jobData.sql`).toString();
const jobArgsQuery = fs.readFileSync(`sql/jobArgs.sql`).toString(); const jobArgsQuery = fs.readFileSync(`sql/jobArgs.sql`).toString();
const updateQuery = fs.readFileSync(`sql/updateState.sql`).toString(); const updateQuery = fs.readFileSync(`sql/updateState.sql`).toString();
const appDir = path.dirname(require.main.filename); const appDir = path.dirname(require.main.filename);
@ -92,7 +93,6 @@ class PrintServer {
} }
jobId = printJob.id; jobId = printJob.id;
this.method = printJob.method;
await conn.query(updateQuery, ['printing', null, jobId]); await conn.query(updateQuery, ['printing', null, jobId]);
await conn.commit(); await conn.commit();
@ -102,22 +102,27 @@ class PrintServer {
} }
try { try {
// Job data
const [[jobData]] = await conn.query(jobDataQuery, jobId);
const args = {}; const args = {};
const res = await conn.query(jobArgsQuery, jobId); const [res] = await conn.query(jobArgsQuery, jobId);
for (const row of res[0]) for (const row of res)
args[row.name] = row.value; args[row.name] = row.value;
try {
// Path params
const usedParams = new Set();
let methodPath = this.method.replace(/{\w+}/g, function(match) {
const key = match.substr(1, match.length - 2);
const value = args[key];
usedParams.add(key);
return value !== undefined ? value : match;
});
// Path params
const usedParams = new Set();
const methodPath = jobData.method.replace(/{\w+}/g, function(match) {
const key = match.substr(1, match.length - 2);
const value = args[key];
usedParams.add(key);
return value !== undefined ? value : match;
});
let pdfData;
for (let attempts = 0; !pdfData && attempts <= 1; attempts++) {
// URL params // URL params
let params = { const params = {
access_token: this.token, access_token: this.token,
userFk: printJob.userFk userFk: printJob.userFk
}; };
@ -128,34 +133,34 @@ class PrintServer {
const urlParams = new URLSearchParams(params); const urlParams = new URLSearchParams(params);
// Request // Request
const response = await axios({ try {
method: 'get', const response = await axios({
url: `${conf.salix.url}/api/${methodPath}?${urlParams.toString()}`, method: 'get',
responseType: 'arraybuffer', url: `${conf.salix.url}/api/${methodPath}?${urlParams.toString()}`,
headers: { responseType: 'arraybuffer',
'Accept': 'application/pdf' headers: {
} 'Accept': 'application/pdf'
});
this.pdfData = response.data
}
catch (err) {
switch(err.response.statusText) {
case 'Unauthorized':
try {
await this.getToken();
} catch(err) {
throw new Error(`Could not get token: ${err.message}`);
} }
break; });
pdfData = response.data;
}
catch (err) {
if (err.response?.statusText === 'Unauthorized') {
await this.getToken();
} else
throw err;
} }
} }
const printer = printJob.printer;
// Save PDF to disk
const printer = jobData.printer;
const tmpPath = path.join(appDir, 'tmp') const tmpPath = path.join(appDir, 'tmp')
if (!fs.existsSync(tmpPath)) if (!fs.existsSync(tmpPath))
fs.mkdirSync(tmpPath) fs.mkdirSync(tmpPath)
const tmpFilePath = path.join(tmpPath, `${Math.random().toString(36).substring(7)}.pdf`); const tmpFilePath = path.join(tmpPath, `${Math.random().toString(36).substring(7)}.pdf`);
await fs.writeFile(tmpFilePath, this.pdfData, 'binary'); await fs.writeFile(tmpFilePath, pdfData, 'binary');
// Print PDF
try { try {
await pExec(`lp -d "${printer}" "${tmpFilePath}"`); await pExec(`lp -d "${printer}" "${tmpFilePath}"`);
} catch(err) { } catch(err) {
@ -166,7 +171,7 @@ class PrintServer {
await conn.query(updateQuery, ['printed', null, jobId]); await conn.query(updateQuery, ['printed', null, jobId]);
if (conf.debug) if (conf.debug)
console.debug(`(${colors.yellow(jobId)}) Document has been printed`, `[${args.collectionFk}, ${printJob.report}, ${printer}]`.green); console.debug(`(${colors.yellow(jobId)}) Document has been printed`, `[${args.collectionFk}, ${jobData.report}, ${printer}]`.green);
await fs.unlink(tmpFilePath); await fs.unlink(tmpFilePath);
} catch (err) { } catch (err) {

7
sql/jobData.sql Normal file
View File

@ -0,0 +1,7 @@
SELECT r.name report,
p.name printer,
r.method
FROM printQueue pq
JOIN report r ON r.id = pq.reportFk
JOIN printer p ON p.id = pq.printerFk
WHERE pq.id = ?

View File

@ -1,15 +1,9 @@
SELECT pq.id, SELECT pq.id,
r.name report,
p.name printer,
pqa.name arg,
pqa.value,
r.method,
pq.workerFk userFk pq.workerFk userFk
FROM printQueue pq FROM printQueue pq
JOIN report r ON r.id = pq.reportFk JOIN report r ON r.id = pq.reportFk
JOIN printQueueArgs pqa ON pqa.printQueueFk = pq.id
LEFT JOIN printer p ON p.id = pq.printerFk
WHERE pq.statusCode = 'queued' WHERE pq.statusCode = 'queued'
AND NOT r.method IS NULL AND r.method IS NOT NULL
ORDER BY pq.priorityFk ASC ORDER BY pq.priorityFk ASC
LIMIT 1 LIMIT 1
FOR UPDATE