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 { Config } from "./config";
|
||||||
import { logger } from "./logger";
|
import { logger } from "./logger";
|
||||||
import { fetchDiscord } from "./discord/core";
|
import * as Discord from "./discord";
|
||||||
|
|
||||||
const COMMANDS = [
|
const COMMANDS = [
|
||||||
{
|
{
|
||||||
@ -23,18 +23,55 @@ const COMMANDS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const registerCommand = async () => {
|
const normalizeCommand = (cmd: any) => ({
|
||||||
logger.info(
|
name: cmd.name,
|
||||||
{ command: COMMANDS, guildId: Config.DEFAULT_GUILD_ID },
|
description: cmd.description,
|
||||||
"Registering commands to discord server",
|
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 sortedNew = [...newCommands].sort((a, b) =>
|
||||||
const response = await fetchDiscord(
|
a.name.localeCompare(b.name),
|
||||||
`/applications/${Config.APP_ID}/guilds/${Config.DEFAULT_GUILD_ID}/commands`,
|
);
|
||||||
{
|
|
||||||
method: "POST",
|
for (let i = 0; i < sortedNew.length; i++) {
|
||||||
body: JSON.stringify(commmand),
|
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 "./audit-log";
|
||||||
export * from "./core";
|
export * from "./core";
|
||||||
export * from "./guild";
|
export * from "./guild";
|
||||||
|
|||||||
@ -3,12 +3,17 @@ import { Config } from "./config";
|
|||||||
import { logger } from "./logger";
|
import { logger } from "./logger";
|
||||||
import * as nacl from "tweetnacl";
|
import * as nacl from "tweetnacl";
|
||||||
import * as Discord from "./discord";
|
import * as Discord from "./discord";
|
||||||
|
import { registerCommand } from "./commands";
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
{ port: Config.PORT, guildId: Config.DEFAULT_GUILD_ID },
|
{ port: Config.PORT, guildId: Config.DEFAULT_GUILD_ID },
|
||||||
"Discord police bot is starting",
|
"Discord police bot is starting",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
registerCommand().catch((err) =>
|
||||||
|
logger.error(err, "Failed to register commands"),
|
||||||
|
);
|
||||||
|
|
||||||
const snowflakeToMs = (id: string) =>
|
const snowflakeToMs = (id: string) =>
|
||||||
Number((BigInt(id) >> BigInt(22)) + BigInt(1420070400000));
|
Number((BigInt(id) >> BigInt(22)) + BigInt(1420070400000));
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user