Create admin endpoint to register Discord commands from web UI
cgen-313ec6ce04ef4104b5e86da3c2e89329
This commit is contained in:
parent
53bb0c8eb0
commit
332f7c2803
1 changed files with 166 additions and 0 deletions
166
api/discord/admin-register-commands.ts
Normal file
166
api/discord/admin-register-commands.ts
Normal file
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue