init: parameters
This commit is contained in:
parent
874a28552b
commit
5bfad661ef
8
index.js
8
index.js
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/>
|
||||||
|
|
56
routes.js
56
routes.js
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue