fix(channels): reconcile an already-followed channel instead of erroring
Subscribing to a channel the user already follows on YouTube (a local/YouTube desync — e.g. a stale import dropped the local row, so it resurfaced in the discovery list) made YouTube return 400 "subscription already exists", which the endpoint reported as a 502 — and the client shows a 502 as a transient "connection lost" blip, not the real reason. Treat the duplicate as success: record the subscription locally (the desired end state already holds; the next resync fills in the resource id). Surface any other YouTube error as 422 with a clear message, on both subscribe and unsubscribe, so it isn't mistaken for a connection drop.
This commit is contained in:
parent
62de01f7ea
commit
0e8913ccc6
1 changed files with 14 additions and 2 deletions
|
|
@ -313,7 +313,17 @@ def subscribe(
|
||||||
if channel.details_synced_at is None:
|
if channel.details_synced_at is None:
|
||||||
apply_channel_details(db, yt.get_channels([channel_id]))
|
apply_channel_details(db, yt.get_channels([channel_id]))
|
||||||
except YouTubeError as exc:
|
except YouTubeError as exc:
|
||||||
raise HTTPException(status_code=502, detail=f"YouTube subscribe failed: {exc}")
|
# Already following on YouTube but not recorded here (a desync — e.g. a stale import
|
||||||
|
# dropped the local row, so it resurfaced in discovery). That's not a failure: the end
|
||||||
|
# state the user wanted already holds, so record it locally and move on. The next
|
||||||
|
# subscription resync fills in the resource id. Any other YouTube error is a real
|
||||||
|
# problem — surface it with a clear message (422, not a 502 that the client would
|
||||||
|
# mistake for a transient "connection lost").
|
||||||
|
msg = str(exc).lower()
|
||||||
|
if "already exists" in msg or "duplicate" in msg:
|
||||||
|
yt_sub_id = ""
|
||||||
|
else:
|
||||||
|
raise HTTPException(status_code=422, detail=f"YouTube couldn't subscribe you: {exc}")
|
||||||
db.add(
|
db.add(
|
||||||
Subscription(
|
Subscription(
|
||||||
user_id=user.id,
|
user_id=user.id,
|
||||||
|
|
@ -349,7 +359,9 @@ def unsubscribe(
|
||||||
with quota.attribute(user.id, "unsubscribe"), YouTubeClient(db, user) as yt:
|
with quota.attribute(user.id, "unsubscribe"), YouTubeClient(db, user) as yt:
|
||||||
yt.delete_subscription(sub.yt_subscription_id)
|
yt.delete_subscription(sub.yt_subscription_id)
|
||||||
except YouTubeError as exc:
|
except YouTubeError as exc:
|
||||||
raise HTTPException(status_code=502, detail=f"YouTube unsubscribe failed: {exc}")
|
# 422 (a real, explainable error → speaking modal), not 502 which the client treats as
|
||||||
|
# a transient "connection lost" gateway blip.
|
||||||
|
raise HTTPException(status_code=422, detail=f"YouTube couldn't unsubscribe you: {exc}")
|
||||||
db.delete(sub)
|
db.delete(sub)
|
||||||
db.commit()
|
db.commit()
|
||||||
return {"unsubscribed": channel_id}
|
return {"unsubscribed": channel_id}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue