Compare commits

..

No commits in common. "98962423339bdf6d3b6739162a19e3522881b4b3" and "c92613b19e6e20bd153c3cdd053196480eaeb87a" have entirely different histories.

13 changed files with 195 additions and 293 deletions

View File

@ -30,7 +30,7 @@
## 项目简介 ## 项目简介
网易云音乐第三方 Node.js API, 支持丰富的音乐相关接口,适合自建服务、二次开发和多平台部署 网易云音乐第三方 Node.js API, 支持丰富的音乐相关接口,适合自建服务、二次开发和多平台部署(如果原版诈尸, 我会及时同步 or 归档)。
> [!IMPORTANT] > [!IMPORTANT]
> >
@ -215,7 +215,7 @@ pnpm test
原作者 [Binaryify/NeteaseCloudMusicApi](https://github.com/binaryify/NeteaseCloudMusicApi) 项目为本项目基础 (该项目在`npmjs`网站上仍持续维护, 但 github 仓库已不再更新) 原作者 [Binaryify/NeteaseCloudMusicApi](https://github.com/binaryify/NeteaseCloudMusicApi) 项目为本项目基础 (该项目在`npmjs`网站上仍持续维护, 但 github 仓库已不再更新)
感谢大佬们为逆向eapi, weapi, xeapi等加密算法所做的贡献 感谢大佬们为逆向eapi, weapi等加密算法所做的贡献
项目参考: 项目参考:
@ -244,8 +244,6 @@ pnpm test
- [Yueby/music-together](https://github.com/Yueby/music-together) - [Yueby/music-together](https://github.com/Yueby/music-together)
- [chthollyphlie/folia-major](https://github.com/chthollyphile/folia-major)
## License ## License
[MIT License](https://github.com/MoeFurina/NeteaseCloudMusicApiEnhanced/blob/main/LICENSE) [MIT License](https://github.com/MoeFurina/NeteaseCloudMusicApiEnhanced/blob/main/LICENSE)

36
interface.d.ts vendored
View File

@ -2053,7 +2053,9 @@ export function listen_data_today_song(
params: RequestBaseConfig, params: RequestBaseConfig,
): Promise<Response> ): Promise<Response>
export function listen_data_total(params: RequestBaseConfig): Promise<Response> export function listen_data_total(
params: RequestBaseConfig,
): Promise<Response>
export function listen_data_year_report( export function listen_data_year_report(
params: RequestBaseConfig, params: RequestBaseConfig,
@ -2190,7 +2192,9 @@ export function radio_sport_get(
} & RequestBaseConfig, } & RequestBaseConfig,
): Promise<Response> ): Promise<Response>
export function recent_listen_list(params: RequestBaseConfig): Promise<Response> export function recent_listen_list(
params: RequestBaseConfig,
): Promise<Response>
export function recommend_songs_dislike( export function recommend_songs_dislike(
params: { params: {
@ -2198,7 +2202,9 @@ export function recommend_songs_dislike(
} & RequestBaseConfig, } & RequestBaseConfig,
): Promise<Response> ): Promise<Response>
export function register_anonimous(params: RequestBaseConfig): Promise<Response> export function register_anonimous(
params: RequestBaseConfig,
): Promise<Response>
export function sati_resource_list( export function sati_resource_list(
params: { params: {
@ -2223,7 +2229,9 @@ export function sati_resource_sub_list(
params: RequestBaseConfig, params: RequestBaseConfig,
): Promise<Response> ): Promise<Response>
export function sati_tag_list(params: RequestBaseConfig): Promise<Response> export function sati_tag_list(
params: RequestBaseConfig,
): Promise<Response>
export function sati_timescene_resources_get( export function sati_timescene_resources_get(
params: RequestBaseConfig, params: RequestBaseConfig,
@ -2355,7 +2363,9 @@ export function song_url_match(
} & RequestBaseConfig, } & RequestBaseConfig,
): Promise<Response> ): Promise<Response>
export function song_url_ncmget(params: RequestBaseConfig): Promise<Response> export function song_url_ncmget(
params: RequestBaseConfig,
): Promise<Response>
export function song_url_v1_302( export function song_url_v1_302(
params: { params: {
@ -2378,7 +2388,9 @@ export function threshold_detail_get(
params: RequestBaseConfig, params: RequestBaseConfig,
): Promise<Response> ): Promise<Response>
export function toplist_detail_v2(params: RequestBaseConfig): Promise<Response> export function toplist_detail_v2(
params: RequestBaseConfig,
): Promise<Response>
export function ugc_album_get( export function ugc_album_get(
params: { params: {
@ -2421,7 +2433,9 @@ export function ugc_song_get(
} & RequestBaseConfig, } & RequestBaseConfig,
): Promise<Response> ): Promise<Response>
export function ugc_user_devote(params: RequestBaseConfig): Promise<Response> export function ugc_user_devote(
params: RequestBaseConfig,
): Promise<Response>
export function user_detail_new( export function user_detail_new(
params: { params: {
@ -2502,9 +2516,13 @@ export function verify_qrcodestatus(
} & RequestBaseConfig, } & RequestBaseConfig,
): Promise<Response> ): Promise<Response>
export function vip_sign(params: RequestBaseConfig): Promise<Response> export function vip_sign(
params: RequestBaseConfig,
): Promise<Response>
export function vip_sign_info(params: RequestBaseConfig): Promise<Response> export function vip_sign_info(
params: RequestBaseConfig,
): Promise<Response>
export function vip_tasks_v1( export function vip_tasks_v1(
params: { params: {

View File

@ -1,5 +1,4 @@
// 私信和通知接口 // 私信和通知接口
const createOption = require('../util/option.js') const createOption = require('../util/option.js')
module.exports = (query, request) => { module.exports = (query, request) => {
const data = {} const data = {}

View File

@ -1,74 +0,0 @@
const { default: axios } = require('axios')
const encrypt = require('../util/crypto')
const { APP_CONF } = require('../util/config.json')
const generateNonce = () => {
let nonce = ''
for (let i = 0; i < 16; i++) {
nonce += Math.floor(Math.random() * 10).toString()
}
return nonce
}
module.exports = async (query, request) => {
const nonce = generateNonce()
const timestamp = String(Date.now())
const deviceId = query.deviceId || global.deviceId || ''
const currentKeyVersion = query.currentKeyVersion || ''
const data = {
appVersion: '9.1.65',
currentKeyVersion,
deviceId,
nonce,
os: 'android',
requestType: 'active',
signature: encrypt.xeapiSign(timestamp, nonce),
t1: '',
t2: '',
timestamp,
uid: '',
}
const res = await axios({
method: 'POST',
url: APP_CONF.apiDomain + '/api/gorilla/anti/crawler/security/key/get',
headers: {
'User-Agent':
'NeteaseMusic/9.1.65.240927161425(9001065);Dalvik/2.1.0 (Linux; U; Android 14; 23013RK75C Build/UKQ1.230804.001)',
Cookie: deviceId ? `deviceId=${encodeURIComponent(deviceId)}` : '',
},
data: new URLSearchParams(data).toString(),
proxy: false,
})
if (
!res.data ||
res.data.code !== 200 ||
!res.data.data ||
!res.data.data.encryptedData
) {
throw new Error('xeapi public key request failed')
}
if (
!res.data.data.signature ||
encrypt.xeapiSign(res.data.data.timestamp, nonce) !==
res.data.data.signature
) {
throw new Error('xeapi public key response signature mismatch')
}
const publicKey = encrypt.xeapiDecryptPublicKey(res.data.data.encryptedData)
if (!publicKey.sk) {
throw new Error('xeapi public key response missing sk')
}
return {
status: 200,
body: {
...publicKey,
deviceId,
},
cookie: [],
}
}

View File

@ -1,49 +0,0 @@
// 提交歌曲播放状态
const createOption = require('../util/option.js')
const generateSessionId = () =>
Array.from(
{ length: 12 },
() =>
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'[Math.floor(Math.random() * 36)],
).join('')
module.exports = (query, request) => {
const {
id,
sessionId,
progress = 0,
playMode = 'list_loop',
type = 'song',
} = query
if (!id) {
return Promise.reject({
status: 400,
body: {
code: 400,
msg: '缺少必要参数id',
},
})
}
const playStateSubmitReq = JSON.stringify({
resource: {
id: String(id),
type: type,
},
progress: Number(progress) || 0,
sessionId: sessionId || generateSessionId(),
playMode: playMode,
})
const data = {
playStateSubmitReq: playStateSubmitReq,
}
return request(
'/api/relay/play/state/submit',
data,
createOption(query, 'weapi'),
)
}

View File

@ -1,9 +0,0 @@
// 从云盘获取歌曲下载链接
const createOption = require('../util/option.js')
module.exports = (query, request) => {
const data = {
songId: query.id,
}
return request(`/api/cloud/dowonload`, data, createOption(query, 'eapi'))
}

View File

@ -1,6 +1,6 @@
{ {
"name": "@neteasecloudmusicapienhanced/api", "name": "@neteasecloudmusicapienhanced/api",
"version": "4.35.0", "version": "4.34.3",
"description": "全网最全的网易云音乐API接口 || A revival project for NeteaseCloudMusicApi Node.js Services (Half Refactor & Enhanced) || 网易云音乐 API 备份 + 增强 || 本项目自原版v4.28.0版本后开始自行维护", "description": "全网最全的网易云音乐API接口 || A revival project for NeteaseCloudMusicApi Node.js Services (Half Refactor & Enhanced) || 网易云音乐 API 备份 + 增强 || 本项目自原版v4.28.0版本后开始自行维护",
"scripts": { "scripts": {
"dev": "nodemon app.js", "dev": "nodemon app.js",
@ -74,7 +74,7 @@
], ],
"dependencies": { "dependencies": {
"@neteasecloudmusicapienhanced/unblockmusic-utils": "^0.3.2", "@neteasecloudmusicapienhanced/unblockmusic-utils": "^0.3.2",
"axios": "^1.17.0", "axios": "^1.16.1",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"dotenv": "^17.4.2", "dotenv": "^17.4.2",
"express": "^5.2.1", "express": "^5.2.1",
@ -96,8 +96,8 @@
"@types/express-fileupload": "^1.5.1", "@types/express-fileupload": "^1.5.1",
"@types/mocha": "^10.0.10", "@types/mocha": "^10.0.10",
"@types/node": "25.5.0", "@types/node": "25.5.0",
"@typescript-eslint/eslint-plugin": "^8.60.1", "@typescript-eslint/eslint-plugin": "^8.60.0",
"@typescript-eslint/parser": "^8.60.1", "@typescript-eslint/parser": "^8.60.0",
"eslint": "^9.39.4", "eslint": "^9.39.4",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-html": "^8.1.4", "eslint-plugin-html": "^8.1.4",

203
pnpm-lock.yaml generated
View File

@ -12,8 +12,8 @@ importers:
specifier: ^0.3.2 specifier: ^0.3.2
version: 0.3.2 version: 0.3.2
axios: axios:
specifier: ^1.17.0 specifier: ^1.16.1
version: 1.17.0 version: 1.16.1
crypto-js: crypto-js:
specifier: ^4.2.0 specifier: ^4.2.0
version: 4.2.0 version: 4.2.0
@ -73,11 +73,11 @@ importers:
specifier: 25.5.0 specifier: 25.5.0
version: 25.5.0 version: 25.5.0
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^8.60.1 specifier: ^8.60.0
version: 8.60.1(@typescript-eslint/parser@8.60.1(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3) version: 8.60.0(@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^8.60.1 specifier: ^8.60.0
version: 8.60.1(eslint@9.39.4)(typescript@5.9.3) version: 8.60.0(eslint@9.39.4)(typescript@5.9.3)
eslint: eslint:
specifier: ^9.39.4 specifier: ^9.39.4
version: 9.39.4 version: 9.39.4
@ -301,63 +301,63 @@ packages:
'@types/serve-static@2.2.0': '@types/serve-static@2.2.0':
resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==}
'@typescript-eslint/eslint-plugin@8.60.1': '@typescript-eslint/eslint-plugin@8.60.0':
resolution: {integrity: sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==} resolution: {integrity: sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^8.60.1 '@typescript-eslint/parser': ^8.60.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/parser@8.60.1': '@typescript-eslint/parser@8.60.0':
resolution: {integrity: sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==} resolution: {integrity: sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/project-service@8.60.1': '@typescript-eslint/project-service@8.60.0':
resolution: {integrity: sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==} resolution: {integrity: sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/scope-manager@8.60.1': '@typescript-eslint/scope-manager@8.60.0':
resolution: {integrity: sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==} resolution: {integrity: sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.60.1': '@typescript-eslint/tsconfig-utils@8.60.0':
resolution: {integrity: sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==} resolution: {integrity: sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/type-utils@8.60.1': '@typescript-eslint/type-utils@8.60.0':
resolution: {integrity: sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==} resolution: {integrity: sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/types@8.60.1': '@typescript-eslint/types@8.60.0':
resolution: {integrity: sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==} resolution: {integrity: sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.60.1': '@typescript-eslint/typescript-estree@8.60.0':
resolution: {integrity: sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==} resolution: {integrity: sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/utils@8.60.1': '@typescript-eslint/utils@8.60.0':
resolution: {integrity: sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==} resolution: {integrity: sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0' typescript: '>=4.8.4 <6.1.0'
'@typescript-eslint/visitor-keys@8.60.1': '@typescript-eslint/visitor-keys@8.60.0':
resolution: {integrity: sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==} resolution: {integrity: sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@unblockneteasemusic/server@0.28.0': '@unblockneteasemusic/server@0.28.0':
@ -485,8 +485,8 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
axios@1.17.0: axios@1.16.1:
resolution: {integrity: sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==} resolution: {integrity: sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==}
balanced-match@1.0.2: balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@ -1557,8 +1557,8 @@ packages:
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
engines: {node: '>=10'} engines: {node: '>=10'}
js-yaml@4.2.0: js-yaml@4.1.1:
resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true hasBin: true
jsesc@2.5.2: jsesc@2.5.2:
@ -2149,8 +2149,8 @@ packages:
secure-json-parse@2.7.0: secure-json-parse@2.7.0:
resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==}
semver@7.8.2: semver@7.8.1:
resolution: {integrity: sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==} resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==}
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true hasBin: true
@ -2316,12 +2316,12 @@ packages:
resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==}
engines: {node: '>=20'} engines: {node: '>=20'}
string.prototype.trim@1.2.11: string.prototype.trim@1.2.10:
resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
string.prototype.trimend@1.0.10: string.prototype.trimend@1.0.9:
resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
string.prototype.trimstart@1.0.8: string.prototype.trimstart@1.0.8:
@ -2384,12 +2384,12 @@ packages:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
tinyexec@1.2.4: tinyexec@1.2.3:
resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} resolution: {integrity: sha512-g62dB+w1/OEFnPvmX0yd/HnetYITOL+1nJW7kitOycOeAvmbWC/nu0fwmmQ/kupNojqExzyC/T++pST/jRJ2mQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
tinyglobby@0.2.17: tinyglobby@0.2.16:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
to-fast-properties@2.0.0: to-fast-properties@2.0.0:
@ -2542,8 +2542,8 @@ packages:
which-module@2.0.1: which-module@2.0.1:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
which-typed-array@1.1.22: which-typed-array@1.1.21:
resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} resolution: {integrity: sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
which@2.0.2: which@2.0.2:
@ -2702,7 +2702,7 @@ snapshots:
globals: 14.0.0 globals: 14.0.0
ignore: 5.3.2 ignore: 5.3.2
import-fresh: 3.3.1 import-fresh: 3.3.1
js-yaml: 4.2.0 js-yaml: 4.1.1
minimatch: 3.1.5 minimatch: 3.1.5
strip-json-comments: 3.1.1 strip-json-comments: 3.1.1
transitivePeerDependencies: transitivePeerDependencies:
@ -2759,7 +2759,7 @@ snapshots:
'@neteasecloudmusicapienhanced/unblockmusic-utils@0.3.2': '@neteasecloudmusicapienhanced/unblockmusic-utils@0.3.2':
dependencies: dependencies:
'@unblockneteasemusic/server': 0.28.0 '@unblockneteasemusic/server': 0.28.0
axios: 1.17.0 axios: 1.16.1
dotenv: 17.4.2 dotenv: 17.4.2
express: 4.22.2 express: 4.22.2
https: 1.0.0 https: 1.0.0
@ -2851,14 +2851,14 @@ snapshots:
'@types/http-errors': 2.0.5 '@types/http-errors': 2.0.5
'@types/node': 25.5.0 '@types/node': 25.5.0
'@typescript-eslint/eslint-plugin@8.60.1(@typescript-eslint/parser@8.60.1(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3)': '@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.2 '@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.60.1(eslint@9.39.4)(typescript@5.9.3) '@typescript-eslint/parser': 8.60.0(eslint@9.39.4)(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.60.1 '@typescript-eslint/scope-manager': 8.60.0
'@typescript-eslint/type-utils': 8.60.1(eslint@9.39.4)(typescript@5.9.3) '@typescript-eslint/type-utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3)
'@typescript-eslint/utils': 8.60.1(eslint@9.39.4)(typescript@5.9.3) '@typescript-eslint/utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.60.1 '@typescript-eslint/visitor-keys': 8.60.0
eslint: 9.39.4 eslint: 9.39.4
ignore: 7.0.5 ignore: 7.0.5
natural-compare: 1.4.0 natural-compare: 1.4.0
@ -2867,41 +2867,41 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.60.1(eslint@9.39.4)(typescript@5.9.3)': '@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.60.1 '@typescript-eslint/scope-manager': 8.60.0
'@typescript-eslint/types': 8.60.1 '@typescript-eslint/types': 8.60.0
'@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.60.1 '@typescript-eslint/visitor-keys': 8.60.0
debug: 4.4.3 debug: 4.4.3
eslint: 9.39.4 eslint: 9.39.4
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/project-service@8.60.1(typescript@5.9.3)': '@typescript-eslint/project-service@8.60.0(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/tsconfig-utils': 8.60.1(typescript@5.9.3) '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@5.9.3)
'@typescript-eslint/types': 8.60.1 '@typescript-eslint/types': 8.60.0
debug: 4.4.3 debug: 4.4.3
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/scope-manager@8.60.1': '@typescript-eslint/scope-manager@8.60.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.60.1 '@typescript-eslint/types': 8.60.0
'@typescript-eslint/visitor-keys': 8.60.1 '@typescript-eslint/visitor-keys': 8.60.0
'@typescript-eslint/tsconfig-utils@8.60.1(typescript@5.9.3)': '@typescript-eslint/tsconfig-utils@8.60.0(typescript@5.9.3)':
dependencies: dependencies:
typescript: 5.9.3 typescript: 5.9.3
'@typescript-eslint/type-utils@8.60.1(eslint@9.39.4)(typescript@5.9.3)': '@typescript-eslint/type-utils@8.60.0(eslint@9.39.4)(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/types': 8.60.1 '@typescript-eslint/types': 8.60.0
'@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.60.1(eslint@9.39.4)(typescript@5.9.3) '@typescript-eslint/utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3)
debug: 4.4.3 debug: 4.4.3
eslint: 9.39.4 eslint: 9.39.4
ts-api-utils: 2.5.0(typescript@5.9.3) ts-api-utils: 2.5.0(typescript@5.9.3)
@ -2909,37 +2909,37 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/types@8.60.1': {} '@typescript-eslint/types@8.60.0': {}
'@typescript-eslint/typescript-estree@8.60.1(typescript@5.9.3)': '@typescript-eslint/typescript-estree@8.60.0(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/project-service': 8.60.1(typescript@5.9.3) '@typescript-eslint/project-service': 8.60.0(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.60.1(typescript@5.9.3) '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@5.9.3)
'@typescript-eslint/types': 8.60.1 '@typescript-eslint/types': 8.60.0
'@typescript-eslint/visitor-keys': 8.60.1 '@typescript-eslint/visitor-keys': 8.60.0
debug: 4.4.3 debug: 4.4.3
minimatch: 10.2.5 minimatch: 10.2.5
semver: 7.8.2 semver: 7.8.1
tinyglobby: 0.2.17 tinyglobby: 0.2.16
ts-api-utils: 2.5.0(typescript@5.9.3) ts-api-utils: 2.5.0(typescript@5.9.3)
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.60.1(eslint@9.39.4)(typescript@5.9.3)': '@typescript-eslint/utils@8.60.0(eslint@9.39.4)(typescript@5.9.3)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4)
'@typescript-eslint/scope-manager': 8.60.1 '@typescript-eslint/scope-manager': 8.60.0
'@typescript-eslint/types': 8.60.1 '@typescript-eslint/types': 8.60.0
'@typescript-eslint/typescript-estree': 8.60.1(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3)
eslint: 9.39.4 eslint: 9.39.4
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/visitor-keys@8.60.1': '@typescript-eslint/visitor-keys@8.60.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.60.1 '@typescript-eslint/types': 8.60.0
eslint-visitor-keys: 5.0.1 eslint-visitor-keys: 5.0.1
'@unblockneteasemusic/server@0.28.0': '@unblockneteasemusic/server@0.28.0':
@ -3056,7 +3056,7 @@ snapshots:
dependencies: dependencies:
possible-typed-array-names: 1.1.0 possible-typed-array-names: 1.1.0
axios@1.17.0: axios@1.16.1:
dependencies: dependencies:
follow-redirects: 1.16.0 follow-redirects: 1.16.0
form-data: 4.0.5 form-data: 4.0.5
@ -3511,15 +3511,15 @@ snapshots:
safe-regex-test: 1.1.0 safe-regex-test: 1.1.0
set-proto: 1.0.0 set-proto: 1.0.0
stop-iteration-iterator: 1.1.0 stop-iteration-iterator: 1.1.0
string.prototype.trim: 1.2.11 string.prototype.trim: 1.2.10
string.prototype.trimend: 1.0.10 string.prototype.trimend: 1.0.9
string.prototype.trimstart: 1.0.8 string.prototype.trimstart: 1.0.8
typed-array-buffer: 1.0.3 typed-array-buffer: 1.0.3
typed-array-byte-length: 1.0.3 typed-array-byte-length: 1.0.3
typed-array-byte-offset: 1.0.4 typed-array-byte-offset: 1.0.4
typed-array-length: 1.0.8 typed-array-length: 1.0.8
unbox-primitive: 1.1.0 unbox-primitive: 1.1.0
which-typed-array: 1.1.22 which-typed-array: 1.1.21
es-define-property@1.0.1: {} es-define-property@1.0.1: {}
@ -4314,7 +4314,7 @@ snapshots:
is-typed-array@1.1.15: is-typed-array@1.1.15:
dependencies: dependencies:
which-typed-array: 1.1.22 which-typed-array: 1.1.21
is-unicode-supported@0.1.0: {} is-unicode-supported@0.1.0: {}
@ -4345,7 +4345,7 @@ snapshots:
joycon@3.1.1: {} joycon@3.1.1: {}
js-yaml@4.2.0: js-yaml@4.1.1:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
@ -4385,7 +4385,7 @@ snapshots:
listr2: 9.0.5 listr2: 9.0.5
picomatch: 4.0.4 picomatch: 4.0.4
string-argv: 0.3.2 string-argv: 0.3.2
tinyexec: 1.2.4 tinyexec: 1.2.3
yaml: 2.9.0 yaml: 2.9.0
listr2@9.0.5: listr2@9.0.5:
@ -4492,7 +4492,7 @@ snapshots:
glob: 10.5.0 glob: 10.5.0
he: 1.2.0 he: 1.2.0
is-path-inside: 3.0.3 is-path-inside: 3.0.3
js-yaml: 4.2.0 js-yaml: 4.1.1
log-symbols: 4.1.0 log-symbols: 4.1.0
minimatch: 9.0.9 minimatch: 9.0.9
ms: 2.1.3 ms: 2.1.3
@ -4549,7 +4549,7 @@ snapshots:
node-abi@3.92.0: node-abi@3.92.0:
dependencies: dependencies:
semver: 7.8.2 semver: 7.8.1
node-fetch@2.7.0: node-fetch@2.7.0:
dependencies: dependencies:
@ -4569,7 +4569,7 @@ snapshots:
ignore-by-default: 1.0.1 ignore-by-default: 1.0.1
minimatch: 10.2.5 minimatch: 10.2.5
pstree.remy: 1.1.8 pstree.remy: 1.1.8
semver: 7.8.2 semver: 7.8.1
simple-update-notifier: 2.0.0 simple-update-notifier: 2.0.0
supports-color: 5.5.0 supports-color: 5.5.0
touch: 3.1.1 touch: 3.1.1
@ -4744,7 +4744,7 @@ snapshots:
https-proxy-agent: 5.0.1 https-proxy-agent: 5.0.1
node-fetch: 2.7.0 node-fetch: 2.7.0
progress: 2.0.3 progress: 2.0.3
semver: 7.8.2 semver: 7.8.1
tar-fs: 2.1.4 tar-fs: 2.1.4
yargs: 16.2.0 yargs: 16.2.0
transitivePeerDependencies: transitivePeerDependencies:
@ -5038,7 +5038,7 @@ snapshots:
secure-json-parse@2.7.0: {} secure-json-parse@2.7.0: {}
semver@7.8.2: {} semver@7.8.1: {}
send@0.19.2: send@0.19.2:
dependencies: dependencies:
@ -5168,7 +5168,7 @@ snapshots:
simple-update-notifier@2.0.0: simple-update-notifier@2.0.0:
dependencies: dependencies:
semver: 7.8.2 semver: 7.8.1
slash@3.0.0: {} slash@3.0.0: {}
@ -5261,7 +5261,7 @@ snapshots:
get-east-asian-width: 1.6.0 get-east-asian-width: 1.6.0
strip-ansi: 7.2.0 strip-ansi: 7.2.0
string.prototype.trim@1.2.11: string.prototype.trim@1.2.10:
dependencies: dependencies:
call-bind: 1.0.9 call-bind: 1.0.9
call-bound: 1.0.4 call-bound: 1.0.4
@ -5270,9 +5270,8 @@ snapshots:
es-abstract: 1.24.2 es-abstract: 1.24.2
es-object-atoms: 1.1.2 es-object-atoms: 1.1.2
has-property-descriptors: 1.0.2 has-property-descriptors: 1.0.2
safe-regex-test: 1.1.0
string.prototype.trimend@1.0.10: string.prototype.trimend@1.0.9:
dependencies: dependencies:
call-bind: 1.0.9 call-bind: 1.0.9
call-bound: 1.0.4 call-bound: 1.0.4
@ -5348,9 +5347,9 @@ snapshots:
inherits: 2.0.4 inherits: 2.0.4
readable-stream: 3.6.2 readable-stream: 3.6.2
tinyexec@1.2.4: {} tinyexec@1.2.3: {}
tinyglobby@0.2.17: tinyglobby@0.2.16:
dependencies: dependencies:
fdir: 6.5.0(picomatch@4.0.4) fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4 picomatch: 4.0.4
@ -5377,7 +5376,7 @@ snapshots:
dependencies: dependencies:
gopd: 1.2.0 gopd: 1.2.0
typedarray.prototype.slice: 1.0.5 typedarray.prototype.slice: 1.0.5
which-typed-array: 1.1.22 which-typed-array: 1.1.21
ts-api-utils@2.5.0(typescript@5.9.3): ts-api-utils@2.5.0(typescript@5.9.3):
dependencies: dependencies:
@ -5522,7 +5521,7 @@ snapshots:
isarray: 2.0.5 isarray: 2.0.5
which-boxed-primitive: 1.1.1 which-boxed-primitive: 1.1.1
which-collection: 1.0.2 which-collection: 1.0.2
which-typed-array: 1.1.22 which-typed-array: 1.1.21
which-collection@1.0.2: which-collection@1.0.2:
dependencies: dependencies:
@ -5533,7 +5532,7 @@ snapshots:
which-module@2.0.1: {} which-module@2.0.1: {}
which-typed-array@1.1.22: which-typed-array@1.1.21:
dependencies: dependencies:
available-typed-arrays: 1.0.7 available-typed-arrays: 1.0.7
call-bind: 1.0.9 call-bind: 1.0.9

View File

@ -1,14 +1,13 @@
# NeteaseCloudMusicAPI Enhanced # 网易云音乐 API Enhanced
> 🎉 全网收集最全的网易云音乐api接口 基于[NeteaseCloudMusicAPI](https://github.com/binaryify/NeteaseCloudMusicApi)的复刻版本 > 🔍 网易云音乐API Node.js服务的复兴项目
- ⚡ 四种加密模式 · 后端代理 - 基于原版网易云API新增更多有趣的功能
- 🪛 具备多达200多个接口 - 具备登录接口,多达200多个接口
- 📄 更完善的文档 - 更完善的文档
[Github](https://github.com/neteasecloudmusicapienhanced/api-enhanced) [Github](https://github.com/neteasecloudmusicapienhanced/api-enhanced)
[前往本家](https://github.com/binaryify/NeteaseCloudMusicApi) [Get Started](#neteasecloudmusicapienhanced)
[快速开始](#neteasecloudmusicapienhanced)
![color](#ffffff) ![color](#ffffff)

View File

@ -2492,18 +2492,6 @@ privilege:权限相关信息
**调用例子 :** `/scrobble?id=518066366&sourceid=36780169&time=291` **调用例子 :** `/scrobble?id=518066366&sourceid=36780169&time=291`
### 提交歌曲播放状态
说明 : 调用此接口可提交歌曲播放状态,支持会话追踪和播放模式记录,未传入 `sessionId` 时后端会自动生成
**必选参数 :** `id`: 歌曲 id
**可选参数 :** `sessionId`: 播放会话 ID12 位大写字母和数字),不传则自动生成, `progress`: 播放进度(秒),默认 0, `playMode`: 播放模式,默认 `list_loop`, `type`: 资源类型,默认 `song`
**接口地址 :** `/relay/play/state/submit`
**调用例子 :** `/relay/play/state/submit?id=518066366&progress=30`
### 热门歌手 ### 热门歌手
说明 : 调用此接口 , 可获取热门歌手数据 说明 : 调用此接口 , 可获取热门歌手数据
@ -5390,16 +5378,6 @@ let data = encodeURIComponent(
**调用例子 :** `/vip/sign/history` **调用例子 :** `/vip/sign/history`
### 直接获取云盘歌曲下载链接
说明 : 调用此接口, 传入云盘歌曲 id, 可直接获取云盘歌曲下载链接
**必选参数 :** `id`: 云盘歌曲 id
**接口地址 :** `/song/cloud/download`
**调用例子 :** `/song/cloud/download?id=123456789`
## 离线访问此文档 ## 离线访问此文档
此文档同时也是 Progressive Web Apps(PWA), 加入了 serviceWorker, 可离线访问 此文档同时也是 Progressive Web Apps(PWA), 加入了 serviceWorker, 可离线访问

View File

@ -11,7 +11,6 @@
}, },
"APP_CONF": { "APP_CONF": {
"apiDomain": "https://interface.music.163.com", "apiDomain": "https://interface.music.163.com",
"xeapiDomain": "https://interface3.music.163.com",
"domain": "https://music.163.com", "domain": "https://music.163.com",
"encrypt": true, "encrypt": true,
"encryptResponse": false, "encryptResponse": false,

View File

@ -110,7 +110,7 @@ const userAgentMap = {
// 预先定义常量 // 预先定义常量
const DOMAIN = APP_CONF.domain const DOMAIN = APP_CONF.domain
const API_DOMAIN = APP_CONF.apiDomain const API_DOMAIN = APP_CONF.apiDomain
const XEAPI_DOMAIN = APP_CONF.xeapiDomain const XEAPI_DOMAIN = 'https://interface3.music.163.com'
const ENCRYPT_RESPONSE = APP_CONF.encryptResponse const ENCRYPT_RESPONSE = APP_CONF.encryptResponse
const SPECIAL_STATUS_CODES = new Set([201, 302, 400, 502, 800, 801, 802, 803]) const SPECIAL_STATUS_CODES = new Set([201, 302, 400, 502, 800, 801, 802, 803])

View File

@ -1,15 +1,59 @@
const registerXeapiKey = require('../module/register_xeapikey') const { default: axios } = require('axios')
const encrypt = require('./crypto')
const { APP_CONF } = require('./config.json')
const generateNonce = () => {
let nonce = ''
for (let i = 0; i < 16; i++) {
nonce += Math.floor(Math.random() * 10).toString()
}
return nonce
}
const getXeapiPublicKey = async (currentPublicKey = {}, deviceId = '') => { const getXeapiPublicKey = async (currentPublicKey = {}, deviceId = '') => {
const result = await registerXeapiKey( const nonce = generateNonce()
{ const timestamp = String(Date.now())
deviceId, const data = {
appVersion: '9.1.65',
currentKeyVersion: currentPublicKey.version || '', currentKeyVersion: currentPublicKey.version || '',
deviceId,
nonce,
os: 'android',
requestType: 'active',
signature: encrypt.xeapiSign(timestamp, nonce),
t1: '',
t2: '',
timestamp,
uid: '',
}
const res = await axios({
method: 'POST',
url: APP_CONF.apiDomain + '/api/gorilla/anti/crawler/security/key/get',
headers: {
'User-Agent':
'NeteaseMusic/9.1.65.240927161425(9001065);Dalvik/2.1.0 (Linux; U; Android 14; 23013RK75C Build/UKQ1.230804.001)',
Cookie: deviceId ? `deviceId=${encodeURIComponent(deviceId)}` : '',
}, },
null, data: new URLSearchParams(data).toString(),
) proxy: false,
})
if (
!res.data ||
res.data.code !== 200 ||
!res.data.data ||
!res.data.data.encryptedData
) {
throw new Error('xeapi public key request failed')
}
if (
!res.data.data.signature ||
encrypt.xeapiSign(res.data.data.timestamp, nonce) !==
res.data.data.signature
) {
throw new Error('xeapi public key response signature mismatch')
}
const publicKey = result.body const publicKey = encrypt.xeapiDecryptPublicKey(res.data.data.encryptedData)
if (!publicKey.sk && currentPublicKey.sk) { if (!publicKey.sk && currentPublicKey.sk) {
publicKey.sk = currentPublicKey.sk publicKey.sk = currentPublicKey.sk
} }