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

+44 -5
View File
@@ -12,9 +12,11 @@ from pathlib import Path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.stdout.reconfigure(encoding="utf-8")
from reaction_board.bilibili.models import LoginState # noqa: E402
from reaction_board.cli import main # noqa: E402
from reaction_board.database import Database # noqa: E402
from reaction_board.repository import Repository # noqa: E402
import reaction_board.cli as cli # noqa: E402
def write_config(tmp, *, cookie="SESSDATA=x; buvid3=y", csrf="csrf"):
@@ -86,24 +88,61 @@ def test_sync_requires_auth_without_network():
assert not (Path(tmp) / "app.db").exists()
def test_run_once_without_folders():
def test_snapshot_offline_empty_db():
with tempfile.TemporaryDirectory() as tmp:
path = write_config(tmp, cookie="", csrf="")
data = json.loads(path.read_text(encoding="utf-8"))
data["folders"] = []
data["track_fans"] = []
path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
code, output = run_cli(["snapshot", "--config", str(path)])
assert code == 0
assert '"completed": true' in output
assert '"total": 0' in output
assert len(list((Path(tmp) / "backup").glob("app-*.db"))) == 1
def test_auth_check_without_cookie():
with tempfile.TemporaryDirectory() as tmp:
path = write_config(tmp, cookie="", csrf="")
code, output = run_cli(["auth-check", "--config", str(path)])
assert code == 1
payload = json.loads(output)
assert payload["is_login"] is False
assert "未配置 cookie" in payload["message"]
def test_run_once_offline():
class FakeClient:
def check_login(self):
return LoginState(True, 1, "tester", 0, "OK")
with tempfile.TemporaryDirectory() as tmp:
path = write_config(tmp)
data = json.loads(path.read_text(encoding="utf-8"))
data["folders"] = []
data["track_fans"] = []
path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
code, output = run_cli(["run", "--once", "--config", str(path)])
original = cli._client
cli._client = lambda *args, **kwargs: FakeClient()
try:
code, output = run_cli(["run", "--once", "--config", str(path)])
finally:
cli._client = original
assert code == 0
assert '"name": "folder_sync"' in output
assert '"ok": true' in output
assert '"name": "snapshot"' in output
def main_test():
test_init_and_status()
test_missing_config()
test_sync_requires_auth_without_network()
test_run_once_without_folders()
print("OK: CLI init/sync/run/status/错误路径测试全部通过")
test_snapshot_offline_empty_db()
test_auth_check_without_cookie()
test_run_once_offline()
print("OK: CLI init/sync/snapshot/auth-check/run/status/错误路径测试全部通过")
if __name__ == "__main__":