Files
Apollo/structs/Bot.ts
T
2024-10-26 20:33:18 +08:00

115 lines
3.7 KiB
TypeScript

import {
ApplicationCommandDataResolvable,
ChatInputCommandInteraction,
Client,
Collection,
Events,
Interaction,
REST,
Routes,
Snowflake
} from "discord.js";
import { readdirSync } from "fs";
import { join } from "path";
import { Command } from "../interfaces/Command";
import { checkPermissions, PermissionResult } from "../utils/checkPermissions";
import { config } from "../utils/config";
import { i18n } from "../utils/i18n";
import { MissingPermissionsException } from "../utils/MissingPermissionsException";
import { MusicQueue } from "./MusicQueue";
export class Bot {
public readonly prefix = "/";
public commands = new Collection<string, Command>();
public slashCommands = new Array<ApplicationCommandDataResolvable>();
public slashCommandsMap = new Collection<string, Command>();
public cooldowns = new Collection<string, Collection<Snowflake, number>>();
public queues = new Collection<Snowflake, MusicQueue>();
public constructor(public readonly client: Client) {
this.client.login(config.TOKEN);
this.client.on("ready", () => {
console.log(`${this.client.user!.username} ready!`);
this.registerSlashCommands();
});
this.client.on("warn", (info) => console.log(info));
this.client.on("error", console.error);
this.onInteractionCreate();
}
private async registerSlashCommands() {
const rest = new REST({ version: "9" }).setToken(config.TOKEN);
const commandFiles = readdirSync(join(__dirname, "..", "commands")).filter((file) => !file.endsWith(".map"));
for (const file of commandFiles) {
const command = await import(join(__dirname, "..", "commands", `${file}`));
this.slashCommands.push(command.default.data);
this.slashCommandsMap.set(command.default.data.name, command.default);
}
await rest.put(Routes.applicationCommands(this.client.user!.id), { body: this.slashCommands });
}
private async onInteractionCreate() {
this.client.on(Events.InteractionCreate, async (interaction: Interaction): Promise<any> => {
if (!interaction.isChatInputCommand()) return;
const command = this.slashCommandsMap.get(interaction.commandName);
if (!command) return;
if (!this.cooldowns.has(interaction.commandName)) {
this.cooldowns.set(interaction.commandName, new Collection());
}
const now = Date.now();
const timestamps = this.cooldowns.get(interaction.commandName)!;
const cooldownAmount = (command.cooldown || 1) * 1000;
const timestamp = timestamps.get(interaction.user.id);
if (timestamp) {
const expirationTime = timestamp + cooldownAmount;
if (now < expirationTime) {
const timeLeft = (expirationTime - now) / 1000;
return interaction.reply({
content: i18n.__mf("common.cooldownMessage", {
time: timeLeft.toFixed(1),
name: interaction.commandName
}),
ephemeral: true
});
}
}
timestamps.set(interaction.user.id, now);
setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount);
try {
const permissionsCheck: PermissionResult = await checkPermissions(command, interaction);
if (permissionsCheck.result) {
command.execute(interaction as ChatInputCommandInteraction);
} else {
throw new MissingPermissionsException(permissionsCheck.missing);
}
} catch (error: any) {
console.error(error);
if (error.message.includes("permissions")) {
interaction.reply({ content: error.toString(), ephemeral: true }).catch(console.error);
} else {
interaction.reply({ content: i18n.__("common.errorCommand"), ephemeral: true }).catch(console.error);
}
}
});
}
}