2dd94daa54
新增内容(145 行):
- 快速启动 6 步(config init → login → .env → up -d → logs → down)
- 首次登录两种方案:
A. 先在主机登录(推荐)
B. docker-compose run --rm 容器内登录
- Dockerfile 设计要点(多阶段 / 层缓存 / strip / tini / 非 root)
- 镜像版本管理(build-arg + tag/push)
- 容器内调试命令(exec / version / ffmpeg / yt-dlp / logs)
- 常见 Docker 问题:
- crates.io 拉取慢 → rsproxy 镜像源
- 容器立即退出 → 缺环境变量 / 配置 / data
- 升级后 crypto.db 不兼容 → 删除重建 + 重新信任
参考 README 系统要求章节了解详细依赖。
656 lines
22 KiB
Markdown
656 lines
22 KiB
Markdown
# Matrix 点歌机器人 (matrix-music-bot)
|
||
|
||
一个运行在 Matrix(兼容 Element / Element Call)房间中的点歌机器人,使用
|
||
`matrix-rust-sdk` 实现 **端到端加密 (E2EE)** 房间内搜索、点歌与音频投递。
|
||
|
||
> v1 已完成基础闭环:登录 → 加入加密房间 → 接收 `!req` / `!req-url` 命令 →
|
||
> yt-dlp 搜索 → 用户通过 emoji 反应选择 → 后台下载 → ffmpeg 转码 →
|
||
> 通过 `Timeline::send` 投递加密 `m.audio`。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
- [功能特性](#功能特性)
|
||
- [架构概览](#架构概览)
|
||
- [系统要求](#系统要求)
|
||
- [快速部署](#快速部署)
|
||
- [配置说明](#配置说明)
|
||
- [使用指南](#使用指南)
|
||
- [命令列表](#命令列表)
|
||
- [故障排查](#故障排查)
|
||
- [开发指南](#开发指南)
|
||
- [已知限制](#已知限制)
|
||
- [路线图](#路线图)
|
||
|
||
---
|
||
|
||
## 功能特性
|
||
|
||
| 能力 | 说明 |
|
||
|---|---|
|
||
| ✅ E2EE 房间 | 完全支持 Megolm 加密(聊天消息 + 音频文件) |
|
||
| ✅ Element Call 兼容 | MSC3401 call.member 状态事件观测(不参与通话媒体) |
|
||
| ✅ 多种点歌入口 | `!req <关键词>` 搜索 + `!req-url <URL>` 直传 |
|
||
| ✅ 用户两步选择 | 搜索后发带 1️⃣~5️⃣ emoji 的候选列表,点击 emoji 选定 |
|
||
| ✅ yt-dlp 通用后端 | 支持 YouTube / B 站 / SoundCloud 等 |
|
||
| ✅ 立体声 Opus 128k | 通过 ffmpeg 转码为 `audio/ogg; codecs=opus` |
|
||
| ✅ 每房间独立队列 | tokio mpsc 通道,房间间互不阻塞 |
|
||
| ✅ 队列去重 | 同 (source_kind, source_id) 同房间去重 |
|
||
| ✅ 反应超时清理 | 60 秒未选择自动取消搜索会话 |
|
||
| ✅ 加密会话存储 | access_token 用 Argon2id + AES-256-GCM 加密保存到 `data/secret.bin` |
|
||
| ✅ 自动交叉签名 | homeserver 支持 MSC3967 时自动建立交叉签名 |
|
||
|
||
---
|
||
|
||
## 架构概览
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ matrix-music-bot (Rust binary) │
|
||
│ │
|
||
│ main.rs (CLI) │
|
||
│ ├─ login → bootstrap → secret_store::save │
|
||
│ ├─ run → bootstrap::restore → event_loop │
|
||
│ └─ config → init / path / print │
|
||
│ │
|
||
│ event_loop.rs │
|
||
│ ├─ client.sync() ──────────────────┐ │
|
||
│ ├─ add_event_handler (m.room.message) │
|
||
│ ├─ add_event_handler (m.reaction) │ Megolm 解密 │
|
||
│ ├─ add_event_handler (MSC3401 state)│ │
|
||
│ └─ commands::parse → 派发 │
|
||
│ │
|
||
│ worker.rs (每房间一个) │
|
||
│ resolve → downloader (yt-dlp) → transcoder (ffmpeg) │
|
||
│ → delivery::audio_upload (m.audio via Timeline::send) │
|
||
│ │
|
||
│ 数据存储: │
|
||
│ data/crypto.db matrix-sdk crypto (Olm/Megolm) │
|
||
│ data/bot.db (预留,应用状态;v1 暂用内存) │
|
||
│ data/secret.bin AES-256-GCM 加密的 access_token │
|
||
│ data/cache/opus 转码后的 Opus/WebM │
|
||
└─────────────────────────────────────────────────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
Matrix homeserver yt-dlp ffmpeg
|
||
(E2EE Megolm) (HTTP 下载) (音频转码)
|
||
```
|
||
|
||
详细架构见 `C:\Users\Administrator\.claude\plans\lexical-meandering-lighthouse.md`。
|
||
|
||
---
|
||
|
||
## 系统要求
|
||
|
||
### 操作系统
|
||
|
||
- Windows 10/11(x86_64)
|
||
- Linux(理论上可编译,需把 `Cargo.toml` 中 `.cargo/config.toml` 的
|
||
`linker = "C:/msys64/mingw64/bin/gcc.exe"` 改为本地 gcc)
|
||
|
||
### 必备外部工具
|
||
|
||
| 工具 | 版本要求 | 安装方式(Windows) | 验证命令 |
|
||
|---|---|---|---|
|
||
| **Rust** | stable-x86_64-pc-windows-gnu ≥ 1.96 | `winget install Rustlang.Rustup` | `rustc --version` |
|
||
| **MinGW gcc** | ≥ 13(链接器) | `winget install MSYS2.MSYS2` 后 `pacman -S mingw-w64-x86_64-gcc` | `gcc --version` |
|
||
| **SQLite3** | 系统库(矩阵 SDK 链接) | `pacman -S mingw-w64-x86_64-sqlite3` | 系统 PATH 中 |
|
||
| **FFmpeg** | ≥ 5.0(音频转码) | https://www.gyan.dev/ffmpeg/builds/ 或 choco/scoop | `ffmpeg -version` |
|
||
| **yt-dlp** | ≥ 2024(音乐下载) | `pip install yt-dlp` 或下载 standalone binary | `yt-dlp --version` |
|
||
|
||
### 验证脚本
|
||
|
||
```bash
|
||
rustc --version # rustc 1.96.x
|
||
cargo --version # cargo 1.96.x
|
||
gcc --version # gcc.exe (Rev built by MSYS2 project)
|
||
ffmpeg -version # ffmpeg version 8.x
|
||
yt-dlp --version # 2026.x.x
|
||
sqlite3 --version # 3.x.x
|
||
```
|
||
|
||
---
|
||
|
||
## 快速部署
|
||
|
||
### 1. 克隆与编译
|
||
|
||
```bash
|
||
git clone http://192.168.6.200:3080/1076code/matrix.git
|
||
cd matrix
|
||
|
||
# Debug 编译(开发用)
|
||
cargo build
|
||
|
||
# Release 编译(生产用)
|
||
cargo build --release
|
||
```
|
||
|
||
二进制产物:
|
||
|
||
- Debug:`target/x86_64-pc-windows-gnu/debug/matrix-music-bot.exe`
|
||
- Release:`target/x86_64-pc-windows-gnu/release/matrix-music-bot.exe`
|
||
|
||
### 2. 创建配置文件
|
||
|
||
```bash
|
||
./target/release/matrix-music-bot.exe config init
|
||
# 生成 ./config/bot.toml
|
||
```
|
||
|
||
编辑 `./config/bot.toml`:
|
||
|
||
```toml
|
||
[homeserver]
|
||
url = "https://matrix.example.cn" # ← 改成你的 homeserver
|
||
|
||
[bot]
|
||
user_id = "@musicbot:example.cn" # ← 改成 bot 账户 MXID
|
||
device_name = "matrix-music-bot-v1"
|
||
admin_user_ids = ["@owner:example.cn"] # ← 可选
|
||
|
||
[data]
|
||
dir = "./data" # 默认即可
|
||
|
||
[commands]
|
||
prefix = "!"
|
||
mention_required_in_rooms = true # 房间中需 @-mention bot
|
||
allow_dm = true
|
||
|
||
[crypto]
|
||
auto_enable_cross_signing = true # 自动建立交叉签名
|
||
auto_enable_key_backup = false # bot 不参与密钥备份
|
||
|
||
[music]
|
||
ytdlp_path = "yt-dlp" # yt-dlp 路径或 PATH 中
|
||
search_limit = 5 # reactions 候选数
|
||
search_timeout_secs = 30 # 搜索超时
|
||
```
|
||
|
||
### 3. 首次登录
|
||
|
||
```bash
|
||
# 必须设置 passphrase(用于加密 secret.bin 中的 access_token)
|
||
export MATRIX_BOT_SECRET_PASSPHRASE="your-strong-passphrase-min-8-chars"
|
||
|
||
./target/release/matrix-music-bot.exe login \
|
||
--user-id "@musicbot:example.cn" \
|
||
--homeserver "https://matrix.example.cn"
|
||
|
||
# CLI 会提示输入密码(也可通过 MATRIX_BOT_PASSWORD 环境变量)
|
||
```
|
||
|
||
成功后输出类似:
|
||
|
||
```
|
||
╭─────────────────────────────────────────────────────────────╮
|
||
│ ✅ 登录成功 │
|
||
│ │
|
||
│ user_id: @musicbot:example.cn │
|
||
│ device_id: AAAAAAAAAA │
|
||
│ homeserver: https://matrix.example.cn │
|
||
╰─────────────────────────────────────────────────────────────╯
|
||
|
||
📋 下一步(重要):
|
||
在 Element 桌面客户端登录 @musicbot:example.cn,
|
||
进入 设置 → 设备 → 找到 device_id `AAAAAAAAAA`
|
||
点击 "信任"
|
||
```
|
||
|
||
### 4. Element 客户端信任 bot 设备
|
||
|
||
这一步**必须做**,否则交叉签名不通过、其他客户端会显示黄色盾牌。
|
||
|
||
1. 在 Element Web/Desktop 用 `@musicbot:example.cn` 登录
|
||
2. 设置 → 设备与会话 → 找到 `matrix-music-bot-v1`
|
||
3. 点击"信任"(或选中"Verify all sessions")
|
||
|
||
### 5. 启动 bot
|
||
|
||
```bash
|
||
export MATRIX_BOT_SECRET_PASSPHRASE="your-strong-passphrase-min-8-chars"
|
||
|
||
./target/release/matrix-music-bot.exe run
|
||
```
|
||
|
||
预期日志:
|
||
|
||
```
|
||
2026-07-02T13:00:00 INFO 恢复登录成功 user_id=@musicbot:example.cn
|
||
2026-07-02T13:00:01 INFO 开始初始 sync_once...
|
||
2026-07-02T13:00:05 INFO 初始 sync 完成
|
||
2026-07-02T13:00:05 INFO 已注册 m.room.message 事件 handler
|
||
2026-07-02T13:00:05 INFO 已注册 MSC3401 call.member state event handler
|
||
2026-07-02T13:00:05 INFO 开始 long-running sync(按 Ctrl-C 停止)
|
||
```
|
||
|
||
### 6. 加入加密房间
|
||
|
||
在 Element 中把 bot 邀请进一个加密房间。bot 会自动发现并启动 worker。
|
||
|
||
### 7. 测试点歌
|
||
|
||
在房间中发送:
|
||
|
||
```
|
||
@musicbot:example.cn !help
|
||
@musicbot:example.cn !req 周杰伦 晴天
|
||
@musicbot:example.cn !req-url https://www.youtube.com/watch?v=xxxxxxxxxxx
|
||
```
|
||
|
||
---
|
||
|
||
## 配置说明
|
||
|
||
### `MATRIX_BOT_SECRET_PASSPHRASE` 环境变量(必填)
|
||
|
||
用于加密 `data/secret.bin` 中的 access_token + device_id。**必须 ≥ 8 字符**。
|
||
|
||
```bash
|
||
# Linux/macOS
|
||
export MATRIX_BOT_SECRET_PASSPHRASE="correct-horse-battery-staple"
|
||
|
||
# Windows cmd
|
||
set MATRIX_BOT_SECRET_PASSPHRASE=correct-horse-battery-staple
|
||
|
||
# Windows PowerShell
|
||
$env:MATRIX_BOT_SECRET_PASSPHRASE = "correct-horse-battery-staple"
|
||
```
|
||
|
||
如果忘记此环境变量,bot 会输出明确错误:
|
||
|
||
```
|
||
ERROR 密钥存储错误: 未设置 MATRIX_BOT_SECRET_PASSPHRASE 环境变量
|
||
```
|
||
|
||
### `MATRIX_BOT_PASSWORD` 环境变量(仅 `login` 时需要)
|
||
|
||
仅在交互式登录时使用。可选——不设置则 `login` 提示输入密码。
|
||
|
||
---
|
||
|
||
## 命令列表
|
||
|
||
| 命令 | 别名 | 说明 |
|
||
|---|---|---|
|
||
| `!help` | `!h`, `!?` | 显示帮助 |
|
||
| `!req <关键词>` | `!request`, `!点歌`, `!来一首` | 关键词搜索(用 reactions 选) |
|
||
| `!req-url <URL>` | `!url` | 直传 URL(YouTube/B站等 yt-dlp 支持的源) |
|
||
| `!queue` | `!q`, `!队列` | 查看当前房间队列 |
|
||
| `!np` | `!nowplaying`, `!当前` | 当前正在播放 |
|
||
| `!skip` | `!next`, `!跳过` | 跳过当前播放 |
|
||
|
||
### 房间权限
|
||
|
||
- **DM**:无需 `@-mention`,直接发命令即可
|
||
- **房间**:默认需 `@-mention` bot 才会响应(可在 `[commands]` 配置关闭)
|
||
|
||
### reactions 选择流程
|
||
|
||
```
|
||
@musicbot !req 周杰伦 晴天
|
||
↓
|
||
bot: 🔍 搜索「周杰伦 晴天」找到 5 个结果,点击 emoji 选择:
|
||
1️⃣ 晴天 - 周杰伦 (3:42)
|
||
2️⃣ 晴天 (Live) - 周杰伦 (5:18)
|
||
3️⃣ 晴天 (Piano) - 周杰伦 (4:01)
|
||
4️⃣ 晴天 (Remix) - 周杰伦 (3:30)
|
||
5️⃣ 晴天故事 - 周杰伦 (4:12)
|
||
⏰ 60 秒后未选择自动取消
|
||
↓
|
||
你:点击 2️⃣(emoji 反应)
|
||
↓
|
||
bot: ✅ 已加入队列:晴天 (Live) - 周杰伦
|
||
bot: 🎵 [内嵌音频播放器] ← Element 内显示,可直接播放
|
||
```
|
||
|
||
---
|
||
|
||
## Docker 部署(推荐用于生产服务器)
|
||
|
||
仓库自带 `Dockerfile`(多阶段 Debian bookworm-slim 构建)+ `docker-compose.yml`(单服务编排)。
|
||
镜像内含 Rust 工具链、ffmpeg、yt-dlp standalone 二进制(锁版本)、tini(PID 1)。
|
||
|
||
### 快速启动
|
||
|
||
```bash
|
||
# 1. 准备配置
|
||
./target/release/matrix-music-bot.exe config init # 或在 Linux 上:./matrix-music-bot config init
|
||
# 编辑 ./config/bot.toml
|
||
|
||
# 2. 首次登录(如未在本机登录过)
|
||
./target/release/matrix-music-bot.exe login
|
||
# 或在 docker 内执行(见下方"首次登录")
|
||
|
||
# 3. 创建 .env
|
||
cp .env.example .env
|
||
# 编辑 .env,至少设置 MATRIX_BOT_SECRET_PASSPHRASE
|
||
|
||
# 4. 启动容器
|
||
docker-compose up -d --build
|
||
|
||
# 5. 查看日志
|
||
docker-compose logs -f matrix-music-bot
|
||
|
||
# 6. 停止
|
||
docker-compose down
|
||
```
|
||
|
||
### 首次登录(如果未在本机登录过)
|
||
|
||
两种方案:
|
||
|
||
**方案 A:先在主机登录,再启动容器**(推荐)
|
||
|
||
```bash
|
||
# 在 Linux 主机上 build 并登录
|
||
cargo build --release
|
||
MATRIX_BOT_SECRET_PASSPHRASE="..." ./target/release/matrix-music-bot login
|
||
# 登录成功后 data/secret.bin 与 data/crypto.db 已生成
|
||
# 启动容器时会自动用这些文件
|
||
docker-compose up -d
|
||
```
|
||
|
||
**方案 B:在容器内登录**
|
||
|
||
```bash
|
||
# 启动一次性容器执行 login
|
||
docker-compose run --rm matrix-music-bot login
|
||
# 按提示输入 homeserver / user_id / password
|
||
# 完成登录后退出,secret.bin 与 crypto.db 已写入 ./data/
|
||
docker-compose up -d
|
||
```
|
||
|
||
### Dockerfile 设计要点
|
||
|
||
- **多阶段**:builder=`rust:1.96-bookworm`(约 1.5 GB),runtime=`debian:bookworm-slim`(约 400 MB 含 ffmpeg)
|
||
- **层缓存优化**:先复制 Cargo.toml 预编译 deps,再复制 src 编译
|
||
- **strip 二进制**:runtime 镜像中减小可执行文件体积
|
||
- **非 root 运行**:`bot:bot` 用户
|
||
- **tini 作为 PID 1**:正确转发 SIGTERM/SIGINT 给 bot(避免僵尸进程)
|
||
- **健康检查**:仅检测进程存活(bot 无内置 health endpoint)
|
||
- **yt-dlp checksum 校验**:用 ADD --checksum=sha256 确保下载完整
|
||
|
||
### 镜像版本管理
|
||
|
||
```bash
|
||
# 锁定 yt-dlp 版本(构建参数)
|
||
docker-compose build --build-arg YTDLP_VERSION=2026.03.17
|
||
|
||
# 推送镜像到 registry
|
||
docker tag matrix-music-bot:latest your-registry/matrix-music-bot:v0.1.0
|
||
docker push your-registry/matrix-music-bot:v0.1.0
|
||
```
|
||
|
||
### 容器内手动调试
|
||
|
||
```bash
|
||
# 进入运行中的容器
|
||
docker-compose exec matrix-music-bot /bin/bash
|
||
|
||
# 查看版本
|
||
docker-compose exec matrix-music-bot matrix-music-bot version
|
||
|
||
# 检查 ffmpeg / yt-dlp
|
||
docker-compose exec matrix-music-bot ffmpeg -version
|
||
docker-compose exec matrix-music-bot yt-dlp --version
|
||
|
||
# 查看日志
|
||
docker-compose logs --tail=100 matrix-music-bot
|
||
```
|
||
|
||
### 常见 Docker 问题
|
||
|
||
**镜像构建失败:`failed to fetch`**
|
||
|
||
国内服务器拉取 crates.io 慢。方案:
|
||
|
||
```bash
|
||
# 在 Cargo 配置中加镜像源(项目内 .cargo/config.toml 已配 git-fetch-with-cli=true)
|
||
# 或临时设环境变量:
|
||
CARGO_NET_GIT_FETCH_WITH_CLI=true docker-compose build
|
||
```
|
||
|
||
或编辑 `~/.cargo/config.toml`(主机):
|
||
|
||
```toml
|
||
[source.crates-io]
|
||
replace-with = "rsproxy-sparse"
|
||
|
||
[source.rsproxy-sparse]
|
||
registry = "sparse+https://rsproxy.cn/index/"
|
||
```
|
||
|
||
**容器启动后立即退出**
|
||
|
||
查看日志:`docker-compose logs matrix-music-bot`。常见原因:
|
||
|
||
- `MATRIX_BOT_SECRET_PASSPHRASE` 未设置 → `Environment` 块报错退出
|
||
- `./config/bot.toml` 不存在 → 用 `config init` 生成
|
||
- `./data/` 为空且未在主机登录过 → 用方案 A 或 B 先登录
|
||
|
||
**升级 bot 后旧配置不兼容**
|
||
|
||
`data/crypto.db` 是 matrix-sdk 的 crypto store,升级 bot 版本可能导致 schema 不匹配。
|
||
如果 bot 启动后 sync 异常,删除 `data/crypto.db` 重启(需要重新在 Element 信任 bot 设备)。
|
||
|
||
---
|
||
|
||
## 故障排查
|
||
|
||
### 登录失败:`error sending request`
|
||
|
||
- 检查 `[homeserver] url` 是否正确
|
||
- 检查 bot 账户密码是否正确
|
||
- 检查 homeserver 是否能从 bot 所在服务器访问
|
||
|
||
### `linker 'gcc.exe' not found`
|
||
|
||
```bash
|
||
# 安装 MinGW gcc
|
||
winget install MSYS2.MSYS2
|
||
# 在 MSYS2 中:
|
||
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-sqlite3
|
||
```
|
||
|
||
### `cannot find -lsqlite3`
|
||
|
||
```bash
|
||
pacman -S mingw-w64-x86_64-sqlite3
|
||
```
|
||
|
||
### `ffmpeg not found`
|
||
|
||
确保 `ffmpeg.exe` 在 PATH 中,或在 `[music] ytdlp_path` 中设置绝对路径。
|
||
|
||
### `yt-dlp not found`
|
||
|
||
```bash
|
||
pip install yt-dlp
|
||
# 或下载 standalone exe 放到 PATH 中
|
||
```
|
||
|
||
### 反应选择不生效
|
||
|
||
v1 妥协:SendHandle 的 `transaction_id` 是私有的,reactions 监听使用占位 event_id,
|
||
可能匹配不到对应的搜索会话。M8 修复方向是通过 timeline 订阅事件→匹配
|
||
`transaction_id` 与真实 `event_id`。
|
||
|
||
**临时方案**:使用 `!req-url`(不走 reactions)作为可靠路径。
|
||
|
||
### `UnableToDecrypt` 警告
|
||
|
||
- bot 加入加密房间后需要几秒同步 room keys
|
||
- 检查 bot 账户的设备是否在 Element 中被信任
|
||
- 若 homeserver 不支持 MSC3967,bot 自动建立交叉签名可能失败
|
||
|
||
### CPU 占用高 / 卡顿
|
||
|
||
- 减少 `[music] search_limit`(默认 5)
|
||
- 检查 yt-dlp 是否在并发拉取(搜索时短暂占用)
|
||
|
||
---
|
||
|
||
## 开发指南
|
||
|
||
### 项目结构
|
||
|
||
```
|
||
matrix-music-bot/
|
||
├── Cargo.toml 依赖
|
||
├── .cargo/config.toml MinGW gcc 链接器配置
|
||
├── config/bot.toml 操作员配置(不进 git)
|
||
├── data/
|
||
│ ├── crypto.db matrix-sdk crypto store(Olm/Megolm)
|
||
│ ├── secret.bin AES-256-GCM 加密的 access_token
|
||
│ └── cache/opus/ 转码缓存
|
||
└── src/
|
||
├── main.rs CLI 入口 + tokio runtime
|
||
├── config.rs AppConfig 结构 + TOML 加载
|
||
├── error.rs AppError 枚举(thiserror)
|
||
├── secret_store.rs Argon2id + AES-256-GCM
|
||
├── client.rs matrix-sdk Client 构造
|
||
├── bootstrap.rs login / restore
|
||
├── commands.rs !req / !queue 等命令解析
|
||
├── event_loop.rs sync + add_event_handler + Timeline 加密通道
|
||
├── queue.rs 队列(in-memory + 去重)
|
||
├── reaction_store.rs reaction 选择存储
|
||
├── rtc_handler.rs MSC3401 call.member 状态事件
|
||
├── transcoder.rs ffmpeg 子进程 → Opus 128k
|
||
├── delivery/
|
||
│ ├── mod.rs DeliveryStrategy trait
|
||
│ ├── audio_upload.rs Pattern A(m.audio via Timeline)
|
||
│ └── url_link.rs Pattern B(v2 stub)
|
||
├── music/
|
||
│ ├── mod.rs MusicSource trait + SearchFacade
|
||
│ ├── ytdlp.rs YtDlpBackend(完整)
|
||
│ ├── netease.rs NetEaseBackend(stub)
|
||
│ ├── qq.rs QqMusicBackend(stub)
|
||
│ └── selfhosted.rs LocalFsBackend(stub)
|
||
├── downloader.rs yt-dlp 子进程下载
|
||
└── worker.rs 每房间 worker(resolve → download → transcode → upload)
|
||
```
|
||
|
||
### 重新登录(重新生成 secret.bin)
|
||
|
||
```bash
|
||
rm data/secret.bin
|
||
export MATRIX_BOT_SECRET_PASSPHRASE="..."
|
||
./target/release/matrix-music-bot.exe login
|
||
```
|
||
|
||
### 清理 crypto.db(重置 E2EE 状态)
|
||
|
||
```bash
|
||
rm data/crypto.db
|
||
# 下次启动会重新建立 crypto store
|
||
# 注意:其他客户端需要重新信任 bot 设备
|
||
```
|
||
|
||
### 运行测试
|
||
|
||
```bash
|
||
cargo test # 全部
|
||
cargo test commands # 仅 commands 模块
|
||
cargo test -- --ignored # 包含需要 yt-dlp/ffmpeg/网络的测试
|
||
```
|
||
|
||
### 添加新音乐源
|
||
|
||
实现 `MusicSource` trait 即可自动接入:
|
||
|
||
```rust
|
||
// src/music/mysource.rs
|
||
use crate::music::{MusicSource, SongCandidate, ResolvedSong};
|
||
|
||
pub struct MySource { /* ... */ }
|
||
|
||
#[async_trait]
|
||
impl MusicSource for MySource {
|
||
fn kind(&self) -> &'static str { "mysource" }
|
||
fn display_name(&self) -> &'static str { "我的音乐源" }
|
||
async fn search(&self, query: &str, limit: u8) -> Result<Vec<SongCandidate>, AppError> { /* ... */ }
|
||
async fn resolve(&self, candidate: &SongCandidate) -> Result<ResolvedSong, AppError> { /* ... */ }
|
||
}
|
||
```
|
||
|
||
在 `src/event_loop.rs::build_facade()` 中加入你的 backend。
|
||
|
||
---
|
||
|
||
## 已知限制
|
||
|
||
| 限制 | 原因 | 影响 | 计划修复 |
|
||
|---|---|---|---|
|
||
| event_id 跟踪用占位 | `SendHandle.transaction_id` 私有 | reactions 选择 v1 可能不生效 | M8: timeline subscription 匹配 |
|
||
| 队列进程重启清空 | rusqlite 与 matrix-sdk-sqlite 共享 libsqlite3-sys 冲突 | 重启后未完成的歌曲丢失 | v2:解决链接冲突后用 SqliteQueue |
|
||
| HEAD 探测未实现 | 未引入 reqwest | 上传前无法预知大小 | M5+ 加 reqwest |
|
||
| 不参与通话媒体 | v1 范围外(需要 matrix_sdk::rtc + livekit-rs) | 不能在 Element Call 中"唱歌" | v2 |
|
||
| 国内 YouTube 不稳定 | 网络限制 | 部分搜索/下载失败 | fallback 到 NetEase/QQ(M3+ 可实现) |
|
||
| 候选仅按 title+artist 去重 | 简单实现 | 不同版本可能被错误合并 | v2 加 (duration, album) 二次校验 |
|
||
|
||
---
|
||
|
||
## 路线图
|
||
|
||
### v1(已完成)
|
||
|
||
- ✅ M1 骨架 + 配置 + 加密 secret_store
|
||
- ✅ M2 命令解析 + E2EE Timeline 加密通道
|
||
- ✅ M3 MusicSource trait + yt-dlp backend
|
||
- ✅ M4 转码 + 投递
|
||
- ✅ M5 端到端(!req/!req-url/!queue/!np/!skip)
|
||
- ✅ M6 Element Call 兼容(MSC3401 状态事件)
|
||
- ✅ M7 reactions 两步选择
|
||
|
||
### v1.x(可选优化)
|
||
|
||
- ⏳ M8: event_id 跟踪修复(reactions 选择真实可用)
|
||
- ⏳ M9: NetEase / QQ 音乐 backend 完整实现
|
||
- ⏳ M10: 队列持久化(解决 libsqlite3-sys 冲突)
|
||
- ⏳ M11: Pattern B(URL 链接兜底,当文件过大时降级)
|
||
- ⏳ M12: HEAD 探测(reqwest 集成)
|
||
|
||
### v2(未来)
|
||
|
||
- 🔮 bot 作为 Element Call 参与者(matrix_sdk::rtc + livekit-rs)
|
||
- 🔮 多语言 NLP 解析(自然语言点歌)
|
||
- 🔮 用户点歌历史 + 收藏夹
|
||
- 🔮 歌单导入(网易云 / QQ 音乐)
|
||
- 🔮 投票跳过(多用户协同)
|
||
|
||
---
|
||
|
||
## 测试
|
||
|
||
```bash
|
||
cargo test # 29 passed + 4 ignored
|
||
```
|
||
|
||
测试覆盖:
|
||
|
||
- 命令解析(11 测试):DM/房间 mention、缺参、中英文别名
|
||
- TOML 配置(2):最小配置解析、示例配置往返
|
||
- secret_store(2):加密往返、错误口令拒绝
|
||
- music(4):AudioFormat 推断、serde 往返
|
||
- queue(3):入队去重、不同 source_id 不去重、skip
|
||
- reaction_store(4):emoji 解析、会话记录消费、过期清理
|
||
|
||
ignored 测试需要 yt-dlp / ffmpeg / 真实网络。
|
||
|
||
---
|
||
|
||
## 许可证
|
||
|
||
待定(项目内未声明)。
|
||
|
||
---
|
||
|
||
## 致谢
|
||
|
||
- [matrix-rust-sdk](https://github.com/matrix-org/matrix-rust-sdk) — Matrix 协议 Rust SDK
|
||
- [yt-dlp](https://github.com/yt-dlp/yt-dlp) — 通用视频/音频下载器
|
||
- [FFmpeg](https://ffmpeg.org/) — 音频转码
|
||
- [Argon2](https://github.com/P-H-C/phc-winner-argon2) — 密钥派生
|
||
- [aes-gcm](https://github.com/RustCrypto/AEADs) — 认证加密 |