update UI details for new stream

This commit is contained in:
2026-08-14 12:20:46 -07:00
parent acc4c117f7
commit a36d511d39
18 changed files with 424 additions and 146 deletions
+4 -2
View File
@@ -6,7 +6,8 @@
## 核心目标
- 每个账户拥有一个可切换的 Bilibili 直播间、一个 CookieCloud 来源和一条独立监听连接。
- 组件不绑定或选择直播源;账户事件流会提供给该账户所有启用的组件实例。
- 组件不绑定或选择直播源;账户事件流会提供给该账户所有启用的组件实例。同一 kind 可以拥有多个实例,每个实例独立保存名称、设置、OBS
token 和实时通道。
- 平台原始命令先转换成稳定的领域事件,组件不直接依赖 Bilibili `CMD`。
- HTTP 会话、直播源、组件、OBS token 和实时通道均以租户为边界。
- 新组件可以增加设置、投影和持久化副作用,而不修改直播连接核心。
@@ -37,7 +38,8 @@ flowchart LR
只标识账户级监听,不存储在组件行中。
4. 匹配订阅后,路由器先执行可持久化的 `EventHandler`,再执行无副作用的 `EventProjection`。
5. 投影结果只发布到该 `component_id` 的广播通道。没有全局 WebSocket 事件总线。
6. OBS 使用组件级只读 token 订阅一个组件,不能读取控制台 API。
6. OBS 使用实例级只读 token 订阅一个组件实例,不能读取控制台 API;同类型的其他实例拥有不同
`component_id`,可在不同 OBS 场景中使用不同样式。
## 状态所有权
+7 -1
View File
@@ -3,6 +3,11 @@
组件是“消费所属账户事件流的独立功能实例”。当前内建 `danmaku_overlay`、`song_request`、 `gift_effect`
与 `gift_menu`,未来礼物墙或统计组件也应使用同一套契约。
账户注册时会为每种内建 kind 创建一个初始实例。控制台可以为同一 kind 再创建多个命名实例;每个实例都有独立 settings、OBS
token、`publicId` 与 `EventHub`
channel。当前每账户每 kind 最多 16 个实例,且至少保留一个,避免误删后由启动回填产生一个意外的新地址。删除实例会级联删除它的 token 与组件专属关系数据,并立即关闭该实例的 WebSocket
channel。
## 一个组件由什么组成
| 部分 | Rust 契约 | 职责 |
@@ -28,7 +33,8 @@
- 数据库操作必须包含 owner/component 条件。
- 上游可能重试或出现组合事件,因此 handler 自己负责幂等。
6. 在 `ComponentRegistry::with_builtin_components` 注册定义与投影,再注册 handler。
7. 增加数据库创建/设置 API;不要把组件专属关系数据无限塞入 JSON settings。
7. 增加数据库创建/设置 API;初始化组件专属关系数据,并确认删除实例时可以安全级联。不要把组件专属关系数据无限塞入JSON
settings。
8. 在控制台增加设置编辑器,在 OBS 前端增加对应事件渲染器。
9. 增加以下测试:设置边界、版本迁移、订阅、跨租户拒绝、handler 幂等、投影 wire shape 和 OBS 渲染。
+1 -1
View File
@@ -1,6 +1,6 @@
# `danmaku_overlay` 弹幕姬
弹幕姬把一个租户直播源的互动事件投影为透明 OBS 消息墙。它是被动展示组件:不记账、不回复弹幕,也不把 WebSocket 当作持久化业务通道。
弹幕姬把一个租户直播源的互动事件投影为透明 OBS 消息墙。它是被动展示组件:不记账、不回复弹幕,也不把 WebSocket 当作持久化业务通道。账户注册时会创建一个初始实例;同一账户可以继续添加多个弹幕姬实例,为横屏、竖屏或其他 OBS 场景分别保存样式和 OBS 地址。所有实例共享账户直播监听,但事件投影和 WebSocket 广播仍按实例 ID 隔离。
## 订阅事件
+3 -2
View File
@@ -1,7 +1,8 @@
# 全屏礼物特效组件
`gift_effect` 是每个账户自动拥有且不可删除的单例组件。它消费账户级直播源中的 `live.gift` 和
`live.guard.buy`,使用独立只读 token 作为透明 OBS 浏览器源;不订阅
`gift_effect`
在账户注册时创建一个初始实例,并允许为不同 OBS 场景添加多个独立样式实例。每个实例消费账户级直播源中的
`live.gift` 和 `live.guard.buy`,使用自己的只读 token 作为透明 OBS 浏览器源;不订阅
`live.gift.combo`,避免一次连击重复触发完整特效。
## 展示行为
+1 -1
View File
@@ -1,7 +1,7 @@
# 礼物菜单组件
`gift_menu`
是每个账户自动拥有且不可删除的单例组件。它把直播间礼物或大航海投喂映射为主播提供的内容说明,并以独立只读 token 输出透明 OBS 浏览器源。
在账户注册时创建一个初始实例,也可以为不同 OBS 场景添加多个实例。每个实例独立保存菜单内容、样式和只读 token;它把直播间礼物或大航海投喂映射为主播提供的内容说明,并输出透明 OBS 浏览器源。
## 目录与触发器
+2 -2
View File
@@ -1,7 +1,7 @@
# `song_request` 点歌姬
每个账户自动拥有一个不可删除、不可重复创建的 `song_request`
实例,并与该账户的固定直播源绑定。组件只订阅规范化的
每个账户自动拥有一个初始 `song_request`
实例,也可以再创建同类型的命名实例。每个实例拥有独立设置、OBS 地址、队列、评分和 revision,但共享账户的固定直播监听;删除实例会同时删除该实例的队列历史。组件只订阅规范化的
`live.danmaku`;业务状态由 PostgreSQL 保存,不依赖 OBS 是否在线。
## 弹幕命令
+3
View File
@@ -43,6 +43,9 @@ log。WebSocket 建立后,客户端必须在 8 秒内发送第一帧:
`overlay.settings.snapshot` 兼容帧。token 无效、被轮换或属于其他组件时,服务端以 policy
close 结束连接。
`componentId`/`publicId` 标识组件实例,而不是组件类型。同一账户可以创建多个相同 `componentKind`
的实例;它们使用各自的设置、token 和 WebSocket 地址,客户端不能把同 kind 视为同一个订阅通道。
`language` 是组件所属账户的 locale。用户在控制台修改语言后,所有已连接组件会立即收到
`component.language.updated`,payload 为 `{ "language": "en-US" }`;新连接以认证帧为准。
+2 -1
View File
@@ -14,6 +14,7 @@ token。以下规则是实现约束,而不是可选部署建议。
- tenant 查询必须在事务中执行 `SET LOCAL app.user_id`,不能使用会泄漏到连接池的 session-level
`SET`。
- 实时广播按 `component_id` 建立独立 channel,不提供全局订阅。
- 同一 kind 的多个实例仍逐行执行 owner 归属校验;实例 token 不能订阅同账户的另一个实例。
- 路由器按事件的可信 `owner_id` 扇出,并在投影发布前再次验证 owner、账户 source 和 component ID。
## Secret 生命周期
@@ -25,7 +26,7 @@ token。以下规则是实现约束,而不是可选部署建议。
| 登录 session | HttpOnly Cookie | SHA-256 摘要 | 到期、登出或撤销 |
| CookieCloud Key/密码 | 用户提交时 | XChaCha20-Poly1305 密文 | 覆盖更新 |
| 邀请码 | 创建时显示一次 | SHA-256 摘要和前缀 | 单次消费或撤销 |
| OBS token | 创建/轮换时显示一次 | SHA-256 摘要 | 组件级轮换 |
| OBS token | 创建/轮换时显示一次 | SHA-256 摘要 | 组件实例级轮换 |
`security.data_encryption_key`
是恢复密文所必需的主密钥。它必须独立备份,但不能提交到 Git 或写入镜像。