mirror of
https://github.com/NeteaseCloudMusicApiEnhanced/api-enhanced.git
synced 2026-06-27 21:25:08 +00:00
Compare commits
No commits in common. "60ee927e3224ab675679d023065225af11bdc693" and "6fc4231142e2a91913cdf54f27cc9722391e30c0" have entirely different histories.
60ee927e32
...
6fc4231142
23
AGENTS.md
23
AGENTS.md
@ -1,23 +0,0 @@
|
||||
# Agent Instructions for NeteaseCloudMusicApiEnhanced
|
||||
|
||||
## Quick Start
|
||||
- **Package Manager**: Use `pnpm` (not npm or yarn).
|
||||
- **Node Version**: Requires Node.js 18 or later.
|
||||
|
||||
## Developer Commands
|
||||
- **Install dependencies**: `pnpm i`
|
||||
- **Start server**: `pnpm start` or `node app.js`
|
||||
- **Start dev server**: `pnpm dev` (uses nodemon)
|
||||
- **Run tests**: `pnpm test` (uses Mocha)
|
||||
- **Linting**: `pnpm lint` (check) or `pnpm lint-fix` (auto-fix)
|
||||
|
||||
## Architecture & Entrypoints
|
||||
- **Executable Server**: `app.js` is the main entrypoint for running the API server.
|
||||
- **Module Exports**: `main.js` is the entrypoint when the project is imported as a Node.js dependency.
|
||||
- **API Endpoints**: Located in the `module/` directory. Each file typically corresponds to an API route.
|
||||
- **Core Utilities**: Request handling, encryption, and core utilities are found in the `util/` directory.
|
||||
|
||||
## Important Gotchas & Quirks
|
||||
- **Environment Variables**: The server defaults to port 3000 but can be overridden with the `PORT` environment variable.
|
||||
- **Proxy Variables**: Be very careful with proxy environment variables (`http_proxy`, `https_proxy`, `no_proxy`). The request library (like axios) will automatically pick these up. If they point to an unavailable proxy (especially common in Docker environments), requests will fail silently or throw connection errors.
|
||||
- **Code Style**: The project uses ESLint and Prettier. Always run `pnpm lint-fix` before committing changes to ensure formatting consistency.
|
||||
@ -1,40 +1,8 @@
|
||||
// 听歌打卡
|
||||
|
||||
const createOption = require('../util/option.js')
|
||||
module.exports = async (query, request) => {
|
||||
// 注入 os=osx 的 cookie
|
||||
let cookie = query.cookie || ''
|
||||
if (typeof cookie === 'object') {
|
||||
cookie = Object.assign({ os: 'osx' }, cookie)
|
||||
} else if (typeof cookie === 'string') {
|
||||
if (cookie.indexOf('os=') > -1) {
|
||||
cookie = cookie.replace(/os=[^;]+/g, 'os=osx')
|
||||
} else {
|
||||
cookie = cookie + '; os=osx'
|
||||
}
|
||||
} else {
|
||||
cookie = 'os=osx'
|
||||
}
|
||||
query.cookie = cookie
|
||||
|
||||
// 1) startplay → 进「最近播放」
|
||||
const startplayData = {
|
||||
logs: JSON.stringify([
|
||||
{
|
||||
action: 'startplay',
|
||||
json: {
|
||||
id: query.id,
|
||||
type: 'song',
|
||||
mainsite: '1',
|
||||
mainsiteWeb: '1',
|
||||
content: `id=${query.sourceid}`,
|
||||
},
|
||||
},
|
||||
]),
|
||||
}
|
||||
|
||||
// 2) play → 涨「听歌排行」计数
|
||||
const playData = {
|
||||
module.exports = (query, request) => {
|
||||
const data = {
|
||||
logs: JSON.stringify([
|
||||
{
|
||||
action: 'play',
|
||||
@ -47,30 +15,12 @@ module.exports = async (query, request) => {
|
||||
type: 'song',
|
||||
wifi: 0,
|
||||
source: 'list',
|
||||
mainsite: '1',
|
||||
mainsiteWeb: '1',
|
||||
content: `id=${query.sourceid}`,
|
||||
mainsite: 1,
|
||||
content: '',
|
||||
},
|
||||
},
|
||||
]),
|
||||
}
|
||||
|
||||
const option = createOption(query, 'eapi')
|
||||
option.domain = 'https://clientlog.music.163.com'
|
||||
|
||||
// 发送两次请求
|
||||
const res1 = await request(`/api/feedback/weblog`, startplayData, option)
|
||||
const res2 = await request(`/api/feedback/weblog`, playData, option)
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
code: 200,
|
||||
data: 'success',
|
||||
details: {
|
||||
startplay: res1.body,
|
||||
play: res2.body,
|
||||
},
|
||||
},
|
||||
}
|
||||
return request(`/api/feedback/weblog`, data, createOption(query, 'weapi'))
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@neteasecloudmusicapienhanced/api",
|
||||
"version": "4.35.2",
|
||||
"version": "4.35.1",
|
||||
"description": "全网最全的网易云音乐API接口 || A revival project for NeteaseCloudMusicApi Node.js Services (Half Refactor & Enhanced) || 网易云音乐 API 备份 + 增强 || 本项目自原版v4.28.0版本后开始自行维护",
|
||||
"scripts": {
|
||||
"dev": "nodemon app.js",
|
||||
|
||||
21
server.js
21
server.js
@ -10,7 +10,6 @@ const { cookieToJson } = require('./util/index')
|
||||
const fileUpload = require('express-fileupload')
|
||||
const decode = require('safe-decode-uri-component')
|
||||
const logger = require('./util/logger.js')
|
||||
const { APP_CONF } = require('./util/config.json')
|
||||
|
||||
/**
|
||||
* The version check result.
|
||||
@ -300,15 +299,15 @@ async function constructServer(moduleDefs) {
|
||||
)
|
||||
|
||||
try {
|
||||
let usedCrypto = ''
|
||||
const moduleResponse = await moduleDef.module(query, (...params) => {
|
||||
// 参数注入客户端IP
|
||||
const obj = [...params]
|
||||
const options = obj[2] || {}
|
||||
usedCrypto = options.crypto || ''
|
||||
let ip = ''
|
||||
|
||||
if (options.randomCNIP) {
|
||||
ip = global.cnIp
|
||||
// logger.info('Using random Chinese IP for request:', ip)
|
||||
} else {
|
||||
ip = req.ip
|
||||
|
||||
@ -318,6 +317,7 @@ async function constructServer(moduleDefs) {
|
||||
if (ip == '::1') {
|
||||
ip = global.cnIp
|
||||
}
|
||||
// logger.info('Requested from ip:', ip)
|
||||
}
|
||||
|
||||
obj[2] = {
|
||||
@ -327,10 +327,7 @@ async function constructServer(moduleDefs) {
|
||||
|
||||
return request(...obj)
|
||||
})
|
||||
const displayCrypto = usedCrypto || (APP_CONF.encrypt ? 'eapi' : 'api')
|
||||
logger.info(
|
||||
`Request Success: [${displayCrypto}] ${decode(req.originalUrl)}`,
|
||||
)
|
||||
logger.info(`Request Success: ${decode(req.originalUrl)}`)
|
||||
|
||||
// 夹带私货部分:如果开启了通用解锁,并且是获取歌曲URL的接口,则尝试解锁(如果需要的话)ヾ(≧▽≦*)o
|
||||
if (
|
||||
@ -425,7 +422,7 @@ async function serveNcmApi(options) {
|
||||
options.checkVersion &&
|
||||
checkVersion().then(({ npmVersion, ourVersion, status }) => {
|
||||
if (status == VERSION_CHECK_RESULT.NOT_LATEST) {
|
||||
logger.warn(
|
||||
logger.info(
|
||||
`最新版本: ${npmVersion}, 当前版本: ${ourVersion}, 请及时更新`,
|
||||
)
|
||||
}
|
||||
@ -447,9 +444,11 @@ async function serveNcmApi(options) {
|
||||
╠═╣╠═╝║ ║╣ ║║║╠═╣╠═╣║║║║ ║╣ ║║
|
||||
╩ ╩╩ ╩ ╚═╝╝╚╝╩ ╩╩ ╩╝╚╝╚═╝╚═╝═╩╝
|
||||
`)
|
||||
logger.info(
|
||||
`Server started successfully @ http://${host ? host : 'localhost'}:${port}`,
|
||||
)
|
||||
logger.info(`
|
||||
- Server started successfully @ http://${host ? host : 'localhost'}:${port}
|
||||
- Environment: ${process.env.NODE_ENV || 'development'}
|
||||
- Node Version: ${process.version}
|
||||
- Process ID: ${process.pid}`)
|
||||
})
|
||||
|
||||
return appExt
|
||||
|
||||
@ -62,9 +62,9 @@ const chinaIPRanges = (function loadChinaIPRanges() {
|
||||
// attach total for convenience
|
||||
arr.totalCount = total
|
||||
|
||||
// logger.info(
|
||||
// `Loaded ${arr.length} Chinese IP ranges from china_ip_ranges.txt, total ${total} IPs`,
|
||||
// )
|
||||
logger.info(
|
||||
`Loaded ${arr.length} Chinese IP ranges from china_ip_ranges.txt, total ${total} IPs`,
|
||||
)
|
||||
return arr
|
||||
} catch (error) {
|
||||
logger.error('Failed to load china_ip_ranges.txt:', error.message)
|
||||
|
||||
@ -88,12 +88,6 @@ const osMap = {
|
||||
osver: '16.2',
|
||||
channel: 'distribution',
|
||||
},
|
||||
osx: {
|
||||
os: 'osx',
|
||||
appver: '3.1.10.5100',
|
||||
osver: '15.5',
|
||||
channel: 'netease',
|
||||
},
|
||||
}
|
||||
|
||||
// 预先定义userAgentMap
|
||||
@ -312,11 +306,7 @@ const createRequest = (uri, data, options) => {
|
||||
if (cookie.MUSIC_A) header['MUSIC_A'] = cookie.MUSIC_A
|
||||
|
||||
headers['Cookie'] = createHeaderCookie(header)
|
||||
headers['User-Agent'] =
|
||||
options.ua ||
|
||||
(cookie.os === 'osx'
|
||||
? 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
|
||||
: chooseUserAgent('api', 'iphone'))
|
||||
headers['User-Agent'] = options.ua || chooseUserAgent('api', 'iphone')
|
||||
|
||||
if (crypto === 'eapi') {
|
||||
// headers['x-aeapi'] = true // 服务器会使用gzip压缩返回值
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user