Guide discord.js
Créer votre application

Gestion des commandes

Sauf si votre projet bot est petit, ce n'est pas une très bonne idée d'avoir un seul fichier avec une chaîne géante if/else if pour les commandes. Si vous voulez implémenter des fonctionnalités dans votre bot et rendre votre processus de développement beaucoup moins douloureux, vous voudrez implémenter un gestionnaire de commandes. Commençons !

Pour les commandes slash pleinement fonctionnelles, vous avez besoin de trois éléments de code importants :

Command Files

The individual command files, containing slash command definitions and functionality.

Command Handler

The command handler, dynamically reads the command files and executes commands.

Command Deployment

The command deployment script to register your slash commands with Discord.

Ces étapes peuvent être suivies dans n'importe quel ordre, mais sont toutes nécessaires pour que votre bot fonctionne. Cette page détaille l'étape 2. Assurez-vous de vérifier les autres pages liées.

Chargement des fichiers de commande

Maintenant que vos fichiers de commande ont été créés, votre bot doit charger ces fichiers au démarrage.

In your index.js file, make these additions to the base template:

index.js
const fs = require('node:fs');
const path = require('node:path');
const { Client, Collection, Events, GatewayIntentBits, MessageFlags } = require('discord.js');
const { token } = require('./config.json');

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.once(Events.ClientReady, (readyClient) => {
	console.log(`Ready! Logged in as ${readyClient.user.tag}`);
});

client.commands = new Collection(); 

We recommend attaching a .commands property to your client instance so that you can access your commands in other files. The rest of the examples in this guide will follow this convention. For TypeScript users, we recommend extending the base Client class to add this property, casting, or augmenting the module type.

  • The fs module is Node's native file system module. fs is used to read the commands directory and identify our command files. - The path module is Node's native path utility module. path helps construct paths to access files and directories. One of the advantages of the path module is that it automatically detects the operating system and uses the appropriate joiners. - The Collection class extends JavaScript's native Map class, and includes more extensive, useful functionality. Collection is used to store and efficiently retrieve commands for execution.

Next, using the modules imported above, dynamically retrieve your command files with a few more additions to the index.js file:

index.js
client.commands = new Collection();

const foldersPath = path.join(__dirname, 'commands');
const commandFolders = fs.readdirSync(foldersPath);

for (const folder of commandFolders) {
	const commandsPath = path.join(foldersPath, folder);
	const commandFiles = fs.readdirSync(commandsPath).filter((file) => file.endsWith('.js'));
	for (const file of commandFiles) {
		const filePath = path.join(commandsPath, file);
		const command = require(filePath);
		// Set a new item in the Collection with the key as the command name and the value as the exported module
		if ('data' in command && 'execute' in command) {
			client.commands.set(command.data.name, command);
		} else {
			console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
		}
	}
}

D'abord, path.join() aide à construire un chemin vers le répertoire commands. La première méthode fs.readdirSync() lit alors le chemin du répertoire et retourne un tableau de tous les noms de dossiers qu'il contient, actuellement ['utility']. La deuxième méthode fs.readdirSync() lit le chemin de ce répertoire et retourne un tableau de tous les noms de fichiers qu'il contient, actuellement ['ping.js', 'server.js', 'user.js']. Pour s'assurer que seuls les fichiers de commande sont traités, Array.filter() supprime tous les fichiers non-JavaScript du tableau.

Avec les fichiers corrects identifiés, la dernière étape consiste à définir dynamiquement chaque commande dans la Collection client.commands. Pour chaque fichier étant chargé, vérifiez qu'il a au moins les propriétés data et execute. Cela aide à prévenir les erreurs résultant du chargement de fichiers de commande vides, incomplets ou autrement incorrects pendant que vous développez.

Réception des interactions de commande

Vous recevrez une interaction pour chaque commande slash exécutée. Pour répondre à une commande, vous devez créer un écouteur pour l'événement interactionCreate qui exécutera du code quand votre application recevra une interaction. Placez le code ci-dessous dans le fichier index.js que vous avez créé plus tôt.

index.js
client.on(Events.InteractionCreate, (interaction) => {
	console.log(interaction);
});

Pas toutes les interactions sont des commandes slash (par exemple, les interactions MessageComponent). Assurez-vous de ne gérer que les commandes slash dans cette fonction en utilisant la méthode BaseInteraction#isChatInputCommand pour quitter le gestionnaire si un autre type est rencontré. Cette méthode fournit également un garde de type pour les utilisateurs TypeScript, rétrécissant le type de BaseInteraction à ChatInputCommandInteraction.

index.js
client.on(Events.InteractionCreate, (interaction) => {
	if (!interaction.isChatInputCommand()) return; 
	console.log(interaction);
});

Exécution des commandes

Quand votre bot reçoit un événement interactionCreate, l'objet d'interaction contient toutes les informations dont vous avez besoin pour récupérer et exécuter dynamiquement vos commandes !

Jetons un coup d'oeil à la commande ping à nouveau. Notez la fonction execute() qui répondra à l'interaction avec "Pong!".

commands/utility/ping.js
module.exports = {
	data: new SlashCommandBuilder().setName('ping').setDescription('Replies with Pong!'),
	async execute(interaction) {
		await interaction.reply('Pong!');
	},
};

First, you need to get the matching command from the client.commands Collection based on the interaction.commandName. Your Client instance is always available via interaction.client. If no matching command is found, log an error to the console and ignore the event.

With the right command identified, all that's left to do is call the command's .execute() method and pass in the interaction variable as its argument. In case something goes wrong, catch and log any error to the console.

index.js
client.on(Events.InteractionCreate, async (interaction) => {
	if (!interaction.isChatInputCommand()) return;
	const command = interaction.client.commands.get(interaction.commandName);

	if (!command) {
		console.error(`No command matching ${interaction.commandName} was found.`);
		return;
	}

	try {
		await command.execute(interaction);
	} catch (error) {
		console.error(error);
		if (interaction.replied || interaction.deferred) {
			await interaction.followUp({
				content: 'There was an error while executing this command!',
				flags: MessageFlags.Ephemeral,
			});
		} else {
			await interaction.reply({
				content: 'There was an error while executing this command!',
				flags: MessageFlags.Ephemeral,
			});
		}
	}
});

Next steps

Your command files are now loaded into your bot, and the event listener is prepared and ready to respond. In the next section, we cover the final step: a command deployment script you'll need to register your commands so they appear in the Discord client.