feat: yt-dlp cookie support + surface real failure reason; default workers 4
Bulk --repair on unauthenticated YouTube trips the bot-check (HTTP 429 "Sign in to confirm you're not a bot"), after which every call fails until the IP flag clears. Add cookie support so authenticated requests bypass it: - --cookies FILE / --cookies-from-browser BROWSER (and $YTDLP_COOKIES / $YTDLP_COOKIES_FROM_BROWSER for the API container), threaded into every yt-dlp invocation (search, probe, download, repair metadata fetch). - run_yt_dlp_get_metadata now logs yt-dlp's last stderr line (the actual 429 / bot-check / network reason) instead of a bare exit code. - Default --repair workers lowered 8 -> 4 (safe without cookies; raise with). - compose: optional YTDLP_COOKIES env + commented cookies mount. - README: how to obtain cookies (Chrome/Firefox, browser-read vs cookies.txt export); gitignore cookies.txt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -367,3 +367,45 @@ def test_repair_library_default_workers_still_works(tmp_path, monkeypatch):
|
||||
(root / "A" / "youtube" / f"T [{YT_ID}].opus").write_text("x")
|
||||
monkeypatch.setattr(mf, "repair_file", lambda p, s, d: ["x"])
|
||||
assert mf.repair_library(str(root), dry_run=False) == (1, 1)
|
||||
|
||||
|
||||
# ---- cookies + error visibility ----
|
||||
def test_cookie_args_file_takes_precedence(monkeypatch):
|
||||
monkeypatch.setattr(mf, "COOKIES_FILE", "/c.txt")
|
||||
monkeypatch.setattr(mf, "COOKIES_FROM_BROWSER", "firefox")
|
||||
assert mf._cookie_args() == ["--cookies", "/c.txt"]
|
||||
|
||||
|
||||
def test_cookie_args_browser(monkeypatch):
|
||||
monkeypatch.setattr(mf, "COOKIES_FILE", "")
|
||||
monkeypatch.setattr(mf, "COOKIES_FROM_BROWSER", "firefox")
|
||||
assert mf._cookie_args() == ["--cookies-from-browser", "firefox"]
|
||||
|
||||
|
||||
def test_cookie_args_none(monkeypatch):
|
||||
monkeypatch.setattr(mf, "COOKIES_FILE", "")
|
||||
monkeypatch.setattr(mf, "COOKIES_FROM_BROWSER", "")
|
||||
assert mf._cookie_args() == []
|
||||
|
||||
|
||||
def test_metadata_fetch_passes_cookies(monkeypatch):
|
||||
captured = {}
|
||||
|
||||
class _R:
|
||||
stdout = '{"title": "x"}'
|
||||
monkeypatch.setattr(mf, "COOKIES_FILE", "/cookies.txt")
|
||||
monkeypatch.setattr(mf, "COOKIES_FROM_BROWSER", "")
|
||||
monkeypatch.setattr(mf.subprocess, "run", lambda cmd, **k: captured.update(cmd=cmd) or _R())
|
||||
mf.run_yt_dlp_get_metadata("http://u")
|
||||
assert "--cookies" in captured["cmd"]
|
||||
assert "/cookies.txt" in captured["cmd"]
|
||||
|
||||
|
||||
def test_metadata_fetch_logs_stderr(monkeypatch, capsys):
|
||||
def boom(cmd, **k):
|
||||
raise mf.subprocess.CalledProcessError(
|
||||
1, cmd, output="", stderr="WARNING: foo\nERROR: Sign in to confirm you're not a bot.")
|
||||
monkeypatch.setattr(mf.subprocess, "run", boom)
|
||||
assert mf.run_yt_dlp_get_metadata("http://u") is None
|
||||
out = capsys.readouterr().err
|
||||
assert "not a bot" in out # the actionable last stderr line surfaces
|
||||
|
||||
Reference in New Issue
Block a user