diff --git a/README.md b/README.md index 724878b..43c13ae 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ SQLite default tersimpan di `./data/booster-role.sqlite`. bun run dev ``` +Saat startup, bot otomatis register slash command ke guild dari `DISCORD_GUILD_ID`. Pastikan bot di-invite dengan scope `applications.commands`. + ## Testing ```bash diff --git a/src/discord/registerCommands.test.ts b/src/discord/registerCommands.test.ts new file mode 100644 index 0000000..f018652 --- /dev/null +++ b/src/discord/registerCommands.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, test } from "bun:test"; +import { registerGuildCommands, type DiscordRestClient } from "./registerCommands"; + +class FakeRestClient implements DiscordRestClient { + route: string | null = null; + body: unknown = null; + + async put(route: string, input: { body: unknown }): Promise { + this.route = route; + this.body = input.body; + return null; + } +} + +describe("registerGuildCommands", () => { + test("registers booster role command to the configured guild", async () => { + const rest = new FakeRestClient(); + + await registerGuildCommands(rest, { clientId: "client", guildId: "guild" }); + + expect(rest.route).toBe("/applications/client/guilds/guild/commands"); + expect(rest.body).toEqual([ + expect.objectContaining({ name: "booster-role", description: "Manage your cosmetic booster role" }) + ]); + }); +}); diff --git a/src/discord/registerCommands.ts b/src/discord/registerCommands.ts new file mode 100644 index 0000000..480b716 --- /dev/null +++ b/src/discord/registerCommands.ts @@ -0,0 +1,22 @@ +import { REST, Routes } from "discord.js"; +import { boosterRoleCommand } from "./commands/booster-role"; + +export type DiscordRestClient = { + put(route: string, input: { body: unknown }): Promise; +}; + +export type RegisterCommandsConfig = { + clientId: string; + guildId: string; +}; + +export async function registerGuildCommands(rest: DiscordRestClient, config: RegisterCommandsConfig): Promise { + await rest.put(Routes.applicationGuildCommands(config.clientId, config.guildId), { + body: [boosterRoleCommand.toJSON()] + }); +} + +export async function registerGuildCommandsWithToken(token: string, config: RegisterCommandsConfig): Promise { + const rest = new REST({ version: "10" }).setToken(token); + await registerGuildCommands(rest, config); +} diff --git a/src/index.ts b/src/index.ts index a6b3c84..a15298f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,16 @@ import { loadConfig } from "./config"; import { createDiscordClient } from "./discord/client"; +import { registerGuildCommandsWithToken } from "./discord/registerCommands"; const config = loadConfig(); +await registerGuildCommandsWithToken(config.discordToken, { + clientId: config.discordClientId, + guildId: config.discordGuildId +}); + const client = createDiscordClient(); -client.once("ready", () => { +client.once("clientReady", () => { console.log(`Logged in as ${client.user?.tag ?? "unknown bot"}`); });