217 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const logger = require('./logger')
// 预先定义常量和函数引用
// 中国 IP 段来源data/ChineseIPGenerate.csv
const chinaIPRangesRaw = [
// 开始IP,结束IP,IP个数,位置
['1.0.1.0','1.0.3.255',768,'福州'],
['1.0.8.0','1.0.15.255',2048,'广州'],
['1.0.32.0','1.0.63.255',8192,'广州'],
['1.1.0.0','1.1.0.255',256,'福州'],
['1.1.2.0','1.1.63.255',15872,'广州'],
['1.2.0.0','1.2.2.255',768,'北京'],
['1.2.4.0','1.2.127.255',31744,'广州'],
['1.3.0.0','1.3.255.255',65536,'广州'],
['1.4.1.0','1.4.127.255',32512,'广州'],
['1.8.0.0','1.8.255.255',65536,'北京'],
['1.10.0.0','1.10.9.255',2560,'福州'],
['1.10.11.0','1.10.127.255',29952,'广州'],
['1.12.0.0','1.15.255.255',262144,'上海'],
['1.18.128.0','1.18.128.255',256,'北京'],
['1.24.0.0','1.31.255.255',524288,'赤峰'],
['1.45.0.0','1.45.255.255',65536,'北京'],
['1.48.0.0','1.51.255.255',262144,'济南'],
['1.56.0.0','1.63.255.255',524288,'伊春'],
['1.68.0.0','1.71.255.255',262144,'忻州'],
['1.80.0.0','1.95.255.255',1048576,'北京'],
['1.116.0.0','1.117.255.255',131072,'上海'],
['1.119.0.0','1.119.255.255',65536,'北京'],
['1.180.0.0','1.185.255.255',393216,'桂林'],
['1.188.0.0','1.199.255.255',786432,'洛阳'],
['1.202.0.0','1.207.255.255',393216,'铜仁'],
]
// 将原始字符串段转换为数值段并计算总数(在模块初始化时完成一次)
function ipToInt(ip) {
const parts = ip.split('.').map(Number)
return ((parts[0] << 24) >>> 0) + (parts[1] << 16) + (parts[2] << 8) + parts[3]
}
function intToIp(int) {
return [ (int >>> 24) & 0xFF, (int >>> 16) & 0xFF, (int >>> 8) & 0xFF, int & 0xFF ].join('.')
}
const chinaIPRanges = (function buildRanges() {
const arr = []
let total = 0
for (let i = 0; i < chinaIPRangesRaw.length; i++) {
const r = chinaIPRangesRaw[i]
const start = ipToInt(r[0])
const end = ipToInt(r[1])
const count = r[2] || (end - start + 1)
arr.push({ start, end, count, location: r[3] || '' })
total += count
}
// attach total for convenience
arr.totalCount = total
return arr
})()
const floor = Math.floor
const random = Math.random
const keys = Object.keys
// 预编译encodeURIComponent以减少查找开销
const encode = encodeURIComponent
module.exports = {
toBoolean(val) {
if (typeof val === 'boolean') return val
if (val === '') return val
return val === 'true' || val == '1'
},
cookieToJson(cookie) {
if (!cookie) return {}
let cookieArr = cookie.split(';')
let obj = {}
// 优化使用for循环替代forEach性能更好
for (let i = 0, len = cookieArr.length; i < len; i++) {
let item = cookieArr[i]
let arr = item.split('=')
// 优化:使用严格等于
if (arr.length === 2) {
obj[arr[0].trim()] = arr[1].trim()
}
}
return obj
},
cookieObjToString(cookie) {
// 优化使用预绑定的keys函数和for循环
const cookieKeys = keys(cookie)
const result = []
// 优化使用for循环和预分配数组
for (let i = 0, len = cookieKeys.length; i < len; i++) {
const key = cookieKeys[i]
result[i] = `${encode(key)}=${encode(cookie[key])}`
}
return result.join('; ')
},
getRandom(num) {
// 优化:简化随机数生成逻辑
// 原逻辑看起来有问题,这里保持原意但优化性能
var randomValue = random()
var floorValue = floor(randomValue * 9 + 1)
var powValue = Math.pow(10, num - 1)
var randomNum = floor((randomValue + floorValue) * powValue)
return randomNum
},
generateRandomChineseIP() {
// 从预定义的中国 IP 段中按权重随机选择一个段,然后在该段内生成随机 IP
const total = chinaIPRanges.totalCount || 0
if (!total) {
// 兜底:回退到旧逻辑(随机 116.x 前缀)
const fallback = `116.${getRandomInt(25,94)}.${generateIPSegment()}.${generateIPSegment()}`
logger.info('Generated Random Chinese IP (fallback):', fallback)
return fallback
}
// 选择一个全局随机偏移([0, total)
let offset = Math.floor(random() * total)
let chosen = null
for (let i = 0; i < chinaIPRanges.length; i++) {
const seg = chinaIPRanges[i]
if (offset < seg.count) {
chosen = seg
break
}
offset -= seg.count
}
// 如果没有选中(理论上不应该发生),回退到最后一个段
if (!chosen) chosen = chinaIPRanges[chinaIPRanges.length - 1]
// 在段内随机生成一个 IP使用段真实的数值范围而非 csv 中的 count
const segSize = chosen.end - chosen.start + 1
const ipInt = chosen.start + Math.floor(random() * segSize)
const ip = intToIp(ipInt)
logger.info('Generated Random Chinese IP:', ip, 'location:', chosen.location)
return ip
},
// 生成chainId的函数
generateChainId(cookie) {
const version = 'v1'
const randomNum = Math.floor(Math.random() * 1e6)
const deviceId =
getCookieValue(cookie, 'sDeviceId') || 'unknown-' + randomNum
const platform = 'web'
const action = 'login'
const timestamp = Date.now()
return `${version}_${deviceId}_${platform}_${action}_${timestamp}`
},
generateDeviceId() {
const hexChars = '0123456789ABCDEF'
const chars = []
for (let i = 0; i < 52; i++) {
const randomIndex = Math.floor(Math.random() * hexChars.length)
chars.push(hexChars[randomIndex])
}
return chars.join('')
},
}
// 优化:预先绑定函数
function getRandomInt(min, max) {
// 优化:简化计算
return floor(random() * (max - min + 1)) + min
}
// 优化预先绑定generateIPSegment函数引用
function generateIPSegment() {
// 优化:内联常量
return getRandomInt(1, 255)
}
// 进一步优化版本(如果需要更高性能):
/*
const cookieToJsonOptimized = (function() {
// 预编译trim函数
const trim = String.prototype.trim
return function(cookie) {
if (!cookie) return {}
const cookieArr = cookie.split(';')
const obj = {}
for (let i = 0, len = cookieArr.length; i < len; i++) {
const item = cookieArr[i]
const eqIndex = item.indexOf('=')
if (eqIndex > 0 && eqIndex < item.length - 1) {
const key = trim.call(item.substring(0, eqIndex))
const value = trim.call(item.substring(eqIndex + 1))
obj[key] = value
}
}
return obj
}
})()
*/
// 用于从cookie字符串中获取指定值的辅助函数
function getCookieValue(cookieStr, name) {
if (!cookieStr) return ''
const cookies = '; ' + cookieStr
const parts = cookies.split('; ' + name + '=')
if (parts.length === 2) return parts.pop().split(';').shift()
return ''
}