返回 Social Auto Upload
2026-03-25-bilibili-cli-design.md
根目录 / docs / superpowers / specs / 2026-03-25-bilibili-cli-design.md
1 # Bilibili CLI 设计
2
3 日期:2026-03-25
4
5 ## 概要
6
7 这份设计要把 `bilibili` 挂到 `sau` 下面,用户侧体验尽量和现在的 `douyin`、`kuaishou` 保持一致。
8
9 核心约束只有两个:
10
11 - 用户不需要自己安装 `biliup`
12 - 外部统一走 `sau bilibili ...`
13
14 程序会把 `biliup` 当作内部运行时依赖来处理:
15
16 - `sau bilibili ...` 是唯一公开入口
17 - 本地没有 `biliup` 时自动下载
18 - 每次运行都检查 GitHub Release 最新版本
19 - 如果发现有更新,先自动更新,再继续执行当前命令
20
21 这份设计刻意保持轻量,不重新发明一套 B 站上传语义,而是直接复用仓库里现有的 B 站上传模型。
22
23 ## 目标
24
25 - 让 `sau bilibili ...` 和 `sau douyin ...`、`sau kuaishou ...` 保持统一心智
26 - 隐藏 `biliup` 的安装细节,降低用户使用成本
27 - 复用项目里已经存在的账号文件、`VideoZoneTypes`、定时发布等能力
28 - 不做过度封装
29
30 ## 非目标
31
32 - 第一版不把 `biliup` 二进制直接提交进仓库
33 - 第一版不维护本地 release manifest
34 - 第一版不做 B 站图文发布
35 - 第一版不重做现有的 B 站上传领域模型
36
37 ## 当前项目基础
38
39 仓库里已经有 B 站上传能力:
40
41 - `uploader/bilibili_uploader/main.py` 目前直接封装了 `biliup.plugins.bili_webup`
42 - `examples/upload_video_to_bilibili.py` 已经在使用现有上传参数
43 - `utils/constant.py` 已经定义了完整的 `VideoZoneTypes`
44
45 也就是说,你现在项目里的 B 站上传语义已经很明确,核心就是:
46
47 - `file`
48 - `title`
49 - `desc`
50 - `tid`
51 - `tags`
52 - `dtime`
53
54 所以第一版 CLI 不需要重新造模型,直接沿用这套。
55
56 ## 用户侧 CLI 设计
57
58 ### 支持的命令
59
60 - `sau bilibili login`
61 - `sau bilibili check`
62 - `sau bilibili upload-video`
63
64 ### 命令契约
65
66 #### `sau bilibili login`
67
68 作用:
69
70 - 自动准备 `biliup`
71 - 如果有更新则先升级
72 - 然后调用 `biliup` 完成登录
73 - 将账号数据按项目自己的账号文件规则保存下来
74
75 第一版行为:
76
77 - 本地没有 `biliup` 时自动下载最新 release
78 - 本地已有但上游有更新时自动升级
79 - 升级完成后继续执行登录流程
80
81 #### `sau bilibili check`
82
83 作用:
84
85 - 自动准备 `biliup`
86 - 检查当前账号是否可用
87
88 第一版行为:
89
90 - 结合本地账号文件存在性和 `biliup` 实际可用性来判断
91 - 输出风格和其他平台保持一致:
92 - `valid`
93 - `invalid`
94
95 #### `sau bilibili upload-video`
96
97 作用:
98
99 - 自动准备 `biliup`
100 - 走项目当前已有的 B 站上传参数体系完成视频上传
101
102 第一版参数:
103
104 - `--account` 必填
105 - `--file` 必填
106 - `--title` 必填
107 - `--desc` 必填
108 - `--tid` 必填
109 - `--tags` 选填
110 - `--schedule` 选填
111
112 明确决定:
113
114 - `tid` 在第一版里必须传
115 - 不给默认分区,避免猜测和隐式错误
116
117 ## 运行时依赖策略
118
119 ### 选定方案
120
121 `biliup` 不提交进仓库,也不要求用户手工安装。
122
123 `sau bilibili ...` 在运行时自动处理它:
124
125 1. 查找本地是否已有 `biliup`
126 2. 检查 GitHub Release 最新版本
127 3. 如果缺失或过期,则自动下载最新版本
128 4. 替换本地运行时副本
129 5. 继续执行本次命令
130
131 ### 选择这个方案的原因
132
133 - 仓库体积更干净
134 - 用户不需要自己找 release、自己下载
135 - 对外仍然只有一个统一入口 `sau`
136 - 不需要使用 `git submodule`
137
138 ### 接受的代价
139
140 这套方案明确接受一个现实:
141
142 - 每次运行都会检查上游 release
143 - 上游如果改 CLI 行为,可能会影响这层适配
144
145 所以这里的应对方式不是做重封装,而是保持 wrapper 很薄,减少被动维护成本。
146
147 ## 存储与解析
148
149 `biliup` 应该存放在本地运行时缓存目录中,而不是源码目录中。
150
151 缓存目录只需要满足:
152
153 - 当前用户可写
154 - 可跨命令复用
155 - 不进入 git 管理
156
157 解析器的职责应当是:
158
159 - 识别当前操作系统
160 - 选择对应平台的 release asset
161 - 下载并替换可执行文件
162 - 返回最终可执行路径
163
164 ## 轻量封装边界
165
166 为了避免过度封装,第一版只建议拆成 3 个很薄的部分。
167
168 ### 1. Resolver
169
170 职责:
171
172 - 判断本地是否已有 `biliup`
173 - 检查 GitHub Release 最新版本
174 - 下载或更新可执行文件
175 - 返回最终可执行文件路径
176
177 ### 2. Runner
178
179 职责:
180
181 - 调用解析出来的 `biliup`
182 - 收集退出码、标准输出、标准错误
183 - 对明显的进程级错误做一层项目内友好的报错转换
184
185 ### 3. `sau_cli.py` 中的 bilibili 子命令
186
187 职责:
188
189 - 解析 `sau bilibili ...` 参数
190 - 把这些参数翻译成底层运行逻辑
191 - 让帮助信息风格和其他平台一致
192
193 第一版不需要更多层,也不需要再抽一套很重的统一框架。
194
195 ## 与现有项目概念的映射
196
197 ### 账号文件
198
199 B 站也继续沿用现在项目的账号别名机制:
200
201 - 用户传 `--account <name>`
202 - 程序解析成对应的账号文件路径
203
204 ### 分区
205
206 `tid` 保持为一等参数。
207
208 `VideoZoneTypes` 继续保留并服务于:
209
210 - example
211 - 文档
212 - 后续可能的辅助工具
213
214 ### 定时发布
215
216 `--schedule` 保持和当前 `sau` 其他平台一致的使用方式:
217
218 - 不传就是立即发布
219 - 传了就是定时发布
220
221 具体如何映射到底层 B 站执行逻辑,由 adapter 负责,不暴露给用户。
222
223 ## 错误处理
224
225 第一版错误处理保持直接,不做花哨包装:
226
227 - 下载失败:明确告诉用户自动下载 `biliup` 失败
228 - 更新失败:明确告诉用户最新 release 准备失败
229 - 登录失败:保留 `biliup` 登录失败上下文
230 - 检查失败:输出 `invalid`
231 - 上传失败:返回非零退出码,并展示上游错误摘要
232
233 第一版不追求把所有 `biliup` 错误文本都重新翻译一遍。
234
235 ## 文档影响范围
236
237 实现完成后,至少需要补齐这些地方:
238
239 - `README.md`
240 - `docs/CLI.md`
241 - 安装与更新文档
242 - 一套对应的 Bilibili skill
243 - Bilibili example 脚本
244
245 对外表达应当统一成:
246
247 - 用户使用的是 `sau bilibili ...`
248 - `biliup` 由程序自动准备
249
250 ## 测试策略
251
252 第一版最少需要验证这些路径:
253
254 - `sau bilibili login --account <name>`
255 - `sau bilibili check --account <name>`
256 - `sau bilibili upload-video ...`
257 - 本地没有 `biliup` 时能自动下载
258 - 本地已有旧版本时能先升级再执行
259 - 本地已有最新版本时能直接复用
260
261 因为登录和上传涉及真实外部平台,第一版以手工验证为主是可以接受的。
262
263 ## 推荐实现顺序
264
265 1. 在 `sau_cli.py` 中加入 `bilibili` 子命令
266 2. 增加一个最小可用的 `biliup` resolver
267 3. 增加一个最小可用的 `biliup` runner
268 4. 接上 `login / check / upload-video`
269 5. 补文档、example、skill
270
271 ## 最终结论
272
273 - 对外入口固定为 `sau bilibili ...`
274 - 第一版支持 `login`、`check`、`upload-video`
275 - `tid` 必填
276 - `biliup` 不需要用户手动安装
277 - 每次运行都检查 GitHub Release
278 - 有新版本时先自动更新,再继续执行
279 - 整体实现保持轻量,不做过度封装
280
280 lines MARKDOWN