import Link from "next/link"; import { redirect } from "next/navigation"; import { detectMultiAccounts, type MultiAccountCluster } from "@/actions/multi-account-detect"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { canAccess, getAdminContext, PERMS } from "@/lib/permissions"; export default async function MultiAccountsPage({ searchParams, }: { searchParams: Promise>; }) { const { session, permissions } = await getAdminContext(); if (!canAccess(permissions, PERMS.USERS_VIEW, session.user.rank)) redirect("/admin"); const params = await searchParams; const minAccounts = Math.max(2, Number(params.min) || 2); const limit = Math.min(200, Number(params.limit) || 50); const result = await detectMultiAccounts({ minAccounts, limit }); const clusters: MultiAccountCluster[] = result.ok ? ((result.data as { clusters: MultiAccountCluster[] }).clusters ?? []) : []; return (

Multi-account detector

Clusters of users sharing a registration IP, current IP, or machine ID. Detection is passive — no AI, just a GROUP BY with index support.

{clusters.length === 0 ? ( No clusters found at the current thresholds. ) : (
{clusters.map((cluster) => ( {cluster.label} {cluster.accountCount} accounts share this identifier
{cluster.accounts.map((acc) => ( {acc.username} #{acc.id} {acc.rank >= 5 && staff} {acc.online === "1" && ( )} ))} {cluster.accountCount > cluster.accounts.length && ( … and {cluster.accountCount - cluster.accounts.length} more )}
))}
)}
); }