@neteasecloudmusicapienhanced/api 4.30.0 → 4.30.2
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/README.MD +47 -23
- package/data/china_ip_ranges.txt +4147 -0
- package/module/cloud.js +136 -119
- package/module/cloud_upload_complete.js +72 -0
- package/module/cloud_upload_token.js +111 -0
- package/module/comment_info_list.js +30 -0
- package/module/song_url_ncmget.js +2 -74
- package/module/user_playlist_collect.js +14 -0
- package/module/user_playlist_create.js +14 -0
- package/module/voice_upload.js +36 -22
- package/package.json +19 -21
- package/plugins/songUpload.js +67 -19
- package/plugins/upload.js +5 -7
- package/public/cloud.html +406 -39
- package/public/docs/home.md +168 -1
- package/public/docs/index.html +1 -1
- package/public/docs/logo.svg +6 -0
- package/public/docs/netease.png +0 -0
- package/public/index.html +29 -4
- package/public/static/docs.png +0 -0
- package/server.js +37 -17
- package/util/fileHelper.js +88 -0
- package/util/index.js +55 -52
- package/util/request.js +6 -6
- package/data/ChineseIPGenerate.csv +0 -26
- package/public/docs/ncmapireborn.png +0 -0
- /package/public/static/{screenshot1.png → module_test.png} +0 -0
package/public/docs/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="KEYWords" contect="网易云音乐,网易云音乐 api,网易云音乐 nodejs,网易云音乐 node.js">
|
|
6
6
|
<meta name="description" content="网易云音乐 NodeJS API Enhanced">
|
|
7
7
|
<title>网易云音乐 NodeJS API Enhanced</title>
|
|
8
|
-
<link rel="icon" href="
|
|
8
|
+
<link rel="icon" href="netease.png">
|
|
9
9
|
<meta name="description" content="Description">
|
|
10
10
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
11
11
|
<meta name="referrer" content="never">
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
2
|
+
<g>
|
|
3
|
+
<path fill="none" d="M0 0h24v24H0z"/>
|
|
4
|
+
<path d="M10.421 11.375c-.294 1.028.012 2.064.784 2.653 1.061.81 2.565.3 2.874-.995.08-.337.103-.722.027-1.056-.23-1.001-.52-1.988-.792-2.996-1.33.154-2.543 1.172-2.893 2.394zm5.548-.287c.273 1.012.285 2.017-.127 3-1.128 2.69-4.721 3.14-6.573.826-1.302-1.627-1.28-3.961.06-5.734.78-1.032 1.804-1.707 3.048-2.054l.379-.104c-.084-.415-.188-.816-.243-1.224-.176-1.317.512-2.503 1.744-3.04 1.226-.535 2.708-.216 3.53.76.406.479.395 1.08-.025 1.464-.412.377-.996.346-1.435-.09-.247-.246-.51-.44-.877-.436-.525.006-.987.418-.945.937.037.468.173.93.3 1.386.022.078.216.135.338.153 1.334.197 2.504.731 3.472 1.676 2.558 2.493 2.861 6.531.672 9.44-1.529 2.032-3.61 3.168-6.127 3.409-4.621.44-8.664-2.53-9.7-7.058C2.515 10.255 4.84 5.831 8.795 4.25c.586-.234 1.143-.031 1.371.498.232.537-.019 1.086-.61 1.35-2.368 1.06-3.817 2.855-4.215 5.424-.533 3.433 1.656 6.776 5 7.72 2.723.77 5.658-.166 7.308-2.33 1.586-2.08 1.4-5.099-.427-6.873a3.979 3.979 0 0 0-1.823-1.013c.198.716.389 1.388.57 2.062z"/>
|
|
5
|
+
</g>
|
|
6
|
+
</svg>
|
|
Binary file
|
package/public/index.html
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
7
|
+
<link rel="icon" href="docs/netease.png">
|
|
7
8
|
<title>网易云音乐 API Enhanced</title>
|
|
8
9
|
<style>
|
|
9
10
|
:root {
|
|
@@ -18,20 +19,33 @@
|
|
|
18
19
|
html, body { height: 100%; }
|
|
19
20
|
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: var(--fg); background: var(--bg); line-height: 1.6; }
|
|
20
21
|
.container { max-width: 960px; margin: 40px auto; padding: 0 20px; }
|
|
22
|
+
@media (max-width: 480px) {
|
|
23
|
+
.container { margin: 20px auto; padding: 0 16px; }
|
|
24
|
+
header.site-header h1 { font-size: 22px; }
|
|
25
|
+
.block { padding: 16px; }
|
|
26
|
+
}
|
|
21
27
|
header.site-header { margin-bottom: 24px; }
|
|
22
28
|
header.site-header h1 { font-size: 28px; font-weight: 600; margin: 0; }
|
|
23
29
|
.badge { display: inline-block; margin-left: 8px; padding: 4px 10px; border: 1px solid var(--border); border-radius: 12px; font-size: 12px; color: var(--muted); }
|
|
24
30
|
.sub { margin-top: 8px; color: var(--muted); font-size: 14px; }
|
|
25
31
|
.block { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px; margin-bottom: 16px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); }
|
|
26
32
|
.block h2 { margin: 0 0 12px; font-size: 18px; font-weight: 600; }
|
|
27
|
-
.kvs { display: grid; grid-template-columns:
|
|
28
|
-
.kvs div:first-child { color: var(--muted); }
|
|
33
|
+
.kvs { display: grid; grid-template-columns: 100px 1fr; gap: 8px 12px; align-items: start; }
|
|
34
|
+
.kvs div:first-child { color: var(--muted); flex-shrink: 0; }
|
|
35
|
+
.kvs div:last-child { word-break: break-all; overflow-wrap: anywhere; min-width: 0; overflow: hidden; }
|
|
36
|
+
@media (max-width: 480px) {
|
|
37
|
+
.kvs { grid-template-columns: 1fr; gap: 4px 12px; }
|
|
38
|
+
.kvs div:first-child { font-weight: 500; }
|
|
39
|
+
}
|
|
29
40
|
ul.links { list-style: none; padding: 0; margin: 0; }
|
|
30
41
|
ul.links li { margin: 8px 0; }
|
|
31
42
|
ul.links a { color: var(--fg); text-decoration: none; border-bottom: 1px dotted var(--border); transition: all 0.2s ease; }
|
|
32
43
|
ul.links a:hover { color: var(--accent); border-bottom-color: var(--accent); }
|
|
33
|
-
pre { margin: 0; background: #f9f9f9; border: 1px solid var(--border); border-radius: 6px; padding: 12px; overflow: auto; }
|
|
44
|
+
pre { margin: 0; background: #f9f9f9; border: 1px solid var(--border); border-radius: 6px; padding: 12px; overflow-x: auto; white-space: pre-wrap; word-break: break-all; }
|
|
34
45
|
code { font-family: 'Courier New', monospace; font-size: 13px; }
|
|
46
|
+
@media (max-width: 480px) {
|
|
47
|
+
code { font-size: 12px; }
|
|
48
|
+
}
|
|
35
49
|
footer.site-footer { margin-top: 24px; padding-top: 12px; border-top: 1px solid var(--border); color: var(--muted); text-align: center; }
|
|
36
50
|
footer.site-footer a { color: var(--fg); text-decoration: none; transition: color 0.2s ease; }
|
|
37
51
|
footer.site-footer a:hover { color: var(--accent); }
|
|
@@ -71,7 +85,18 @@
|
|
|
71
85
|
<h2>调试部分</h2>
|
|
72
86
|
<pre><code>curl -s {origin}/inner/version
|
|
73
87
|
curl -s {origin}/search?keywords=网易云</code></pre>
|
|
74
|
-
<
|
|
88
|
+
<div style="margin-top:10px; line-height:2;">
|
|
89
|
+
<a href="/api.html">交互式调试</a> ·
|
|
90
|
+
<a href="/qrlogin.html">二维码登录示例</a> ·
|
|
91
|
+
<a href="/unblock_test.html">解灰测试</a> ·
|
|
92
|
+
<a href="/audio_match_demo/index.html">听歌识曲 Demo</a> ·
|
|
93
|
+
<a href="/cloud.html">云盘上传</a> ·
|
|
94
|
+
<a href="/playlist_import.html">歌单导入</a> ·
|
|
95
|
+
<a href="/eapi_decrypt.html">EAPI 解密</a> ·
|
|
96
|
+
<a href="/listen_together_host.html">一起听示例</a> ·
|
|
97
|
+
<a href="/playlist_cover_update.html">更新歌单封面示例</a> ·
|
|
98
|
+
<a href="/avatar_update.html">头像更新示例</a>
|
|
99
|
+
</div>
|
|
75
100
|
</section>
|
|
76
101
|
|
|
77
102
|
<footer class="site-footer">
|
package/public/static/docs.png
CHANGED
|
Binary file
|
package/server.js
CHANGED
|
@@ -178,10 +178,25 @@ async function consturctServer(moduleDefs) {
|
|
|
178
178
|
/**
|
|
179
179
|
* Body Parser and File Upload
|
|
180
180
|
*/
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
app.use(
|
|
181
|
+
const MAX_UPLOAD_SIZE_MB = 500
|
|
182
|
+
const MAX_UPLOAD_SIZE_BYTES = MAX_UPLOAD_SIZE_MB * 1024 * 1024
|
|
183
|
+
|
|
184
|
+
app.use(express.json({ limit: `${MAX_UPLOAD_SIZE_MB}mb` }))
|
|
185
|
+
app.use(
|
|
186
|
+
express.urlencoded({ extended: false, limit: `${MAX_UPLOAD_SIZE_MB}mb` }),
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
app.use(
|
|
190
|
+
fileUpload({
|
|
191
|
+
limits: {
|
|
192
|
+
fileSize: MAX_UPLOAD_SIZE_BYTES,
|
|
193
|
+
},
|
|
194
|
+
useTempFiles: true,
|
|
195
|
+
tempFileDir: require('os').tmpdir(),
|
|
196
|
+
abortOnLimit: true,
|
|
197
|
+
parseNested: true,
|
|
198
|
+
}),
|
|
199
|
+
)
|
|
185
200
|
|
|
186
201
|
/**
|
|
187
202
|
* Cache
|
|
@@ -227,25 +242,30 @@ async function consturctServer(moduleDefs) {
|
|
|
227
242
|
const moduleResponse = await moduleDef.module(query, (...params) => {
|
|
228
243
|
// 参数注入客户端IP
|
|
229
244
|
const obj = [...params]
|
|
230
|
-
|
|
245
|
+
const options = obj[2] || {}
|
|
246
|
+
if (!options.randomCNIP) {
|
|
247
|
+
let ip = req.ip
|
|
231
248
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
249
|
+
if (ip.substring(0, 7) == '::ffff:') {
|
|
250
|
+
ip = ip.substring(7)
|
|
251
|
+
}
|
|
252
|
+
if (ip == '::1') {
|
|
253
|
+
ip = global.cnIp
|
|
254
|
+
}
|
|
255
|
+
// logger.info('Requested from ip:', ip)
|
|
256
|
+
obj[2] = {
|
|
257
|
+
...options,
|
|
258
|
+
ip,
|
|
259
|
+
}
|
|
242
260
|
}
|
|
261
|
+
|
|
243
262
|
return request(...obj)
|
|
244
263
|
})
|
|
245
264
|
logger.info(`Request Success: ${decode(req.originalUrl)}`)
|
|
246
265
|
|
|
266
|
+
// 夹带私货部分:如果开启了通用解锁,并且是获取歌曲URL的接口,则尝试解锁(如果需要的话)ヾ(≧▽≦*)o
|
|
247
267
|
if (
|
|
248
|
-
|
|
268
|
+
req.baseUrl === '/song/url/v1' &&
|
|
249
269
|
process.env.ENABLE_GENERAL_UNBLOCK === 'true'
|
|
250
270
|
) {
|
|
251
271
|
const song = moduleResponse.body.data[0]
|
|
@@ -260,7 +280,7 @@ async function consturctServer(moduleDefs) {
|
|
|
260
280
|
logger.info('Starting unblock(uses general unblock):', req.query.id)
|
|
261
281
|
const result = await matchID(req.query.id)
|
|
262
282
|
song.url = result.data.url
|
|
263
|
-
song.freeTrialInfo =
|
|
283
|
+
song.freeTrialInfo = null
|
|
264
284
|
logger.info('Unblock success! url:', song.url)
|
|
265
285
|
}
|
|
266
286
|
if (song.url && song.url.includes('kuwo')) {
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const crypto = require('crypto')
|
|
3
|
+
const logger = require('./logger')
|
|
4
|
+
|
|
5
|
+
function isTempFile(file) {
|
|
6
|
+
return !!(file && file.tempFilePath)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async function getFileSize(file) {
|
|
10
|
+
if (isTempFile(file)) {
|
|
11
|
+
const stats = await fs.promises.stat(file.tempFilePath)
|
|
12
|
+
return stats.size
|
|
13
|
+
}
|
|
14
|
+
return file.data ? file.data.byteLength : file.size || 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function getFileMd5(file) {
|
|
18
|
+
if (file.md5) {
|
|
19
|
+
return file.md5
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (isTempFile(file)) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const hash = crypto.createHash('md5')
|
|
25
|
+
const stream = fs.createReadStream(file.tempFilePath)
|
|
26
|
+
stream.on('data', (chunk) => hash.update(chunk))
|
|
27
|
+
stream.on('end', () => resolve(hash.digest('hex')))
|
|
28
|
+
stream.on('error', reject)
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (file.data) {
|
|
33
|
+
return crypto.createHash('md5').update(file.data).digest('hex')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
throw new Error('无法计算文件MD5: 缺少文件数据')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getUploadData(file) {
|
|
40
|
+
if (isTempFile(file)) {
|
|
41
|
+
return fs.createReadStream(file.tempFilePath)
|
|
42
|
+
}
|
|
43
|
+
return file.data
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function cleanupTempFile(filePath) {
|
|
47
|
+
if (!filePath) return
|
|
48
|
+
try {
|
|
49
|
+
await fs.promises.unlink(filePath)
|
|
50
|
+
} catch (e) {
|
|
51
|
+
logger.info('临时文件清理失败:', e.message)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function readFileChunk(filePath, offset, length) {
|
|
56
|
+
const fd = await fs.promises.open(filePath, 'r')
|
|
57
|
+
const buffer = Buffer.alloc(length)
|
|
58
|
+
await fd.read(buffer, 0, length, offset)
|
|
59
|
+
await fd.close()
|
|
60
|
+
return buffer
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getFileExtension(filename) {
|
|
64
|
+
if (!filename) return 'mp3'
|
|
65
|
+
if (filename.includes('.')) {
|
|
66
|
+
return filename.split('.').pop().toLowerCase()
|
|
67
|
+
}
|
|
68
|
+
return 'mp3'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function sanitizeFilename(filename) {
|
|
72
|
+
if (!filename) return 'unknown'
|
|
73
|
+
return filename
|
|
74
|
+
.replace(/\.[^.]+$/, '')
|
|
75
|
+
.replace(/\s/g, '')
|
|
76
|
+
.replace(/\./g, '_')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = {
|
|
80
|
+
isTempFile,
|
|
81
|
+
getFileSize,
|
|
82
|
+
getFileMd5,
|
|
83
|
+
getUploadData,
|
|
84
|
+
cleanupTempFile,
|
|
85
|
+
readFileChunk,
|
|
86
|
+
getFileExtension,
|
|
87
|
+
sanitizeFilename,
|
|
88
|
+
}
|
package/util/index.js
CHANGED
|
@@ -1,36 +1,8 @@
|
|
|
1
1
|
const logger = require('./logger')
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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, '铜仁'],
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
// 将原始字符串段转换为数值段并计算总数(在模块初始化时完成一次)
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
|
|
5
|
+
// IP地址转换函数
|
|
34
6
|
function ipToInt(ip) {
|
|
35
7
|
const parts = ip.split('.').map(Number)
|
|
36
8
|
const a = (parts[0] << 24) >>> 0
|
|
@@ -49,20 +21,56 @@ function intToIp(int) {
|
|
|
49
21
|
].join('.')
|
|
50
22
|
}
|
|
51
23
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
24
|
+
// 解析CIDR格式的IP段
|
|
25
|
+
function parseCIDR(cidr) {
|
|
26
|
+
const [ipStr, prefixLengthStr] = cidr.split('/')
|
|
27
|
+
const prefixLength = parseInt(prefixLengthStr, 10)
|
|
28
|
+
|
|
29
|
+
const ipInt = ipToInt(ipStr)
|
|
30
|
+
const mask = (0xffffffff << (32 - prefixLength)) >>> 0
|
|
31
|
+
const start = (ipInt & mask) >>> 0
|
|
32
|
+
const end = (start | (~mask >>> 0)) >>> 0
|
|
33
|
+
const count = end - start + 1
|
|
34
|
+
|
|
35
|
+
return { start, end, count, cidr }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 从china_ip_ranges.txt加载中国IP段(CIDR格式)
|
|
39
|
+
const chinaIPRanges = (function loadChinaIPRanges() {
|
|
40
|
+
try {
|
|
41
|
+
const filePath = path.join(__dirname, '../data/china_ip_ranges.txt')
|
|
42
|
+
const content = fs.readFileSync(filePath, 'utf-8')
|
|
43
|
+
const lines = content
|
|
44
|
+
.split('\n')
|
|
45
|
+
.filter((line) => line.trim() && !line.startsWith('#'))
|
|
46
|
+
|
|
47
|
+
const arr = []
|
|
48
|
+
let total = 0
|
|
49
|
+
|
|
50
|
+
for (let i = 0; i < lines.length; i++) {
|
|
51
|
+
const line = lines[i].trim()
|
|
52
|
+
if (!line) continue
|
|
53
|
+
|
|
54
|
+
const range = parseCIDR(line)
|
|
55
|
+
arr.push(range)
|
|
56
|
+
total += range.count
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 按IP段大小排序,提高随机选择效率
|
|
60
|
+
arr.sort((a, b) => b.count - a.count)
|
|
61
|
+
|
|
62
|
+
// attach total for convenience
|
|
63
|
+
arr.totalCount = total
|
|
64
|
+
|
|
65
|
+
logger.info(
|
|
66
|
+
`Loaded ${arr.length} Chinese IP ranges from china_ip_ranges.txt, total ${total} IPs`,
|
|
67
|
+
)
|
|
68
|
+
return arr
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logger.error('Failed to load china_ip_ranges.txt:', error.message)
|
|
71
|
+
// 返回空数组,generateRandomChineseIP会使用兜底逻辑
|
|
72
|
+
return { totalCount: 0 }
|
|
62
73
|
}
|
|
63
|
-
// attach total for convenience
|
|
64
|
-
arr.totalCount = total
|
|
65
|
-
return arr
|
|
66
74
|
})()
|
|
67
75
|
const floor = Math.floor
|
|
68
76
|
const random = Math.random
|
|
@@ -144,16 +152,11 @@ module.exports = {
|
|
|
144
152
|
// 如果没有选中(理论上不应该发生),回退到最后一个段
|
|
145
153
|
if (!chosen) chosen = chinaIPRanges[chinaIPRanges.length - 1]
|
|
146
154
|
|
|
147
|
-
// 在段内随机生成一个 IP
|
|
155
|
+
// 在段内随机生成一个 IP(使用段真实的数值范围)
|
|
148
156
|
const segSize = chosen.end - chosen.start + 1
|
|
149
157
|
const ipInt = chosen.start + Math.floor(random() * segSize)
|
|
150
158
|
const ip = intToIp(ipInt)
|
|
151
|
-
logger.info(
|
|
152
|
-
'Generated Random Chinese IP:',
|
|
153
|
-
ip,
|
|
154
|
-
'location:',
|
|
155
|
-
chosen.location,
|
|
156
|
-
)
|
|
159
|
+
logger.info('Generated Random Chinese IP:', ip, 'from CIDR:', chosen.cidr)
|
|
157
160
|
return ip
|
|
158
161
|
},
|
|
159
162
|
// 生成chainId的函数
|
package/util/request.js
CHANGED
|
@@ -194,11 +194,11 @@ const createRequest = (uri, data, options) => {
|
|
|
194
194
|
// 根据加密方式处理
|
|
195
195
|
switch (crypto) {
|
|
196
196
|
case 'weapi':
|
|
197
|
-
headers['Referer'] = DOMAIN
|
|
197
|
+
headers['Referer'] = options.domain || DOMAIN
|
|
198
198
|
headers['User-Agent'] = options.ua || chooseUserAgent('weapi')
|
|
199
199
|
data.csrf_token = csrfToken
|
|
200
200
|
encryptData = encrypt.weapi(data)
|
|
201
|
-
url = DOMAIN + '/weapi/' + uri.substr(5)
|
|
201
|
+
url = (options.domain || DOMAIN) + '/weapi/' + uri.substr(5)
|
|
202
202
|
break
|
|
203
203
|
|
|
204
204
|
case 'linuxapi':
|
|
@@ -206,10 +206,10 @@ const createRequest = (uri, data, options) => {
|
|
|
206
206
|
options.ua || chooseUserAgent('linuxapi', 'linux')
|
|
207
207
|
encryptData = encrypt.linuxapi({
|
|
208
208
|
method: 'POST',
|
|
209
|
-
url: DOMAIN + uri,
|
|
209
|
+
url: (options.domain || DOMAIN) + uri,
|
|
210
210
|
params: data,
|
|
211
211
|
})
|
|
212
|
-
url = DOMAIN + '/api/linux/forward'
|
|
212
|
+
url = (options.domain || DOMAIN) + '/api/linux/forward'
|
|
213
213
|
break
|
|
214
214
|
|
|
215
215
|
case 'eapi':
|
|
@@ -249,9 +249,9 @@ const createRequest = (uri, data, options) => {
|
|
|
249
249
|
: ENCRYPT_RESPONSE,
|
|
250
250
|
)
|
|
251
251
|
encryptData = encrypt.eapi(uri, data)
|
|
252
|
-
url = API_DOMAIN + '/eapi/' + uri.substr(5)
|
|
252
|
+
url = (options.domain || API_DOMAIN) + '/eapi/' + uri.substr(5)
|
|
253
253
|
} else if (crypto === 'api') {
|
|
254
|
-
url = API_DOMAIN + uri
|
|
254
|
+
url = (options.domain || API_DOMAIN) + uri
|
|
255
255
|
encryptData = data
|
|
256
256
|
}
|
|
257
257
|
break
|
|
@@ -1,26 +0,0 @@
|
|
|
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,铜仁
|
|
Binary file
|
|
File without changes
|