From 5bfad661efa7ae5219061a8c642c9dbebbb6c555 Mon Sep 17 00:00:00 2001 From: b1ek Date: Sat, 24 Jun 2023 02:14:01 +1000 Subject: [PATCH] init: parameters --- index.js | 8 +++++-- package.json | 3 ++- public/index.html | 12 +++++++++- routes.js | 56 +++++++++++++++++++++++++++++++++++++---------- 4 files changed, 63 insertions(+), 16 deletions(-) diff --git a/index.js b/index.js index cf55f1b..2fa8035 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ require('dotenv').config(); -const { APP_DEBUG } = process.env; +const { APP_DEBUG, SCRIPT_PROD } = process.env; const fastify = require('fastify')({ logger: APP_DEBUG == 'true' }); const path = require('path'); @@ -11,7 +11,11 @@ fastify.register(require('@fastify/static'), { // load routes from routes.js 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) => { if (err) throw err; diff --git a/package.json b/package.json index ec5a051..e52bf66 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "sharp": "^0.32.1" }, "scripts": { - "dev": "gulp dev" + "dev": "gulp dev", + "prod": "SCRIPT_PROD=true node index.js" } } diff --git a/public/index.html b/public/index.html index 4af8b86..67caa4a 100644 --- a/public/index.html +++ b/public/index.html @@ -11,7 +11,17 @@

Send a GET to /catpcha/v{version}/{text}, where version - captcha version, and - text is the text of your captcha + text is the text of your captcha. +

+

+ Also you can pass additional props in the query. Supported props are:
+


diff --git a/routes.js b/routes.js index bff81cf..c6e8ae0 100644 --- a/routes.js +++ b/routes.js @@ -1,21 +1,54 @@ const sharp = require('sharp'); 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 */ module.exports = (fastify) => { 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({ create: { - width: 150, - height: 50, + width: size.width, + height: size.height, channels: 4, background: { r: 0, g: 0, b: 0, alpha: 0 } } })); - const text = req.params.text; pic.composite([ { @@ -23,11 +56,12 @@ module.exports = (fastify) => { text: { text: text, font: 'Arial', - dpi: crypto.randomInt(150, 200), + dpi: settings.dpi, rgba: true } }, - blend: 'over' + blend: 'over', + gravity: 0 } ]); @@ -36,17 +70,15 @@ module.exports = (fastify) => { .toFormat('png', { compressionLevel: 6 }) .toBuffer(); - const draw = canvas.createCanvas(150, 50); + const draw = canvas.createCanvas(size.width, size.height); 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, 50); + const strokes = randint(25, 40); for (let i = 0; i != strokes; i++) { ctx.strokeStyle = `rgba(0,0,0,${10})`; 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(); }