Implement SonarCloud generic fix
This commit is contained in:
parent
ecc8c2dd1b
commit
a3935bb90a
@ -5,7 +5,7 @@ module.exports = {
|
|||||||
'node': true,
|
'node': true,
|
||||||
},
|
},
|
||||||
'extends': [
|
'extends': [
|
||||||
'eslint:recommended',
|
'google',
|
||||||
],
|
],
|
||||||
'parserOptions': {
|
'parserOptions': {
|
||||||
'ecmaVersion': 'latest',
|
'ecmaVersion': 'latest',
|
||||||
|
@ -4,7 +4,11 @@
|
|||||||
},
|
},
|
||||||
"shared": {
|
"shared": {
|
||||||
"presDir": "/var/bigbluebutton",
|
"presDir": "/var/bigbluebutton",
|
||||||
"presAnnDropboxDir": "/tmp/pres-ann-dropbox"
|
"presAnnDropboxDir": "/tmp/pres-ann-dropbox",
|
||||||
|
"cairosvg": "/usr/bin/cairosvg",
|
||||||
|
"ghostscript": "/usr/bin/gs",
|
||||||
|
"imagemagick": "/usr/bin/convert",
|
||||||
|
"pdftocairo": "/usr/bin/pdftocairo"
|
||||||
},
|
},
|
||||||
"collector": {
|
"collector": {
|
||||||
"pngWidthRasterizedSlides": 2560
|
"pngWidthRasterizedSlides": 2560
|
||||||
|
@ -4,7 +4,7 @@ const fs = require('fs');
|
|||||||
const redis = require('redis');
|
const redis = require('redis');
|
||||||
const {Worker, workerData, parentPort} = require('worker_threads');
|
const {Worker, workerData, parentPort} = require('worker_threads');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const {execSync} = require('child_process');
|
const cp = require('child_process');
|
||||||
|
|
||||||
const jobId = workerData;
|
const jobId = workerData;
|
||||||
|
|
||||||
@ -77,7 +77,6 @@ const exportJob = JSON.parse(job);
|
|||||||
// so it matches what was shown in the browser.
|
// so it matches what was shown in the browser.
|
||||||
|
|
||||||
const extract_png_from_pdf = [
|
const extract_png_from_pdf = [
|
||||||
'pdftocairo',
|
|
||||||
'-png',
|
'-png',
|
||||||
'-f', pageNumber,
|
'-f', pageNumber,
|
||||||
'-l', pageNumber,
|
'-l', pageNumber,
|
||||||
@ -85,9 +84,9 @@ const exportJob = JSON.parse(job);
|
|||||||
'-singlefile',
|
'-singlefile',
|
||||||
'-cropbox',
|
'-cropbox',
|
||||||
pdfFile, outputFile,
|
pdfFile, outputFile,
|
||||||
].join(' ');
|
];
|
||||||
|
|
||||||
execSync(extract_png_from_pdf);
|
cp.spawnSync(config.shared.pdftocairo, extract_png_from_pdf, {shell: false});
|
||||||
}
|
}
|
||||||
// If PNG file already available
|
// If PNG file already available
|
||||||
} else if (fs.existsSync(`${presFile}.png`)) {
|
} else if (fs.existsSync(`${presFile}.png`)) {
|
||||||
|
@ -8,7 +8,7 @@ const path = require('path');
|
|||||||
|
|
||||||
const {workerData, parentPort} = require('worker_threads');
|
const {workerData, parentPort} = require('worker_threads');
|
||||||
|
|
||||||
const [jobType, jobId, filename] = workerData;
|
const [jobType, jobId, filename_with_extension] = workerData;
|
||||||
|
|
||||||
const logger = new Logger('presAnn Notifier Worker');
|
const logger = new Logger('presAnn Notifier Worker');
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ async function notifyMeetingActor() {
|
|||||||
|
|
||||||
await client.connect();
|
await client.connect();
|
||||||
client.on('error', (err) => logger.info('Redis Client Error', err));
|
client.on('error', (err) => logger.info('Redis Client Error', err));
|
||||||
const link = `${config.notifier.protocol}://${config.notifier.host}/bigbluebutton/presentation/${exportJob.parentMeetingId}/${exportJob.parentMeetingId}/${exportJob.presId}/pdf/${jobId}/${filename}.pdf`;
|
const link = `${config.notifier.protocol}://${config.notifier.host}/bigbluebutton/presentation/${exportJob.parentMeetingId}/${exportJob.parentMeetingId}/${exportJob.presId}/pdf/${jobId}/${filename_with_extension}`;
|
||||||
const notification = {
|
const notification = {
|
||||||
envelope: {
|
envelope: {
|
||||||
name: config.notifier.msgName,
|
name: config.notifier.msgName,
|
||||||
@ -59,7 +59,7 @@ async function notifyMeetingActor() {
|
|||||||
async function upload() {
|
async function upload() {
|
||||||
const callbackUrl = `http://${config.bbbWeb.host}:${config.bbbWeb.port}/bigbluebutton/presentation/${exportJob.presentationUploadToken}/upload`;
|
const callbackUrl = `http://${config.bbbWeb.host}:${config.bbbWeb.port}/bigbluebutton/presentation/${exportJob.presentationUploadToken}/upload`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
const file = `${exportJob.presLocation}/pdfs/${jobId}/${filename}.pdf`;
|
const file = `${exportJob.presLocation}/pdfs/${jobId}/${filename_with_extension}`;
|
||||||
|
|
||||||
formData.append('conference', exportJob.parentMeetingId);
|
formData.append('conference', exportJob.parentMeetingId);
|
||||||
formData.append('pod_id', config.notifier.pod_id);
|
formData.append('pod_id', config.notifier.pod_id);
|
||||||
|
@ -2,7 +2,7 @@ const Logger = require('../lib/utils/logger');
|
|||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const {create} = require('xmlbuilder2', {encoding: 'utf-8'});
|
const {create} = require('xmlbuilder2', {encoding: 'utf-8'});
|
||||||
const {execSync} = require('child_process');
|
const cp = require('child_process');
|
||||||
const {Worker, workerData, parentPort} = require('worker_threads');
|
const {Worker, workerData, parentPort} = require('worker_threads');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const sanitize = require('sanitize-filename');
|
const sanitize = require('sanitize-filename');
|
||||||
@ -130,12 +130,13 @@ function to_px(pt) {
|
|||||||
// the escape-string-regexp npm package, and Pango markup.
|
// the escape-string-regexp npm package, and Pango markup.
|
||||||
function escapeText(string) {
|
function escapeText(string) {
|
||||||
return string
|
return string
|
||||||
|
.replace(/[~`!.*+?%^${}()|[\]\\/]/g, '\\$&')
|
||||||
|
.replace(/-/g, '\\-')
|
||||||
.replace(/&/g, '\\&')
|
.replace(/&/g, '\\&')
|
||||||
.replace(/'/g, '\\'')
|
.replace(/'/g, '\\'')
|
||||||
|
.replace(/"/g, '\\"')
|
||||||
.replace(/>/g, '\\>')
|
.replace(/>/g, '\\>')
|
||||||
.replace(/</g, '\\<')
|
.replace(/</g, '\\<');
|
||||||
.replace(/[~`!".*+?%^${}()|[\]\\/]/g, '\\$&')
|
|
||||||
.replace(/-/g, '\\-');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth = null) {
|
function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth = null) {
|
||||||
@ -144,7 +145,7 @@ function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxW
|
|||||||
|
|
||||||
// Sticky notes need automatic line wrapping: take width into account
|
// Sticky notes need automatic line wrapping: take width into account
|
||||||
// Texbox scaled by a constant factor to improve resolution at small scales
|
// Texbox scaled by a constant factor to improve resolution at small scales
|
||||||
const size = textBoxWidth ? `-size ${textBoxWidth * config.process.textScaleFactor}x` : '';
|
const size = textBoxWidth ? ['-size', `${textBoxWidth * config.process.textScaleFactor}x`] : [];
|
||||||
|
|
||||||
const pangoText = `pango:"<span font_family='${font}' font='${fontSize}' color='${textColor}'>${text}</span>"`;
|
const pangoText = `pango:"<span font_family='${font}' font='${fontSize}' color='${textColor}'>${text}</span>"`;
|
||||||
|
|
||||||
@ -152,19 +153,18 @@ function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxW
|
|||||||
textAlign = justify ? 'left' : textAlign;
|
textAlign = justify ? 'left' : textAlign;
|
||||||
|
|
||||||
const commands = [
|
const commands = [
|
||||||
'convert',
|
|
||||||
'-encoding', `${config.process.whiteboardTextEncoding}`,
|
'-encoding', `${config.process.whiteboardTextEncoding}`,
|
||||||
'-density', config.process.pixelsPerInch,
|
'-density', config.process.pixelsPerInch,
|
||||||
'-background', 'transparent',
|
'-background', 'transparent'].concat(size,
|
||||||
size,
|
[
|
||||||
'-define', `pango:align=${textAlign}`,
|
'-define', `pango:align=${textAlign}`,
|
||||||
'-define', `pango:justify=${justify}`,
|
'-define', `pango:justify=${justify}`,
|
||||||
'-define', 'pango:wrap=word-char',
|
'-define', 'pango:wrap=word-char',
|
||||||
pangoText,
|
pangoText,
|
||||||
path.join(dropbox, `text${id}.png`),
|
path.join(dropbox, `text${id}.png`),
|
||||||
].join(' ');
|
]);
|
||||||
|
|
||||||
execSync(commands);
|
cp.spawnSync(config.shared.imagemagick, commands, {shell: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_gap(dash, size) {
|
function get_gap(dash, size) {
|
||||||
@ -244,7 +244,7 @@ function getPath(annotationPoints) {
|
|||||||
.map((strokePoint) => strokePoint.point);
|
.map((strokePoint) => strokePoint.point);
|
||||||
|
|
||||||
let [max_x, max_y] = [0, 0];
|
let [max_x, max_y] = [0, 0];
|
||||||
const path = stroke.reduce(
|
const inner_path = stroke.reduce(
|
||||||
(acc, [x0, y0], i, arr) => {
|
(acc, [x0, y0], i, arr) => {
|
||||||
if (!arr[i + 1]) return acc;
|
if (!arr[i + 1]) return acc;
|
||||||
const [x1, y1] = arr[i + 1];
|
const [x1, y1] = arr[i + 1];
|
||||||
@ -261,8 +261,7 @@ function getPath(annotationPoints) {
|
|||||||
['M', ...stroke[0], 'Q'],
|
['M', ...stroke[0], 'Q'],
|
||||||
);
|
);
|
||||||
|
|
||||||
path.join(' ');
|
return [inner_path, max_x, max_y];
|
||||||
return [path, max_x, max_y];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOutlinePath(annotationPoints) {
|
function getOutlinePath(annotationPoints) {
|
||||||
@ -273,7 +272,7 @@ function getOutlinePath(annotationPoints) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let [max_x, max_y] = [0, 0];
|
let [max_x, max_y] = [0, 0];
|
||||||
const path = stroke.reduce(
|
const outline_path = stroke.reduce(
|
||||||
(acc, [x0, y0], i, arr) => {
|
(acc, [x0, y0], i, arr) => {
|
||||||
const [x1, y1] = arr[(i + 1) % arr.length];
|
const [x1, y1] = arr[(i + 1) % arr.length];
|
||||||
if (x1 >= max_x) {
|
if (x1 >= max_x) {
|
||||||
@ -289,10 +288,9 @@ function getOutlinePath(annotationPoints) {
|
|||||||
['M', ...stroke[0], 'Q'],
|
['M', ...stroke[0], 'Q'],
|
||||||
);
|
);
|
||||||
|
|
||||||
path.push('Z');
|
outline_path.push('Z');
|
||||||
path.join(' ');
|
|
||||||
|
|
||||||
return [path, max_x, max_y];
|
return [outline_path, max_x, max_y];
|
||||||
}
|
}
|
||||||
|
|
||||||
function circleFromThreePoints(A, B, C) {
|
function circleFromThreePoints(A, B, C) {
|
||||||
@ -474,10 +472,9 @@ function overlay_arrow(svg, annotation) {
|
|||||||
|
|
||||||
function overlay_draw(svg, annotation) {
|
function overlay_draw(svg, annotation) {
|
||||||
const dash = annotation.style.dash;
|
const dash = annotation.style.dash;
|
||||||
|
const [calculated_path, max_x, max_y] = (dash == 'draw') ? getOutlinePath(annotation.points) : getPath(annotation.points);
|
||||||
|
|
||||||
const [path, max_x, max_y] = (dash == 'draw') ? getOutlinePath(annotation.points) : getPath(annotation.points);
|
if (!calculated_path.length) return;
|
||||||
|
|
||||||
if (!path.length) return;
|
|
||||||
|
|
||||||
const shapeColor = color_to_hex(annotation.style.color);
|
const shapeColor = color_to_hex(annotation.style.color);
|
||||||
const rotation = rad_to_degree(annotation.rotation);
|
const rotation = rad_to_degree(annotation.rotation);
|
||||||
@ -514,7 +511,7 @@ function overlay_draw(svg, annotation) {
|
|||||||
|
|
||||||
svg.ele('path', {
|
svg.ele('path', {
|
||||||
style: `stroke:${shapeColor};stroke-width:${thickness};fill:${fill};${stroke_dasharray}`,
|
style: `stroke:${shapeColor};stroke-width:${thickness};fill:${fill};${stroke_dasharray}`,
|
||||||
d: path,
|
d: calculated_path,
|
||||||
transform: shapeTransform,
|
transform: shapeTransform,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -780,7 +777,7 @@ const exportJob = JSON.parse(job);
|
|||||||
const annotations = fs.readFileSync(path.join(dropbox, 'whiteboard'));
|
const annotations = fs.readFileSync(path.join(dropbox, 'whiteboard'));
|
||||||
const whiteboard = JSON.parse(annotations);
|
const whiteboard = JSON.parse(annotations);
|
||||||
const pages = JSON.parse(whiteboard.pages);
|
const pages = JSON.parse(whiteboard.pages);
|
||||||
let ghostScriptInput = '';
|
const ghostScriptInput = [];
|
||||||
|
|
||||||
// 3. Convert annotations to SVG
|
// 3. Convert annotations to SVG
|
||||||
for (const currentSlide of pages) {
|
for (const currentSlide of pages) {
|
||||||
@ -848,16 +845,15 @@ for (const currentSlide of pages) {
|
|||||||
// generates with the original size in pt.
|
// generates with the original size in pt.
|
||||||
|
|
||||||
const convertAnnotatedSlide = [
|
const convertAnnotatedSlide = [
|
||||||
'cairosvg',
|
|
||||||
SVGfile,
|
SVGfile,
|
||||||
'--output-width', to_px(slideWidth),
|
'--output-width', to_px(slideWidth),
|
||||||
'--output-height', to_px(slideHeight),
|
'--output-height', to_px(slideHeight),
|
||||||
'-o', PDFfile,
|
'-o', PDFfile,
|
||||||
].join(' ');
|
];
|
||||||
|
|
||||||
execSync(convertAnnotatedSlide);
|
cp.spawnSync(config.shared.cairosvg, convertAnnotatedSlide, {shell: false});
|
||||||
|
|
||||||
ghostScriptInput += `${PDFfile} `;
|
ghostScriptInput.push(PDFfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create PDF output directory if it doesn't exist
|
// Create PDF output directory if it doesn't exist
|
||||||
@ -867,23 +863,20 @@ if (!fs.existsSync(outputDir)) {
|
|||||||
fs.mkdirSync(outputDir, {recursive: true});
|
fs.mkdirSync(outputDir, {recursive: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
const filename = sanitize(exportJob.filename.replace(/\s/g, '_'));
|
const filename_with_extension = `${sanitize(exportJob.filename.replace(/\s/g, '_'))}.pdf`;
|
||||||
|
|
||||||
const mergePDFs = [
|
const mergePDFs = [
|
||||||
'gs',
|
|
||||||
'-dNOPAUSE',
|
'-dNOPAUSE',
|
||||||
'-sDEVICE=pdfwrite',
|
'-sDEVICE=pdfwrite',
|
||||||
`-sOUTPUTFILE="${path.join(outputDir, `${filename}.pdf`)}"`,
|
`-sOUTPUTFILE="${path.join(outputDir, filename_with_extension)}"`,
|
||||||
`-dBATCH`,
|
`-dBATCH`].concat(ghostScriptInput);
|
||||||
ghostScriptInput,
|
|
||||||
].join(' ');
|
|
||||||
|
|
||||||
// Resulting PDF file is stored in the presentation dir
|
// Resulting PDF file is stored in the presentation dir
|
||||||
execSync(mergePDFs);
|
cp.spawnSync(config.shared.ghostscript, mergePDFs, {shell: false});
|
||||||
|
|
||||||
// Launch Notifier Worker depending on job type
|
// Launch Notifier Worker depending on job type
|
||||||
logger.info(`Saved PDF at ${outputDir}/${jobId}/${filename}.pdf`);
|
logger.info(`Saved PDF at ${outputDir}/${jobId}/${filename_with_extension}`);
|
||||||
|
|
||||||
kickOffNotifierWorker(exportJob.jobType, filename);
|
kickOffNotifierWorker(exportJob.jobType, filename_with_extension);
|
||||||
|
|
||||||
parentPort.postMessage({message: workerData});
|
parentPort.postMessage({message: workerData});
|
||||||
|
Loading…
Reference in New Issue
Block a user