tamil-captcha
Version:
A lightweight math-based CAPTCHA generator in Tamil language for Node.js and browser applications
207 lines (186 loc) • 5.84 kB
JavaScript
/**
* Tamil CAPTCHA - A lightweight math-based CAPTCHA generator in Tamil language
* Author: Your Name
* License: MIT
*/
// Tamil number mappings (1-10)
const TAMIL_NUMBERS = {
1: 'ஒன்று',
2: 'இரண்டு',
3: 'மூன்று',
4: 'நான்கு',
5: 'ஐந்து',
6: 'ஆறு',
7: 'ஏழு',
8: 'எட்டு',
9: 'ஒன்பது',
10: 'பத்து'
};
// Tamil operations
const TAMIL_OPERATIONS = {
'+': {
symbol: '+',
word: 'கூட்டல்',
operation: (a, b) => a + b
},
'-': {
symbol: '-',
word: 'கழித்தல்',
operation: (a, b) => a - b
},
'*': {
symbol: '×',
word: 'பெருக்கல்',
operation: (a, b) => a * b
}
};
/**
* Generates a random integer between min and max (inclusive)
* @param {number} min - Minimum value
* @param {number} max - Maximum value
* @returns {number} Random integer
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/**
* Gets a random operation type
* @returns {string} Operation key ('+', '-', or '*')
*/
function getRandomOperation() {
const operations = Object.keys(TAMIL_OPERATIONS);
return operations[getRandomInt(0, operations.length - 1)];
}
/**
* Generates a Tamil math CAPTCHA challenge
* @param {Object} options - Configuration options
* @param {number} options.minNumber - Minimum number to use (default: 1)
* @param {number} options.maxNumber - Maximum number to use (default: 10)
* @param {string[]} options.operations - Array of operations to use (default: ['+', '-', '*'])
* @returns {Object} CAPTCHA object with question and answer
*/
function generateCaptcha(options = {}) {
const {
minNumber = 1,
maxNumber = 10,
operations = ['+', '-', '*']
} = options;
// Validate inputs
if (minNumber < 1 || maxNumber > 10) {
throw new Error('Numbers must be between 1 and 10 for Tamil support');
}
if (minNumber > maxNumber) {
throw new Error('minNumber cannot be greater than maxNumber');
}
// Generate two random numbers
let num1 = getRandomInt(minNumber, maxNumber);
let num2 = getRandomInt(minNumber, maxNumber);
// Get random operation from allowed operations
const validOps = operations.filter(op => TAMIL_OPERATIONS[op]);
if (validOps.length === 0) {
throw new Error('No valid operations provided');
}
const operationType = validOps[getRandomInt(0, validOps.length - 1)];
const operation = TAMIL_OPERATIONS[operationType];
// For subtraction, ensure result is positive
if (operationType === '-' && num2 > num1) {
[num1, num2] = [num2, num1]; // Swap numbers
}
// For multiplication, use smaller numbers to avoid large results, but respect minNumber and maxNumber
if (operationType === '*') {
const upper = Math.min(5, maxNumber);
// Ensure upper is not less than minNumber
if (upper < minNumber) {
throw new Error('maxNumber must be at least 5 for multiplication');
}
num1 = getRandomInt(minNumber, upper);
num2 = getRandomInt(minNumber, upper);
}
// Calculate the answer
const answer = operation.operation(num1, num2);
// Create Tamil question
const tamilNum1 = TAMIL_NUMBERS[num1];
const tamilNum2 = TAMIL_NUMBERS[num2];
const question = `${tamilNum1} ${operation.symbol} ${tamilNum2} = ?`;
return {
question,
answer,
operation: operationType,
numbers: [num1, num2],
metadata: {
tamilNumbers: [tamilNum1, tamilNum2],
operationWord: operation.word
}
};
}
/**
* Verifies if the user's input matches the CAPTCHA answer
* @param {string|number} userInput - User's answer
* @param {number} actualAnswer - Correct answer
* @returns {boolean} True if answer is correct
*/
function verifyCaptcha(userInput, actualAnswer) {
// Reject decimal strings or numbers
if (typeof userInput === 'string') {
const trimmed = userInput.trim();
// Reject if string is a decimal (e.g., "5.5", "10.0")
if (/^[-+]?\d*\.\d+$/.test(trimmed)) return false;
// Reject if string contains non-numeric except whitespace
if (!/^[-+]?\d+$/.test(trimmed)) return false;
// Parse as integer
const userAnswer = parseInt(trimmed, 10);
return userAnswer === actualAnswer;
} else if (typeof userInput === 'number') {
// Reject if number is not an integer
if (!Number.isInteger(userInput)) return false;
return userInput === actualAnswer;
}
return false;
}
/**
* Gets Tamil word for a number (1-10)
* @param {number} number - Number to convert
* @returns {string} Tamil word for the number
*/
function getTamilNumber(number) {
if (number < 1 || number > 10) {
throw new Error('Number must be between 1 and 10');
}
return TAMIL_NUMBERS[number];
}
/**
* Gets all available Tamil numbers
* @returns {Object} Object mapping numbers to Tamil words
*/
function getAllTamilNumbers() {
return { ...TAMIL_NUMBERS };
}
/**
* Gets information about available operations
* @returns {Object} Object with operation details
*/
function getOperations() {
return Object.keys(TAMIL_OPERATIONS).map(key => ({
key,
symbol: TAMIL_OPERATIONS[key].symbol,
word: TAMIL_OPERATIONS[key].word
}));
}
// Export functions
module.exports = {
generateCaptcha,
verifyCaptcha,
getTamilNumber,
getAllTamilNumbers,
getOperations
};
// ES6 module support
if (typeof exports === 'object' && typeof module !== 'undefined') {
module.exports = {
generateCaptcha,
verifyCaptcha,
getTamilNumber,
getAllTamilNumbers,
getOperations
};
}