UNPKG

qd-arabic-words

Version:

A package for generating random Arabic words that belongs to the Quantum Developers server in discord.

236 lines (201 loc) 7.21 kB
const arabicWords = require('./words'); // Constants for validation const MIN_WORD_LENGTH = 1; const MAX_WORD_LENGTH = Math.max(...arabicWords.map(word => word.length)); const MAX_REQUESTED_WORDS = 100; // Prevent excessive memory usage /** * Validates input parameters * @param {any} options - The input options to validate * @throws {TypeError} When input is invalid */ function validateInput(options) { // Check for null or undefined (explicit checks) if (options === null || options === undefined) { return; // Allowed as it means use defaults } // Validate number input if (Number.isInteger(options)) { if (options <= 0) { throw new TypeError('Number of words must be positive'); } if (options > MAX_REQUESTED_WORDS) { throw new RangeError(`Cannot request more than ${MAX_REQUESTED_WORDS} words`); } return; } // Validate object input if (typeof options === 'object') { // Check for invalid object properties const validProperties = ['num', 'minLength', 'maxLength', 'join']; const invalidProps = Object.keys(options).filter( prop => !validProperties.includes(prop) ); if (invalidProps.length > 0) { throw new TypeError(`Invalid properties: ${invalidProps.join(', ')}`); } // Validate num if (options.num !== undefined) { if (!Number.isInteger(options.num)) { throw new TypeError('num must be an integer'); } if (options.num <= 0) { throw new RangeError('num must be positive'); } if (options.num > MAX_REQUESTED_WORDS) { throw new RangeError(`num cannot exceed ${MAX_REQUESTED_WORDS}`); } } // Validate lengths if (options.minLength !== undefined) { if (!Number.isInteger(options.minLength)) { throw new TypeError('minLength must be an integer'); } if (options.minLength < MIN_WORD_LENGTH) { throw new RangeError(`minLength must be at least ${MIN_WORD_LENGTH}`); } } if (options.maxLength !== undefined) { if (!Number.isInteger(options.maxLength)) { throw new TypeError('maxLength must be an integer'); } if (options.maxLength > MAX_WORD_LENGTH) { throw new RangeError(`maxLength cannot exceed ${MAX_WORD_LENGTH}`); } } // Validate length range if (options.minLength !== undefined && options.maxLength !== undefined) { if (options.minLength > options.maxLength) { throw new RangeError('minLength cannot be greater than maxLength'); } } // Validate join if (options.join !== undefined && typeof options.join !== 'string') { throw new TypeError('join must be a string'); } return; } throw new TypeError('Invalid input type. Expected number or options object'); } /** * Generate random Arabic words with various options * @param {number|Object} [options={}] - Can be a number or options object * @returns {Promise<string|Array<string>>} - Single word or array of words * @throws {Error} When no words match criteria */ async function generateArabicWords(options = {}) { try { // Input validation validateInput(options); // Default case: single random word if (Object.keys(options).length === 0 && !Number.isInteger(options)) { return getRandomWord(); } // Number case: array of words if (Number.isInteger(options)) { return getMultipleWords(options); } // Object options case const { num, minLength, maxLength, join } = options; // Handle num with join if (num !== undefined && join !== undefined) { const words = await getFilteredWords(num, minLength, maxLength); return words.join(join); } // Handle num without join if (num !== undefined) { return getFilteredWords(num, minLength, maxLength); } // Handle length constraints if (minLength !== undefined || maxLength !== undefined) { return getWordByLength(minLength, maxLength); } // Fallback to single word if no recognized options return getRandomWord(); } catch (error) { console.error('Generation error:', error.message); throw error; // Re-throw for caller to handle } } // Helper: Get single random word with safety check function getRandomWord() { if (arabicWords.length === 0) { throw new Error('Word database is empty'); } return arabicWords[Math.floor(Math.random() * arabicWords.length)]; } // Helper: Get multiple random words with validation function getMultipleWords(count) { if (arabicWords.length === 0) { throw new Error('Word database is empty'); } // For small databases, ensure we don't request duplicates if not enough words if (count > arabicWords.length) { throw new Error(`Cannot return ${count} unique words from a pool of ${arabicWords.length}`); } // Create a copy to avoid modifying original array const wordPool = [...arabicWords]; const result = []; // Fisher-Yates shuffle algorithm for better randomness for (let i = wordPool.length - 1; i > 0 && result.length < count; i--) { const j = Math.floor(Math.random() * (i + 1)); [wordPool[i], wordPool[j]] = [wordPool[j], wordPool[i]]; result.push(wordPool[i]); } return result.slice(0, count); } // Helper: Get word by length constraints with thorough validation function getWordByLength(minLength, maxLength) { const filteredWords = arabicWords.filter(word => { const length = word.length; return ( (minLength === undefined || length >= minLength) && (maxLength === undefined || length <= maxLength) ); }); if (filteredWords.length === 0) { throw new Error( `No words found matching length criteria: ${ minLength !== undefined ? `minLength=${minLength}` : '' }${ minLength !== undefined && maxLength !== undefined ? ', ' : '' }${ maxLength !== undefined ? `maxLength=${maxLength}` : '' }` ); } return filteredWords[Math.floor(Math.random() * filteredWords.length)]; } // Helper: Get filtered words with constraints async function getFilteredWords(count, minLength, maxLength) { const filteredWords = arabicWords.filter(word => { const length = word.length; return ( (minLength === undefined || length >= minLength) && (maxLength === undefined || length <= maxLength) ); }); if (filteredWords.length === 0) { throw new Error( `No words found matching criteria: ${ minLength !== undefined ? `minLength=${minLength}` : '' }${ minLength !== undefined && maxLength !== undefined ? ', ' : '' }${ maxLength !== undefined ? `maxLength=${maxLength}` : '' }` ); } if (count > filteredWords.length) { throw new Error( `Cannot return ${count} words. Only ${filteredWords.length} words match the criteria` ); } // Improved shuffling algorithm const shuffled = [...filteredWords]; for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; } return shuffled.slice(0, count); } module.exports = generateArabicWords;