fix: close data integrity and hot-reload review findings
Backfill same-day snapshots for newly added or restored videos, preserve successful fan snapshots on resume, persist incomplete state before forced re-runs, and split collection completion from backup completion so failed backups can retry without API calls. Reject missing data payloads instead of treating them as empty folders, guard against mass-unfav on suspicious empty remote folders, rebuild Bilibili clients when credentials change, recompute primary folder ownership from active relations with per-folder fav_time, preserve original titles for dropped invalid videos, poll config every 60 seconds, and fix favsort verify interval and mixed resource types.
This commit is contained in:
1 parent
178ab64b18
commit
6a21b5d905
21 files changed
+895
-82
No files matched your search
+23
-2
@@ -346,6 +346,7 @@ def cmd_plan(cfg, args):
|
||||
"current_order": cur,
|
||||
"target_order": tgt,
|
||||
"moves": moves,
|
||||
"types": {v["avid"]: v["type"] for v in applied},
|
||||
"titles": {
|
||||
v["avid"]: {
|
||||
"title": v["title"],
|
||||
@@ -395,8 +396,12 @@ def cmd_run(cfg, args):
|
||||
plan = load_plan(media_id)
|
||||
target = plan["target_order"]
|
||||
titles = plan["titles"]
|
||||
types = plan.get("types") or {}
|
||||
sc = cfg["sleep"]
|
||||
verify_every = args.verify_every
|
||||
if verify_every < 1:
|
||||
print("[run] --verify-every 必须 >= 1;未执行任何写操作")
|
||||
return 2
|
||||
|
||||
print("[run] 读取当前顺序 ...")
|
||||
actual = [x["id"] for x in fetch_ids(cfg, media_id)]
|
||||
@@ -428,7 +433,13 @@ def cmd_run(cfg, args):
|
||||
long_after = random.randint(sc["long_every_min"], sc["long_every_max"])
|
||||
|
||||
for i, m in enumerate(moves, 1):
|
||||
body = {"media_id": media_id, "sort": f"{m['pred']}:2:{m['moved']}:2", "csrf": cfg["csrf"]}
|
||||
pred_type = types.get(m["pred"], 2)
|
||||
moved_type = types.get(m["moved"], 2)
|
||||
body = {
|
||||
"media_id": media_id,
|
||||
"sort": f"{m['pred']}:{pred_type}:{m['moved']}:{moved_type}",
|
||||
"csrf": cfg["csrf"],
|
||||
}
|
||||
print(f"[run] {i}/{total} {titles[str(m['moved'])]['title'][:30]} "
|
||||
f"-> after {m['pred']}", end=" ", flush=True)
|
||||
resp = post_form(cfg, API["sort"].format(base=BASE), body)
|
||||
@@ -541,6 +552,16 @@ COMMAND_HELP = {
|
||||
}
|
||||
|
||||
|
||||
def _positive_int(value):
|
||||
try:
|
||||
number = int(value)
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise argparse.ArgumentTypeError("必须是整数") from exc
|
||||
if number < 1:
|
||||
raise argparse.ArgumentTypeError("必须 >= 1")
|
||||
return number
|
||||
|
||||
|
||||
def build_parser():
|
||||
p = argparse.ArgumentParser(
|
||||
prog="favsort",
|
||||
@@ -565,7 +586,7 @@ def build_parser():
|
||||
|
||||
pr = sub.add_parser("run", help=COMMAND_HELP["run"])
|
||||
pr.add_argument("media_id", type=int, help="收藏夹 media_id")
|
||||
pr.add_argument("--verify-every", type=int, default=1, metavar="N",
|
||||
pr.add_argument("--verify-every", type=_positive_int, default=1, metavar="N",
|
||||
help="每 N 步回读校验一次(默认 1;前 3 步始终逐步校验)")
|
||||
|
||||
pv = sub.add_parser("verify", help=COMMAND_HELP["verify"])
|
||||
|
||||
Reference in new issue
Block a user