Improve typing.
All checks were successful
Build and Publish Docker Image / build_and_push (push) Successful in 42s

This commit is contained in:
2024-09-16 14:13:37 +00:00
parent 73d06b2a54
commit 3a9fc1897a
8 changed files with 125 additions and 68 deletions

View File

@@ -1,33 +0,0 @@
import * as birthday from './commands/birthday';
import * as corrupt from './commands/corrupt';
import * as countdown from './commands/countdown';
import * as eyecandy from './commands/eyecandy';
import * as game from './commands/game';
import * as image from './commands/image';
import * as imdb from './commands/imdb';
import * as kanye from './commands/kanye';
import * as magicEightBall from './commands/magic8Ball';
import * as payday from './commands/payday';
import * as plant from './commands/plant';
import * as reminder from './commands/reminder';
import * as servertime from './commands/servertime';
import * as taylor from './commands/taylor';
import * as twentyTwenty from './commands/twentyTwenty';
export const commands = {
birthday,
corrupt,
countdown,
eyecandy,
game,
image,
imdb,
kanye,
magicEightBall,
payday,
plant,
reminder,
servertime,
taylor,
twentyTwenty,
};

View File

@@ -10,9 +10,10 @@ interface Config {
omdbApiKey: string;
replicateApiKey: string;
mongodbUri: string;
registerSlashCommands?: boolean;
}
const getEnv = (key: string, required = true): string | undefined => {
const getEnv = (key: string, required = true): string | boolean | undefined => {
const value = process.env[key];
if (!value && required) {
throw new Error(`${key} is not set in the environment variables.`);
@@ -28,6 +29,7 @@ const config: Config = {
omdbApiKey: getEnv('OMDB_API_KEY') as string,
replicateApiKey: getEnv('REPLICATE_API_KEY') as string,
mongodbUri: getEnv('MONGODB_URI') as string,
registerSlashCommands: getEnv('REGISTER_SLASH_COMMANDS', false) as boolean,
};
export default config;

View File

@@ -6,25 +6,50 @@ import {
GatewayIntentBits,
Interaction,
} from 'discord.js';
import { commands } from './commands';
import { getCommands, registerSlashCommands } from './utils/commands';
import { Command } from './utils/types';
import config from './config';
// Define an extended version of the Client interface to include commands
interface ExtendedClient extends Client {
commands: Collection<string, any>;
commands: Collection<string, Command>;
}
const client: ExtendedClient = new Client({
intents: [GatewayIntentBits.Guilds],
}) as ExtendedClient;
// Add the commands to the client
client.commands = getCommands();
// If REGISTER_SLASH_COMMANDS is set to true, register the commands.
if (config.registerSlashCommands) {
registerSlashCommands(client.commands)
.then(() => {
console.log('Successfully registered slash commands');
})
.catch((error) => {
console.error('Failed to register slash commands:', error);
process.exit(1);
});
}
// Register the event listener for command interactions.
client.on(Events.InteractionCreate, async (interaction: Interaction) => {
if (!interaction.isChatInputCommand()) return;
const { commandName } = interaction;
const command = client.commands.get(interaction.commandName);
if (commands[commandName as keyof typeof commands]) {
commands[commandName as keyof typeof commands].execute(interaction);
if (command) {
try {
await command.execute(interaction);
} catch (error) {
console.error(`Error executing ${interaction.commandName}:`, error);
await interaction.reply({
content: 'There was an error executing that command!',
ephemeral: true,
});
}
}
});

View File

@@ -1,25 +0,0 @@
import { REST, Routes } from 'discord.js';
import { commands } from './commands';
import config from './config';
// Register all slash commands, globally across all Guilds.
const commandData = Object.values(commands).map(
(command) => command.data.toJSON() as any
);
const rest = new REST().setToken(config.discordApiKey);
try {
console.log('Started refreshing application (/) commands.');
// Refresh all slash commands globally.
rest.put(Routes.applicationCommands(config.discordApplicationId), {
body: commandData,
});
// Exit the process.
process.exit();
} catch (error) {
// And of course, make sure you catch and log any errors!
console.error(error);
}

View File

@@ -0,0 +1,12 @@
import { getCommands, registerSlashCommands } from './utils/commands';
const commands = getCommands();
registerSlashCommands(commands)
.then(() => {
console.log('Successfully registered slash commands');
})
.catch((error) => {
console.error('Failed to register slash commands:', error);
process.exit(1);
});

58
src/utils/commands.ts Normal file
View File

@@ -0,0 +1,58 @@
import { Collection, REST, Routes } from 'discord.js';
import * as birthday from '../commands/birthday';
import * as corrupt from '../commands/corrupt';
import * as countdown from '../commands/countdown';
import * as eyecandy from '../commands/eyecandy';
import * as game from '../commands/game';
import * as image from '../commands/image';
import * as imdb from '../commands/imdb';
import * as kanye from '../commands/kanye';
import * as magicEightBall from '../commands/magic8Ball';
import * as payday from '../commands/payday';
import * as plant from '../commands/plant';
import * as reminder from '../commands/reminder';
import * as servertime from '../commands/servertime';
import * as taylor from '../commands/taylor';
import * as twentyTwenty from '../commands/twentyTwenty';
import config from '../config';
import { Command } from './types';
/**
* Get all commands as a collection.
* @returns A collection of commands.
*/
export function getCommands(): Collection<string, Command> {
const commands = new Collection<string, Command>();
commands.set(birthday.data.name, birthday);
commands.set(corrupt.data.name, corrupt);
commands.set(countdown.data.name, countdown);
commands.set(eyecandy.data.name, eyecandy);
commands.set(game.data.name, game);
commands.set(image.data.name, image);
commands.set(imdb.data.name, imdb);
commands.set(kanye.data.name, kanye);
commands.set(magicEightBall.data.name, magicEightBall);
commands.set(payday.data.name, payday);
commands.set(plant.data.name, plant);
commands.set(reminder.data.name, reminder);
commands.set(servertime.data.name, servertime);
commands.set(taylor.data.name, taylor);
commands.set(twentyTwenty.data.name, twentyTwenty);
return commands;
}
/**
* Register all slash commands globally across all Guilds.
* @param commands A collection of commands to register.
*/
export async function registerSlashCommands(
commands: Collection<string, Command>
) {
const commandData = commands.map((command) => command.data.toJSON());
const rest = new REST({ version: '10' }).setToken(config.discordApiKey);
await rest.put(Routes.applicationCommands(config.discordApplicationId), {
body: commandData,
});
}

18
src/utils/types.ts Normal file
View File

@@ -0,0 +1,18 @@
import {
SlashCommandBuilder,
SlashCommandSubcommandsOnlyBuilder,
SlashCommandOptionsOnlyBuilder,
ChatInputCommandInteraction,
} from 'discord.js';
// Create a generic type to cover all relevant SlashCommandBuilder types
export type CommandBuilder =
| SlashCommandBuilder
| SlashCommandSubcommandsOnlyBuilder
| SlashCommandOptionsOnlyBuilder;
// Define the Command interface
export interface Command {
data: CommandBuilder; // Use the generic CommandBuilder type
execute: (interaction: ChatInputCommandInteraction) => Promise<void>;
}