Compare commits

..

3 Commits

Author SHA1 Message Date
2047bdfa65
Merge branch 'main' into 'main'
refactor: Refactor random Chinese IP generator
2026-02-15 00:20:25 +08:00
bc9d7b949f
fix: 修复注入随机ip不生效 2026-02-15 00:06:42 +08:00
f08f192328
refactor: 重构随机中国ip 2026-02-14 23:50:59 +08:00
10 changed files with 4221 additions and 92 deletions

View File

@ -7,9 +7,9 @@
!/app.js !/app.js
!/server.js !/server.js
!/package.json !/package.json
!/package-lock.json
!/index.js !/index.js
!/generateConfig.js !/generateConfig.js
!/main.js !/main.js
!/data !/data
!/.env !/.env
!/pnpm-lock.yaml

View File

@ -16,7 +16,7 @@ updates:
# 自动合并小版本更新的 PR (可选) # 自动合并小版本更新的 PR (可选)
# 可以设置针对 patch 或 minor 版本更新自动合并 # 可以设置针对 patch 或 minor 版本更新自动合并
commit-message: commit-message:
prefix: "chore(packages):" # PR 合并提交信息的前缀 prefix: "build(packages):" # PR 合并提交信息的前缀
# 更新 GitHub Actions 依赖 # 更新 GitHub Actions 依赖
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"

View File

@ -1,26 +0,0 @@
开始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,铜仁
1 开始IP 结束IP IP个数 位置
2 1.0.1.0 1.0.3.255 768 福州
3 1.0.8.0 1.0.15.255 2048 广州
4 1.0.32.0 1.0.63.255 8192 广州
5 1.1.0.0 1.1.0.255 256 福州
6 1.1.2.0 1.1.63.255 15872 广州
7 1.2.0.0 1.2.2.255 768 北京
8 1.2.4.0 1.2.127.255 31744 广州
9 1.3.0.0 1.3.255.255 65536 广州
10 1.4.1.0 1.4.127.255 32512 广州
11 1.8.0.0 1.8.255.255 65536 北京
12 1.10.0.0 1.10.9.255 2560 福州
13 1.10.11.0 1.10.127.255 29952 广州
14 1.12.0.0 1.15.255.255 262144 上海
15 1.18.128.0 1.18.128.255 256 北京
16 1.24.0.0 1.31.255.255 524288 赤峰
17 1.45.0.0 1.45.255.255 65536 北京
18 1.48.0.0 1.51.255.255 262144 济南
19 1.56.0.0 1.63.255.255 524288 伊春
20 1.68.0.0 1.71.255.255 262144 忻州
21 1.80.0.0 1.95.255.255 1048576 北京
22 1.116.0.0 1.117.255.255 131072 上海
23 1.119.0.0 1.119.255.255 65536 北京
24 1.180.0.0 1.185.255.255 393216 桂林
25 1.188.0.0 1.199.255.255 786432 洛阳
26 1.202.0.0 1.207.255.255 393216 铜仁

