ef93f9615f
新增模块:
src/queue.rs ── QueueStore(内存版)+ SongQueue trait + QueueItem/QueueState
src/downloader.rs ── yt-dlp 子进程下载到 data/cache/raw/<source>-<id>.<ext>
src/worker.rs ── 每房间 worker:resolve → download → transcode → deliver
src/event_loop.rs 改造:
- 构造 SearchFacade(包含 YtDlpBackend + 3 stub backend)
- 命令 handler 分发:
!help → render_reply + send_text
!req <q> → search_all → 自动取第一条入队(M7 接 reactions)
!req-url → 构造 candidate → 入队
!queue → 渲染队列状态
!np → 渲染当前播放
!skip → 弹出当前播放
- ensure_room_worker:首次收到消息时启动该房间 worker
- extract_video_id:支持 YouTube v= / youtu.be/ / B站 BV 号提取
src/main.rs:
- 引入 queue/downloader/worker 模块
CLAUDE.md 同步:
- 当前阶段改为 "M1-M5 已完成" + 已完成模块清单
- 列出已确认技术决策 11 条(不可变)
- 列出待办 M6-M7
E2EE 通道保持:
- 所有出站经 Timeline::send
- audio_upload.deliver() 内部仍走 TimelineBuilder + send
依赖决策(注意):
- 放弃 rusqlite(libsqlite3-sys 与 matrix-sdk-sqlite 链接冲突)
- 放弃 reqwest(用 yt-dlp 子进程下载,简化 deps)
- 队列改 in-memory(重启清空,v1 接受)
- 这两条记入 CLAUDE.md "已确认技术决策" 第 10、11 条
测试:cargo test → 24 passed + 4 ignored
新增 3 个 queue 测试:
- enqueue_and_dedup:同 song 同房间去重
- different_sources_not_dedup:不同 source_id 允许入队
- skip_current_returns_head:skip 弹出当前
5.3 KiB
5.3 KiB
Matrix 点歌机器人 - 项目协作规范
⚠️ 核心协作要求(项目全程必须遵守)
1. 技术决策流程
在整个项目开发过程中,任何关于技术方面的事情,用户无法提供具体要求,必须遵循以下流程:
- 列出方案:对于每一个技术决策点(技术选型、架构设计、实现方式、依赖库选择等),我必须主动列出 2 个或以上 的可选方案
- 解释方案:对每个方案,需要详细说明:
- 该方案的具体内容
- 优缺点
- 适用场景
- 潜在风险
- 等待决策:在用户明确选择之前,不得自行决定或默认选择任何一个方案
- 用户决定:由用户拍板决定采用哪个方案,或要求更多方案
- 记录决策:用户选定后,再开始实施
2. Git 实时提交规范
项目全程必须实时提交到 git,禁止积累大批改动后一次性提交。具体要求:
- ✅ 每个独立的逻辑单元完成后立即提交(单个文件完成、单个函数实现、单个 milestone 结束)
- ✅ 每个 milestone 结束后必须有可运行的 commit(即使只是占位实现)
- ✅ commit message 用中文,按 Conventional Commits 风格(
feat:/fix:/docs:/chore:/refactor:/test:/style:) - ✅ 每次提交前确保
cargo build或cargo check通过(避免 broken commit) - ✅ 重要决策点(用户已确认的方案)必须在 commit message 中体现
commit 粒度参考:
docs: 初始化 CLAUDE.md 项目协作规范
docs: 添加 v1 实施计划
chore: 初始化 Cargo 项目骨架与依赖
feat(bootstrap): 实现 matrix-sdk login + 恢复登录
feat(client): 构造 matrix-sdk Client(双 db 文件 + E2EE settings)
feat(event_loop): 实现 Timeline 订阅与 !help 命令
...
适用范围
上述规则适用于项目中的所有技术决策,包括但不限于:
- 编程语言版本
- 框架与依赖库选择
- 数据库 / 存储方案
- 网络通信协议
- 加密与安全方案
- 项目目录结构
- API 设计
- 部署方式
- 测试方案
- 错误处理策略
- 日志方案
- 配置文件格式
例外情况
仅以下情况可以无需列出方案直接执行:
- 用户明确指定了具体技术或方案("用 XX 库"、"按 YY 方式实现")
- 纯粹的代码 bug 修复、错别字修正等无技术分歧的微调
- 用户明确要求"直接做"或"你自己定"
项目概述
目标:开发一个运行在 Element Call 房间中的点歌机器人(Song Request Bot)
核心能力:
- 监听 Matrix 房间中的点歌指令
- 在房间内返回点歌结果(歌曲信息、播放链接等)
- 支持点歌队列管理
- 必须支持 E2EE(端到端加密)房间 —— 在加密房间中也能正常工作
技术栈基线:
- Matrix SDK:
matrix-rust-sdk0.18(用户指定) - 音乐源: yt-dlp 作为通用后端
- 运行环境:国内已有的 Matrix homeserver
当前阶段
✅ M1-M5 已完成 —— 骨架 + 配置 + 加密 secret_store + matrix-sdk 登录/恢复 + 命令解析 + E2EE Timeline 读写 + yt-dlp backend + ffmpeg 转码 + m.audio 投递 + !req/!req-url/!queue/!np/!skip 端到端
🚧 M6 准备开始 —— Element Call 房间兼容性验证(MSC3401 状态事件观测)
✅ v1 计划详见 C:\Users\Administrator\.claude\plans\lexical-meandering-lighthouse.md
已完成模块清单
| 模块 | 文件 | 状态 |
|---|---|---|
| CLI 骨架 | src/main.rs |
✅ |
| 错误类型 | src/error.rs |
✅ |
| TOML 配置 | src/config.rs |
✅ |
| 加密密钥存储 (Argon2id + AES-256-GCM) | src/secret_store.rs |
✅ |
| matrix-sdk Client 构造 | src/client.rs |
✅ |
| 登录/恢复 | src/bootstrap.rs |
✅ |
| 命令解析 | src/commands.rs |
✅ |
| Event loop + Timeline 加密通道 | src/event_loop.rs |
✅ |
| MusicSource trait + yt-dlp + 其他 stub | src/music/ |
✅ |
| ffmpeg 转码 | src/transcoder.rs |
✅ |
| m.audio 投递 | src/delivery/audio_upload.rs |
✅ |
| 队列管理(内存版) | src/queue.rs |
✅ |
| yt-dlp 下载 | src/downloader.rs |
✅ |
| 每房间 worker | src/worker.rs |
✅ |
测试:24 个单元测试 + 4 个 ignored(需要 ffmpeg/yt-dlp + 网络)
已确认的技术决策(不可变)
- Matrix SDK: matrix-sdk 0.18(matrix-sdk-crypto + matrix-sdk-ui)
- 音乐源: yt-dlp 作为通用后端
- 命令风格: 前缀
!req/!queue/!skip(房间中需 @-mention bot) - 音频编码: 立体声 Opus 128 kbit/s
- 搜索交互:
!req-url直传 + 关键词搜索(reactions 选择待 M7) - E2EE 信任: 自动首次信任(
auto_enable_cross_signing: true) - 多房间并发: 每房间独立 worker,并行
- 依赖: rustup + stable-x86_64-pc-windows-gnu + MinGW gcc(避开 VS Build Tools)
- secret.bin 加密: Argon2id (m=19456 KiB, t=2, p=1) + AES-256-GCM
- 队列: v1 内存版(重启清空;后续可改 SqliteQueue 需解决 libsqlite3-sys 冲突)
- 音频下载: yt-dlp 子进程(避免 reqwest 增加 deps)
待办(M6-M7)
- M6: Element Call 房间兼容(MSC3401 状态事件观测,确保 bot 在 call 进行中也能收发消息)
- M7: reactions 选择 +
!queue/!np/!skip完整闭环 + 队列持久化(可选)