@eternaljs/captcha
Version:
This npm package generates secure and customizable CAPTCHA images for web applications, preventing automated abuse with ease.
67 lines (51 loc) • 2.32 kB
text/typescript
import { createCanvas } from 'canvas';
import { CaptchaInterface, OptionsInterface } from './interface';
function generateCaptcha(options: OptionsInterface): CaptchaInterface {
const canvas = createCanvas(options['width'], options['height']);
const ctx = canvas.getContext('2d');
const captchaText = generateCaptchaText(options['length'] ?? 6);
ctx.font = `${options['font_size']}px Arial`;
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
const textX = options['width'] / 2;
const textY = options['height'] / 2;
ctx.fillText(captchaText, textX, textY);
ctx.beginPath();
ctx.moveTo(textX - ctx.measureText(captchaText).width / 2, textY);
ctx.lineTo(textX + ctx.measureText(captchaText).width / 2, textY);
ctx.strokeStyle = 'rgba(0,0,0)';
ctx.stroke();
const lines: number = options['lines'] ?? 6
for (let i = 0; i < lines; i++) {
ctx.beginPath();
ctx.moveTo(0, Math.random() * options['height']);
ctx.lineTo(options['width'], Math.random() * options['height']);
ctx.strokeStyle = 'rgba(0,0,0,0.8)';
ctx.stroke();
}
return { text: captchaText, image: canvas, };
}
function generateCaptchaText(length: number): string {
const charSet: Record<string, string> = {
digit: '0123456789',
lowercase: 'abcdefghijklmnopqrstuvwxyz',
uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
}
let captchaText = '';
for (const type in charSet) {
captchaText += charSet[type].charAt(Math.floor(Math.random() * charSet[type].length));
}
const remaining: number = length - captchaText.length;
if (!remaining) return captchaText;
for (let i = 0; i < remaining; i++) {
if (i === 0) {
captchaText += charSet["uppercase"].charAt(Math.floor(Math.random() * charSet["uppercase"].length));
} else if (i === 1) {
captchaText += charSet["lowercase"].charAt(Math.floor(Math.random() * charSet["lowercase"].length));
} else {
captchaText += charSet["digit"].charAt(Math.floor(Math.random() * charSet["digit"].length));
}
}
return captchaText.split('').sort(() => Math.random() - 0.5).join('');
}
export default generateCaptcha;