From 64abd7126fcc61ef77062a9d314e2430fb691b69 Mon Sep 17 00:00:00 2001 From: Ben_Kosytorz Date: Sun, 4 Oct 2026 19:16:08 +0200 Subject: [PATCH] GoFileEmpty: no retries for content that exists but is empty; add tools/debug_gofile.py for raw content-API inspection --- dlp.py | 7 ++++- dlphelper/gofile.py | 7 +++++ tools/debug_gofile.py | 68 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tools/debug_gofile.py diff --git a/dlp.py b/dlp.py index 0776c0d..0be4071 100644 --- a/dlp.py +++ b/dlp.py @@ -157,7 +157,7 @@ def run_gofile( try: files_spec = client.list_files(f.url) if not files_spec: - raise dlph_gofile.GoFileError("no files found under URL") + raise dlph_gofile.GoFileEmpty("content exists but contains no files") files: list[dict] = [] for relpath, name, link in files_spec: dest = Path(args.out_dir) / "downloads" / "gofile" / relpath / name @@ -182,6 +182,11 @@ def run_gofile( log.error("DEAD LINK %s: %s", f.url, exc) state.mark(f.url, status="failed", error=str(exc), files=[]) break + except dlph_gofile.GoFileEmpty as exc: + # Emptied content is stable - no retry + log.error("EMPTY CONTENT %s: %s", f.url, exc) + state.mark(f.url, status="failed", error=str(exc), files=[]) + break except dlph_gofile.GoFileAuthError as exc: # Token may have died mid-run (rate limit); re-auth once per attempt log.warning("Auth error for %s: %s - re-authenticating", f.url, exc) diff --git a/dlphelper/gofile.py b/dlphelper/gofile.py index 9c30054..651962f 100644 --- a/dlphelper/gofile.py +++ b/dlphelper/gofile.py @@ -60,6 +60,13 @@ class GoFileNotFound(GoFileError): """ +class GoFileEmpty(GoFileError): + """The content exists but contains no files (e.g. emptied folder). + + Stable state like a dead link: no retry. + """ + + class GoFileAuthError(GoFileError): """The account token was rejected; the client can re-auth once.""" diff --git a/tools/debug_gofile.py b/tools/debug_gofile.py new file mode 100644 index 0000000..941f519 --- /dev/null +++ b/tools/debug_gofile.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""One-off diagnostic: inspect the raw gofile API response for one content id. + +Prints everything except the account token. Creates exactly one guest account. +""" + +import hashlib +import json +import sys +import time + +import requests + +CID = sys.argv[1] + +USER_AGENT = "Mozilla/5.0" +LOCALE = "en-US" +TOKEN_SECRET = "12af056dacea0b" +WINDOW_SEC = 14400 +COMMON = {"User-Agent": USER_AGENT, "Accept-Encoding": "gzip", "Accept": "*/*", + "Connection": "keep-alive"} + +resp = requests.post("https://api.gofile.io/accounts", headers=COMMON, timeout=15) +data = resp.json() +assert data.get("status") == "ok", data +token = data["data"]["token"] + +window = int(time.time()) // WINDOW_SEC +seed = f"{USER_AGENT}::{LOCALE}::{token}::{window}::{TOKEN_SECRET}" +wtoken = hashlib.sha256(seed.encode()).hexdigest() +headers = { + **COMMON, + "Authorization": f"Bearer {token}", + "X-Website-Token": wtoken, + "X-BL": LOCALE, +} + +r = requests.get( + f"https://api.gofile.io/contents/{CID}?cache=true&sortField=createTime&sortDirection=1", + headers=headers, timeout=30, +) +print("HTTP", r.status_code) +body = r.json() +print("api status:", body.get("status")) + + +def scrub(node): + """Remove anything token-like from the tree before printing.""" + if isinstance(node, dict): + return { + k: ("" if k in ("token", "accountToken") else scrub(v)) + for k, v in node.items() + } + if isinstance(node, list): + return [scrub(x) for x in node] + return node + + +d = body.get("data") or {} +print("data keys:", sorted(d.keys())) +print("type:", d.get("type")) +children = d.get("children") or {} +print("children count:", len(children)) +for cid, child in list(children.items())[:5]: + print(" child:", cid, "type:", child.get("type"), "name:", child.get("name"), + "has link:", "link" in child) +print() +print(json.dumps(scrub(body), indent=2)[:3000])