docs: decouple favorites, manual ingest, write-for-sort-only
This commit is contained in:
1 parent
6c4287b43a
commit
0d6e62f9ee
5 files changed
+197
-206
No files matched your search
+77
-78
@@ -1,6 +1,6 @@
|
||||
# 咻咻满 Reaction 视频数据看板开发文档
|
||||
|
||||
> **状态:** P0(数据底座与收藏夹同步)、P1(每日快照与粉丝追踪)、P2(只读本地看板)、P3(Telegram 与一键加入)已实施
|
||||
> **状态:** P0(数据底座与手动入库)、P1(每日快照与粉丝追踪)、P2(只读本地看板)、P3(Telegram 发现与入库)已实施;项目已与 B 站收藏夹解耦
|
||||
>
|
||||
> **技术基线:** Python 3.14、Python 标准库、SQLite、原生 HTML/CSS/JavaScript、`uv`
|
||||
>
|
||||
@@ -89,10 +89,11 @@ uv run python tests/test_moves.py
|
||||
# 建库、迁移与黑名单种子(离线,P0)
|
||||
uv run python app.py init
|
||||
|
||||
# 收藏夹只读同步/首次导入(P0)
|
||||
uv run python app.py sync
|
||||
# 手动入库:视频链接、BV 号、av 号或 b23.tv 短链(只写本地库)
|
||||
uv run python app.py ingest BV1x8x166EzY
|
||||
uv run python app.py ingest https://www.bilibili.com/video/BV1x8x166EzY
|
||||
|
||||
# 按配置周期常驻同步(P0);--once 只跑一次
|
||||
# 按配置周期常驻运行发现与快照(P0/P3);--once 只跑一次
|
||||
uv run python app.py run
|
||||
uv run python app.py run --once
|
||||
|
||||
@@ -104,9 +105,6 @@ uv run python app.py snapshot --force
|
||||
uv run python app.py backfill-followers
|
||||
uv run python app.py backfill-followers --dry-run
|
||||
|
||||
# 全量同步默认会在结尾采集缺失粉丝数;可用 --no-capture-followers 跳过
|
||||
uv run python app.py sync --full --no-capture-followers
|
||||
|
||||
# 检查 Cookie 登录态(P1)
|
||||
uv run python app.py auth-check
|
||||
|
||||
@@ -171,7 +169,7 @@ uv sync --all-groups
|
||||
│ 单一 Python 进程 │
|
||||
│ │
|
||||
│ Web 线程:ThreadingHTTPServer :8080 │
|
||||
│ 调度线程:发现 / 收藏夹同步 / 快照 / 清理 │
|
||||
│ 调度线程:发现 / 快照 / 清理 │
|
||||
│ Telegram:getUpdates long polling │
|
||||
│ 写入线程:SQLite 单写队列 │
|
||||
│ │
|
||||
@@ -186,7 +184,7 @@ uv sync --all-groups
|
||||
- 所有 SQLite 写操作经单写队列串行执行,避免 `database is locked`;
|
||||
- 读操作使用短生命周期连接;
|
||||
- 网络请求期间不得持有数据库写事务;
|
||||
- 收藏操作通过 `fav_action` 状态锁保证幂等;
|
||||
- 入库操作通过 `video` 存在性判断保证幂等;
|
||||
- SQLite 启用 WAL、外键和合理的 busy timeout。
|
||||
|
||||
```sql
|
||||
@@ -219,11 +217,11 @@ PRAGMA synchronous = NORMAL;
|
||||
│ ├── scheduler.py # 内置任务调度
|
||||
│ ├── logging_json.py # 脱敏 JSON 日志
|
||||
│ ├── classify.py # 标题归一化、时长解析与打分
|
||||
│ ├── fav_position.py # 新视频插入位置计算
|
||||
│ ├── video_ref.py # BV/av/URL/b23.tv 引用解析(纯函数)
|
||||
│ ├── timeutil.py # 上海时区与每日时间
|
||||
│ ├── bilibili/
|
||||
│ │ ├── client.py # 只读 HTTP、重试与限速
|
||||
│ │ ├── write_client.py # deal / sort 写客户端
|
||||
│ │ ├── client.py # 只读 HTTP、重试与限速(含 view 详情、短链解析)
|
||||
│ │ ├── write_client.py # sort 写客户端(仅收藏夹重排序)
|
||||
│ │ ├── search.py # WBI 搜索与旧接口降级
|
||||
│ │ ├── provider.py # 凭据变化重建客户端
|
||||
│ │ ├── auth.py # Cookie、设备指纹与请求头工具
|
||||
@@ -231,9 +229,8 @@ PRAGMA synchronous = NORMAL;
|
||||
│ │ └── models.py # 接口响应模型
|
||||
│ ├── services/
|
||||
│ │ ├── discovery.py # 搜索发现与候选池
|
||||
│ │ ├── favorites.py # 收藏 / 忽略 / 拉黑
|
||||
│ │ ├── telegram_poller.py # getUpdates 与回调分发
|
||||
│ │ ├── folder_sync.py
|
||||
│ │ ├── library.py # 入库(候选/手动)/ 忽略 / 拉黑
|
||||
│ │ ├── telegram_poller.py # getUpdates、回调分发与私聊手动入库
|
||||
│ │ ├── snapshot.py
|
||||
│ │ ├── up_profile.py # UP 粉丝快照采集与历史回填
|
||||
│ │ └── maintenance.py
|
||||
@@ -292,8 +289,6 @@ PRAGMA synchronous = NORMAL;
|
||||
"up_blacklist_seed": [261052419, 1908537643, 1701121088, 542262],
|
||||
"schedule": {
|
||||
"discover_minutes": 60,
|
||||
"folder_sync_minutes": 60,
|
||||
"full_folder_refresh_hours": 6,
|
||||
"snapshot_at": "00:01",
|
||||
"candidate_ttl_days": 7
|
||||
},
|
||||
@@ -301,17 +296,17 @@ PRAGMA synchronous = NORMAL;
|
||||
}
|
||||
```
|
||||
|
||||
- `folders` 中的年度夹由人工创建,系统只读;
|
||||
- `folders` 仅作为历史来源与 `favsort.py` 重排序目标,系统不再自动同步或建夹;
|
||||
- 配置必须为 `bilibili.read` / `bilibili.write` 双账号结构;不兼容顶层扁平 `mid` / `csrf` / `cookie`;
|
||||
- P0 已实现的命令行:`python app.py init`、`python app.py sync [--full]`、`python app.py status`。
|
||||
- P0/P3 已实现的命令行:`python app.py init`、`python app.py ingest`、`python app.py status`、`python app.py run`。
|
||||
|
||||
### 5.2 安全规则- Windows 本地开发时应限制 `config.json` 的文件访问权限;部署到 Linux 时权限必须为 `600`;
|
||||
- 配置文件每 60 秒检查一次 mtime,凭据、收藏夹、分类规则和权重变更后无需重启;
|
||||
- 配置文件每 60 秒检查一次 mtime,凭据、分类规则和权重变更后无需重启;
|
||||
- Cookie / CSRF 变化时由 `ClientProvider` 重建 B 站请求客户端,并保留该角色的限速与重试策略;
|
||||
- `schedule.folder_sync_minutes` 与 `schedule.snapshot_at` 在启动时固化,修改后需重启 `run`;
|
||||
- `schedule.discover_minutes` 与 `schedule.snapshot_at` 在启动时固化,修改后需重启 `run`;
|
||||
- Telegram 操作必须同时验证 `from.id` 和 `chat.id` 是否为配置的私聊用户;
|
||||
- 仅允许环境变量临时覆盖敏感配置,不能将真实凭据硬编码进源代码;
|
||||
- `GET` 路由绝不进行收藏、忽略、拉黑等写操作。
|
||||
- `GET` 路由绝不进行入库、忽略、拉黑等写操作。
|
||||
|
||||
---
|
||||
|
||||
@@ -322,12 +317,11 @@ PRAGMA synchronous = NORMAL;
|
||||
| 表 | 状态 | 含义 | 是否参与每日快照 |
|
||||
|---|---|---|---|
|
||||
| `video` | `active` | 在库追踪的视频 | 是 |
|
||||
| `video` | `unfaved` | 已从收藏夹移除,但保留历史追踪 | 是 |
|
||||
| `video` | `unfaved` | 历史遗留状态(迁移 v5 已归一为 `active`) | 是 |
|
||||
| `video` | `removed` | 视频失效、删除或不可访问 | 否 |
|
||||
| `video` | `dropped` | 在看板中手动移出库 | 否 |
|
||||
| `video` | `dropped` | 手动移出库;再次入库会恢复 `active` | 否 |
|
||||
| `candidate` | `NULL` | 待人工决策 | 否 |
|
||||
| `candidate` | `rejected` | 已忽略 | 否 |
|
||||
| `candidate` | `blacklisted` | 所属 UP 已拉黑 | 否 |
|
||||
| `candidate` | `rejected` | 已忽略 / 所属 UP 已拉黑 | 否 |
|
||||
|
||||
### 6.2 建表原则
|
||||
|
||||
@@ -335,12 +329,11 @@ PRAGMA synchronous = NORMAL;
|
||||
|
||||
- `snapshot` 主键为 `(stat_date, aid)`,保证同日幂等;
|
||||
- `up_stat` 主键为 `(stat_date, mid)`;
|
||||
- `folder_resource(media_id, aid)` 记录每个收藏夹实际拥有的资源,不能仅依赖 `video.folder_id`;
|
||||
- `folder_resource.fav_time` 记录该视频在该夹的加入时间,用于跨夹主归属选择;
|
||||
- `video.folder_id` 表示视频的主归属夹,按有效收藏关系重算,不依赖收藏夹遍历顺序;
|
||||
- `up_blacklist` 只在发现任务中生效,收藏夹同步不得用它过滤既有视频;
|
||||
- `folder` / `folder_resource` 保留为历史数据与重排序参考,**不再由服务写入**;
|
||||
- `up_blacklist` 只在发现任务中生效,不影响已入库视频;
|
||||
- `seen_aid` 永久保留搜索去重标记,候选过期删除后也不重复通知;
|
||||
- `fav_action` 保存 Telegram 或签名链接的动作状态,防止重复点击造成重复写入。
|
||||
- `fav_action` 保留为通用动作状态表(当前入库幂等由 `video` 存在性判断承担);
|
||||
- 迁移 v5 把历史 `unfaved` 行归一为 `active`;表结构不做破坏式删除。
|
||||
|
||||
### 6.3 迁移规范
|
||||
|
||||
@@ -360,13 +353,13 @@ PRAGMA synchronous = NORMAL;
|
||||
|---|---|---|
|
||||
| 发现 | `x/web-interface/wbi/search/type` | 每小时搜索候选 |
|
||||
| 搜索降级 | `x/web-interface/search/type` | WBI 搜索失败时使用 |
|
||||
| 收藏夹 ID | `x/v3/fav/resource/ids` | 计算新增和移除差集 |
|
||||
| 收藏夹详情 | `x/v3/fav/resource/infos` | 元数据同步、失效识别 |
|
||||
| 视频统计 | `x/web-interface/view?aid=` | 日更七项指标的唯一事实来源 |
|
||||
| 粉丝数 | `x/relation/stat?vmid=` | 每日粉丝快照 |
|
||||
| 收藏夹列表 | `x/v3/fav/folder/created/list-all` | 容量监控 |
|
||||
| 加入收藏 | `x/v3/fav/resource/deal` | 确认候选后收藏 |
|
||||
| 收藏夹排序 | `x/v3/fav/resource/sort` | 定位至同 UP 分组 |
|
||||
| 视频详情 | `x/web-interface/view?aid=` / `?bvid=` | 快照七项指标、手动入库元数据 |
|
||||
| 短链解析 | `b23.tv/<token>` | 跟随重定向还原为视频 URL |
|
||||
| 粉丝数 | `x/relation/stat?vmid=` | 每日粉丝快照 / 入库时粉丝数 |
|
||||
| 收藏夹 ID | `x/v3/fav/resource/ids` | `favsort.py` 重排序计划 |
|
||||
| 收藏夹详情 | `x/v3/fav/resource/infos` | `favsort.py` 重排序计划 |
|
||||
| 收藏夹列表 | `x/v3/fav/folder/created/list-all` | 列出重排序目标夹 |
|
||||
| 收藏夹排序 | `x/v3/fav/resource/sort` | 收藏夹重排序(唯一写操作) |
|
||||
|
||||
B 站请求统一使用 `httpx` 连接池,并按 `data/raw-request.txt` 对齐浏览器特征:
|
||||
|
||||
@@ -421,21 +414,17 @@ P3 实现说明:
|
||||
- 关键词、页数和时间窗由 `discover` 配置控制;
|
||||
- 同一 aid 在多个关键词/页重复出现时,候选与通知都按 aid 去重;
|
||||
- 已通知但未决策的候选不会重复通知;未通知的候选会在后续发现轮次补发;
|
||||
- 人工把候选加入收藏夹后,收藏夹同步会入库并删除同 aid 候选。
|
||||
- 候选确认入库后会删除同 aid 候选;私聊手动入库也可直接创建视频行。
|
||||
|
||||
### 7.3 收藏夹同步
|
||||
### 7.3 收藏夹解耦
|
||||
|
||||
每小时对所有已配置年度夹执行:
|
||||
项目**不再轮询收藏夹**,也不再根据收藏夹内容标记视频入库/出库:
|
||||
|
||||
1. 请求 `resource/ids` 获取远端 aid 集合;
|
||||
2. 与 `folder_resource` 的有效本地集合做差集;
|
||||
3. 对新增 aid 每 200 条请求 `resource/infos` 并入库;
|
||||
4. 对移除 aid 标记对应 `folder_resource.active=0`;若视频不在任何配置夹中,视频状态改为 `unfaved`;
|
||||
5. 每 6 小时全量刷新 infos,刷新元数据、`attr` 和收藏夹容量;
|
||||
6. `attr=9` 或请求集合中静默缺失的资源改为 `removed`;
|
||||
7. 容量达到 950 条时发送预警;系统绝不自动换夹。
|
||||
|
||||
`infos` 只能作为元数据和失效同步来源。它缺少点赞、投币、转发,且评论字段不可靠,不能替代 `view` 日更。
|
||||
- 不再调用 `x/v3/fav/resource/ids` / `infos` 做差集同步;
|
||||
- 历史 `folder` / `folder_resource` / `video.folder_id` 数据保留,仅供历史展示与 `favsort.py` 重排序参考;
|
||||
- 迁移 v5 把历史 `unfaved` 状态归一为 `active`;
|
||||
- 收藏夹由人工维护;需要时用 `favsort.py`(唯一使用 `bilibili.write`)做低频重排序;
|
||||
- 入库只依赖只读接口(`view` / `relation/stat`)。
|
||||
|
||||
### 7.4 每日快照与粉丝采集
|
||||
|
||||
@@ -466,45 +455,42 @@ P1 实现说明:
|
||||
|
||||
---
|
||||
|
||||
## 8. Telegram 与收藏操作
|
||||
## 8. Telegram 与入库操作
|
||||
|
||||
### 8.1 通知动作
|
||||
|
||||
候选通知提供:
|
||||
|
||||
- **收藏**:加入目标收藏夹并入库;
|
||||
- **入库**:写入本地 `video(status='active')` 并补当天快照,**不写 B 站收藏夹**;
|
||||
- **忽略**:候选标记 `rejected`,不再通知;
|
||||
- **拉黑**:写入 `up_blacklist`,同时拒绝该 UP 的其他待决策候选;
|
||||
- **打开视频**:外链到 B 站视频页。
|
||||
|
||||
拉黑只影响未来搜索发现;不清理、不停止追踪已有视频,也不影响从收藏夹同步进来的视频。
|
||||
私聊文本消息还会被解析为视频引用(链接 / BV 号 / av 号 / `b23.tv` 短链)并逐条入库。拉黑只影响未来搜索发现;不清理、不停止追踪已有视频。
|
||||
|
||||
### 8.2 幂等与失败处理
|
||||
|
||||
Telegram `callback_data` 只包含短操作 ID,例如 `fav:<id>`;真实 aid、目标夹、过期时间和状态保存在 `fav_action` 表。
|
||||
Telegram `callback_data` 只包含短操作 ID,例如 `add:<aid>` / `ign:<aid>` / `blk:<aid>`;`fav:<aid>` 为旧按钮兼容。
|
||||
|
||||
收藏流程:
|
||||
入库流程:
|
||||
|
||||
1. 将动作从 `pending` 原子切换为 `processing`;
|
||||
2. 先读取目标夹 ids,若视频已存在则按成功处理;
|
||||
3. 按“同 UP 最早视频所在夹优先,否则当年夹”的规则选择目标夹;
|
||||
4. 调用 `deal` 加入收藏;
|
||||
5. 调用 `sort` 将视频放进同 UP 连续分组;
|
||||
6. 回读 ids 校验最终位置;
|
||||
7. 成功:动作标记 `done`,视频标记 `active`,删除候选;
|
||||
8. 失败:动作标记 `failed`,保留候选与原始错误,允许用户重试。
|
||||
1. 候选存在校验;若视频已在库则返回「已在库」;
|
||||
2. 用只读客户端取一次 `view` 详情(失败时回退候选元数据);
|
||||
3. 写 `video(status='active')`,删除同 aid 候选;
|
||||
4. 用取到的 `view` 数据写一条当天快照(同日已有成功记录则跳过);
|
||||
5. 采集该 UP 当前粉丝数并提升缓存版本。
|
||||
|
||||
私聊手动入库按消息中的每个引用重复上述步骤,错误逐条隔离,不中断其余引用。
|
||||
|
||||
GET 页面或链接预览只能展示信息,绝不能触发任何写操作。
|
||||
|
||||
P3 实现说明:
|
||||
|
||||
- `callback_data` 使用 `fav:<aid>` / `ign:<aid>` / `blk:<aid>`,真实状态存 `fav_action`;
|
||||
- `begin_fav_action` 把 `pending/failed` 原子切换为 `processing`;并发点击返回 `busy`;
|
||||
- 已在目标夹时直接成功,不重复 `deal`;
|
||||
- 目标夹优先同 UP 在库最早视频所在夹,其次当前自然年夹,最后最新年度夹;
|
||||
- 插入位置由 `fav_position.plan_insertion` 计算;组头需要两次 `sort`;
|
||||
- `deal` 或 `sort` 失败写 `fav_action.state='failed'`,保留候选,用户可再次点击重试;
|
||||
- Telegram 只接受 `chat_id` 与 `from.id` 都等于配置私聊用户的回调。
|
||||
- `callback_data` 使用 `add:<aid>` / `ign:<aid>` / `blk:<aid>`(`fav:` 兼容旧消息);
|
||||
- 入库只写本地库;`video` 的 `removed` / `dropped` / `unfaved` 状态会被重新激活;
|
||||
- 引用解析是纯函数 `video_ref.extract_video_refs`,`b23.tv` 短链由 `bilibili.client.resolve_short_link` 跟随跳转;
|
||||
- 手动入库不做「标题含咻咻满」等规则校验;单条消息的引用数量有上限;
|
||||
- Telegram 只接受 `chat_id` 与 `from.id` 都等于配置私聊用户的回调与消息。
|
||||
|
||||
---
|
||||
|
||||
@@ -513,16 +499,16 @@ P3 实现说明:
|
||||
### 9.1 API 原则
|
||||
|
||||
- P2 看板**只读**:业务接口只注册 GET,写方法统一返回 `405`;
|
||||
- 数据管理(收藏、忽略、拉黑、移出库、移除黑名单)继续通过 Telegram、CLI 或数据库完成;
|
||||
- 数据管理(入库、忽略、拉黑、移出库、移除黑名单)继续通过 Telegram、CLI 或数据库完成;
|
||||
- `/api/health` 和 `/api/session` 可匿名;
|
||||
- 首页、榜单、视频/UP、粉丝页面和接口访客可见;
|
||||
- 配置 `web.auth_token` 后,`/api/candidates`、`/api/system` 和 `/candidates`、`/system` 页面要求 Cookie 或 `Authorization: Bearer <token>`,未登录访问页面会跳转 `/login?next=<原路径>`;
|
||||
- 未配置 token 时视为无鉴权,全部页面可见;
|
||||
- 只读接口不需要 CSRF;登录 POST 只建立会话,不修改业务数据;
|
||||
- API 返回 JSON;前端不复制热度、状态机或收藏夹归属判断;
|
||||
- API 返回 JSON;前端不复制热度或状态机判断;
|
||||
- 不提供导出接口,结果只通过页面浏览;
|
||||
- 首页、榜单和粉丝的聚合结果使用内存 TTL 缓存:首页/榜单 1 小时,粉丝 24 小时;
|
||||
- 缓存版本存放在 `kv`(`cache:v:videos` / `cache:v:fans`);快照、收藏夹同步、发现、收藏/忽略/拉黑、候选清理和粉丝 CSV 导入都会提升对应版本,使缓存立刻失效。
|
||||
- 缓存版本存放在 `kv`(`cache:v:videos` / `cache:v:fans`);快照、发现、入库/忽略/拉黑、候选清理和粉丝 CSV 导入都会提升对应版本,使缓存立刻失效。
|
||||
|
||||
核心接口:
|
||||
|
||||
@@ -633,13 +619,14 @@ uv run python tests/test_moves.py
|
||||
新增模块至少覆盖:
|
||||
|
||||
- 标题归一化、时长解析、分类打分;
|
||||
- 视频引用解析(BV/av/URL/`b23.tv` 短链)与 `view?bvid=` 契约;
|
||||
- 黑名单只影响发现;
|
||||
- `infos` 静默缺失资源的识别;
|
||||
- `active`、`unfaved`、`removed`、`dropped` 状态迁移;
|
||||
- 数据库迁移与幂等写入;
|
||||
- 每日快照缺失处理;
|
||||
- 热度、增长和互动率计算;
|
||||
- 收藏夹目标选择与排序锚点;
|
||||
- 入库动作(候选确认 / 手动)与幂等;
|
||||
- `fav_action` 的重复点击、失败重试和过期处理;
|
||||
- Telegram 用户与 chat ID 授权校验;
|
||||
- 看板查询的筛选、分页、增长冷启动与状态过滤;
|
||||
@@ -655,7 +642,7 @@ uv run python tests/test_moves.py
|
||||
|
||||
## 12. 实施阶段
|
||||
|
||||
### P0:数据底座与收藏夹同步 ✅
|
||||
### P0:数据底座与收藏夹同步 ✅(收藏夹同步已于第 10 轮移除)
|
||||
|
||||
- SQLite 迁移、配置加载、B 站只读客户端;
|
||||
- 收藏夹首次导入与每小时差集同步;
|
||||
@@ -682,7 +669,7 @@ uv run python tests/test_moves.py
|
||||
|
||||
- 已实现 `services/snapshot.py`:`view` 七项指标、`relation/stat` 粉丝数、`ok=0` 失败占位、`ok=1` 断点跳过;
|
||||
- 实测不可访问视频返回 `62012`,已和旧口径 `-404`、`62002` 一起按 `removed` 处理;
|
||||
- `run` 调度器同时注册收藏夹同步与每日 `snapshot_at` 任务,启动时立即检查当日是否完成以支持补跑;
|
||||
- `run` 调度器注册每日 `snapshot_at` 任务,启动时立即检查当日是否完成以支持补跑(早期同时注册收藏夹同步,已于第 10 轮移除);
|
||||
- 每次快照后生成日备份并清理超过 14 天的日备份;
|
||||
- `auth-check` 与快照启动时检查 Cookie 登录态,失效写 `kv` 并告警;
|
||||
- 真实全量联调:795 条视频全部 `ok=1`,0 失败、0 移除,耗时 1124 秒;粉丝 `follower=2767270`;日备份 `data/backup/app-20261031.db` 含 795 条快照;二次执行正确命中完成标记并跳过;
|
||||
@@ -737,7 +724,7 @@ uv run python tests/test_moves.py
|
||||
### 第 9 轮:时长效率榜、粉丝快照与导航拆分 ✅(2026-11-01)
|
||||
|
||||
- 迁移 v4:`video.pages`、`video.up_follower` / `up_follower_at` / `up_follower_backfilled`、`up_profile`;
|
||||
- 收藏夹同步结束时采集缺失 UP 的粉丝数(`relation/stat`,匿名可用);`first_seen >= 运行开始 - 1h` 记为实时,更早的记为回填;`sync --no-capture-followers` 可跳过;
|
||||
- 收藏夹同步(已于第 10 轮移除)结束时采集缺失 UP 的粉丝数(`relation/stat`,匿名可用);`first_seen >= 运行开始 - 1h` 记为实时,更早的记为回填;第 10 轮起改为「入库时」采集;
|
||||
- 粉丝采集对每条 `relation/stat` 加 45s 硬超时看门狗(防 DNS/传输层挂起),每 25 条输出 `up_profile.progress` 进度;单条失败不阻塞整批;
|
||||
- `app.py backfill-followers`:一次性回填历史视频粉丝数,支持 `--limit` / `--dry-run`;
|
||||
- 新增内容效率/互动效率榜与 UP 内容效率(Gamma–Poisson EB 收缩),过滤 < 600 秒与未满 2 天的视频;
|
||||
@@ -748,6 +735,18 @@ uv run python tests/test_moves.py
|
||||
- 本地只保留可再生的预览库 `data/preview/app.db`;
|
||||
- 自动化测试新增 `tests/test_up_profile.py`,并扩展 `test_analytics.py`、`test_repository.py`、`test_config.py`、`test_folder_sync.py`、`test_web_queries.py`、`test_web_server.py`、`test_migrations.py`、`test_database.py`、`test_cli.py`。
|
||||
|
||||
### 第 10 轮:收藏夹解耦、手动入库与写鉴权收口 ✅(2026-11-01)
|
||||
|
||||
- **入库只写本地库**:候选确认不再调用 `deal` / `sort` 写收藏夹,改为写 `video(status='active')` 并补当天快照;
|
||||
- **移除收藏夹追踪**:删除 `services/folder_sync.py`、`FavoriteActionService`、`app.py sync` 与调度中的 `folder_sync` 任务;`folder` / `folder_resource` / `video.folder_id` 仅保留为历史数据;
|
||||
- **迁移 v5**:把历史 `unfaved` 状态归一为 `active`(不再有「取消收藏」语义);
|
||||
- **手动入库**:新增 `video_ref.py` 纯函数解析 BV/av/URL/`b23.tv` 短链;`bilibili/client.py` 新增 `view?bvid=` 详情与短链跳转;`services/library.py` 统一候选/手动入库;
|
||||
- **Telegram**:`get_updates` 订阅 `callback_query` + `message`;私聊文本消息自动解析并入库;按钮改为「入库 / 忽略 / 拉黑」(`add:`,兼容旧 `fav:`);
|
||||
- **写鉴权收口**:删除 `write_client.deal`,`bilibili.write` 仅用于 `favsort.py` 收藏夹重排序;
|
||||
- **配置**:移除 `schedule.folder_sync_minutes` / `full_folder_refresh_hours`;`folders` 语义变为历史来源与重排序目标;
|
||||
- 看板:系统页与首页把「收藏夹同步/容量」改为「历史收藏夹」;候选页文案改为「入库」。
|
||||
- 自动化测试:新增 `tests/test_video_ref.py`、`tests/test_library.py`,重写 `test_telegram.py`,删除 `test_folder_sync.py` / `test_fav_position.py` / `test_favorites.py`,并更新 `test_bilibili_client.py`、`test_cli.py`、`test_migrations.py`、`test_database.py`、`test_web_queries.py`、`test_web_server.py`、`web_fixtures.py`。
|
||||
|
||||
### P4:可选部署
|
||||
|
||||
- 反向代理、TLS、远程访问鉴权;
|
||||
@@ -761,7 +760,7 @@ uv run python tests/test_moves.py
|
||||
第一期不实现:
|
||||
|
||||
- 多用户、注册、角色权限;
|
||||
- 自动创建收藏夹或容量满后自动换夹;
|
||||
- 自动创建收藏夹、自动加入收藏夹或容量满后自动换夹;
|
||||
- AI 自动判定 reaction;
|
||||
- UP 白名单;
|
||||
- 视频历史统计回填;
|
||||
|
||||
Reference in new issue
Block a user