4147
data/china_ip_ranges.txt Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2,6 +2,8 @@
网易云音乐 NodeJS API Enhanced 网易云音乐 NodeJS API Enhanced
最后更新于: 2026.2.15
## 灵感来自 ## 灵感来自
[disoul/electron-cloud-music](https://github.com/disoul/electron-cloud-music) [disoul/electron-cloud-music](https://github.com/disoul/electron-cloud-music)

View File

@ -227,20 +227,23 @@ async function consturctServer(moduleDefs) {
const moduleResponse = await moduleDef.module(query, (...params) => { const moduleResponse = await moduleDef.module(query, (...params) => {
// 参数注入客户端IP // 参数注入客户端IP
const obj = [...params] const obj = [...params]
// 获取请求中的 IP 参数 const options = obj[2] || {}
let ip = req.ip if (!options.randomCNIP) {
let ip = req.ip
if (ip.substring(0, 7) == '::ffff:') { if (ip.substring(0, 7) == '::ffff:') {
ip = ip.substring(7) ip = ip.substring(7)
} }
if (ip == '::1') { if (ip == '::1') {
ip = global.cnIp ip = global.cnIp
} }
// logger.info('Requested from ip:', ip) // logger.info('Requested from ip:', ip)
obj[2] = { obj[2] = {
...(obj[2] || {}), ...options,
ip, ip,
}
} }
return request(...obj) return request(...obj)
}) })
logger.info(`Request Success: ${decode(req.originalUrl)}`) logger.info(`Request Success: ${decode(req.originalUrl)}`)

View File

@ -1,36 +1,8 @@
const logger = require('./logger') const logger = require('./logger')
// 预先定义常量和函数引用 const fs = require('fs')
// 中国 IP 段来源data/ChineseIPGenerate.csv const path = require('path')
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, '铜仁'],
]
// 将原始字符串段转换为数值段并计算总数(在模块初始化时完成一次) // IP地址转换函数
function ipToInt(ip) { function ipToInt(ip) {
const parts = ip.split('.').map(Number) const parts = ip.split('.').map(Number)
const a = (parts[0] << 24) >>> 0 const a = (parts[0] << 24) >>> 0
@ -49,20 +21,56 @@ function intToIp(int) {
].join('.') ].join('.')
} }
const chinaIPRanges = (function buildRanges() { // 解析CIDR格式的IP段
const arr = [] function parseCIDR(cidr) {
let total = 0 const [ipStr, prefixLengthStr] = cidr.split('/')
for (let i = 0; i < chinaIPRangesRaw.length; i++) { const prefixLength = parseInt(prefixLengthStr, 10)
const r = chinaIPRangesRaw[i]
const start = ipToInt(r[0]) const ipInt = ipToInt(ipStr)
const end = ipToInt(r[1]) const mask = (0xffffffff << (32 - prefixLength)) >>> 0
const count = r[2] || end - start + 1 const start = (ipInt & mask) >>> 0
arr.push({ start, end, count, location: r[3] || '' }) const end = (start | (~mask >>> 0)) >>> 0
total += count const count = end - start + 1
return { start, end, count, cidr }
}
// 从china_ip_ranges.txt加载中国IP段CIDR格式
const chinaIPRanges = (function loadChinaIPRanges() {
try {
const filePath = path.join(__dirname, '../data/china_ip_ranges.txt')
const content = fs.readFileSync(filePath, 'utf-8')
const lines = content
.split('\n')
.filter((line) => line.trim() && !line.startsWith('#'))
const arr = []
let total = 0
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim()
if (!line) continue
const range = parseCIDR(line)
arr.push(range)
total += range.count
}
// 按IP段大小排序提高随机选择效率
arr.sort((a, b) => b.count - a.count)
// attach total for convenience
arr.totalCount = total
logger.info(
`Loaded ${arr.length} Chinese IP ranges from china_ip_ranges.txt, total ${total} IPs`,
)
return arr
} catch (error) {
logger.error('Failed to load china_ip_ranges.txt:', error.message)
// 返回空数组generateRandomChineseIP会使用兜底逻辑
return { totalCount: 0 }
} }
// attach total for convenience
arr.totalCount = total
return arr
})() })()
const floor = Math.floor const floor = Math.floor
const random = Math.random const random = Math.random
@ -144,16 +152,11 @@ module.exports = {
// 如果没有选中(理论上不应该发生),回退到最后一个段 // 如果没有选中(理论上不应该发生),回退到最后一个段
if (!chosen) chosen = chinaIPRanges[chinaIPRanges.length - 1] if (!chosen) chosen = chinaIPRanges[chinaIPRanges.length - 1]
// 在段内随机生成一个 IP使用段真实的数值范围,而非 csv 中的 count // 在段内随机生成一个 IP使用段真实的数值范围
const segSize = chosen.end - chosen.start + 1 const segSize = chosen.end - chosen.start + 1
const ipInt = chosen.start + Math.floor(random() * segSize) const ipInt = chosen.start + Math.floor(random() * segSize)
const ip = intToIp(ipInt) const ip = intToIp(ipInt)
logger.info( logger.info('Generated Random Chinese IP:', ip, 'from CIDR:', chosen.cidr)
'Generated Random Chinese IP:',
ip,
'location:',
chosen.location,
)
return ip return ip
}, },
// 生成chainId的函数 // 生成chainId的函数