diff --git a/backend/app/downloads/errors.py b/backend/app/downloads/errors.py index 68947a8a..0c883bfa 100644 --- a/backend/app/downloads/errors.py +++ b/backend/app/downloads/errors.py @@ -24,6 +24,16 @@ _RULES: tuple[tuple[str, str], ...] = ( # Some extractors (e.g. Reddit) gate content behind a logged-in account: "Account # authentication is required." — an auth wall we deliberately don't cross, not a transient error. ("authentication is required", "login_required"), + # Closed-group / private-post auth walls (Facebook groups, Instagram private, …). yt-dlp phrases + # these many ways; the common thread is "you must be signed in" or its own suggestion to supply + # cookies. Treating the cookie suggestion as an auth signal is what makes a login-walled link read + # honestly (and stay non-retryable) when the acting user has no usable cookie for that host. + ("log in to", "login_required"), + ("login required", "login_required"), + ("you must be logged in", "login_required"), + ("only available for registered users", "login_required"), + ("use --cookies", "login_required"), + ("--cookies-from-browser", "login_required"), # Geo-restricted. ("in your country", "geo_blocked"), ("available in your location", "geo_blocked"), @@ -42,6 +52,10 @@ _RULES: tuple[tuple[str, str], ...] = ( ("account associated with this video has been terminated", "unavailable"), ("this video is not available", "unavailable"), ("this video has been removed", "unavailable"), + # yt-dlp doesn't support this site at all ("Unsupported URL: …") — distinct from an auth wall on a + # supported site. Non-retryable: no cookie or retry can make an unsupported host downloadable. + ("unsupported url", "unsupported_host"), + ("no video could be found in this url", "unsupported_host"), # DRM. ("drm protected", "drm"), ("drm-protected", "drm"), diff --git a/backend/app/downloads/links.py b/backend/app/downloads/links.py index 38dc2038..0344bf17 100644 --- a/backend/app/downloads/links.py +++ b/backend/app/downloads/links.py @@ -83,6 +83,10 @@ def public_meta( from app.downloads import service source_url = service.reference_url(job, asset) + # Audio-only assets (mp3 rips, extracted audio) carry a codec but no video stream. WebKit (all + # iOS browsers) refuses to play them inside a