Files
MusicServer/docs/API.md
T
snowy-yang 3381e9b906 refactor(api)!: 平台 id 改两字母短码——qian→bd、joox→jx、5sing→5s、bili→bl
对外 id 统一为两字母短码,与既有的 kw/kg/tx/wy/qs/xm/me/qt/lr 对齐;
migu 与 apple 保持原样(Apple Music 没有自然的短码)。

**破坏性变更**:id 出现在所有 URL、/sources 返回、OpenAPI 示例以及
data/auth.json 的凭据键里,这四个平台已存的登录态会失效,需重新登录。

- sdk/index.ts:id 与 supportQuality 映射键
- sdk/types.ts:Source 联合类型
- src/routes.ts 与 routes-login.ts:路由路径与 schema 描述
  (/login/bili/qr → /login/bl/qr 等)、/login/status 的响应键
- test/smoke-test.ts、README.md、docs/API.md 同步

有意未改:sdk 目录与文件名仍用平台名(sdk/qian/、sdk/apis/joox.ts …),
规则定为「目录=平台名,id=对外短码」,映射只在 SUPPORTED_SOURCES 一处声明。
域名与正则(joox.com、5sing.kugou.com、/joox\.com\//)、jooxSign 等标识符、
错误文案里的中文平台名、以及 kg 榜单名(含「joox本地热歌榜」)全部保持原样——
它们只是恰好含平台名,并不是 id。

验证:typecheck ✓、pnpm test 112/112 ✓;另起临时实例实证 /sources 与
/login/status 的新 id 与展示名,新旧 id 均无残留。
2026-10-03 11:03:06 +08:00

154 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MusicServer 聚合音乐 API
多平台音乐聚合接口:搜索、播放地址、歌词、封面、榜单、歌单、专辑、歌手、链接解析、登录。
共 15 个平台:`kw`(酷我)/ `kg`(酷狗)/ `tx`(QQ音乐)/ `wy`(网易云)/ `qs`(汽水)/ `migu`(咪咕)/
`bd`(千千)/ `jx` / `bl`(哔哩哔哩)/ `5s` / `apple`(Apple Music,仅试听),
以及有声平台 `xm`(喜马拉雅)/ `me`(猫耳FM)/ `qt`(蜻蜓FM)/ `lr`(懒人听书)。
> **本文档是人工速查版,可能滞后于代码。**
> 接口与参数以服务器自动生成的规范为准(路由 schema 同源,永远与实现同步):
>
> - **Swagger UI**:`/docs`(可直接调试)
> - **ReDoc**:`/redoc`
> - **OpenAPI 3.1**:`/openapi.json`(可生成各语言客户端)
> - **平台能力位**:`GET /sources` —— 各接口具体支持哪些平台,一律以它的能力位为准,本文不再硬列
## 约定
- 默认端口 **16688**(`PORT` 环境变量可改)。
- **全部接口为路径参数风格**,分页走 path 段且第 1 页可省略:`/search/kw/稻香`、`/search/kw/稻香/2`、
`/album/kg/123/2`。查询参数只用于修饰(`?quality=`、`?limit=`、`?singer=` 等)。
- 默认返回 `Access-Control-Allow-Origin: *`,可直接在浏览器/前端调用。
- **成功**:`200` + `{"code": 0, "data": ...}`
- **失败**:对应 HTTP 状态码 + `{"code": <状态码>, "msg": "...", "detail": ...}`
| 状态码 | 含义 |
| --- | --- |
| `422` | 参数校验失败(Fastify/Ajv,FastAPI 风格) |
| `404` | 接口不存在,或平台不支持该能力 |
| `405` | 方法不允许(响应带 `Allow` 头) |
| `502` | 上游平台请求失败 |
| `500` | 服务器内部错误 |
### 鉴权与限流
- 设置 `AUTH_KEY` 后**全部路径**都要求 `X-Server-Key: <AUTH_KEY>`(含文档页与 404,防止扫描探测接口存在性)。
- `/stream/*` 流代理例外:播放器无法携带自定义头,改用 `/url` 返回流地址时自动附带的 `?exp=&sig=` 短时签名(HMAC 派生,10 分钟有效)。
- `RATE_LIMIT` 为每 IP 每分钟允许的请求数(默认 120,设 0 关闭),超限返回 `429` + `Retry-After`。
### 歌曲 id 形态
各平台 id 约定(含 `kw` 的 songmid、`kg` 的 hash、`qs`/`xm`/`me` 的 id、`migu` 的三元组、
`qt`/`lr` 的复合 id、`bl` 的 `<bvid>|<cid>` 等)详见 README「歌曲 ID 约定」。
复合 id 含 `|` / `:` 时在 URL 中需编码(`|` → `%7C`)。
## 接口速查
### 系统
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| GET | `/health` | 健康检查(status / uptime / 平台数) |
| GET | `/sources` | 平台列表:音质与全部能力位(**判断某接口支持哪些平台的唯一依据**) |
| GET | `/` | 302 重定向到 `/docs` |
| GET | `/docs` · `/redoc` · `/openapi.json` | Swagger UI / ReDoc / OpenAPI 3.1 规范 |
### 搜索
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| GET | `/search/:source/:keyword[/:page]` | 搜索歌曲;`source` 为平台 id 或 `all`(聚合,自带 `noAggregate` 的平台不参与)。`?singer=` 附加歌手、`?limit=` 每页条数 |
| GET | `/find/:source/:keyword` | 精确匹配搜索;`?singer=` `?albumName=` `?interval=` 辅助匹配,`source=all` 时 `?excludeSource=` 跳过平台 |
### 歌曲资源
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| GET | `/url/:source/:id` | 播放地址;`?quality=`(64k/128k/320k/flac/flac24bit,默认 128k)。取流链:外部音源(启用时)→ SDK 直连 → 酷我兜底(响应 `via` 标记实际命中通道) |
| GET | `/stream/:source/:id` | 加密流解密代理,`source` 用 path 段区分(`qs` 汽水解密流 / `migu` 咪咕 Z3D 加密流)。供 `/url` 返回的相对地址使用,不接受自行构造 |
| GET | `/lyric/:source/:id` | 歌词;可带 `?name=` `?interval=`(部分平台搜索歌词时需要) |
| GET | `/pic/:source/:id` | 封面;可带 `?albumId=`(kg 需要) |
### 榜单 / 歌单 / 热搜
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| GET | `/boards/:source` | 榜单列表 |
| GET | `/boards/:source/:boardId[/:page]` | 榜单详情(分页 path 段)。`boardId` 兼容带前缀 id(`kw__93`)与裸 `bangid`(`93`) |
| GET | `/hot-search/:source` | 热搜词 |
| GET | `/song-list/:source[/:page]` | 歌单列表;`?sortId=` `?tagId=` 各平台词汇不同,省略时用平台默认 |
| GET | `/playlist/:source/:id[/:page]` | 歌单详情与曲目;`?limit=`。bl 支持合集/多分P |
| GET | `/playlist/:source/search/:keyword` | 歌单搜索(`?page=` `?limit=`) |
| GET | `/playlist/:source/categories` | 歌单分类列表 |
| GET | `/playlist/:source/categories/:categoryId` | 分类下的歌单(`?page=` `?limit=`) |
| GET | `/user-playlist/:source` | 个人歌单(需登录;仅 tx/wy 有完整实现,其余 404/502) |
### 歌手 & 专辑
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| GET | `/singer/:source/:id` | 歌手信息(name/desc/avatar 与歌曲/专辑数量) |
| GET | `/singer/:source/:id/songs[/:page]` | 歌手歌曲列表;`?limit=` |
| GET | `/singer/:source/:id/albums[/:page]` | 歌手专辑列表;`?limit=` |
| GET | `/album/:source/:id[/:page]` | 专辑详情与曲目;`?limit=` |
| GET | `/album/:source/search/:keyword` | 专辑搜索(`?page=` `?limit=`) |
### 链接解析
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| POST | `/parse/song/:source` | 解析歌曲网页链接 → 歌曲信息,body `{"link": "..."}` |
| POST | `/parse/album/:source` | 解析专辑链接 → 专辑信息与曲目 |
| POST | `/parse/playlist/:source` | 解析歌单链接 → 歌单信息与曲目 |
支持的平台见 `/sources` 的 `parse` 能力位;不支持的平台返回 404。
### 登录
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| POST | `/login/wy/qr` → `/login/wy/qr/check` | 网易云扫码(`check` body 传 `{"key": "..."}`) |
| POST | `/login/wy/cellphone` | 网易云手机号登录(`password` 明文或 `captcha`) |
| DELETE | `/login/wy` | 退出网易云 |
| POST | `/login/kg/qr` → `/login/kg/qr/check` | 酷狗扫码 |
| POST | `/login/kg/captcha` → `/login/kg/cellphone` | 酷狗短信验证码登录 |
| POST | `/login/kg/password` | 酷狗账密登录(命中风控返回挑战,配合 `/login/kg/verify` 重试) |
| POST | `/login/kg` | 绑定酷狗 token(App 抓包) |
| DELETE | `/login/kg` | 退出酷狗 |
| POST | `/login/tx/qr` → `/login/tx/qr/check` | QQ 音乐扫码 |
| POST | `/login/tx` | 绑定 QQ 音乐 cookie(可选 App 抓包字段供自动续期) |
| DELETE | `/login/tx` | 退出 QQ 音乐 |
| POST | `/login/qs/qr` → `/login/qs/qr/check` | 汽水音乐扫码(用**汽水音乐 App** 扫一扫) |
| DELETE | `/login/qs` | 退出汽水音乐 |
| POST | `/login/xm` · `/login/me` | 绑定喜马拉雅 cookie / 猫耳FM token |
| DELETE | `/login/xm` · `/login/me` | 退出对应平台 |
| POST | `/login/lr` | 懒人听书账号登录(`account` + `password`) |
| DELETE | `/login/lr` | 退出懒人听书 |
| POST | `/login/bl/qr` → `/login/bl/qr/check` | 哔哩哔哩扫码(解锁大会员音质) |
| DELETE | `/login/bl` | 退出哔哩哔哩 |
| POST | `/login/refresh` | 手动触发登录态续期(kg/tx) |
| GET | `/login/status` | 登录状态总览(各平台 `logged` 与账号资料) |
- 凭据持久化于 `data/auth.json`(不入库,文件权限 0600),登录后取流与平台请求自动携带。
- 自动续期:启动 10s 后对 kg/tx 执行一次,此后每 24h 一次(音源模式下不参与取流,自动续期不启动)。
## 响应示例
```jsonc
// GET /url/kw/228908?quality=320k
{ "code": 0, "data": { "type": "320k", "url": "https://..." } }
// GET /lyric/kw/228908
{ "code": 0, "data": { "lyric": "[00:00.00]...", "tlyric": "", "yrc": "" } }
// 参数非法 → 422
{ "code": 422, "msg": "params/source must be equal to one of the allowed values", "detail": [...] }
// 平台不支持该能力 → 404
{ "code": 404, "msg": "不支持的平台: xx" }
// 方法不允许 → 405 + Allow 头
{ "code": 405, "msg": "方法 POST 不允许,请使用 GET, HEAD" }
```