@neteasecloudmusicapienhanced/api 4.30.1 → 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/voice_upload.js +36 -22
- package/package.json +19 -25
- package/plugins/songUpload.js +67 -19
- package/plugins/upload.js +5 -7
- package/public/cloud.html +406 -39
- package/public/docs/home.md +134 -4
- 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/data/ChineseIPGenerate.csv +0 -26
- package/public/docs/ncmapireborn.png +0 -0
- /package/public/static/{screenshot1.png → module_test.png} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neteasecloudmusicapienhanced/api",
|
|
3
|
-
"version": "4.30.
|
|
3
|
+
"version": "4.30.2",
|
|
4
4
|
"description": "全网最全的网易云音乐API接口 || A revival project for NeteaseCloudMusicApi Node.js Services (Half Refactor & Enhanced) || 网易云音乐 API 备份 + 增强 || 本项目自原版v4.28.0版本后开始自行维护",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "nodemon app.js",
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
"node_modules/axios",
|
|
21
21
|
"node_modules/express",
|
|
22
22
|
"node_modules/express-fileupload",
|
|
23
|
-
"node_modules/md5",
|
|
24
23
|
"node_modules/music-metadata",
|
|
25
24
|
"node_modules/pac-proxy-agent",
|
|
26
25
|
"node_modules/qrcode",
|
|
@@ -66,18 +65,13 @@
|
|
|
66
65
|
"data"
|
|
67
66
|
],
|
|
68
67
|
"dependencies": {
|
|
69
|
-
"@neteasecloudmusicapienhanced/unblockmusic-utils": "^0.2.
|
|
70
|
-
"axios": "^1.13.5",
|
|
71
|
-
"@neteasecloudmusicapienhanced/unblockmusic-utils": "^0.2.2",
|
|
68
|
+
"@neteasecloudmusicapienhanced/unblockmusic-utils": "^0.2.3",
|
|
72
69
|
"axios": "^1.13.5",
|
|
73
70
|
"crypto-js": "^4.2.0",
|
|
74
|
-
"dotenv": "^17.
|
|
75
|
-
"dotenv": "^17.2.4",
|
|
71
|
+
"dotenv": "^17.3.1",
|
|
76
72
|
"express": "^5.2.1",
|
|
77
73
|
"express-fileupload": "^1.5.2",
|
|
78
|
-
"
|
|
79
|
-
"music-metadata": "^11.12.0",
|
|
80
|
-
"music-metadata": "^11.12.0",
|
|
74
|
+
"music-metadata": "^11.12.1",
|
|
81
75
|
"node-forge": "^1.3.3",
|
|
82
76
|
"pac-proxy-agent": "^7.2.0",
|
|
83
77
|
"qrcode": "^1.5.4",
|
|
@@ -88,26 +82,26 @@
|
|
|
88
82
|
},
|
|
89
83
|
"devDependencies": {
|
|
90
84
|
"@eslint/eslintrc": "^3.3.3",
|
|
91
|
-
"@eslint/js": "^9.39.
|
|
85
|
+
"@eslint/js": "^9.39.3",
|
|
92
86
|
"@types/express": "^5.0.6",
|
|
93
87
|
"@types/express-fileupload": "^1.5.1",
|
|
94
88
|
"@types/mocha": "^10.0.10",
|
|
95
89
|
"@types/node": "25.0.9",
|
|
96
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
97
|
-
"@typescript-eslint/parser": "8.
|
|
98
|
-
"eslint": "9.39.
|
|
99
|
-
"eslint-config-prettier": "10.1.8",
|
|
100
|
-
"eslint-plugin-html": "8.1.
|
|
101
|
-
"eslint-plugin-prettier": "5.5.5",
|
|
90
|
+
"@typescript-eslint/eslint-plugin": "^8.56.0",
|
|
91
|
+
"@typescript-eslint/parser": "^8.56.0",
|
|
92
|
+
"eslint": "^9.39.3",
|
|
93
|
+
"eslint-config-prettier": "^10.1.8",
|
|
94
|
+
"eslint-plugin-html": "^8.1.4",
|
|
95
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
102
96
|
"globals": "^16.5.0",
|
|
103
|
-
"husky": "9.1.7",
|
|
104
|
-
"intelli-espower-loader": "1.1.0",
|
|
105
|
-
"lint-staged": "16.2.7",
|
|
106
|
-
"mocha": "11.7.5",
|
|
107
|
-
"nodemon": "^3.1.
|
|
97
|
+
"husky": "^9.1.7",
|
|
98
|
+
"intelli-espower-loader": "^1.1.0",
|
|
99
|
+
"lint-staged": "^16.2.7",
|
|
100
|
+
"mocha": "^11.7.5",
|
|
101
|
+
"nodemon": "^3.1.14",
|
|
108
102
|
"pkg": "^5.8.1",
|
|
109
|
-
"power-assert": "1.6.1",
|
|
110
|
-
"prettier": "3.
|
|
111
|
-
"typescript": "5.9.3"
|
|
103
|
+
"power-assert": "^1.6.1",
|
|
104
|
+
"prettier": "^3.8.1",
|
|
105
|
+
"typescript": "^5.9.3"
|
|
112
106
|
}
|
|
113
107
|
}
|
package/plugins/songUpload.js
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
const { default: axios } = require('axios')
|
|
2
2
|
const createOption = require('../util/option.js')
|
|
3
3
|
const logger = require('../util/logger.js')
|
|
4
|
+
const {
|
|
5
|
+
getUploadData,
|
|
6
|
+
getFileExtension,
|
|
7
|
+
sanitizeFilename,
|
|
8
|
+
} = require('../util/fileHelper')
|
|
9
|
+
|
|
4
10
|
module.exports = async (query, request) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// ext = 'flac'
|
|
8
|
-
// }
|
|
9
|
-
if (query.songFile.name.includes('.')) {
|
|
10
|
-
ext = query.songFile.name.split('.').pop()
|
|
11
|
-
}
|
|
12
|
-
const filename = query.songFile.name
|
|
13
|
-
.replace('.' + ext, '')
|
|
14
|
-
.replace(/\s/g, '')
|
|
15
|
-
.replace(/\./g, '_')
|
|
11
|
+
const ext = getFileExtension(query.songFile.name)
|
|
12
|
+
const filename = sanitizeFilename(query.songFile.name)
|
|
16
13
|
const bucket = 'jd-musicrep-privatecloud-audio-public'
|
|
17
|
-
|
|
14
|
+
|
|
18
15
|
const tokenRes = await request(
|
|
19
16
|
`/api/nos/token/alloc`,
|
|
20
17
|
{
|
|
@@ -29,31 +26,82 @@ module.exports = async (query, request) => {
|
|
|
29
26
|
createOption(query, 'weapi'),
|
|
30
27
|
)
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
if (!tokenRes.body.result || !tokenRes.body.result.objectKey) {
|
|
30
|
+
logger.error('Token分配失败:', tokenRes.body)
|
|
31
|
+
throw {
|
|
32
|
+
status: 500,
|
|
33
|
+
body: {
|
|
34
|
+
code: 500,
|
|
35
|
+
msg: '获取上传token失败',
|
|
36
|
+
detail: tokenRes.body,
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const objectKey = tokenRes.body.result.objectKey.replace(/\//g, '%2F')
|
|
42
|
+
let lbs
|
|
34
43
|
try {
|
|
35
|
-
|
|
44
|
+
lbs = (
|
|
36
45
|
await axios({
|
|
37
46
|
method: 'get',
|
|
38
47
|
url: `https://wanproxy.127.net/lbs?version=1.0&bucketname=${bucket}`,
|
|
48
|
+
timeout: 10000,
|
|
39
49
|
})
|
|
40
50
|
).data
|
|
51
|
+
} catch (error) {
|
|
52
|
+
logger.error('LBS获取失败:', error.message)
|
|
53
|
+
throw {
|
|
54
|
+
status: 500,
|
|
55
|
+
body: {
|
|
56
|
+
code: 500,
|
|
57
|
+
msg: '获取上传服务器地址失败',
|
|
58
|
+
detail: error.message,
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!lbs || !lbs.upload || !lbs.upload[0]) {
|
|
64
|
+
logger.error('无效的LBS响应:', lbs)
|
|
65
|
+
throw {
|
|
66
|
+
status: 500,
|
|
67
|
+
body: {
|
|
68
|
+
code: 500,
|
|
69
|
+
msg: '获取上传服务器地址无效',
|
|
70
|
+
detail: lbs,
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
41
76
|
await axios({
|
|
42
77
|
method: 'post',
|
|
43
78
|
url: `${lbs.upload[0]}/${bucket}/${objectKey}?offset=0&complete=true&version=1.0`,
|
|
44
79
|
headers: {
|
|
45
80
|
'x-nos-token': tokenRes.body.result.token,
|
|
46
81
|
'Content-MD5': query.songFile.md5,
|
|
47
|
-
'Content-Type': 'audio/mpeg',
|
|
82
|
+
'Content-Type': query.songFile.mimetype || 'audio/mpeg',
|
|
48
83
|
'Content-Length': String(query.songFile.size),
|
|
49
84
|
},
|
|
50
|
-
data: query.songFile
|
|
85
|
+
data: getUploadData(query.songFile),
|
|
51
86
|
maxContentLength: Infinity,
|
|
52
87
|
maxBodyLength: Infinity,
|
|
88
|
+
timeout: 300000,
|
|
53
89
|
})
|
|
90
|
+
logger.info('上传成功:', filename)
|
|
54
91
|
} catch (error) {
|
|
55
|
-
logger.
|
|
56
|
-
|
|
92
|
+
logger.error('上传失败:', {
|
|
93
|
+
status: error.response?.status,
|
|
94
|
+
data: error.response?.data,
|
|
95
|
+
message: error.message,
|
|
96
|
+
})
|
|
97
|
+
throw {
|
|
98
|
+
status: error.response?.status || 500,
|
|
99
|
+
body: {
|
|
100
|
+
code: error.response?.status || 500,
|
|
101
|
+
msg: '文件上传失败',
|
|
102
|
+
detail: error.response?.data || error.message,
|
|
103
|
+
},
|
|
104
|
+
}
|
|
57
105
|
}
|
|
58
106
|
return {
|
|
59
107
|
...tokenRes,
|
package/plugins/upload.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const { default: axios } = require('axios')
|
|
2
2
|
const createOption = require('../util/option.js')
|
|
3
|
+
const { getUploadData } = require('../util/fileHelper')
|
|
4
|
+
|
|
3
5
|
module.exports = async (query, request) => {
|
|
4
6
|
const data = {
|
|
5
7
|
bucket: 'yyimgs',
|
|
@@ -10,27 +12,23 @@ module.exports = async (query, request) => {
|
|
|
10
12
|
return_body: `{"code":200,"size":"$(ObjectSize)"}`,
|
|
11
13
|
type: 'other',
|
|
12
14
|
}
|
|
13
|
-
// 获取key和token
|
|
14
15
|
const res = await request(
|
|
15
16
|
`/api/nos/token/alloc`,
|
|
16
17
|
data,
|
|
17
18
|
createOption(query, 'weapi'),
|
|
18
19
|
)
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
const res2 = await axios({
|
|
21
22
|
method: 'post',
|
|
22
23
|
url: `https://nosup-hz1.127.net/yyimgs/${res.body.result.objectKey}?offset=0&complete=true&version=1.0`,
|
|
23
24
|
headers: {
|
|
24
25
|
'x-nos-token': res.body.result.token,
|
|
25
|
-
'Content-Type': 'image/jpeg',
|
|
26
|
+
'Content-Type': query.imgFile.mimetype || 'image/jpeg',
|
|
26
27
|
},
|
|
27
|
-
data: query.imgFile
|
|
28
|
+
data: getUploadData(query.imgFile),
|
|
28
29
|
})
|
|
29
30
|
|
|
30
31
|
return {
|
|
31
|
-
// ...res.body.result,
|
|
32
|
-
// ...res2.data,
|
|
33
|
-
// ...res3.body,
|
|
34
32
|
url_pre: 'https://p1.music.126.net/' + res.body.result.objectKey,
|
|
35
33
|
imgId: res.body.result.docId,
|
|
36
34
|
}
|