diff --git a/bot.py b/bot.py index f764505..742199f 100644 --- a/bot.py +++ b/bot.py @@ -62,10 +62,18 @@ _NODE22 = "/opt/node22/bin/node" JS_RUNTIME = f"node:{_NODE22}" if os.path.exists(_NODE22) else "node" # YouTube is the one host where we must NOT send cookies: with account cookies -# present, yt-dlp skips the cookieless `android_vr`/`android` clients (whose media -# URLs work) and falls back to the `tv` client, whose URLs now 403 on the data -# download. A cookieless YouTube request just works. Cookies are still needed for -# Instagram/TikTok/X, so we withhold them per-URL rather than dropping the file. +# present, yt-dlp skips the cookieless client it would otherwise pick (currently +# `visionos`, which offers the full ladder of split renditions) and falls back to +# a `tv` client that only ever yields muxed 360p — and whose URLs have repeatedly +# 403'd on the data download. A cookieless YouTube request just works. Cookies are +# still needed for Instagram/TikTok/X, so we withhold them per-URL rather than +# dropping the file. +# +# Which cookieless client yt-dlp picks is not stable — YouTube retires them and +# yt-dlp re-points at a working one. When every YouTube download starts failing at +# the data stage with "HTTP Error 403: Forbidden" (extraction succeeds, the +# transfer does not), that is the signal that the pinned client has been retired: +# upgrade yt-dlp rather than touching the cookie or format logic here. _YOUTUBE_HOST_RE = re.compile(r"(?:^|\.)(?:youtube\.com|youtu\.be|youtube-nocookie\.com)$", re.I) def _is_youtube(url: str) -> bool: diff --git a/requirements.txt b/requirements.txt index 6947e99..4c3c39d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ signalbot==1.1.0 # yt-dlp is kept current for site/extractor changes; bump the floor deliberately. -# 2026.6.9 fixes a YouTube 403-on-data-download regression; it also requires the -# JS challenge to run on Node >= 22 (see below). -yt-dlp>=2026.6.9 +# 2026.8.19 restores YouTube downloads: the cookieless client the older build +# pinned (android_vr) was retired and every data transfer 403'd. +yt-dlp>=2026.8.19 # Needed for YouTube: yt-dlp wraps URLs in a JS "n-sig" challenge that a JS # runtime must solve. Requires Node >= 22 on PATH (bot.py points at a standalone # /opt/node22 since Debian 13 only ships Node 20) plus this package.