import { getTranslations } from "next-intl/server"; import Link from "next/link"; import { redirect } from "next/navigation"; import { ContentCard, EmptyState } from "@/components/public/ui"; import { auth } from "@/lib/auth"; import { avatarImageUrl } from "@/lib/format"; import { prisma } from "@/lib/prisma"; import { siteSettings } from "@/lib/services/site-settings"; import { acceptFriend } from "@/actions/messenger"; export const dynamic = "force-dynamic"; function formatTimestamp(seconds: number): string { if (!seconds) return ""; // sended_on is a unix timestamp in seconds (emulator convention). return new Date(seconds * 1000).toISOString().slice(0, 16).replace("T", " "); } export default async function MessagesPage() { const t = await getTranslations("pages.messages"); const session = await auth(); if (!session?.user?.id) redirect("/login"); const userId = Number(session.user.id); // Pending friend requests addressed to the session user, the most recent // offline messages they've received, and the avatar-imager base URL. let requests: { id: number; userFromId: number }[] = []; let messages: { id: number; userFromId: number; message: string; sendedOn: number }[] = []; let imagerBase = "https://www.habbo.com/habbo-imaging/avatarimage"; try { const [reqRows, msgRows, base] = await Promise.all([ prisma.messengerFriendrequests.findMany({ where: { userToId: userId }, select: { id: true, userFromId: true }, orderBy: { id: "desc" }, take: 100, }), prisma.messengerOffline.findMany({ where: { userId }, select: { id: true, userFromId: true, message: true, sendedOn: true }, orderBy: { sendedOn: "desc" }, take: 50, }), siteSettings.get( "habbo_imaging_url", "https://www.habbo.com/habbo-imaging/avatarimage", ), ]); requests = reqRows; messages = msgRows; if (base) imagerBase = base; } catch { requests = []; messages = []; } // Resolve usernames/looks for every counterparty referenced above. const otherIds = Array.from( new Set([ ...requests.map((r) => r.userFromId), ...messages.map((m) => m.userFromId), ]), ).filter((id) => id && id > 0); let userById = new Map< number, { id: number; username: string; look: string } >(); if (otherIds.length > 0) { try { const users = await prisma.user.findMany({ where: { id: { in: otherIds } }, select: { id: true, username: true, look: true }, }); userById = new Map(users.map((u) => [u.id, u])); } catch { userById = new Map(); } } return (
{/* ── Pending friend requests ───────────────────────────── */} {requests.length === 0 ? ( {t("requestsEmptyState")} ) : (
{requests.map((req) => { const from = userById.get(req.userFromId); const avatar = avatarImageUrl(imagerBase, from?.look ?? "", { size: "s", headOnly: true, }); return (
{/* eslint-disable-next-line @next/next/no-img-element */} {`${from?.username

{from ? ( {from.username} ) : ( {t("unknownUser", { id: req.userFromId })} )}

{t("wantsToBeFriend")}

); })}
)}
{/* ── Offline messages ──────────────────────────────────── */} {messages.length === 0 ? ( {t("offlineEmptyState")} ) : (
{messages.map((msg) => { const from = userById.get(msg.userFromId); const avatar = avatarImageUrl(imagerBase, from?.look ?? "", { size: "s", headOnly: true, }); const when = formatTimestamp(msg.sendedOn); return (
{/* eslint-disable-next-line @next/next/no-img-element */} {`${from?.username

{from ? ( {from.username} ) : ( {t("unknownUser", { id: msg.userFromId })} )} {when ? · {when} : null}

{msg.message}

); })}
)}
); }