Files
AzerothAI/app/api/ale/operator/route.ts
T
2026-09-25 18:19:50 -07:00

37 lines
1.9 KiB
TypeScript

import { env } from 'cloudflare:workers';
import { z } from 'zod';
import { requireAleOperator,rawAleEnabled } from '@/core/ale-auth';
import {runGM} from '@/core/gm';
import { compileAleOperatorRequest } from '@/core/ale';
import { queueAleCommand } from '@/core/ale-store';
import type { RuntimeConfig } from '@/core/types';
const scalar=z.union([z.string(),z.number(),z.boolean(),z.null()]);
const schema=z.discriminatedUnion('kind',[
z.object({kind:z.literal('command'),command:z.string().min(1).max(500)}),
z.object({kind:z.literal('global'),method:z.string().min(1).max(100),args:z.array(scalar).max(32).optional()}),
z.object({kind:z.literal('player'),player:z.string().min(1).max(24),method:z.string().min(1).max(100),args:z.array(scalar).max(32).optional()}),
z.object({kind:z.literal('playerbotAI'),player:z.string().min(1).max(24),method:z.string().min(1).max(100),args:z.array(scalar).max(32).optional()}),
z.object({kind:z.literal('raw'),source:z.string().min(1).max(12000)})
]);
export async function POST(request:Request){
const config=env as unknown as RuntimeConfig;
try{
requireAleOperator(request,config);
const text=await request.text();if(text.length>16000)return Response.json({error:'Request too large'},{status:413});
const body=schema.parse(JSON.parse(text));
if(config.GAME_BACKEND==='cmangos-classic'){
if(body.kind!=='command')throw new Error('Classic supports native GM commands here; Lua/ALE methods belong to the Wrath backend.');
const result=await runGM(body.command,true,true,config);
return Response.json({ok:true,result});
}
const source=compileAleOperatorRequest(body,rawAleEnabled(config));
const queued=await queueAleCommand(env.DB!,source);
return Response.json({ok:true,command:queued},{status:202});
}catch(e){
const message=e instanceof Error?e.message:'ALE operator failure';
return Response.json({error:message},{status:message.startsWith('Unauthorized')?401:400});
}
}