import { NextRequest, NextResponse } from "next/server"; import { existsSync } from "fs"; import { join } from "path"; import { exec } from "child_process"; import { auth } from "@/lib/auth"; import { removeMod, isClientOnlyMod, waitForServer, rebuildModpack } from "@/lib/mods"; import { createSnapshot, restoreSnapshot, listSnapshots } from "@/lib/snapshots"; import { MODS_DIR, CLIENT_MODS_DIR } from "@/lib/constants"; function restartServer(): Promise { return new Promise((resolve, reject) => { exec("sudo systemctl restart minecraft.service", (err) => { if (err) reject(err); else resolve(); }); }); } export async function POST(req: NextRequest) { const session = await auth(); if (!session) { return NextResponse.json({ error: "Unauthorized" }, { status: 403 }); } const { filename } = await req.json(); if (!filename || !filename.endsWith(".jar")) { return NextResponse.json({ error: "Invalid filename" }, { status: 400 }); } if (filename.includes("/") || filename.includes("\\")) { return NextResponse.json({ error: "Invalid filename" }, { status: 400 }); } const inServerDir = existsSync(join(MODS_DIR, filename)); const inClientDir = existsSync(join(CLIENT_MODS_DIR, filename)); if (!inServerDir && !inClientDir) { return NextResponse.json({ error: "Mod not found" }, { status: 404 }); } // Create snapshot before removing const snapName = `before-remove-${filename.replace(".jar", "")}`; createSnapshot(snapName); const clientOnly = !inServerDir && inClientDir; // Remove the mod removeMod(filename); if (clientOnly) { // Client-only mod — no restart needed try { rebuildModpack(); } catch {} return NextResponse.json({ success: true, message: `Removed client-only mod "${filename}". No server restart needed.`, }); } // Server mod — restart and verify try { await restartServer(); } catch (e) { const snaps = listSnapshots(); const snap = snaps[0]; if (snap) restoreSnapshot(snap.dirName); return NextResponse.json({ success: false, message: `Restart failed: ${(e as Error).message}`, rolledBack: true, }); } const online = await waitForServer(90000); if (online) { try { rebuildModpack(); } catch {} return NextResponse.json({ success: true, message: `Removed "${filename}". Server is online.`, }); } else { // Rollback const snaps = listSnapshots(); const snap = snaps[0]; if (snap) { restoreSnapshot(snap.dirName); try { await restartServer(); await waitForServer(90000); try { rebuildModpack(); } catch {} } catch {} } return NextResponse.json({ success: false, message: `Server failed after removing "${filename}". Rolled back.`, rolledBack: true, }); } }