From 57529fd1eaec598c5a94a583a089ec0488df1e94 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 11 Oct 2026 21:14:10 +0200 Subject: [PATCH] Fix: badge API now reads from Gamedata/c_images/album1584 The badge GIF files exist at /var/www/Gamedata/c_images/album1584/ but the /api/imaging/badge endpoint only looked in /swf/c_images/album1584/ (relative to process.cwd()). Added GEDATA_IMAGES_BASE candidate and fetchCandidate handler so badges render correctly in the admin UI and on the site. --- src/app/api/imaging/badge/route.ts | 41 +++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/app/api/imaging/badge/route.ts b/src/app/api/imaging/badge/route.ts index 0ee337c6..93892c5b 100644 --- a/src/app/api/imaging/badge/route.ts +++ b/src/app/api/imaging/badge/route.ts @@ -23,6 +23,7 @@ const CODE_RE = /^[A-Za-z0-9_+.-]+$/; const CODE_MAX_LEN = 50; const DEFAULT_BASE = "https://images.habbo.com/c_images/album1584"; const LOCAL_SWF_BASE = "/swf/c_images/album1584"; +const GEDATA_IMAGES_BASE = "/var/www/Gamedata/c_images/album1584"; const FETCH_TIMEOUT_MS = 5_000; // Neutral placeholder (grey rounded square) served as a 200 so broken badge @@ -45,10 +46,11 @@ export async function GET(request: NextRequest) { const sourceLocal = request.nextUrl.searchParams.get("source") === "local"; const candidates: string[] = sourceLocal - ? [LOCAL_SWF_BASE, DEFAULT_BASE] + ? [LOCAL_SWF_BASE, GEDATA_IMAGES_BASE, DEFAULT_BASE] : [ ...((configured && [configured]) as string[]), DEFAULT_BASE, + GEDATA_IMAGES_BASE, LOCAL_SWF_BASE, ]; @@ -105,18 +107,33 @@ async function fetchCandidate( } // Local `/swf/...` path — read straight from the deployed public folder. - try { - const file = join( - process.cwd(), - "public", - normalized.replace(/^\//, ""), - `${code}.gif`, - ); - const body = new Uint8Array(await readFile(file)); - return { body, contentType: "image/gif", source: "local" }; - } catch { - return null; + if (normalized.startsWith("/swf")) { + try { + const file = join( + process.cwd(), + "public", + normalized.replace(/^\//, ""), + `${code}.gif`, + ); + const body = new Uint8Array(await readFile(file)); + return { body, contentType: "image/gif", source: "local" }; + } catch { + return null; + } } + + // Local Gamedata path — read from /var/www/Gamedata/c_images/album1584/ + if (normalized.startsWith("/var/www/Gamedata")) { + try { + const file = join(normalized, `${code}.gif`); + const body = new Uint8Array(await readFile(file)); + return { body, contentType: "image/gif", source: "local" }; + } catch { + return null; + } + } + + return null; } function badgeResponse(