Fix comment fetching: write to temp file instead of parsing stdout

--write-comments writes to .info.json reliably; parsing stdout with
--dump-json was never guaranteed to include comments. Use a TemporaryDirectory,
write the info.json there, read it, then let the context manager clean up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mattias Tall
2026-05-26 11:38:00 +02:00
parent 18b3c572f1
commit 50ce373767

View File

@@ -386,45 +386,36 @@ def fetch_channel_links(channel_id: str) -> list[str]:
def fetch_video_comments(youtube_video_id: str, max_comments: int = 20) -> list[dict]:
"""Fetch top comments via yt-dlp Python API. Returns empty list on failure."""
import yt_dlp as _yt_dlp
"""Fetch top comments via yt-dlp CLI writing to a temp file. Returns empty list on failure."""
import os
import tempfile
with _cookies_lock:
cf = _cookies_file
b = _cookies_browser
oauth2 = _use_oauth2
url = f"https://www.youtube.com/watch?v={youtube_video_id}"
ydl_opts = {
"quiet": True,
"no_warnings": True,
"skip_download": True,
"getcomments": True,
"extractor_args": {
"youtube": {
"max_comments": [str(max_comments), str(max_comments)],
"comment_sort": ["top"],
}
},
}
if oauth2:
ydl_opts["username"] = "oauth2"
ydl_opts["password"] = ""
elif cf and Path(cf).exists():
ydl_opts["cookiefile"] = cf
else:
for candidate in _AUTO_COOKIES_PATHS:
if Path(candidate).exists():
ydl_opts["cookiefile"] = candidate
break
else:
if b and not cf:
ydl_opts["cookiesfrombrowser"] = (b,)
with tempfile.TemporaryDirectory() as tmpdir:
out_tmpl = os.path.join(tmpdir, "%(id)s.%(ext)s")
args = [
"yt-dlp", url,
"--write-info-json",
"--write-comments",
"--extractor-args", f"youtube:max_comments={max_comments};comment_sort=top",
"--no-download",
"--no-playlist",
"--quiet",
"--output", out_tmpl,
*_cookie_args(),
]
_run(args, timeout=90)
info = None
for fname in os.listdir(tmpdir):
if fname.endswith(".info.json"):
try:
with _yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(f"https://www.youtube.com/watch?v={youtube_video_id}", download=False)
with open(os.path.join(tmpdir, fname)) as f:
info = json.load(f)
except Exception:
return []
pass
break
if not info:
return []