import os from "node:os"; import { redirect } from "next/navigation"; import { getTranslations } from "next-intl/server"; import { DiagnosticRow, InfoItem, OnlineUsersWidget, StatusCard, } from "@/components/admin/dashboard"; import { formatDate } from "@/lib/format-date"; import { canAccess, getAdminContext, PERMS } from "@/lib/permissions"; import { prisma } from "@/lib/prisma"; import { rcon } from "@/lib/services/rcon"; import { siteSettings } from "@/lib/services/site-settings"; import { CommandocentrumControls } from "./commandocentrum-controls"; export const dynamic = "force-dynamic"; function decodeStacktrace(raw: unknown): string { if (raw == null) return ""; try { if (typeof raw === "string") return raw; return Buffer.from(raw as Uint8Array).toString("utf8"); } catch { return ""; } } function mb(bytes: number): string { return `${Math.round(bytes / 1024 / 1024)} MB`; } function uptime(seconds: number): string { const d = Math.floor(seconds / 86400); const h = Math.floor((seconds % 86400) / 3600); const m = Math.floor((seconds % 3600) / 60); return d > 0 ? `${d}d ${h}h ${m}m` : h > 0 ? `${h}h ${m}m` : `${m}m`; } export default async function CommandoCentrum() { const { session, permissions } = await getAdminContext(); if (!canAccess(permissions, PERMS.RCON_EXECUTE, session.user.rank)) { redirect("/admin"); } const t = await getTranslations("pages.admin.commandocentrum"); const [ onlineCount, totalUsers, errors, dbOk, emulatorOnline, maintenance, activity, ] = await Promise.all([ prisma.user.count({ where: { online: "1" } }).catch(() => 0), prisma.user.count().catch(() => -1), prisma.emulatorErrors .findMany({ orderBy: { timestamp: "desc" }, take: 50 }) .catch(() => []), prisma.websiteSetting .count() .then(() => true) .catch(() => false), rcon.send("ping", null).catch(() => false), siteSettings.getBool("maintenance_enabled", false), prisma.staffActivities .findMany({ orderBy: { createdAt: "desc" }, take: 12 }) .catch( () => [] as Awaited>, ), ]); const staffIds = Array.from( new Set(activity.map((a) => Number(a.userId))), ).filter((n) => n > 0); let nameById = new Map(); if (staffIds.length) { const users = await prisma.user .findMany({ where: { id: { in: staffIds } }, select: { id: true, username: true }, }) .catch(() => []); nameById = new Map(users.map((u) => [u.id, u.username])); } const appKeySet = !!process.env.APP_KEY; const smtpSet = !!process.env.SMTP_HOST; const rconSet = !!process.env.RCON_HOST; return (
{/* ── Live status ────────────────────────────────────────── */}
= 0 ? t("totalAccounts", { count: totalUsers }) : t("dbUnavailable") } state="neutral" icon="👤" />
{/* ── Online users widget ───────────────────────────────── */}

{t("onlineUsers")}

{/* ── Server info + diagnostics ──────────────────────────── */}

{t("serverInfo")}

{t("systemDiagnostics")}

{/* ── Staff activity ─────────────────────────────────────── */}

{t("recentStaffActivity")}

{activity.length === 0 ? (
{t("noStaffActivity")}
) : (
{activity.map((a) => ( ))}
{t("colWhen")} {t("colStaff")} {t("colAction")} {t("colDescription")}
{formatDate(a.createdAt, "datetime-seconds")} {nameById.get(Number(a.userId)) ?? `#${a.userId}`} {a.action} {a.description}
)}
{/* ── Emulator errors ────────────────────────────────────── */}

{t("recentEmulatorErrors")}

{errors.length === 0 ? (
{t("noEmulatorErrors")}
) : (
{errors.map((e) => { const trace = decodeStacktrace(e.stacktrace); const snippet = trace ? trace.split("\n").slice(0, 20).join("\n") + (trace.split("\n").length > 20 ? `\n… ${t("truncated")}` : "") : t("empty"); return ( ); })}
{t("colWhen")} {t("colType")} {t("colVersion")} {t("colStacktrace")}
{formatDate( e.timestamp ? new Date(e.timestamp * 1000) : null, "datetime-seconds", )} {e.type} {e.version}
													{snippet}
												
)}
); }