add error handling to render pipeline, graceful portrait fallback

This commit is contained in:
esef committed 2026-07-11 18:16:26 +03:00
1 parent 6dbd8f09ca
commit 9faacbc519
2 files changed
+22 -3

No files matched your search

+14 -1
View File
@@ -267,16 +267,29 @@ class BlueArchiveGacha(commands.Cog):
# Render result image # Render result image
spark = user_state["spark"] spark = user_state["spark"]
try:
async with ctx.typing(): async with ctx.typing():
img_bytes = await render_pull(pulls, banner_name, spark) img_bytes = await render_pull(pulls, banner_name, spark)
except Exception as e:
log.exception("Render failed")
try:
await teaser.delete()
except (discord.NotFound, discord.Forbidden):
pass
await ctx.reply(f"Render failed: {e}")
return
# Send image only — the picture says it all # Send image only
try:
file = discord.File(img_bytes, filename="gacha_result.png") file = discord.File(img_bytes, filename="gacha_result.png")
try: try:
await teaser.delete() await teaser.delete()
except (discord.NotFound, discord.Forbidden): except (discord.NotFound, discord.Forbidden):
pass pass
await ctx.reply(file=file) await ctx.reply(file=file)
except Exception as e:
log.exception("Failed to send result image")
await ctx.reply(f"Failed to send result: {e}")
@commands.command(name="spark") @commands.command(name="spark")
async def spark(self, ctx: commands.Context, *, character_name: str = "") -> None: async def spark(self, ctx: commands.Context, *, character_name: str = "") -> None:
+8 -2
View File
@@ -201,9 +201,15 @@ async def render_pull(
_draw_footer(draw, spark_count) _draw_footer(draw, spark_count)
# ── Fetch all portraits ───────────────────────────────────────────── # ── Fetch all portraits ─────────────────────────────────────────────
async with aiohttp.ClientSession() as session: timeout = aiohttp.ClientTimeout(total=60, connect=10)
async with aiohttp.ClientSession(timeout=timeout) as session:
portrait_tasks = [_fetch_portrait(session, p) for p in pulls] portrait_tasks = [_fetch_portrait(session, p) for p in pulls]
portraits = await asyncio.gather(*portrait_tasks) portraits = await asyncio.gather(*portrait_tasks, return_exceptions=True)
# Unwrap exceptions: failed fetches become None
for i, result in enumerate(portraits):
if isinstance(result, Exception):
log.warning("Portrait %d (%s) failed: %s", pulls[i]["Id"], pulls[i]["Name"], result)
portraits[i] = None
# ── Draw cards in grid ────────────────────────────────────────────── # ── Draw cards in grid ──────────────────────────────────────────────
for idx, (student, portrait) in enumerate(zip(pulls, portraits)): for idx, (student, portrait) in enumerate(zip(pulls, portraits)):