import { auth } from '@/auth' import { db } from '@/lib/db' import { machines } from '@/lib/db/schema' import { and, eq } from 'drizzle-orm' import { NextRequest, NextResponse } from 'next/server' import { createSocket } from 'dgram' function buildMagicPacket(mac: string): Buffer { // Normalise: strip separators, expect 12 hex chars const hex = mac.replace(/[:\-]/g, '').toLowerCase() if (hex.length !== 12 || !/^[0-9a-f]+$/.test(hex)) { throw new Error('Invalid MAC address') } const macBytes = Buffer.from(hex, 'hex') // Magic packet: 6x 0xFF + 16x MAC const packet = Buffer.alloc(6 + 16 * 6) packet.fill(0xff, 0, 6) for (let i = 0; i < 16; i++) macBytes.copy(packet, 6 + i * 6) return packet } async function sendMagicPacket(mac: string): Promise { const packet = buildMagicPacket(mac) return new Promise((resolve, reject) => { const sock = createSocket('udp4') sock.once('error', reject) sock.bind(() => { sock.setBroadcast(true) sock.send(packet, 0, packet.length, 9, '255.255.255.255', () => { sock.close() resolve() }) }) }) } export async function POST(request: NextRequest) { const session = await auth() if (!session?.user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) const { machineId } = await request.json() if (!machineId) return NextResponse.json({ error: 'machineId required' }, { status: 400 }) const result = await db .select({ macAddress: machines.macAddress, name: machines.name }) .from(machines) .where(and(eq(machines.id, machineId), eq(machines.userId, session.user.id))) .limit(1) const machine = result[0] if (!machine) return NextResponse.json({ error: 'Machine not found' }, { status: 404 }) if (!machine.macAddress) return NextResponse.json({ error: 'No MAC address recorded for this machine. Agent must reconnect at least once.' }, { status: 422 }) try { await sendMagicPacket(machine.macAddress) return NextResponse.json({ success: true, message: `Magic packet sent to ${machine.macAddress}` }) } catch (e) { return NextResponse.json({ error: String(e) }, { status: 500 }) } }