@neteasecloudmusicapienhanced/api 4.29.16 → 4.29.18

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.
@@ -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,铜仁
@@ -18,7 +18,7 @@ module.exports = async (query, request) => {
18
18
  let result = await request(
19
19
  `/api/w/login/cellphone`,
20
20
  data,
21
- createOption(query),
21
+ createOption(query, 'weapi'),
22
22
  )
23
23
 
24
24
  if (result.body.code === 200) {
@@ -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('开始解灰', query.id, result)
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,7 +1,7 @@
1
1
  {
2
2
  "name": "@neteasecloudmusicapienhanced/api",
3
- "version": "4.29.16",
4
- "description": "为停更的网易云音乐 NodeJs API 提供持续的维护!",
3
+ "version": "4.29.18",
4
+ "description": "A revival project for NeteaseCloudMusicApi Node.js Services (Half Refactor & Enhanced)|| 网易云音乐 API 备份 + 增强 || 本项目自原版v4.28.0版本后开始自行维护",
5
5
  "scripts": {
6
6
  "dev": "nodemon app.js",
7
7
  "start": "node app.js",
@@ -70,11 +70,11 @@
70
70
  "axios": "^1.13.2",
71
71
  "crypto-js": "^4.2.0",
72
72
  "dotenv": "^17.2.3",
73
- "express": "^5.1.0",
73
+ "express": "^5.2.1",
74
74
  "express-fileupload": "^1.5.2",
75
75
  "md5": "^2.3.0",
76
- "music-metadata": "^11.9.0",
77
- "node-forge": "^1.3.1",
76
+ "music-metadata": "^11.10.3",
77
+ "node-forge": "^1.3.3",
78
78
  "pac-proxy-agent": "^7.2.0",
79
79
  "qrcode": "^1.5.4",
80
80
  "safe-decode-uri-component": "^1.2.1",
@@ -83,14 +83,14 @@
83
83
  "yargs": "^18.0.0"
84
84
  },
85
85
  "devDependencies": {
86
- "@eslint/eslintrc": "^3.3.1",
87
- "@eslint/js": "^9.39.1",
88
- "@types/express": "^5.0.5",
86
+ "@eslint/eslintrc": "^3.3.3",
87
+ "@eslint/js": "^9.39.2",
88
+ "@types/express": "^5.0.6",
89
89
  "@types/express-fileupload": "^1.5.1",
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.2",
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",
@@ -99,8 +99,8 @@
99
99
  "husky": "9.1.7",
100
100
  "intelli-espower-loader": "1.1.0",
101
101
  "lint-staged": "16.2.6",
102
- "mocha": "11.7.4",
103
- "nodemon": "^3.1.10",
102
+ "mocha": "11.7.5",
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
- // logger.info(ip)
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('开始解灰', source)
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
- const chinaIPPrefixes = [
4
- '116.25',
5
- '116.76',
6
- '116.77',
7
- '116.78',
8
- '116.79',
9
- '116.80',
10
- '116.81',
11
- '116.82',
12
- '116.83',
13
- '116.84',
14
- '116.85',
15
- '116.86',
16
- '116.87',
17
- '116.88',
18
- '116.89',
19
- '116.90',
20
- '116.91',
21
- '116.92',
22
- '116.93',
23
- '116.94',
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
- const prefixesLength = chinaIPPrefixes.length
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 randomPrefix = chinaIPPrefixes[floor(random() * prefixesLength)]
84
- const returns = `${randomPrefix}.${generateIPSegment()}.${generateIPSegment()}`
85
- logger.info('Generated Random Chinese IP:', returns)
86
- return returns
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) {