diff --git a/asset/lobster.ttf b/asset/lobster.ttf new file mode 100644 index 0000000..21c0073 Binary files /dev/null and b/asset/lobster.ttf differ diff --git a/public/index.html b/public/index.html index 67caa4a..4e88701 100644 --- a/public/index.html +++ b/public/index.html @@ -1,5 +1,12 @@ + + +

This is FreePtcha, a completely open source captcha.


@@ -27,14 +34,32 @@

Example

-

- - /captcha/v1/UwU
- -
-
- A simple text stroked over a lot of times -

+ + + + + + + + + + + +
+ + /captcha/v1/UwU
+ +
+
+ + /captcha/v2/UwU
+ +
+
+ A simple text stroked over a lot of times + + Text with a few random letters and circles in the background +

diff --git a/routes.js b/routes.js index 113b025..3f91865 100644 --- a/routes.js +++ b/routes.js @@ -1,7 +1,10 @@ const sharp = require('sharp'); const canvas = require('canvas'); const crypto = require('crypto'); -const randint = (min, max) => { return crypto.randomInt(max) + min }; +const path = require('path'); +const randint = (min, max) => { return crypto.randomInt(min, max) }; + +canvas.registerFont(path.join(__dirname, 'asset/lobster.ttf'), { family: 'Lobster' }); /** @param {import('fastify').FastifyRequest} req */ const getSettings = (req) => { @@ -89,5 +92,53 @@ module.exports = (fastify) => { res.header('Content-Type', 'png'); return draw.toBuffer(); + }); + + fastify.get('/captcha/v2/: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); + size.height *= 0.5 + + const draw = canvas.createCanvas(size.width, size.height); + const ctx = draw.getContext('2d'); + + const arcs = randint(5, 32); + for (let i = 0; i != arcs; i++) { + ctx.beginPath(); + ctx.strokeStyle = `rgba(${randint(0,255)},${randint(0,255)},${randint(0,255)},${randint(0,255)})`; + ctx.arc(randint(0, size.width), randint(0, size.height), randint(10, 25), 0, 360); + ctx.stroke(); + ctx.closePath(); + } + + // let i = 0; + ctx.textDrawingMode = 'path'; + + const textStyles = ['#f00', '#2a4', '#00f', '#9a0', '#f0f']; + + ctx.strokeStyle = textStyles[randint(0, textStyles.length)]; + ctx.font = `${settings.dpi * 0.2}px sans-serif`; + + textStyles.splice(textStyles.indexOf(ctx.strokeStyle), 1); + const gap = randint(50, 64); + for (const i in text) { + ctx.fillText(text[i], settings.padding + (i * randint(40,48)), randint(Math.floor(settings.padding + settings.dpi * 0.05), size.height - settings.padding + Math.floor(settings.dpi * 0.1)), 200); + ctx.stroke() + } + + const fauxletters = randint(20,40); + let alphabet = 'abcdefghijklmnopqrstuvwxyz'; + alphabet += alphabet.toUpperCase(); + alphabet += '0123456789'; + for (let i = 0; i !== fauxletters; i++) { + ctx.strokeStyle = textStyles[randint(0,textStyles.length)] + '2'; + ctx.font = `${settings.dpi * 0.2}px serif` + ctx.strokeText(alphabet[randint(0, alphabet.length)], randint(0, size.width), randint(0, size.height), 200); + ctx.stroke() + } + + res.header('Content-Type', 'image/png'); + return draw.toBuffer(); }) } \ No newline at end of file