diff --git a/api/discord/admin-register-commands.ts b/api/discord/admin-register-commands.ts new file mode 100644 index 00000000..c6ed17c1 --- /dev/null +++ b/api/discord/admin-register-commands.ts @@ -0,0 +1,166 @@ +import type { VercelRequest, VercelResponse } from "@vercel/node"; +import { REST, Routes } from "discord.js"; + +interface CommandData { + name: string; + description: string; + options?: any[]; +} + +// Define all commands that should be registered +const COMMANDS: CommandData[] = [ + { + name: "verify", + description: "Link your Discord account to AeThex", + }, + { + name: "set-realm", + description: "Choose your primary arm/realm (Labs, GameForge, Corp, etc.)", + options: [ + { + name: "realm", + type: 3, + description: "Your primary realm", + required: true, + choices: [ + { name: "Labs", value: "labs" }, + { name: "GameForge", value: "gameforge" }, + { name: "Corp", value: "corp" }, + { name: "Foundation", value: "foundation" }, + { name: "Dev-Link", value: "devlink" }, + ], + }, + ], + }, + { + name: "profile", + description: "View your linked AeThex profile", + }, + { + name: "unlink", + description: "Disconnect your Discord account from AeThex", + }, + { + name: "verify-role", + description: "Check your assigned Discord roles", + }, +]; + +export default async function handler( + req: VercelRequest, + res: VercelResponse +) { + // Verify this is a POST request + if (req.method !== "POST") { + res.setHeader("Allow", "POST"); + return res.status(405).json({ error: "Method not allowed" }); + } + + // Basic security: Check if requester has admin token + const authHeader = req.headers.authorization; + const adminToken = process.env.DISCORD_ADMIN_REGISTER_TOKEN; + + if (!adminToken || authHeader !== `Bearer ${adminToken}`) { + return res.status(401).json({ error: "Unauthorized" }); + } + + // Validate environment variables + const requiredVars = ["DISCORD_BOT_TOKEN", "DISCORD_CLIENT_ID"]; + const missingVars = requiredVars.filter((v) => !process.env[v]); + + if (missingVars.length > 0) { + return res.status(500).json({ + error: "Missing environment variables", + missing: missingVars, + }); + } + + try { + const rest = new REST({ version: "10" }).setToken( + process.env.DISCORD_BOT_TOKEN! + ); + + console.log( + `📝 Registering ${COMMANDS.length} Discord slash commands...` + ); + + try { + // Try bulk update first + const data = await rest.put( + Routes.applicationCommands(process.env.DISCORD_CLIENT_ID!), + { body: COMMANDS } + ); + + console.log(`✅ Successfully registered ${data.length} slash commands`); + + return res.status(200).json({ + success: true, + message: `Registered ${data.length} slash commands`, + commands: (data as any[]).map((cmd: any) => cmd.name), + }); + } catch (bulkError: any) { + // Handle Error 50240 (Entry Point conflict) + if (bulkError.code === 50240) { + console.warn( + "⚠️ Error 50240: Entry Point detected. Registering individually..." + ); + + const results = []; + let successCount = 0; + let skipCount = 0; + + for (const command of COMMANDS) { + try { + // Try to post individual command + const posted = await rest.post( + Routes.applicationCommands(process.env.DISCORD_CLIENT_ID!), + { body: command } + ); + results.push({ + name: command.name, + status: "registered", + id: (posted as any).id, + }); + successCount++; + } catch (postError: any) { + // If command already exists (50045), skip it + if (postError.code === 50045) { + results.push({ + name: command.name, + status: "already_exists", + }); + skipCount++; + } else { + results.push({ + name: command.name, + status: "error", + error: postError.message, + }); + } + } + } + + console.log( + `✅ Registration complete: ${successCount} new, ${skipCount} already existed` + ); + + return res.status(200).json({ + success: true, + message: `Registered ${successCount} new commands (${skipCount} already existed)`, + results, + note: "Entry Point command is managed by Discord (Activities enabled)", + }); + } + + throw bulkError; + } + } catch (error: any) { + console.error("❌ Failed to register commands:", error); + + return res.status(500).json({ + success: false, + error: error?.message || "Failed to register commands", + code: error?.code, + }); + } +}