Skip to content

Commit

Permalink
refactor: replace path discovery of commands with commandHandler.addC…
Browse files Browse the repository at this point in the history
…ommand

Path discovery has faults; two I discovered are:
- command files aren’t included in checks when run with bun (because
they aren’t part of the file tree)
- Ignoring a command is not possible
  • Loading branch information
tippfehlr committed Aug 11, 2024
1 parent 844c3b9 commit 3fcfa8a
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 72 deletions.
2 changes: 0 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { db, initDB } from './modules/db';
import { connect } from './modules/bot';
import { writeApi } from './modules/metrics';
import { uploadCommands } from './modules/syncCommands';
import config from './modules/config';

export async function close() {
Expand All @@ -15,7 +14,6 @@ async function main() {
process.on('SIGINT', close);
process.on('SIGTERM', close);

if (!config.SKIP_COMMAND_UPLOAD) await uploadCommands();
await initDB();
await connect();
}
Expand Down
38 changes: 32 additions & 6 deletions src/modules/bot.ready.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,43 @@
import { ActivityType, Events } from 'discord.js';
import { getUserCount, getRolesCount, db } from './db';
import { i18n, log } from './messages';

import { client } from './bot';
import CommandHandler from './commandHandler';
import config from './config';
import { configureInfluxDB } from './metrics';
import { client } from './bot';
import { checkRoles } from './commands/checkRoles';
import { getUserCount, getRolesCount, db } from './db';
import { i18n, log } from './messages';

import activityStats from './commands/activityStats';
import addActivityRole from './commands/addActivityRole';
import checkRoles, { checkRolesStandalone } from './commands/checkRoles';
import deleteActivityRole from './commands/deleteActivityRole';
import _export from './commands/export';
import help from './commands/help';
import listRoles from './commands/listRoles';
import requireRole from './commands/requireRole';
import setStatusRole from './commands/setStatusRole';
import stats from './commands/stats';
import toggleAutoRole from './commands/toggleAutoRole';

export let commandHandler: CommandHandler;

export function initClientReady() {
client.on(Events.ClientReady, async () => {
configureInfluxDB();
commandHandler = new CommandHandler(client);
commandHandler = new CommandHandler(client)
.addCommand(activityStats)
.addCommand(addActivityRole)
.addCommand(checkRoles)
.addCommand(deleteActivityRole)
.addCommand(_export)
.addCommand(help)
.addCommand(listRoles)
.addCommand(requireRole)
.addCommand(setStatusRole)
.addCommand(stats)
.addCommand(toggleAutoRole);
if (!config.SKIP_COMMAND_UPLOAD) await commandHandler.uploadCommands();

const setActivityGuilds = () => {
client.user?.setPresence({
status: 'online',
Expand Down Expand Up @@ -98,7 +124,7 @@ async function checkGuilds() {
for (const { guildID } of guildsToCheck) {
await delay(30 * 1000);
const guild = client.guilds.cache.get(guildID);
if (guild) await checkRoles({ guild });
if (guild) await checkRolesStandalone({ guild });
}
}

Expand Down
70 changes: 40 additions & 30 deletions src/modules/commandHandler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { Client, CommandInteraction, InteractionType, SlashCommandBuilder } from 'discord.js';
import fs from 'fs';
import path from 'path';
import {
Client,
CommandInteraction,
InteractionType,
SlashCommandBuilder,
REST,
Routes,
} from 'discord.js';

import config from './config';
import { getLang } from './db';
import { log, __ } from './messages';

Expand All @@ -9,24 +16,13 @@ export interface Command {
execute(interaction: CommandInteraction): Promise<void>;
}

const defaultOptions = {
commandsDir: './commands/',
commandFileExtension: ['.js', '.ts'] as string[]
};

export default class CommandHandler {
private client: Client;
private options: typeof defaultOptions;
public commands: Map<Command['data']['name'], Command>;

constructor(client: Client, options = defaultOptions) {
constructor(client: Client) {
this.client = client;
this.options = options;

this.commands = this.getCommandFiles(
this.options.commandsDir,
this.options.commandFileExtension
);
this.commands = new Map();

client.on('interactionCreate', async interaction => {
if (interaction.type !== InteractionType.ApplicationCommand) return;
Expand All @@ -39,26 +35,40 @@ export default class CommandHandler {
await interaction.reply({
content: __({
phrase: 'There was an error while executing this command!',
locale: getLang(interaction)
locale: getLang(interaction),
}),
ephemeral: true
ephemeral: true,
});
}
});
}

getCommandFiles(commandsDir: string, commandFileExtension: string | string[]) {
const commands = new Map();
const commandFiles = fs.readdirSync(path.join(__dirname, commandsDir)).filter(file => {
for (const extension of commandFileExtension) {
if (file.endsWith(extension)) return true;
}
return false;
});
for (const file of commandFiles) {
const command: Command = require(commandsDir + file).default as Command;
commands.set(command.data.name, command);
public addCommand(command: Command) {
this.commands.set(command.data.name, command);
return this;
}

public async uploadCommands() {
let commandsJSON: any[] = [];

for (const [, command] of this.commands) {
commandsJSON.push(command.data.toJSON());
}

const rest = new REST().setToken(config.TOKEN);

log.info(`Started refreshing ${commandsJSON.length} application (/) commands.`);
let data: any;
if (config.GUILD) {
data = await rest.put(Routes.applicationGuildCommands(config.APPLICATION_ID, config.GUILD), {
body: commandsJSON,
});
} else {
data = await rest.put(Routes.applicationCommands(config.APPLICATION_ID), {
body: commandsJSON,
});
}
return commands as typeof this.commands;
log.info(`Successfully reloaded ${data.length} application (/) commands.`);
return this;
}
}
4 changes: 2 additions & 2 deletions src/modules/commands/checkRoles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ export default {
execute: async interaction => {
if (!interaction.guild) return;
const locale = getLang(interaction);
checkRoles({ guild: interaction.guild, interaction, locale });
checkRolesStandalone({ guild: interaction.guild, interaction, locale });
},
} as Command;

export async function checkRoles({
export async function checkRolesStandalone({
guild,
interaction,
locale,
Expand Down
32 changes: 0 additions & 32 deletions src/modules/syncCommands.ts

This file was deleted.

0 comments on commit 3fcfa8a

Please sign in to comment.