aethex-forge/api/discord/admin-register-commands.ts
Builder.io bbc717abda Fix type casting in admin register commands
cgen-281568370d5a4af6be6d5c043658f1c3
2025-11-16 07:08:36 +00:00

205 lines
6.1 KiB
TypeScript

import type { VercelRequest, VercelResponse } from "@vercel/node";
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",
},
];
const DISCORD_API_VERSION = "10";
const DISCORD_API_URL = `https://discord.com/api/v${DISCORD_API_VERSION}`;
export default async function handler(req: VercelRequest, res: VercelResponse) {
try {
// Allow both GET and POST
if (req.method !== "POST" && req.method !== "GET") {
res.setHeader("Allow", "GET, POST");
return res.status(405).json({ error: "Method not allowed" });
}
// Basic security: Check if requester has admin token
const authHeader = req.headers.authorization;
const queryToken = req.query.token;
const adminToken = process.env.DISCORD_ADMIN_REGISTER_TOKEN;
const providedToken = authHeader
? authHeader.replace("Bearer ", "")
: queryToken;
if (!adminToken || providedToken !== adminToken) {
return res.status(401).json({ error: "Unauthorized - Invalid token" });
}
// 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,
});
}
const botToken = process.env.DISCORD_BOT_TOKEN!;
const clientId = process.env.DISCORD_CLIENT_ID!;
const authorizationHeader = `Bot ${botToken}`;
console.log(`📝 Registering ${COMMANDS.length} Discord slash commands...`);
// Try bulk update first
try {
const bulkResponse = await fetch(
`${DISCORD_API_URL}/applications/${clientId}/commands`,
{
method: "PUT",
headers: {
Authorization: authorizationHeader,
"Content-Type": "application/json",
},
body: JSON.stringify(COMMANDS),
},
);
if (bulkResponse.ok) {
const data = (await bulkResponse.json()) as any[];
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),
});
}
// If bulk update failed, try individual registration
const errorData = (await bulkResponse.json()) as any;
const errorCode = errorData?.code;
if (errorCode === 50240) {
// Error 50240: Entry Point conflict (Discord Activity enabled)
console.warn(
"⚠️ Error 50240: Entry Point detected. Registering individually...",
);
const results = [];
let successCount = 0;
let skipCount = 0;
for (const command of COMMANDS) {
try {
const postResponse = await fetch(
`${DISCORD_API_URL}/applications/${clientId}/commands`,
{
method: "POST",
headers: {
Authorization: authorizationHeader,
"Content-Type": "application/json",
},
body: JSON.stringify(command),
},
);
if (postResponse.ok) {
const posted = await postResponse.json();
results.push({
name: command.name,
status: "registered",
id: posted.id,
});
successCount++;
} else if (postResponse.status === 400) {
// Error 50045: Command already exists
results.push({
name: command.name,
status: "already_exists",
});
skipCount++;
} else {
const errData = await postResponse.json();
results.push({
name: command.name,
status: "error",
error: errData.message || `HTTP ${postResponse.status}`,
});
}
} catch (postError: any) {
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 new Error(
`Discord API error: ${errorData?.message || bulkResponse.statusText}`,
);
} catch (error: any) {
console.error("❌ Failed to register commands:", error);
return res.status(500).json({
success: false,
error: error?.message || "Failed to register commands",
});
}
} catch (error: any) {
console.error("❌ Unexpected error:", error);
return res.status(500).json({
success: false,
error: error?.message || "Internal server error",
});
}
}