/** * Habbo avatar imager helpers. * * Images are loaded directly from Habbo's public imager. The old self-hosted * `/api/imaging/avatar` proxy fails in production (Habbo blocks server-side * fetches), so the browser always hits Habbo.com instead. */ export type { AvatarOptions } from "@/types/admin"; import type { AvatarOptions } from "@/types/admin"; /** Official Habbo avatar imaging endpoint. */ export const HABBO_IMAGER_URL = "https://www.habbo.com/habbo-imaging/avatarimage"; /** * Resolve a usable imager base URL. * Rejects the broken self-hosted proxy if it was 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 HABBO_IMAGER_URL; } return v.replace(/\/+$/, ""); } /** * Build an avatar image URL (Habbo imager 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, }); 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()}`; }