/* eslint-disable @next/next/no-img-element */ import { ImageResponse } from "next/og"; import sharp from "sharp"; import { rarityGradient } from "@/lib/catalog/rarity"; import { imageContentDisposition } from "@/lib/guides/export-image"; import { getPublicWeaponExport } from "@/lib/guides/queries"; const anuphanFonts = Promise.all( [ { subset: "latin", weight: 400 as const }, { subset: "thai", weight: 400 as const }, { subset: "latin", weight: 700 as const }, { subset: "thai", weight: 700 as const }, ].map(async ({ subset, weight }) => { const response = await fetch( `https://unpkg.com/@fontsource/anuphan@5.3.0/files/anuphan-${subset}-${weight}-normal.woff`, ); if (!response.ok) throw new Error(`Unable to load Anuphan ${subset} ${weight}`); return { name: "Anuphan", data: await response.arrayBuffer(), weight, style: "normal" as const, }; }), ).catch(() => []); function metric(value: string | null): string { return value === null ? "—" : `${Number(value).toLocaleString("en-US", { maximumFractionDigits: 2 })}%`; } async function pngDataUrl(url: string): Promise { try { const response = await fetch(url); if (!response.ok) return null; const png = await sharp(Buffer.from(await response.arrayBuffer())) .resize(120, 120, { fit: "contain" }) .png() .toBuffer(); return `data:image/png;base64,${png.toString("base64")}`; } catch { return null; } } export async function GET( _request: Request, context: { params: Promise<{ guideId: string }> }, ) { const { guideId } = await context.params; const guide = await getPublicWeaponExport(guideId); if (!guide) return new Response("Guide not found", { status: 404 }); const [fonts, weaponImages] = await Promise.all([ anuphanFonts, Promise.all(guide.weapons.map((row) => pngDataUrl(row.weapon.imageUrl))), ]); const height = Math.max(360, 190 + guide.weapons.length * 126 + Math.max(0, guide.weapons.length - 1) * 14); return new ImageResponse(
{guide.guideName}
Weapons
{guide.weapons.map((row, index) => (
{weaponImages[index] ? ( ) : (
{index + 1}
)}
{index + 1}. {row.weapon.name} R{row.refinement}
{metric(row.overallPercent)}
ดาเมจทั้งทีม
{metric(row.personalPercent)}
ดาเมจส่วนตัว
))}
, { width: 1000, height, fonts: fonts.length ? fonts : undefined, headers: { "Cache-Control": "no-store", "Content-Disposition": imageContentDisposition(`${guide.guideName} Weapons`, "weapons"), "Content-Type": "image/png", }, }, ); }