Implement P0 of the reaction dashboard: config loading with hot reload, SQLite migrations with backups, single-writer queue, read-only Bilibili fav client, folder import/diff sync, invalid-resource handling, blacklist seed, scheduler, and JSON redacted logging. Includes offline unit and transport-level contract tests; all existing and new tests pass.
164 lines
4.9 KiB
Python
164 lines
4.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""脱敏后的真实接口样本(2026-10-31 只读抓取)。
|
|
|
|
样本只保留 P0 需要的字段结构,但包含真实接口的完整嵌套形状:
|
|
``upper`` / ``cnt_info`` / ``attr`` / ``bv_id`` / ``bvid`` 等。
|
|
不包含 Cookie、token 或任何凭据。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import copy
|
|
from typing import Any
|
|
|
|
# GET x/v3/fav/resource/ids?media_id=3700023351(两条有效 + 两条后来静默缺失)
|
|
IDS_PAYLOAD: dict[str, Any] = {
|
|
"code": 0,
|
|
"message": "0",
|
|
"ttl": 1,
|
|
"data": [
|
|
{"id": 117530286889638, "type": 2, "bv_id": "BV1xvxi6LEZD", "bvid": "BV1xvxi6LEZD"},
|
|
{"id": 117014421051497, "type": 2, "bv_id": "BV17tGN6kETF", "bvid": "BV17tGN6kETF"},
|
|
{"id": 116911710935631, "type": 2, "bv_id": "BV1JoNy66Exp", "bvid": "BV1JoNy66Exp"},
|
|
{"id": 116769540805008, "type": 2, "bv_id": "BV183jw6hEpt", "bvid": "BV183jw6hEpt"},
|
|
],
|
|
}
|
|
|
|
# GET x/v3/fav/resource/infos 的真实有效条目
|
|
VALID_INFO: dict[str, Any] = {
|
|
"id": 117530286889638,
|
|
"type": 2,
|
|
"title": "【咻咻满充电专场①】百变音色机能怪,还有什么风格是你驾驭不了的?!",
|
|
"cover": "http://i1.hdslb.com/bfs/archive/e5d3d4f25777b08c1dfae8bc9dc3d56b21d548f1.jpg",
|
|
"intro": "视频唱见咻咻满充电专场,感谢宝宝的充电@推堡儿",
|
|
"page": 2,
|
|
"duration": 9504,
|
|
"upper": {
|
|
"mid": 434442072,
|
|
"name": "_-抱抱-_",
|
|
"face": "https://i0.hdslb.com/bfs/face/3176d3d551875a4dd7dac202963ec76d393ddd18.jpg",
|
|
"jump_link": "",
|
|
},
|
|
"attr": 0,
|
|
"cnt_info": {
|
|
"collect": 43,
|
|
"play": 799,
|
|
"danmaku": 7,
|
|
"vt": 0,
|
|
"play_switch": 0,
|
|
"reply": 0,
|
|
"view_text_1": "799",
|
|
},
|
|
"link": "bilibili://video/117530286889638",
|
|
"ctime": 1793370433,
|
|
"pubtime": 1793370433,
|
|
"fav_time": 0,
|
|
"bv_id": "BV1xvxi6LEZD",
|
|
"bvid": "BV1xvxi6LEZD",
|
|
"season": None,
|
|
"ogv": None,
|
|
"ugc": {"first_cid": 43184885058},
|
|
"media_list_link": "bilibili://music/playlist/playpage/3728825651?page_type=3&oid=117530286889638&otype=2",
|
|
}
|
|
|
|
# attr=9 表示已失效视频(真实样本)
|
|
INVALID_INFO: dict[str, Any] = {
|
|
"id": 116769540805008,
|
|
"type": 2,
|
|
"title": "已失效视频",
|
|
"cover": "http://i0.hdslb.com/bfs/archive/be27fd62c99036dce67efface486fb0a88ffed06.jpg",
|
|
"intro": "-",
|
|
"page": 1,
|
|
"duration": 4504,
|
|
"upper": {
|
|
"mid": 3707011906669054,
|
|
"name": "裤裤喝可乐",
|
|
"face": "https://i1.hdslb.com/bfs/face/c1d2eb1c9e5c783b8b0aa6e6154892724dfe2812.jpg",
|
|
"jump_link": "",
|
|
},
|
|
"attr": 9,
|
|
"cnt_info": {
|
|
"collect": 27,
|
|
"play": 977,
|
|
"danmaku": 0,
|
|
"vt": 0,
|
|
"play_switch": 0,
|
|
"reply": 0,
|
|
"view_text_1": "977",
|
|
},
|
|
"link": "bilibili://video/116769540805008",
|
|
"ctime": 1781762147,
|
|
"pubtime": 1781762147,
|
|
"fav_time": 0,
|
|
"bv_id": "BV183jw6hEpt",
|
|
"bvid": "BV183jw6hEpt",
|
|
"season": None,
|
|
"ogv": None,
|
|
"ugc": {"first_cid": 39207702089},
|
|
"media_list_link": "bilibili://music/playlist/playpage/3728825651?page_type=3&oid=116769540805008&otype=2",
|
|
}
|
|
|
|
# GET x/v3/fav/folder/created/list-all 的真实条目
|
|
FOLDERS_PAYLOAD: dict[str, Any] = {
|
|
"code": 0,
|
|
"message": "0",
|
|
"ttl": 1,
|
|
"data": {
|
|
"count": 2,
|
|
"list": [
|
|
{
|
|
"id": 4451053851,
|
|
"fid": 44510538,
|
|
"mid": 28802351,
|
|
"attr": 2,
|
|
"title": "咻咻满-reaction-2025",
|
|
"fav_state": 0,
|
|
"media_count": 167,
|
|
"is_kid_playlist": False,
|
|
"kid_playlist_desc": "",
|
|
},
|
|
{
|
|
"id": 3700023351,
|
|
"fid": 37000233,
|
|
"mid": 28802351,
|
|
"attr": 54,
|
|
"title": "咻咻满 -reaction-2026",
|
|
"fav_state": 0,
|
|
"media_count": 664,
|
|
"is_kid_playlist": False,
|
|
"kid_playlist_desc": "",
|
|
},
|
|
],
|
|
},
|
|
}
|
|
|
|
|
|
def info_for(
|
|
aid: int,
|
|
*,
|
|
title: str,
|
|
up_mid: int,
|
|
up_name: str,
|
|
pubdate: int = 1793370433,
|
|
duration: int = 9504,
|
|
attr: int = 0,
|
|
bvid: str | None = None,
|
|
) -> dict[str, Any]:
|
|
"""基于真实样本复制一条 infos 条目,只改测试需要的字段。"""
|
|
item = copy.deepcopy(VALID_INFO)
|
|
item["id"] = aid
|
|
item["title"] = title
|
|
item["upper"]["mid"] = up_mid
|
|
item["upper"]["name"] = up_name
|
|
item["pubtime"] = pubdate
|
|
item["ctime"] = pubdate
|
|
item["duration"] = duration
|
|
item["attr"] = attr
|
|
item["bvid"] = bvid or f"BV{aid}"
|
|
item["bv_id"] = item["bvid"]
|
|
item["link"] = f"bilibili://video/{aid}"
|
|
item["media_list_link"] = (
|
|
f"bilibili://music/playlist/playpage/3728825651?page_type=3&oid={aid}&otype=2"
|
|
)
|
|
return item
|