Compare commits
2 Commits
f3044eb363
...
463c7e318a
Author | SHA1 | Date |
---|---|---|
b1ek | 463c7e318a | |
b1ek | 018d4099e9 |
|
@ -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();
|
||||
})
|
5
index.js
5
index.js
|
@ -9,7 +9,10 @@ fastify.register(require('@fastify/static'), {
|
|||
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) => {
|
||||
if (err) throw err;
|
||||
console.log(`Listening on ${address}`);
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
"author": "blek!",
|
||||
"dependencies": {
|
||||
"@fastify/static": "^6.10.2",
|
||||
"canvas": "^2.11.2",
|
||||
"dotenv": "^16.3.1",
|
||||
"fastify": "^4.18.0"
|
||||
"fastify": "^4.18.0",
|
||||
"gulp": "^4.0.2",
|
||||
"sharp": "^0.32.1"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "node index.js"
|
||||
"dev": "gulp dev"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<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/>
|
||||
<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>
|
||||
</html>
|
|
@ -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();
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue