fix: prevent concurrent yt-dlp sessions that invalidate cookies
Three code paths could fire yt-dlp immediately (polite=False) while a download was already running, causing YouTube to see two simultaneous authenticated sessions and invalidate the cookie: - search.py: live yt-dlp fallback now skipped while any download is active - downloads.py: _ensure_video uses polite=True so it waits for active downloads to finish before fetching metadata for an unknown video - channels.py: follow_by_url uses polite=True when fetching metadata for a brand-new channel Added is_download_active() helper to ytdlp.py to expose the active download state without importing private globals. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1185,7 +1185,7 @@ def follow_by_url(
|
|||||||
|
|
||||||
channel = db.query(Channel).filter_by(youtube_channel_id=yt_channel_id).first()
|
channel = db.query(Channel).filter_by(youtube_channel_id=yt_channel_id).first()
|
||||||
if not channel:
|
if not channel:
|
||||||
meta = ytdlp.fetch_channel_metadata(yt_channel_id, max_videos=30)
|
meta = ytdlp.fetch_channel_metadata(yt_channel_id, max_videos=30, polite=True)
|
||||||
if not meta or not meta.get("channel"):
|
if not meta or not meta.get("channel"):
|
||||||
raise HTTPException(status_code=404, detail="Channel not found on YouTube")
|
raise HTTPException(status_code=404, detail="Channel not found on YouTube")
|
||||||
ch_data = meta["channel"]
|
ch_data = meta["channel"]
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ def _ensure_video(db: Session, youtube_video_id: str) -> Video:
|
|||||||
if video:
|
if video:
|
||||||
return video
|
return video
|
||||||
|
|
||||||
meta = ytdlp.fetch_video_metadata(youtube_video_id)
|
meta = ytdlp.fetch_video_metadata(youtube_video_id, polite=True)
|
||||||
if not meta:
|
if not meta:
|
||||||
raise HTTPException(status_code=404, detail="Video not found on YouTube")
|
raise HTTPException(status_code=404, detail="Video not found on YouTube")
|
||||||
|
|
||||||
|
|||||||
@@ -264,8 +264,9 @@ def search(
|
|||||||
|
|
||||||
source = "local" if (video_results or channel_results) else "none"
|
source = "local" if (video_results or channel_results) else "none"
|
||||||
|
|
||||||
# Fall back to live yt-dlp search if no local results or explicitly requested
|
# Fall back to live yt-dlp search if no local results or explicitly requested.
|
||||||
if not video_results or live:
|
# Skip if a download is active — concurrent yt-dlp sessions invalidate cookies.
|
||||||
|
if (not video_results or live) and not ytdlp.is_download_active():
|
||||||
try:
|
try:
|
||||||
live_raw = ytdlp.search_youtube(q)
|
live_raw = ytdlp.search_youtube(q)
|
||||||
live_results = _live_search_to_results(db, current_user.id, live_raw)
|
live_results = _live_search_to_results(db, current_user.id, live_raw)
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ def _meta_run(args: list[str], timeout: int = 60) -> tuple[str, str, int]:
|
|||||||
_meta_last_call = time.monotonic()
|
_meta_last_call = time.monotonic()
|
||||||
|
|
||||||
|
|
||||||
|
def is_download_active() -> bool:
|
||||||
|
with _active_downloads_lock:
|
||||||
|
return _active_downloads > 0
|
||||||
|
|
||||||
|
|
||||||
def _parse_date(date_str: str | None) -> datetime | None:
|
def _parse_date(date_str: str | None) -> datetime | None:
|
||||||
if not date_str:
|
if not date_str:
|
||||||
return None
|
return None
|
||||||
|
|||||||
Reference in New Issue
Block a user