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:
+
+ - width - ratio width (default 3)
+ - height - ratio height (default 1)
+ - padding - padding of the image (default 20)
+ - format - output format of the image (not supported) (default png)
+ - dpi - dots per inch, basically text scale (default 250)
+
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();
}