UNPKG

captscii

Version:

A simple and powerful Captcha solution for your website

73 lines (72 loc) 3.1 kB
export function generateString(length, rules) { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; let result = ""; if (rules.startsWith) { result += rules.startsWith[Math.floor(Math.random() * rules.startsWith.length)]; } for (let i = result.length; i < length - (rules.endsWith ? 1 : 0); i++) { let randomChar = chars[Math.floor(Math.random() * chars.length)]; if (rules.noRepeatingChars && result.includes(randomChar)) { i--; continue; } result += randomChar; } if (rules.endsWith) { result += rules.endsWith[Math.floor(Math.random() * rules.endsWith.length)]; } if (rules.thirdCharList && result.length >= 3) { result = result.substring(0, 2) + rules.thirdCharList[Math.floor(Math.random() * rules.thirdCharList.length)] + result.substring(3); } if (rules.containsChar && !result.includes(rules.containsChar)) { result = result.substring(0, result.length - 1) + rules.containsChar; } return result; } export function generateCode(str) { return str.split('').map(char => char.charCodeAt(0).toString(16)).join(''); } export function verifyCode(code, originalStr, rules) { let decodedStr = ""; for (let i = 0; i < code.length; i += 2) { decodedStr += String.fromCharCode(parseInt(code.substring(i, i + 2), 16)); } if (rules.sumMultiple) { const sumAscii = decodedStr.split('').reduce((sum, char) => sum + char.charCodeAt(0), 0); if (sumAscii % rules.sumMultiple !== 0) return false; } if (rules.thirdCharList && decodedStr.length >= 3 && !rules.thirdCharList.includes(decodedStr[2])) return false; if (rules.lengthEven && code.length % 2 !== 0) return false; if (rules.startsWith && !rules.startsWith.includes(decodedStr[0])) return false; if (rules.endsWith && !rules.endsWith.includes(decodedStr[decodedStr.length - 1])) return false; if (rules.containsChar && !decodedStr.includes(rules.containsChar)) return false; if (rules.noRepeatingChars && new Set(decodedStr).size !== decodedStr.length) return false; if (rules.maxVowels) { const vowelCount = decodedStr.split('').filter(c => "AEIOU".includes(c)).length; if (vowelCount > rules.maxVowels) return false; } return decodedStr === originalStr; } export function generateAndVerify(length, rules) { let str, code, isValid; let attempts = 0, maxAttempts = 1000; // Evitar bucle infinito const startTime = performance.now(); do { if (attempts++ > maxAttempts) throw new Error("No se pudo generar una cadena válida dentro del límite de intentos"); str = generateString(length, rules); code = generateCode(str); isValid = verifyCode(code, str, rules); } while (!isValid); const endTime = performance.now(); console.log(`Tiempo de ejecución: ${(endTime - startTime).toFixed(4)} ms`); return { str, code, isValid, executionTime: (endTime - startTime).toFixed(4) }; }