Skip to main content
Glama
random.js13.8 kB
/** * 随机数工具模块 * 提供随机数生成、随机字符串生成和随机延迟功能 */ import { logger } from './logger.js'; /** * 随机数工具类 */ export class RandomUtils { constructor() { this.defaultCharset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; this.defaultLength = 8; } /** * 生成随机整数 * @param {number} min - 最小值 * @param {number} max - 最大值 * @returns {number} 随机整数 */ static int(min, max) { if (min > max) { [min, max] = [max, min]; } return Math.floor(Math.random() * (max - min + 1)) + min; } /** * 生成随机浮点数 * @param {number} min - 最小值 * @param {number} max - 最大值 * @param {number} precision - 小数精度 * @returns {number} 随机浮点数 */ static float(min, max, precision = 2) { if (min > max) { [min, max] = [max, min]; } const random = Math.random() * (max - min) + min; return parseFloat(random.toFixed(precision)); } /** * 生成随机布尔值 * @param {number} probability - 为true的概率 (0-1) * @returns {boolean} 随机布尔值 */ static boolean(probability = 0.5) { return Math.random() < probability; } /** * 从数组中随机选择一个元素 * @param {Array} array - 数组 * @returns {*} 随机元素 */ static choice(array) { if (!Array.isArray(array) || array.length === 0) { return null; } return array[this.int(0, array.length - 1)]; } /** * 从数组中随机选择多个元素 * @param {Array} array - 数组 * @param {number} count - 选择数量 * @param {boolean} unique - 是否去重 * @returns {Array} 随机元素数组 */ static choices(array, count = 1, unique = true) { if (!Array.isArray(array) || array.length === 0 || count <= 0) { return []; } if (unique && count > array.length) { count = array.length; } const result = []; const available = unique ? [...array] : array; for (let i = 0; i < count; i++) { if (unique && available.length === 0) break; const index = this.int(0, available.length - 1); result.push(available[index]); if (unique) { available.splice(index, 1); } } return result; } /** * 打乱数组顺序 * @param {Array} array - 数组 * @returns {Array} 打乱后的数组 */ static shuffle(array) { if (!Array.isArray(array)) { return []; } const result = [...array]; for (let i = result.length - 1; i > 0; i--) { const j = this.int(0, i); [result[i], result[j]] = [result[j], result[i]]; } return result; } /** * 生成随机字符串 * @param {number} length - 字符串长度 * @param {string} charset - 字符集 * @returns {string} 随机字符串 */ static string(length = 8, charset = null) { const chars = charset || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(this.int(0, chars.length - 1)); } return result; } /** * 生成随机字母字符串 * @param {number} length - 字符串长度 * @param {string} caseType - 大小写类型 ('upper', 'lower', 'mixed') * @returns {string} 随机字母字符串 */ static letters(length = 8, caseType = 'mixed') { let charset; switch (caseType) { case 'upper': charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; break; case 'lower': charset = 'abcdefghijklmnopqrstuvwxyz'; break; default: charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; } return this.string(length, charset); } /** * 生成随机数字字符串 * @param {number} length - 字符串长度 * @returns {string} 随机数字字符串 */ static digits(length = 8) { return this.string(length, '0123456789'); } /** * 生成随机UUID格式字符串 * @returns {string} UUID格式字符串 */ static uuid() { const segments = [8, 4, 4, 4, 12]; const result = segments.map(length => this.string(length, '0123456789abcdef')).join('-'); return result; } /** * 生成随机十六进制字符串 * @param {number} length - 字符串长度 * @returns {string} 十六进制字符串 */ static hex(length = 8) { return this.string(length, '0123456789abcdef'); } /** * 生成随机Base64字符串 * @param {number} length - 字符串长度 * @returns {string} Base64字符串 */ static base64(length = 8) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; return this.string(length, chars); } /** * 生成随机中文姓名 * @returns {string} 中文姓名 */ static chineseName() { const surnames = ['王', '李', '张', '刘', '陈', '杨', '黄', '赵', '周', '吴', '徐', '孙', '马', '朱', '胡', '林', '郭', '何', '高', '罗']; const names = ['伟', '芳', '娜', '秀英', '敏', '静', '丽', '强', '磊', '军', '洋', '勇', '艳', '杰', '娟', '涛', '明', '超', '秀兰', '霞']; const surname = this.choice(surnames); const name = this.choice(names); return surname + name; } /** * 生成随机IP地址 * @param {string} type - IP类型 ('ipv4', 'ipv6') * @returns {string} IP地址 */ static ip(type = 'ipv4') { if (type === 'ipv6') { const segments = Array.from({ length: 8 }, () => this.hex(4)); return segments.join(':'); } else { return [ this.int(1, 255), this.int(0, 255), this.int(0, 255), this.int(1, 255) ].join('.'); } } /** * 生成随机MAC地址 * @returns {string} MAC地址 */ static mac() { const segments = Array.from({ length: 6 }, () => this.hex(2)); return segments.join(':'); } /** * 生成随机用户代理字符串 * @returns {string} 用户代理字符串 */ static userAgent() { const browsers = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/91.0.864.59' ]; return this.choice(browsers); } /** * 生成随机邮箱地址 * @param {string} domain - 邮箱域名 * @returns {string} 邮箱地址 */ static email(domain = null) { const domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'qq.com', '163.com']; const username = this.letters(this.int(6, 12), 'lower'); const emailDomain = domain || this.choice(domains); return `${username}@${emailDomain}`; } /** * 生成随机手机号码 * @param {string} country - 国家代码 * @returns {string} 手机号码 */ static phoneNumber(country = 'CN') { if (country === 'CN') { const prefixes = ['130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '150', '151', '152', '153', '155', '156', '157', '158', '159', '170', '171', '172', '173', '174', '175', '176', '177', '178', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189']; const prefix = this.choice(prefixes); const suffix = this.digits(8); return prefix + suffix; } else { return '+' + this.digits(this.int(10, 12)); } } /** * 生成随机延迟 * @param {number} min - 最小延迟(毫秒) * @param {number} max - 最大延迟(毫秒) * @returns {Promise<void>} */ static async delay(min, max) { const delayTime = this.int(min, max); logger.debug(`随机延迟: ${delayTime}ms`); return new Promise(resolve => { setTimeout(resolve, delayTime); }); } /** * 生成随机延迟(秒) * @param {number} min - 最小延迟(秒) * @param {number} max - 最大延迟(秒) * @returns {Promise<void>} */ static async delaySeconds(min, max) { const minMs = min * 1000; const maxMs = max * 1000; return this.delay(minMs, maxMs); } /** * 生成随机延迟(分钟) * @param {number} min - 最小延迟(分钟) * @param {number} max - 最大延迟(分钟) * @returns {Promise<void>} */ static async delayMinutes(min, max) { const minMs = min * 60 * 1000; const maxMs = max * 60 * 1000; return this.delay(minMs, maxMs); } /** * 概率测试 * @param {number} probability - 成功概率 (0-1) * @returns {boolean} 是否成功 */ static chance(probability = 0.5) { return this.boolean(probability); } /** * 加权随机选择 * @param {Array<Object>} items - 带权重的项目数组 [{item: any, weight: number}] * @returns {*} 选中的项目 */ static weightedChoice(items) { if (!Array.isArray(items) || items.length === 0) { return null; } const totalWeight = items.reduce((sum, item) => sum + (item.weight || 0), 0); if (totalWeight <= 0) { return this.choice(items.map(item => item.item)); } let random = this.float(0, totalWeight); for (const item of items) { random -= (item.weight || 0); if (random <= 0) { return item.item; } } return items[items.length - 1].item; } /** * 生成随机颜色 * @param {string} format - 颜色格式 ('hex', 'rgb', 'hsl') * @returns {string} 颜色值 */ static color(format = 'hex') { switch (format) { case 'rgb': return `rgb(${this.int(0, 255)}, ${this.int(0, 255)}, ${this.int(0, 255)})`; case 'hsl': return `hsl(${this.int(0, 360)}, ${this.int(0, 100)}%, ${this.int(0, 100)}%)`; default: return '#' + this.hex(6); } } /** * 生成随机地理位置 * @param {Object} bounds - 边界范围 {minLat, maxLat, minLng, maxLng} * @returns {Object} 地理位置 {latitude, longitude} */ static location(bounds = null) { const defaultBounds = { minLat: -90, maxLat: 90, minLng: -180, maxLng: 180 }; const finalBounds = { ...defaultBounds, ...bounds }; return { latitude: this.float(finalBounds.minLat, finalBounds.maxLat, 6), longitude: this.float(finalBounds.minLng, finalBounds.maxLng, 6) }; } /** * 生成随机浏览器指纹参数 * @returns {Object} 浏览器指纹参数 */ static browserFingerprint() { return { userAgent: this.userAgent(), screenWidth: this.choice([1366, 1440, 1536, 1600, 1920]), screenHeight: this.choice([768, 900, 1024, 1080, 1200]), viewportWidth: this.int(1024, 1920), viewportHeight: this.int(768, 1080), deviceMemory: this.choice([4, 8, 16]), hardwareConcurrency: this.choice([4, 8, 12, 16]), timezone: this.choice(['Asia/Shanghai', 'Asia/Tokyo', 'America/New_York', 'Europe/London']), language: this.choice(['zh-CN', 'en-US', 'ja-JP']), platform: this.choice(['Win32', 'MacIntel', 'Linux x86_64']), webglVendor: this.choice(['Intel Inc.', 'NVIDIA Corporation', 'ATI Technologies Inc.']), webglRenderer: this.choice(['Intel Iris OpenGL Engine', 'NVIDIA GeForce GTX 1080', 'AMD Radeon Pro 580']) }; } /** * 生成随机设备信息 * @returns {Object} 设备信息 */ static deviceInfo() { const brands = ['Apple', 'Samsung', 'Huawei', 'Xiaomi', 'OPPO', 'Vivo']; const models = ['iPhone 13', 'Galaxy S21', 'Mate 40', 'Mi 11', 'Find X3', 'X60']; return { brand: this.choice(brands), model: this.choice(models), os: this.choice(['iOS 15', 'Android 11', 'Android 12']), screenSize: this.choice(['6.1', '6.5', '6.7', '5.8']), resolution: this.choice(['1080x2400', '1440x3200', '828x1792']) }; } } /** * 快捷函数 */ export const randomInt = RandomUtils.int; export const randomFloat = RandomUtils.float; export const randomBoolean = RandomUtils.boolean; export const randomChoice = RandomUtils.choice; export const randomChoices = RandomUtils.choices; export const randomShuffle = RandomUtils.shuffle; export const randomString = RandomUtils.string; export const randomLetters = RandomUtils.letters; export const randomDigits = RandomUtils.digits; export const randomUuid = RandomUtils.uuid; export const randomHex = RandomUtils.hex; export const randomDelay = RandomUtils.delay; export const randomDelaySeconds = RandomUtils.delaySeconds; export const randomDelayMinutes = RandomUtils.delayMinutes; export const randomChance = RandomUtils.chance; export const randomWeightedChoice = RandomUtils.weightedChoice; export const randomColor = RandomUtils.color; export const randomLocation = RandomUtils.location; export const randomBrowserFingerprint = RandomUtils.browserFingerprint; export const randomDeviceInfo = RandomUtils.deviceInfo; export default { RandomUtils, randomInt, randomFloat, randomBoolean, randomChoice, randomChoices, randomShuffle, randomString, randomLetters, randomDigits, randomUuid, randomHex, randomDelay, randomDelaySeconds, randomDelayMinutes, randomChance, randomWeightedChoice, randomColor, randomLocation, randomBrowserFingerprint, randomDeviceInfo };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/billyangbc/xiaohongshu-mcp-nodejs'

If you have feedback or need assistance with the MCP directory API, please join our Discord server