feat(p1): add daily snapshots and fan tracking

Implement P1: seven-metric view snapshots, relation/stat fan snapshots, failure placeholders, resume by daily completion markers, Cookie login warnings, daily SQLite backups, Shanghai daily scheduling, and CLI snapshot/auth-check commands. Real read-only run captured 795/795 videos successfully over 1124s with a verified daily backup.
This commit is contained in:
kairee committed 2026-10-31 19:19:24 +08:00
1 parent ee289bfa56
commit 5c2ab7b187
20 files changed
+1680 -54

No files matched your search

+105
View File
@@ -161,3 +161,108 @@ def info_for(
f"bilibili://music/playlist/playpage/3728825651?page_type=3&oid={aid}&otype=2"
)
return item
# GET x/web-interface/view?aid=117530286889638(真实七项 stat)
VIEW_PAYLOAD: dict[str, Any] = {
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"aid": 117530286889638,
"bvid": "BV1xvxi6LEZD",
"cid": 43184885058,
"title": "【咻咻满充电专场①】百变音色机能怪,还有什么风格是你驾驭不了的?!",
"pubdate": 1793370433,
"ctime": 1793370433,
"duration": 9504,
"owner": {"mid": 434442072, "name": "_-抱抱-_", "face": ""},
"stat": {
"aid": 117530286889638,
"view": 819,
"danmaku": 7,
"reply": 16,
"favorite": 43,
"coin": 9,
"share": 1,
"now_rank": 0,
"his_rank": 0,
"like": 44,
"dislike": 0,
"evaluation": "",
"vt": 0,
},
},
}
# 当前实测:收藏夹里已不可访问的 aid 返回 62012,而不是旧文档里的 -404
VIEW_UNAVAILABLE: dict[str, Any] = {
"code": 62012,
"message": "62012",
"ttl": 1,
"data": None,
}
# GET x/relation/stat?vmid=37754047
RELATION_PAYLOAD: dict[str, Any] = {
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"mid": 37754047,
"following": 95,
"whisper": 0,
"black": 0,
"follower": 2767268,
"fans_medal_toast": None,
"fans_effect": None,
},
}
# GET x/web-interface/nav(已登录)
NAV_PAYLOAD: dict[str, Any] = {
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"isLogin": True,
"mid": 28802351,
"uname": "冷萃编译器",
"face": "https://i0.hdslb.com/bfs/face/example.jpg",
"level_info": {"current_level": 5},
"vipStatus": 0,
"wbi_img": {
"img_url": "https://i0.hdslb.com/bfs/wbi/example.png",
"sub_url": "https://i0.hdslb.com/bfs/wbi/example-sub.png",
},
},
}
def view_for(
aid: int,
*,
view: int = 819,
like: int = 44,
coin: int = 9,
favorite: int = 43,
share: int = 1,
reply: int = 16,
danmaku: int = 7,
bvid: str | None = None,
) -> dict[str, Any]:
item = copy.deepcopy(VIEW_PAYLOAD)
data = item["data"]
data["aid"] = aid
data["bvid"] = bvid or f"BV{aid}"
data["stat"].update({
"aid": aid,
"view": view,
"like": like,
"coin": coin,
"favorite": favorite,
"share": share,
"reply": reply,
"danmaku": danmaku,
})
return item