Compare commits

..

2 Commits

Author SHA1 Message Date
b1ek 463c7e318a
init: v1 captcha 2023-06-23 23:11:59 +10:00
b1ek 018d4099e9
init: gulp dev 2023-06-23 21:39:30 +10:00
6 changed files with 2806 additions and 10 deletions

32
gulpfile.js Normal file
View File

@ -0,0 +1,32 @@
const gulp = require('gulp');
const log = require('gulplog');
const { spawn } = require('child_process');
const package = require('./package.json');
gulp.task('dev', (cb) => {
log.info('Running in development mode');
/** @type {import('child_process').ChildProcessWithoutNullStreams} */
let node = null;
async function spawnNode(cb){
log.info('Spawning node');
if (node !== null) {
node.kill(9);
console.log('----- END PROCESS LOG -----')
// grace period
await new Promise(r => {setTimeout(r, 100)});
}
log.info(`Command: \x1b[35mnode "${package.main}"`);
console.log('----- BEGIN PROCESS LOG -----');
node = spawn('node', [ package.main ], { stdio: 'inherit' });
if (typeof cb == 'function')
cb();
}
gulp.watch('**', { events: 'all' }, spawnNode);
spawnNode();
// cb();
})

View File

@ -9,7 +9,10 @@ fastify.register(require('@fastify/static'), {
prefix: '/' prefix: '/'
}); });
// fastify.get('') // load routes from routes.js
require('./routes')(fastify);
console.log('Starting up')
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;
console.log(`Listening on ${address}`); console.log(`Listening on ${address}`);

View File

@ -6,10 +6,13 @@
"author": "blek!", "author": "blek!",
"dependencies": { "dependencies": {
"@fastify/static": "^6.10.2", "@fastify/static": "^6.10.2",
"canvas": "^2.11.2",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"fastify": "^4.18.0" "fastify": "^4.18.0",
"gulp": "^4.0.2",
"sharp": "^0.32.1"
}, },
"scripts": { "scripts": {
"dev": "node index.js" "dev": "gulp dev"
} }
} }

View File

@ -1,7 +1,51 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<body> <body>
<h1 align="center">This is FreePtcha, a completely open source captcha service.</h1> <h1 align="center">This is FreePtcha, a completely open source captcha.</h1>
<hr/> <hr/>
<h2>What is this?</h2>
<p>
It seems that you have sucessfully installed freeptcha.<br/>
</p>
<h2>How do I use this?</h2>
<p>
Send a GET to <b>/catpcha/v{version}/{text}</b>, where
<b>version</b> - captcha version, and
<b>text</b> is the text of your captcha
</p>
<hr/>
<h2>Example</h2>
<p>
<a href="/captcha/v1/UwU">
/captcha/v1/UwU<br/>
<img src="/captcha/v1/UwU" />
</a>
<br/>
A simple text stroked over a lot of times
</p>
<hr/>
<h1>Captcha versions</h1>
<p>
Supported captcha vesions as of this moment:
<br/>
<table>
<tbody>
<tr>
<td>Version №</td>
<td>Description</td>
<td>Example</td>
</tr>
<tr>
<td>1</td>
<td>Text stroked over a lot of times</td>
<td><img src="/captcha/v1/Version 1"/></td>
</tr>
</tbody>
</table>
</p>
</body> </body>
</html> </html>

59
routes.js Normal file
View File

@ -0,0 +1,59 @@
const sharp = require('sharp');
const canvas = require('canvas');
const crypto = require('crypto')
/** @param {import('fastify').FastifyInstance} fastify */
module.exports = (fastify) => {
fastify.get('/captcha/v1/:text', async (req, res) => {
let pic = (await sharp({
create: {
width: 150,
height: 50,
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0 }
}
}));
const text = req.params.text;
pic.composite([
{
input: {
text: {
text: text,
font: 'Arial',
dpi: crypto.randomInt(150, 200),
rgba: true
}
},
blend: 'over'
}
]);
const textpic = await pic
.ensureAlpha()
.toFormat('png', { compressionLevel: 6 })
.toBuffer();
const draw = canvas.createCanvas(150, 50);
const ctx = draw.getContext('2d');
ctx.drawImage(await canvas.loadImage(textpic), 0, 0, 150, 50);
const randint = (min, max) => { return crypto.randomInt(max) + min };
const strokes = randint(25, 50);
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.stroke();
}
ctx.bezierCurveTo(20, 20, 20, 30, 70, 25);
ctx.stroke();
res.header('Content-Type', 'png');
return draw.toBuffer();
})
}

2667
yarn.lock

File diff suppressed because it is too large Load Diff