"use server"; import { revalidatePath } from "next/cache"; import { requireStaff } from "@/lib/admin/guard"; import { prisma } from "@/lib/prisma"; import { rcon } from "@/lib/services/rcon"; import { logStaffActivity } from "@/lib/services/staff-activity"; export async function bulkUnban({ userIds }: { userIds: number[] }) { const staff = await requireStaff(); const result = await prisma.ban.deleteMany({ where: { userId: { in: userIds } } }); await logStaffActivity({ staffId: staff.id, action: "bulk_unban", description: `Unbanned ${result.count} user(s)`, targetType: "user", }); return { ok: true as const, data: { unbanned: result.count, total: userIds.length } }; } export async function bulkBan({ userIds, reason, duration }: { userIds: number[]; reason: string; duration: number }) { const staff = await requireStaff(); const now = Math.floor(Date.now() / 1000); let banned = 0; for (const userId of userIds) { try { await prisma.ban.create({ data: { userId, ip: "", machineId: "", userStaffId: staff.id, timestamp: now, banExpire: duration > 0 ? now + duration : 0, banReason: reason, type: "account", }, }); banned++; } catch { // skip duplicates } } await logStaffActivity({ staffId: staff.id, action: "bulk_ban", description: `Banned ${banned} user(s)`, targetType: "user", }); return { ok: true as const, data: { banned } }; } export async function bulkGiveCurrency({ userIds, amount, type }: { userIds: number[]; amount: number; type: "credits" | "pixels" | "points" }) { const staff = await requireStaff(); let given = 0; const failedIds: Array<{ userId: number; reason: string }> = []; for (const userId of userIds) { try { if (type === "credits") { await prisma.user.update({ where: { id: userId }, data: { credits: { increment: amount } } }); await rcon.giveCredits(userId, amount); } else if (type === "pixels") { await prisma.usersCurrency.upsert({ where: { userId_type: { userId, type: 0 } }, update: { amount: { increment: amount } }, create: { userId, type: 0, amount }, }); await rcon.giveDuckets(userId, amount); } else if (type === "points") { await prisma.usersCurrency.upsert({ where: { userId_type: { userId, type: 101 } }, update: { amount: { increment: amount } }, create: { userId, type: 101, amount }, }); await rcon.givePointsGotw(userId, amount); } given++; } catch { failedIds.push({ userId, reason: "Database error" }); } } await logStaffActivity({ staffId: staff.id, action: "bulk_give_currency", description: `Gave ${amount} ${type} to ${given} user(s)`, targetType: "user", }); return { ok: true as const, data: { given, total: userIds.length, failedIds } }; } export async function bulkGiveBadge({ userIds, badgeCode }: { userIds: number[]; badgeCode: string }) { const staff = await requireStaff(); let given = 0; const failedIds: Array<{ userId: number; reason: string }> = []; for (const userId of userIds) { try { const existing = await prisma.usersBadges.findFirst({ where: { userId, badgeCode }, select: { id: true }, }); if (!existing) { const max = await prisma.usersBadges.aggregate({ where: { userId }, _max: { slotId: true }, }); const slotId = (max._max.slotId ?? 0) + 1; await prisma.usersBadges.create({ data: { userId, slotId, badgeCode } }); await rcon.giveBadge(userId, badgeCode); } given++; } catch { failedIds.push({ userId, reason: "Database error" }); } } await logStaffActivity({ staffId: staff.id, action: "bulk_give_badge", description: `Gave badge "${badgeCode}" to ${given} user(s)`, targetType: "user", }); return { ok: true as const, data: { given, total: userIds.length, failedIds } }; }