init: parameters

This commit is contained in:
b1ek 2023-06-24 02:14:01 +10:00
parent 874a28552b
commit 5bfad661ef
Signed by: blek
GPG Key ID: 14546221E3595D0C
4 changed files with 63 additions and 16 deletions

View File

@ -1,5 +1,5 @@
require('dotenv').config(); require('dotenv').config();
const { APP_DEBUG } = process.env; const { APP_DEBUG, SCRIPT_PROD } = process.env;
const fastify = require('fastify')({ logger: APP_DEBUG == 'true' }); const fastify = require('fastify')({ logger: APP_DEBUG == 'true' });
const path = require('path'); const path = require('path');
@ -11,7 +11,11 @@ fastify.register(require('@fastify/static'), {
// load routes from routes.js // load routes from routes.js
require('./routes')(fastify); require('./routes')(fastify);
console.log('Starting up') console.log('Starting up');
if (SCRIPT_PROD == 'true' && APP_DEBUG == 'true') {
console.warn('\x1b[33mYou are running a production script with APP_DEBUG=true. App will run \x1b[1;31min development mode.\x1b[0m');
}
fastify.listen({ port: process.env.APP_PORT ?? 8000 }, (err, address) => { fastify.listen({ port: process.env.APP_PORT ?? 8000 }, (err, address) => {
if (err) throw err; if (err) throw err;

View File

@ -13,6 +13,7 @@
"sharp": "^0.32.1" "sharp": "^0.32.1"
}, },
"scripts": { "scripts": {
"dev": "gulp dev" "dev": "gulp dev",
"prod": "SCRIPT_PROD=true node index.js"
} }
} }

View File

@ -11,7 +11,17 @@
<p> <p>
Send a GET to <b>/catpcha/v{version}/{text}</b>, where Send a GET to <b>/catpcha/v{version}/{text}</b>, where
<b>version</b> - captcha version, and <b>version</b> - captcha version, and
<b>text</b> is the text of your captcha <b>text</b> is the text of your captcha.
</p>
<p>
Also you can pass additional props in the query. Supported props are:<br/>
<ul>
<li><b>width</b> - ratio width (default 3)</li>
<li><b>height</b> - ratio height (default 1)</li>
<li><b>padding</b> - padding of the image (default 20)</li>
<li><b>format</b> - output format of the image (not supported) (default png)</li>
<li><b>dpi</b> - dots per inch, basically text scale (default 250)</li>
</ul>
</p> </p>
<hr/> <hr/>

View File

@ -1,21 +1,54 @@
const sharp = require('sharp'); const sharp = require('sharp');
const canvas = require('canvas'); const canvas = require('canvas');
const crypto = require('crypto') const crypto = require('crypto');
const randint = (min, max) => { return crypto.randomInt(max) + min };
/** @param {import('fastify').FastifyRequest} req */
const getSettings = (req) => {
const q = req.query;
const settings = {
// Width and height are ratio numbers; actual width & height is calculated from text length & padding
width: q.width ?? 3,
height: q.height ?? 1,
padding: q.padding ?? 20,
format: q.format ?? 'png',
dpi: q.dpi ?? 250
};
for (const key in settings) {
if (['format'].indexOf(key) !== -1) continue;
settings[key] = parseInt(settings[key]);
}
return settings;
}
const get_size = (ratio, dpi, txtlen, padding) => {
return {
width: Math.floor((ratio[0] * dpi * 0.12) + (txtlen * dpi * 0.08)) + (padding * 2),
height: Math.floor(ratio[1] * dpi * 0.2) + (padding * 2)
}
}
/** @param {import('fastify').FastifyInstance} fastify */ /** @param {import('fastify').FastifyInstance} fastify */
module.exports = (fastify) => { module.exports = (fastify) => {
fastify.get('/captcha/v1/:text', async (req, res) => { fastify.get('/captcha/v1/:text', async (req, res) => {
const text = req.params.text;
const settings = getSettings(req);
const size = get_size([settings.width, settings.height], settings.dpi, text.length, settings.padding);
console.log(size)
console.log(settings)
let pic = (await sharp({ let pic = (await sharp({
create: { create: {
width: 150, width: size.width,
height: 50, height: size.height,
channels: 4, channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0 } background: { r: 0, g: 0, b: 0, alpha: 0 }
} }
})); }));
const text = req.params.text;
pic.composite([ pic.composite([
{ {
@ -23,11 +56,12 @@ module.exports = (fastify) => {
text: { text: {
text: text, text: text,
font: 'Arial', font: 'Arial',
dpi: crypto.randomInt(150, 200), dpi: settings.dpi,
rgba: true rgba: true
} }
}, },
blend: 'over' blend: 'over',
gravity: 0
} }
]); ]);
@ -36,17 +70,15 @@ module.exports = (fastify) => {
.toFormat('png', { compressionLevel: 6 }) .toFormat('png', { compressionLevel: 6 })
.toBuffer(); .toBuffer();
const draw = canvas.createCanvas(150, 50); const draw = canvas.createCanvas(size.width, size.height);
const ctx = draw.getContext('2d'); const ctx = draw.getContext('2d');
ctx.drawImage(await canvas.loadImage(textpic), 0, 0, 150, 50); ctx.drawImage(await canvas.loadImage(textpic), 0, 0, size.width, size.height);
const randint = (min, max) => { return crypto.randomInt(max) + min }; const strokes = randint(25, 40);
const strokes = randint(25, 50);
for (let i = 0; i != strokes; i++) { for (let i = 0; i != strokes; i++) {
ctx.strokeStyle = `rgba(0,0,0,${10})`; ctx.strokeStyle = `rgba(0,0,0,${10})`;
ctx.beginPath(); ctx.beginPath();
ctx.bezierCurveTo(randint(0, 150), randint(0, 50), randint(0, 150), randint(0, 50), randint(0, 150), randint(0, 50)); ctx.bezierCurveTo(randint(0, size.width), randint(0, size.height), randint(0, size.width), randint(0, size.height), randint(0, size.width), randint(0, size.height));
ctx.stroke(); ctx.stroke();
} }