fix(youtube): a refused YouTube action answers a 422 that says what to do

The two manual syncs (subscriptions import, playlist pull) had no YouTubeError
handler, so a quota, token or transport failure was a raw 500 and the blocking
"Server error" dialog (E9 F1). The other YouTube routes answered either the
upstream's English or a playlist-scoped "youtube_failed".

One helper, routes/_common.youtube_refusal: 422 {code: "youtube", reason} with
the reason sorted by what the user can do — quota (wait for the reset),
reconnect (the token step refused), unavailable (retry). Used by every route
that surfaces a YouTube failure; localizeDetail translates it.

"Reconnect" had no path: a grant Google revoked still read as granted, so
Settings and the wizard offered no connect button while every call failed.
An invalid_grant from the token endpoint now clears the stored grant.
This commit is contained in:
2026-09-19 06:55:40 +02:00
parent 1cfb19bdc7
commit fad301e7a4
15 changed files with 221 additions and 27 deletions
+2 -2
View File
@@ -29,7 +29,7 @@ from app.models import (
Video,
VideoState,
)
from app.routes._common import get_or_404
from app.routes._common import get_or_404, youtube_refusal
from app.sync.videos import parse_iso8601_duration
from app.utils import iso
from app.youtube.client import YouTubeClient, YouTubeError
@@ -411,7 +411,7 @@ def get_video_detail(
):
items = yt.get_videos([video_id])
except YouTubeError as exc:
raise HTTPException(status_code=422, detail=f"YouTube lookup failed: {exc}")
raise youtube_refusal(exc)
if not items:
raise HTTPException(status_code=404, detail="Unknown video")