Spaces:
Sleeping
Sleeping
Commit ·
2f51a0e
1
Parent(s): 01abd01
Accept base64-encoded YT_COOKIES and auto-add Netscape header
Browse filesHF secret fields can convert the Netscape format's required TAB characters into spaces,
which makes yt-dlp reject the cookie file. _cookiefile now auto-detects and decodes a
base64-encoded cookies.txt (tab-safe), and prepends the Netscape header if missing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
app.py
CHANGED
|
@@ -6,6 +6,8 @@ startup stays fast.
|
|
| 6 |
"""
|
| 7 |
from __future__ import annotations
|
| 8 |
|
|
|
|
|
|
|
| 9 |
import os
|
| 10 |
import re
|
| 11 |
import shutil
|
|
@@ -36,13 +38,50 @@ VLM_CHOICES = [
|
|
| 36 |
]
|
| 37 |
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
def _cookiefile(workdir: str) -> str | None:
|
| 40 |
-
"""Materialize the YT_COOKIES secret
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
data = os.environ.get("YT_COOKIES")
|
| 42 |
-
if not data:
|
| 43 |
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
path = os.path.join(workdir, "cookies.txt")
|
| 45 |
-
with open(path, "w", encoding="utf-8") as fh:
|
| 46 |
fh.write(data)
|
| 47 |
return path
|
| 48 |
|
|
|
|
| 6 |
"""
|
| 7 |
from __future__ import annotations
|
| 8 |
|
| 9 |
+
import base64
|
| 10 |
+
import binascii
|
| 11 |
import os
|
| 12 |
import re
|
| 13 |
import shutil
|
|
|
|
| 38 |
]
|
| 39 |
|
| 40 |
|
| 41 |
+
def _looks_like_netscape(text: str) -> bool:
|
| 42 |
+
"""True if ``text`` is already a tab-separated Netscape cookie file."""
|
| 43 |
+
head = text.lstrip()
|
| 44 |
+
return head.startswith("#") or "\tTRUE\t" in text or "\tFALSE\t" in text
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def _maybe_b64_decode(text: str) -> str | None:
|
| 48 |
+
"""If ``text`` is base64 that decodes to a cookie file, return the decoded text.
|
| 49 |
+
|
| 50 |
+
HF secret fields can turn the required TAB characters into spaces, which breaks the
|
| 51 |
+
Netscape format. Pasting base64 of the file avoids that; we auto-detect and decode it.
|
| 52 |
+
"""
|
| 53 |
+
compact = "".join(text.split())
|
| 54 |
+
if len(compact) < 16 or re.search(r"[^A-Za-z0-9+/=]", compact):
|
| 55 |
+
return None
|
| 56 |
+
try:
|
| 57 |
+
decoded = base64.b64decode(compact, validate=True).decode("utf-8", "replace")
|
| 58 |
+
except (binascii.Error, ValueError):
|
| 59 |
+
return None
|
| 60 |
+
return decoded if _looks_like_netscape(decoded) else None
|
| 61 |
+
|
| 62 |
+
|
| 63 |
def _cookiefile(workdir: str) -> str | None:
|
| 64 |
+
"""Materialize the YT_COOKIES secret to a Netscape cookie file on disk.
|
| 65 |
+
|
| 66 |
+
Accepts either the raw cookies.txt contents (tabs preserved) or a base64 encoding of
|
| 67 |
+
them. A missing header line is added so yt-dlp accepts the file.
|
| 68 |
+
"""
|
| 69 |
data = os.environ.get("YT_COOKIES")
|
| 70 |
+
if not data or not data.strip():
|
| 71 |
return None
|
| 72 |
+
|
| 73 |
+
if not _looks_like_netscape(data):
|
| 74 |
+
decoded = _maybe_b64_decode(data)
|
| 75 |
+
if decoded:
|
| 76 |
+
data = decoded
|
| 77 |
+
|
| 78 |
+
if not data.lstrip().startswith(("# Netscape", "# HTTP")):
|
| 79 |
+
data = "# Netscape HTTP Cookie File\n" + data.lstrip("\n")
|
| 80 |
+
if not data.endswith("\n"):
|
| 81 |
+
data += "\n"
|
| 82 |
+
|
| 83 |
path = os.path.join(workdir, "cookies.txt")
|
| 84 |
+
with open(path, "w", encoding="utf-8", newline="\n") as fh:
|
| 85 |
fh.write(data)
|
| 86 |
return path
|
| 87 |
|