diff --git a/app/shop_routes.py b/app/shop_routes.py index 4bee46a..e355997 100644 --- a/app/shop_routes.py +++ b/app/shop_routes.py @@ -209,7 +209,7 @@ async def shop_audio(release_id: int, db=Depends(get_db)): async def _live_youtube(db, release_id): """Pick a NON-dead YouTube clip — validates unchecked ones via YouTube oembed (200=live) and caches `dead`.""" rows = [dict(r) for r in (await db.execute(text( - "SELECT id, uri, dead FROM disc_release_video WHERE release_id=:r AND uri<>'' ORDER BY id LIMIT 8" + "SELECT DISTINCT uri, dead FROM disc_release_video WHERE release_id=:r AND uri<>'' ORDER BY uri LIMIT 8" ), {"r": release_id})).mappings()] unchecked = [v for v in rows if v["dead"] is None][:4] if unchecked: @@ -217,21 +217,21 @@ async def _live_youtube(db, release_id): async def chk(v): yid = _ytid(v["uri"]) if not yid: - return v["id"], True + return v["uri"], True try: rr = await c.get("https://www.youtube.com/oembed", params={"url": "https://youtu.be/" + yid, "format": "json"}) - return v["id"], rr.status_code != 200 + return v["uri"], rr.status_code != 200 except Exception: - return v["id"], None # network blip — leave unchecked for next time + return v["uri"], None # network blip — leave unchecked for next time checked = await asyncio.gather(*[chk(v) for v in unchecked]) wrote = False - for vid, dead in checked: + for uri, dead in checked: if dead is not None: - await db.execute(text("UPDATE disc_release_video SET dead=:d, checked_at=now() WHERE id=:i"), - {"d": dead, "i": vid}) + await db.execute(text("UPDATE disc_release_video SET dead=:d, checked_at=now() " + "WHERE release_id=:r AND uri=:u"), {"d": dead, "r": release_id, "u": uri}) for v in rows: - if v["id"] == vid: + if v["uri"] == uri: v["dead"] = dead wrote = True if wrote: