feat: implement command registration and management with Discord API
This commit is contained in:
parent
4248c75bd6
commit
fa0584c550
@ -1,6 +1,6 @@
|
||||
import { Config } from "./config";
|
||||
import { logger } from "./logger";
|
||||
import { fetchDiscord } from "./discord/core";
|
||||
import * as Discord from "./discord";
|
||||
|
||||
const COMMANDS = [
|
||||
{
|
||||
@ -23,18 +23,55 @@ const COMMANDS = [
|
||||
},
|
||||
];
|
||||
|
||||
export const registerCommand = async () => {
|
||||
logger.info(
|
||||
{ command: COMMANDS, guildId: Config.DEFAULT_GUILD_ID },
|
||||
"Registering commands to discord server",
|
||||
const normalizeCommand = (cmd: any) => ({
|
||||
name: cmd.name,
|
||||
description: cmd.description,
|
||||
type: cmd.type,
|
||||
options: (cmd.options || [])
|
||||
.map((o: any) => ({
|
||||
name: o.name,
|
||||
description: o.description,
|
||||
type: o.type,
|
||||
required: o.required || false,
|
||||
}))
|
||||
.sort((a: any, b: any) => a.name.localeCompare(b.name)),
|
||||
});
|
||||
|
||||
const commandsAreEqual = (existingCommands: any[], newCommands: any[]) => {
|
||||
if (existingCommands.length !== newCommands.length) return false;
|
||||
|
||||
const sortedExisting = [...existingCommands].sort((a, b) =>
|
||||
a.name.localeCompare(b.name),
|
||||
);
|
||||
for (const commmand of COMMANDS) {
|
||||
const response = await fetchDiscord(
|
||||
`/applications/${Config.APP_ID}/guilds/${Config.DEFAULT_GUILD_ID}/commands`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(commmand),
|
||||
},
|
||||
);
|
||||
const sortedNew = [...newCommands].sort((a, b) =>
|
||||
a.name.localeCompare(b.name),
|
||||
);
|
||||
|
||||
for (let i = 0; i < sortedNew.length; i++) {
|
||||
if (
|
||||
JSON.stringify(normalizeCommand(sortedExisting[i])) !==
|
||||
JSON.stringify(normalizeCommand(sortedNew[i]))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const registerCommand = async () => {
|
||||
try {
|
||||
logger.info("Checking for command updates...");
|
||||
const existingCommands = await Discord.getGuildCommands();
|
||||
|
||||
if (commandsAreEqual(existingCommands, COMMANDS)) {
|
||||
logger.info("Commands are already up to date.");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Commands are different, registering...");
|
||||
await Discord.bulkOverwriteGuildCommands(COMMANDS);
|
||||
logger.info("Commands registered successfully.");
|
||||
} catch (error) {
|
||||
logger.error(error, "Failed to register commands");
|
||||
}
|
||||
};
|
||||
|
||||
58
src/discord/application.ts
Normal file
58
src/discord/application.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { fetchDiscord } from "./core";
|
||||
import { Config } from "../config";
|
||||
|
||||
export interface Application {
|
||||
id: string;
|
||||
name: string;
|
||||
icon: string | null;
|
||||
description: string;
|
||||
bot_public: boolean;
|
||||
bot_require_code_grant: boolean;
|
||||
team: any | null;
|
||||
}
|
||||
|
||||
export const getCurrentApplication = async (): Promise<Application> => {
|
||||
const res = await fetchDiscord("/applications/@me");
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to get current application: ${res.status}`);
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export const editCurrentApplication = async (data: any): Promise<Application> => {
|
||||
const res = await fetchDiscord("/applications/@me", {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to edit current application: ${res.status}`);
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export const getGuildCommands = async () => {
|
||||
const res = await fetchDiscord(
|
||||
`/applications/${Config.APP_ID}/guilds/${Config.DEFAULT_GUILD_ID}/commands`,
|
||||
);
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to get guild commands: ${res.status}`);
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export const bulkOverwriteGuildCommands = async (commands: any[]) => {
|
||||
const res = await fetchDiscord(
|
||||
`/applications/${Config.APP_ID}/guilds/${Config.DEFAULT_GUILD_ID}/commands`,
|
||||
{
|
||||
method: "PUT",
|
||||
body: JSON.stringify(commands),
|
||||
},
|
||||
);
|
||||
if (!res.ok) {
|
||||
const error = await res.text();
|
||||
throw new Error(
|
||||
`Failed to bulk overwrite guild commands: ${res.status} ${error}`,
|
||||
);
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
@ -1,3 +1,4 @@
|
||||
export * from "./application";
|
||||
export * from "./audit-log";
|
||||
export * from "./core";
|
||||
export * from "./guild";
|
||||
|
||||
@ -3,12 +3,17 @@ import { Config } from "./config";
|
||||
import { logger } from "./logger";
|
||||
import * as nacl from "tweetnacl";
|
||||
import * as Discord from "./discord";
|
||||
import { registerCommand } from "./commands";
|
||||
|
||||
logger.info(
|
||||
{ port: Config.PORT, guildId: Config.DEFAULT_GUILD_ID },
|
||||
"Discord police bot is starting",
|
||||
);
|
||||
|
||||
registerCommand().catch((err) =>
|
||||
logger.error(err, "Failed to register commands"),
|
||||
);
|
||||
|
||||
const snowflakeToMs = (id: string) =>
|
||||
Number((BigInt(id) >> BigInt(22)) + BigInt(1420070400000));
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user