@neteasecloudmusicapienhanced/api 4.29.16 → 4.29.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/ChineseIPGenerate.csv +26 -0
- package/module/song_url_v1.js +2 -1
- package/package.json +4 -4
- package/server.js +3 -3
- package/util/index.js +98 -27
|
@@ -0,0 +1,26 @@
|
|
|
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,铜仁
|
package/module/song_url_v1.js
CHANGED
|
@@ -17,7 +17,7 @@ module.exports = async (query, request) => {
|
|
|
17
17
|
if (query.unblock === 'true') {
|
|
18
18
|
try {
|
|
19
19
|
const result = await match(query.id, source)
|
|
20
|
-
logger.info('
|
|
20
|
+
logger.info('Starting unblock(uses modules unblock):', query.id, result)
|
|
21
21
|
// avoid optional chaining for compatibility
|
|
22
22
|
let url
|
|
23
23
|
if (Array.isArray(result)) {
|
|
@@ -40,6 +40,7 @@ module.exports = async (query, request) => {
|
|
|
40
40
|
status: 200,
|
|
41
41
|
body: {
|
|
42
42
|
code: 200,
|
|
43
|
+
msg: 'Warning: you can only adjust unblock source in dotenv config, use /song/url/match instead.',
|
|
43
44
|
data: [
|
|
44
45
|
{
|
|
45
46
|
id: Number(query.id),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neteasecloudmusicapienhanced/api",
|
|
3
|
-
"version": "4.29.
|
|
3
|
+
"version": "4.29.17",
|
|
4
4
|
"description": "为停更的网易云音乐 NodeJs API 提供持续的维护!",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "nodemon app.js",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"express": "^5.1.0",
|
|
74
74
|
"express-fileupload": "^1.5.2",
|
|
75
75
|
"md5": "^2.3.0",
|
|
76
|
-
"music-metadata": "^11.
|
|
76
|
+
"music-metadata": "^11.10.0",
|
|
77
77
|
"node-forge": "^1.3.1",
|
|
78
78
|
"pac-proxy-agent": "^7.2.0",
|
|
79
79
|
"qrcode": "^1.5.4",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"@types/mocha": "^10.0.10",
|
|
91
91
|
"@types/node": "24.10.0",
|
|
92
92
|
"@typescript-eslint/eslint-plugin": "8.46.2",
|
|
93
|
-
"@typescript-eslint/parser": "8.46.
|
|
93
|
+
"@typescript-eslint/parser": "8.46.3",
|
|
94
94
|
"eslint": "9.39.0",
|
|
95
95
|
"eslint-config-prettier": "10.1.8",
|
|
96
96
|
"eslint-plugin-html": "8.1.3",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"intelli-espower-loader": "1.1.0",
|
|
101
101
|
"lint-staged": "16.2.6",
|
|
102
102
|
"mocha": "11.7.4",
|
|
103
|
-
"nodemon": "^3.1.
|
|
103
|
+
"nodemon": "^3.1.11",
|
|
104
104
|
"pkg": "^5.8.1",
|
|
105
105
|
"power-assert": "1.6.1",
|
|
106
106
|
"prettier": "3.6.2",
|
package/server.js
CHANGED
|
@@ -235,7 +235,7 @@ async function consturctServer(moduleDefs) {
|
|
|
235
235
|
if (ip == '::1') {
|
|
236
236
|
ip = global.cnIp
|
|
237
237
|
}
|
|
238
|
-
|
|
238
|
+
logger.info('Requested from ip:', ip)
|
|
239
239
|
obj[3] = {
|
|
240
240
|
...obj[3],
|
|
241
241
|
ip,
|
|
@@ -258,11 +258,11 @@ async function consturctServer(moduleDefs) {
|
|
|
258
258
|
const source = process.env.UNBLOCK_SOURCE
|
|
259
259
|
? process.env.UNBLOCK_SOURCE.split(',')
|
|
260
260
|
: ['pyncmd', 'bodian', 'kuwo', 'qq', 'migu', 'kugou']
|
|
261
|
-
logger.info('
|
|
261
|
+
logger.info('Starting unblock(uses general unblock):', source)
|
|
262
262
|
const { url } = await match(req.query.id, source)
|
|
263
263
|
song.url = url
|
|
264
264
|
song.freeTrialInfo = 'null'
|
|
265
|
-
logger.info('
|
|
265
|
+
logger.info('Unblock success! url:', song.url)
|
|
266
266
|
}
|
|
267
267
|
if (song.url && song.url.includes('kuwo')) {
|
|
268
268
|
const proxy = process.env.PROXY_URL
|
package/util/index.js
CHANGED
|
@@ -1,28 +1,69 @@
|
|
|
1
1
|
const logger = require('./logger')
|
|
2
2
|
// 预先定义常量和函数引用
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
'
|
|
7
|
-
'
|
|
8
|
-
'
|
|
9
|
-
'
|
|
10
|
-
'
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
3
|
+
// 中国 IP 段(来源:data/ChineseIPGenerate.csv)
|
|
4
|
+
const chinaIPRangesRaw = [
|
|
5
|
+
// 开始IP, 结束IP, IP个数, 位置
|
|
6
|
+
['1.0.1.0', '1.0.3.255', 768, '福州'],
|
|
7
|
+
['1.0.8.0', '1.0.15.255', 2048, '广州'],
|
|
8
|
+
['1.0.32.0', '1.0.63.255', 8192, '广州'],
|
|
9
|
+
['1.1.0.0', '1.1.0.255', 256, '福州'],
|
|
10
|
+
['1.1.2.0', '1.1.63.255', 15872, '广州'],
|
|
11
|
+
['1.2.0.0', '1.2.2.255', 768, '北京'],
|
|
12
|
+
['1.2.4.0', '1.2.127.255', 31744, '广州'],
|
|
13
|
+
['1.3.0.0', '1.3.255.255', 65536, '广州'],
|
|
14
|
+
['1.4.1.0', '1.4.127.255', 32512, '广州'],
|
|
15
|
+
['1.8.0.0', '1.8.255.255', 65536, '北京'],
|
|
16
|
+
['1.10.0.0', '1.10.9.255', 2560, '福州'],
|
|
17
|
+
['1.10.11.0', '1.10.127.255', 29952, '广州'],
|
|
18
|
+
['1.12.0.0', '1.15.255.255', 262144, '上海'],
|
|
19
|
+
['1.18.128.0', '1.18.128.255', 256, '北京'],
|
|
20
|
+
['1.24.0.0', '1.31.255.255', 524288, '赤峰'],
|
|
21
|
+
['1.45.0.0', '1.45.255.255', 65536, '北京'],
|
|
22
|
+
['1.48.0.0', '1.51.255.255', 262144, '济南'],
|
|
23
|
+
['1.56.0.0', '1.63.255.255', 524288, '伊春'],
|
|
24
|
+
['1.68.0.0', '1.71.255.255', 262144, '忻州'],
|
|
25
|
+
['1.80.0.0', '1.95.255.255', 1048576, '北京'],
|
|
26
|
+
['1.116.0.0', '1.117.255.255', 131072, '上海'],
|
|
27
|
+
['1.119.0.0', '1.119.255.255', 65536, '北京'],
|
|
28
|
+
['1.180.0.0', '1.185.255.255', 393216, '桂林'],
|
|
29
|
+
['1.188.0.0', '1.199.255.255', 786432, '洛阳'],
|
|
30
|
+
['1.202.0.0', '1.207.255.255', 393216, '铜仁'],
|
|
24
31
|
]
|
|
25
|
-
|
|
32
|
+
|
|
33
|
+
// 将原始字符串段转换为数值段并计算总数(在模块初始化时完成一次)
|
|
34
|
+
function ipToInt(ip) {
|
|
35
|
+
const parts = ip.split('.').map(Number)
|
|
36
|
+
const a = (parts[0] << 24) >>> 0
|
|
37
|
+
const b = parts[1] << 16
|
|
38
|
+
const c = parts[2] << 8
|
|
39
|
+
const d = parts[3]
|
|
40
|
+
return a + b + c + d
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function intToIp(int) {
|
|
44
|
+
return [
|
|
45
|
+
(int >>> 24) & 0xff,
|
|
46
|
+
(int >>> 16) & 0xff,
|
|
47
|
+
(int >>> 8) & 0xff,
|
|
48
|
+
int & 0xff,
|
|
49
|
+
].join('.')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const chinaIPRanges = (function buildRanges() {
|
|
53
|
+
const arr = []
|
|
54
|
+
let total = 0
|
|
55
|
+
for (let i = 0; i < chinaIPRangesRaw.length; i++) {
|
|
56
|
+
const r = chinaIPRangesRaw[i]
|
|
57
|
+
const start = ipToInt(r[0])
|
|
58
|
+
const end = ipToInt(r[1])
|
|
59
|
+
const count = r[2] || end - start + 1
|
|
60
|
+
arr.push({ start, end, count, location: r[3] || '' })
|
|
61
|
+
total += count
|
|
62
|
+
}
|
|
63
|
+
// attach total for convenience
|
|
64
|
+
arr.totalCount = total
|
|
65
|
+
return arr
|
|
66
|
+
})()
|
|
26
67
|
const floor = Math.floor
|
|
27
68
|
const random = Math.random
|
|
28
69
|
const keys = Object.keys
|
|
@@ -79,11 +120,41 @@ module.exports = {
|
|
|
79
120
|
},
|
|
80
121
|
|
|
81
122
|
generateRandomChineseIP() {
|
|
82
|
-
//
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
123
|
+
// 从预定义的中国 IP 段中按权重随机选择一个段,然后在该段内生成随机 IP
|
|
124
|
+
const total = chinaIPRanges.totalCount || 0
|
|
125
|
+
if (!total) {
|
|
126
|
+
// 兜底:回退到旧逻辑(随机 116.x 前缀)
|
|
127
|
+
const fallback = `116.${getRandomInt(25, 94)}.${generateIPSegment()}.${generateIPSegment()}`
|
|
128
|
+
logger.info('Generated Random Chinese IP (fallback):', fallback)
|
|
129
|
+
return fallback
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 选择一个全局随机偏移([0, total))
|
|
133
|
+
let offset = Math.floor(random() * total)
|
|
134
|
+
let chosen = null
|
|
135
|
+
for (let i = 0; i < chinaIPRanges.length; i++) {
|
|
136
|
+
const seg = chinaIPRanges[i]
|
|
137
|
+
if (offset < seg.count) {
|
|
138
|
+
chosen = seg
|
|
139
|
+
break
|
|
140
|
+
}
|
|
141
|
+
offset -= seg.count
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 如果没有选中(理论上不应该发生),回退到最后一个段
|
|
145
|
+
if (!chosen) chosen = chinaIPRanges[chinaIPRanges.length - 1]
|
|
146
|
+
|
|
147
|
+
// 在段内随机生成一个 IP(使用段真实的数值范围,而非 csv 中的 count)
|
|
148
|
+
const segSize = chosen.end - chosen.start + 1
|
|
149
|
+
const ipInt = chosen.start + Math.floor(random() * segSize)
|
|
150
|
+
const ip = intToIp(ipInt)
|
|
151
|
+
logger.info(
|
|
152
|
+
'Generated Random Chinese IP:',
|
|
153
|
+
ip,
|
|
154
|
+
'location:',
|
|
155
|
+
chosen.location,
|
|
156
|
+
)
|
|
157
|
+
return ip
|
|
87
158
|
},
|
|
88
159
|
// 生成chainId的函数
|
|
89
160
|
generateChainId(cookie) {
|