Files
Koneko_api_for_QZ-Music/Koneko_插件开发文档_v0.0.2.md

240 lines
6.4 KiB
Markdown
Raw Permalink 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.
# Koneko QZ Music v2/v3 插件开发文档
> 版本0.0.2 | 作者:云汀(Miao-moe) | 整理日期2026-06-20
---
## 一、概述
为 QZ Music v2/v3 编写 6 个音乐平台拓展插件:
- QQ音乐 (`koneko_tx`)
- 酷狗音乐 (`koneko_kg`)
- 酷我音乐 (`koneko_kw`)
- 网易云音乐 (`koneko_wy`)
- 咪咕音乐 (`koneko_mg`)
- GIT音源 (`koneko_git`)
## 二、插件规范
### 2.1 运行环境
- Node.js 运行时Javet/V8
- CommonJS 模块规范
- `module.exports` 导出接口
- 不支持 `axios`,使用内置 `http`/`https` 模块
### 2.2 ES5 兼容Javet/V8 限制)
| 语法 | 状态 | 替代 |
|------|------|------|
| `let` / `const` | ❌ | `var` |
| 箭头函数 | ❌ | `function() {}` |
| `async`/`await` | ❌ | Promise 链式 |
| `catch { }` 无参数 | ❌ | `catch (e) { }` |
| `Promise.allSettled` | ❌ | `Promise.all` + 手动包装 |
| `Object.entries/values` | ❌ | `for...in` |
| `Array.includes` | ❌ | `indexOf` |
| `String.startsWith` | ❌ | `indexOf(...) === 0` |
| `class` | ❌ | 对象字面量 |
| 模板字符串 `${}` | ✅ | - |
| `Buffer` | ✅ | - |
### 2.3 插件导出格式
```js
module.exports = {
musicSearch: { search: fn, tipSearch: fn, hotSearch: fn },
tipSearch: { getList: fn },
hotSearch: { getList: fn },
getUrl: fn,
getLyric: fn,
songList: { getListDetail: fn },
album: { getListDetail: fn },
pluginInfo: { info, env, ext, quality, supportFunc },
// 网易云特有
userPlaylist: fn,
dailyRecommend: fn,
personalFm: fn,
myLikedSongs: fn
}
```
### 2.4 搜索结果格式
```js
{
list: [{
id: String,
name: String,
artists: String, // 用 "、" 分隔
source: String, // tx/kg/kw/wy/mg
pic: String, // 封面大图
mPic: String, // 封面中图
sPic: String, // 封面小图
albumName: String,
albumId: String,
interval: String, // "m:ss"
qualities: { standard: '3.21MB', exhigh: '7.85MB', ... }
}],
allPage: Number,
limit: Number,
total: Number,
source: String
}
```
### 2.5 环境变量
通过 `global.env` 读取:
```js
var env = global.env || {}
var CERU_KEY = env.ceru_key || ''
var WY_COOKIE = env.cookie || ''
var PLAYLIST_URL = env.playlist_url || ''
```
### 2.6 音质标识
| ID | 含义 |
|----|------|
| `standard` | 标准音质 (128k) |
| `exhigh` | 高品音质 (320k) |
| `lossless` | 无损音质 (FLAC) |
| `hires` | Hi-Res |
| `jyeffect` | 高清环绕声 |
| `sky` | 沉浸环绕声 |
| `jymaster` | 超清母带 |
## 三、各平台 API
### 3.1 QQ音乐 (tx)
**搜索签名**: `zzcSign` = SHA1 + 自定义索引提取 + XOR 混淆 + base64
```js
var PART_1_INDEXES = [23, 14, 6, 36, 16, 40, 7, 19]
var PART_2_INDEXES = [16, 1, 32, 12, 19, 27, 8, 5]
var SCRAMBLE_VALUES = [89, 39, 179, 150, 218, 82, 58, 252, 177, 52, 186, 123, 120, 64, 242, 133, 143, 161, 121, 179]
```
**封面图规则**
- 有专辑ID`https://y.gtimg.cn/music/photo_new/T002R500x500M000{albumId}.jpg`
- 无专辑ID`https://y.gtimg.cn/music/photo_new/T001R500x500M000{singerMid}.jpg`
**getUrl 音质参数**`128k` / `320k` / `999k`
### 3.2 酷狗音乐 (kg)
**搜索接口**`http://mobilecdn.kugou.com/api/v3/search/song`
**注意**:返回字段是 `errcode`(不是 `error_code`
**封面图**:搜索结果自带 `imgurl`,替换 `{size}``400`
### 3.3 酷我音乐 (kw)
**搜索接口**`http://search.kuwo.cn/r.s`
**封面图**`https://img2.kuwo.cn/star/albumcover/300/{ALBUMID}.jpg`
**音质信息**:在 `N_MINFO` 字段中解析
### 3.4 网易云音乐 (wy)
**搜索接口**`https://music.163.com/api/search/get/web`GET不需要 weapi
**封面图**`picId` 需 Base64 编码
```js
var picIdB64 = Buffer.from(String(s.album.picId)).toString('base64').replace(/=/g, '')
var pic = 'https://p2.music.126.net/' + picIdB64 + '/' + picIdStr + '.jpg'
```
**加密接口**
- `eapi`AES-128-ECBkey = `e82ckenh8dichen8`
- `weapi`AES-128-CBC + RSA
**Cookie 功能**(需设置 `cookie` 环境变量):
- `userPlaylist()` - 个人歌单(需 `playlist_url`
- `dailyRecommend()` - 每日推荐
- `personalFm()` - 私人FM
- `myLikedSongs()` - 我喜欢的音乐
- `songList(id)` - 歌单详情
- `album(id)` - 专辑详情
- `getLyric(id)` - 歌词获取
### 3.5 咪咕音乐 (mg)
**搜索签名**MD5 拼接
```js
var sign = crypto.createHash('md5').update(
str + signatureMd5 + 'yyapp2d16148780a1dcc7408e06336b98cfd50' + deviceId + time
).digest('hex')
```
**封面图**:搜索结果可能返回相对路径,需拼接 `https://d.musicapp.migu.cn`
### 3.6 GIT音源 (git)
纯音源插件,无搜索功能,仅 `getUrl`
## 四、getUrl 容灾机制
所有平台统一使用**并发测速**模式:
```js
Promise.all(promises.map(function(p) {
return p.then(function(v) { return { status: 'fulfilled', value: v } })
.catch(function(e) { return { status: 'rejected', reason: e } })
})).then(function(results) {
for (var i = 0; i < results.length; i++) {
if (results[i].status === 'fulfilled') return results[i].value.url
}
return ''
})
```
### 音源 API 列表
| API | 平台 | 说明 |
|-----|------|------|
| 聆澜 | 全部 | 需 `ceru_key`,最稳定 |
| HUIBQ | 全部 | `X-Request-Key: share-v3` |
| 星海 | 全部 | 聚合接口 |
| 念心 | tx/kg/kw/mg | 个人维护 |
| 长青 | tx/kg/kw/mg | 个人维护 |
| 星海备 | 全部 | 备用 |
| fish | 全部 | 个人维护 |
| HYW | 全部 | 需 `X-Card-Key` |
| 忆音 | tx | 直接返回 URL |
| 收集QQ | tx | QQ专用 |
| 收集KW | kw | 酷我专用 |
| bb | wy | 网易云专用 |
| ymc | wy | 网易云专用 |
| unms | wy | 网易云专用 |
| 官方 weapi | wy | 网易云官方 |
## 五、版本管理
- 所有平台统一版本号
- 当前版本:`0.0.2`
- 文件名格式:`Koneko_{平台名}_v{版本号}.js`
## 六、常见问题
| 问题 | 原因 | 解决 |
|------|------|------|
| `Cannot find module 'axios'` | 用了 axios | 改用内置 `http`/`https` |
| `Field 'list' is required` | 返回 `songs` 而非 `list` | 改字段名为 `list` |
| 搜索无结果 | 字段名不匹配 | 检查 `errcode` vs `error_code` |
| 播放失败 | `mapBr` 返回格式不对 | tx/kg/kw/mg/git 用 `320k`wy 用 `320000` |
| 封面图不显示 | URL 格式错误 | 检查各平台拼接规则 |
## 七、相关链接
- Gitea: http://171.80.3.149:4321/miao-moe
- CeruMusic: http://171.80.3.149:4321/miao-moe/CeruMusic
- QZMusic PC: http://171.80.3.149:4321/miao-moe/QZMusic_PC