/** * Avatar imager helpers. * * The public-facing imager URL resolves to the site's own `/imaging` endpoint * by default. That endpoint proxies the image from the configured upstream * (defaults to Habbo's public imager). */ export type { AvatarOptions } from "@/types/admin"; import type { AvatarOptions } from "@/types/admin"; /** Build an absolute default imager URL from public env vars. */ function defaultImagerUrl(): string { const pub = process.env.NEXT_PUBLIC_IMAGER_URL?.trim(); if (pub && !pub.includes("/api/imaging/avatar")) return pub.replace(/\/+$/, ""); const app = process.env.NEXT_PUBLIC_APP_URL?.trim(); if (app) return `${app.replace(/\/+$/, "")}/imaging`; return "/imaging"; } /** * Resolve the public-facing imager base URL. * Rejects the broken self-hosted proxy route if stored in settings. */ export function resolveImagerBase(configured?: string | null): string { const fromEnv = process.env.NEXT_PUBLIC_IMAGER_URL?.trim(); if (fromEnv && !fromEnv.includes("/api/imaging/avatar")) { return fromEnv.replace(/\/+$/, ""); } const v = (configured ?? "").trim(); if (!v || v.includes("/api/imaging/avatar")) { return defaultImagerUrl(); } return v.replace(/\/+$/, ""); } /** * Resolve the upstream URL used by the proxy endpoint. * Falls back to Habbo's public imager when nothing else is configured. */ export function resolveUpstreamBase(): string { const fromEnv = process.env.IMAGING_UPSTREAM_URL?.trim(); if (fromEnv) return fromEnv.replace(/\/+$/, ""); return "https://www.habbo.com/habbo-imaging/avatarimage"; } /** * Build an avatar image URL (site's own `/imaging` endpoint by default). * * @example * getAvatarUrl('hr-893-45.hd-180-1.ch-210-66.lg-270-82') * getAvatarUrl(look, { size: 'l', headOnly: true }) * getAvatarUrl(look, { size: 'm', gesture: 'sml', direction: 2 }) */ export function getAvatarUrl( figure: string, options: AvatarOptions = {}, ): string { const { size = "m", direction = 2, headDirection = 3, headOnly = false, gesture, action, } = options; const params = new URLSearchParams({ figure, direction: String(direction), head_direction: String(headDirection), size, img_format: "png", }); if (headOnly) params.set("headonly", "1"); if (gesture) params.set("gesture", gesture); if (action) params.set("action", action); const base = resolveImagerBase(); return `${base}?${params.toString()}`; }