captchas a bit wider and clean the generating a bit

merge-requests/208/head
fatchan 5 years ago
parent c53d760350
commit 709e695ae7
  1. 107
      helpers/captcha/captchagenerate.js
  2. 7
      models/pages/captcha.js
  3. 2
      views/includes/captcha.pug

@ -1,61 +1,78 @@
const gm = require('gm').subClass({ imageMagick: true })
, { Captchas } = require(__dirname+'/../../db/')
, uploadDirectory = require(__dirname+'/../files/uploadDirectory.js')
, rr = (min, max) => Math.floor(Math.random() * (max-min + 1) + min)
, width = 200
, randomRange = (min, max) => Math.floor(Math.random() * (max-min + 1) + min)
, characterWidth = (char) => {
switch (char) {
case 'w':
case 'm':
return 45;
case 'i':
case 'l':
return 12;
case 'f':
case 'j':
case 't':
return 15;
default:
return 30;
}
}
, totalWidth = (text) => {
return text.split('').reduce((acc, char) => {
return characterWidth(char) + acc + 1;
}, 0);
}
, width = 210
, height = 80
, distortion = 15
, distortion = 13;
module.exports = async () => {
const text = Math.random().toString(36).substr(2,6);
const captchaId = await Captchas.insertOne(text).then(r => r.insertedId);
const distorts = [];
const numDistorts = randomRange(3,5);
const div = width/numDistorts;
for (let i = 0; i < numDistorts; i++) {
const divStart = (div*i)
, divEnd = (div*(i+1));
const originx = randomRange(divStart, divEnd)
, originy = randomRange(0,height);
const destx = randomRange(Math.max(distortion,originx-distortion),Math.min(width-distortion,originx+distortion))
, desty = randomRange(Math.max(distortion,originy-distortion*2),Math.min(height-distortion,originy+distortion*2));
distorts.push([
{x:originx,y:originy}, //origin
{x:destx,y:desty} //dest
]);
}
module.exports = (text, captchaId) => {
return new Promise((resolve, reject) => {
const recy = rr(35,45);
const distorts = [];
const numDistorts = rr(3,5);
const div = width/numDistorts;
for (let i = 0; i < numDistorts; i++) {
const originx = rr((div*i)+distortion, (div*(i+1))-distortion);
const originy = rr(distortion,height-distortion);
const destx = rr(Math.max(distortion,originx-distortion),Math.min(width-distortion,originx+distortion));
const desty = rr(Math.max(distortion,originy-distortion*2),Math.min(height-distortion,originy+distortion*2));
distorts.push([
{x:originx,y:originy}, //origin
{x:destx,y:desty} //dest
]);
}
const x = gm(width,height,'#ffffff')
const captcha = gm(width,height,'#ffffff')
.fill('#000000')
.fontSize(65)
let lastx = 7;
for (let i = 0; i <6; i++) {
x.drawText(lastx, 60, text[i])
switch (text[i]) {
case 'w':
case 'm':
lastx += 45;
break;
case 'i':
case 'l':
lastx += 12;
break;
case 'f':
case 'j':
case 't':
lastx += 15;
break;
default:
lastx += 30;
break;
}
.fontSize(65);
const startX = (width-totalWidth(text))/2;
let charX = startX;
for (let i = 0; i < 6; i++) {
captcha.drawText(charX, 60, text[i]);
charX += characterWidth(text[i]);
}
//.drawText(5, 60, text)
x.drawRectangle(5, recy, 195, recy+4)
const lineY = randomRange(35,45);
captcha
.drawRectangle(startX, lineY, charX, lineY+4)
.distort(distorts, 'Shepards')
.paint(2)
// .quality(30)
.write(`${uploadDirectory}/captcha/${captchaId}.jpg`, (err) => {
if (err) {
return reject(err);
}
return resolve();
return resolve({ id: captchaId, text });
});
})
}

@ -1,6 +1,6 @@
'use strict';
const { Captchas, Ratelimits } = require(__dirname+'/../../db/')
const { Ratelimits } = require(__dirname+'/../../db/')
, generateCaptcha = require(__dirname+'/../../helpers/captcha/captchagenerate.js')
, { secureCookies } = require(__dirname+'/../../configs/main.js')
, production = process.env.NODE_ENV === 'production';
@ -17,9 +17,8 @@ module.exports = async (req, res, next) => {
if (ratelimit > 100) {
return res.status(429).redirect('/img/ratelimit.png');
}
const text = Math.random().toString(36).substr(2,6);
captchaId = await Captchas.insertOne(text).then(r => r.insertedId); //get id of document as filename and captchaid
await generateCaptcha(text, captchaId);
const { id, text } = await generateCaptcha();
captchaId = id;
} catch (err) {
return next(err);
}

@ -1,4 +1,4 @@
noscript.no-m-p
iframe.captcha(src='/captcha.html' 'width=200' height='80' scrolling='no')
iframe.captcha(src='/captcha.html' 'width=210' height='80' scrolling='no')
.jsonly.captcha(style='display:none;')
input.captchafield(type='text' name='captcha' autocomplete='off' placeholder='captcha text' pattern=".{6}" required title='6 characters')

Loading…
Cancel
Save