diff --git a/apps/bot/src/services/cmd/registry/stats.ts b/apps/bot/src/cmd/registry/stats.ts similarity index 89% rename from apps/bot/src/services/cmd/registry/stats.ts rename to apps/bot/src/cmd/registry/stats.ts index fb9df17..d838251 100644 --- a/apps/bot/src/services/cmd/registry/stats.ts +++ b/apps/bot/src/cmd/registry/stats.ts @@ -1,6 +1,6 @@ import { EmbedBuilder, type Message } from "discord.js"; -import type { Command } from "../service"; -import { api } from "../../../util"; +import type { Command } from "../../models"; +import { api } from "../../util"; const ATTRIBUTE_EMOJI: Record = { Strength: "💪", @@ -12,8 +12,11 @@ const ATTRIBUTE_EMOJI: Record = { export default { name: "stats", description: "View your fitness statistics!", + usage: ".stats", execute: async (message: Message) => { const res = await api.accounts({ id: `@${message.author.id}` }).stats.get(); + if (res.error) return; + if (!res.data) { await message.reply("No stats found yet — submit an assessment first!"); return; @@ -38,4 +41,4 @@ export default { await message.reply({ embeds: [embed] }); } -} as Command; +} satisfies Command; diff --git a/apps/bot/src/index.ts b/apps/bot/src/index.ts index d258c63..fa6559c 100644 --- a/apps/bot/src/index.ts +++ b/apps/bot/src/index.ts @@ -1,20 +1,13 @@ import { Client, Events, GatewayIntentBits } from 'discord.js'; -import { CommandService } from './services/cmd/service'; +import CommandService from './services/command'; const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent] }); -// SERVICES -// ----------------------- -const s = (() => { - const Commands = new CommandService(client); - return { Commands }; -})(); - client.once(Events.ClientReady, async (readyClient) => { - // Initialize - await s.Commands.init(); + // Initialize services + await CommandService.init(); console.log(`Ready! Logged in as ${readyClient.user.tag}`); }); @@ -25,8 +18,13 @@ client.on("guildMemberAdd", async (guildMember) => { client.on("messageCreate", async (message) => { if (message.author.bot) return; - const command = s.Commands.parse(message); - if (command) command.execute(message); + try { + const command = CommandService.parse(message); + if (command) await command.execute(message); + } + catch (err) { + console.error(err); + } }); client.login(Bun.env.BOT_TOKEN); diff --git a/apps/bot/src/models.ts b/apps/bot/src/models.ts new file mode 100644 index 0000000..cf920db --- /dev/null +++ b/apps/bot/src/models.ts @@ -0,0 +1,10 @@ +import type { Message } from "discord.js"; + +// COMMANDS + +export interface Command { + name: string, + description: string, + usage: string, + execute: (message: Message) => void | Promise +} diff --git a/apps/bot/src/services/cmd/service.ts b/apps/bot/src/services/cmd/service.ts deleted file mode 100644 index 4b30d16..0000000 --- a/apps/bot/src/services/cmd/service.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { Client, Message } from "discord.js"; -import { readdir } from "fs/promises"; - -const CMD_PREFIX = "."; - -export interface Command { - name: string, - description: string, - execute: (message: Message) => void | Promise -} - -export class CommandService { - private client: Client - private registry: Record = {} - - constructor(client: Client) { - this.client = client; - } - - async init() { - const commands = await Promise.all( - (await readdir(`${import.meta.dir}/registry`)).map(async file => (await import(`./registry/${file}`)).default as Command) - ); - for (const command of commands) - this.registry[command.name] = command; - }; - - parse(message: Message): Command | undefined { - if (!message.content.startsWith(CMD_PREFIX)) return; - const name = message.content.slice(CMD_PREFIX.length).split(/\s+/)[0]; - return this.registry[name ?? ""]; - } -} diff --git a/apps/bot/src/services/command.ts b/apps/bot/src/services/command.ts new file mode 100644 index 0000000..e4d066a --- /dev/null +++ b/apps/bot/src/services/command.ts @@ -0,0 +1,25 @@ +import type { Message } from "discord.js"; +import { readdir } from "fs/promises"; +import { dirname } from "path"; +import type { Command } from "../models"; + +const CMD_PREFIX = "."; +const CMD_REGISTRY_DIR = `${dirname(Bun.main)}/cmd/registry`; + +export default abstract class CommandService { + private static registry: Record = {} + + static async init() { + const commands = await Promise.all( + (await readdir(CMD_REGISTRY_DIR)).map(async file => (await import(`${CMD_REGISTRY_DIR}/${file}`)).default satisfies Command) + ); + for (const command of commands) + CommandService.registry[command.name] = command; + }; + + static parse(message: Message): Command | undefined { + if (!message.content.startsWith(CMD_PREFIX)) return; + const name = message.content.slice(CMD_PREFIX.length).split(/\s+/)[0]; + return this.registry[name ?? ""]; + } +}