Créer des commandes slash (/) pour votre bot Discord
Les commandes slash (/) sont devenues le standard des bots Discord. Voici comment les enregistrer, y répondre et gérer les options, en Node.js comme en Python.
Commandes slash Discord ou commandes à préfixe ?
Les commandes slash Discord sont des commandes natives qui apparaissent lorsque l’utilisateur saisit / dans un salon. Contrairement aux anciennes commandes à préfixe comme !help, elles sont directement intégrées à l’interface de Discord.
Une commande slash possède :
- un nom ;
- une description ;
- des options typées ;
- une autocomplétion ;
- des permissions configurables ;
- une réponse envoyée par le bot.
Par exemple :
/ping
/salut utilisateur:@Alex
/ban utilisateur:@Alex raison:Spam
Elles offrent plusieurs avantages :
| Commande à préfixe | Commande slash |
|---|---|
| L’utilisateur doit connaître la syntaxe | Discord affiche les commandes disponibles |
| Arguments saisis librement | Options validées par Discord |
| Nécessite souvent Message Content Intent | Fonctionne avec les interactions |
| Permissions gérées dans le code | Permissions Discord natives possibles |
| Peu d’autocomplétion | Suggestions et descriptions intégrées |
Pour utiliser des commandes slash, votre application doit être installée avec le scope :
applications.commands
Lors de l’invitation d’un bot classique, sélectionnez généralement :
bot
applications.commands
Le scope applications.commands est aussi inclus automatiquement dans les installations utilisant le scope bot, mais vérifier sa présence évite les erreurs avec d’anciennes URL d’invitation.
Si votre application et son token ne sont pas encore créés, consultez le guide pour créer un bot Discord et obtenir son token.
Enregistrer une commande par serveur ou globalement
Déclarer une commande dans votre code ne suffit pas. Vous devez également l’enregistrer auprès de l’API Discord.
Deux portées sont disponibles :
| Portée | Disponibilité | Usage conseillé |
|---|---|---|
| Guild, ou serveur | Un seul serveur Discord | Développement et tests |
| Globale | Tous les serveurs ayant installé l’application | Mise en production |
Les commandes enregistrées pour une guild sont mises à jour immédiatement. Elles sont donc idéales pour tester rapidement une modification.
Les commandes globales sont destinées à la production. Leur propagation peut ne pas être instantanée sur tous les clients : attendez avant de conclure que l’enregistrement a échoué.
Préparer les variables nécessaires
Ajoutez les identifiants dans votre fichier .env :
DISCORD_TOKEN=VOTRE_TOKEN
CLIENT_ID=IDENTIFIANT_DE_L_APPLICATION
GUILD_ID=IDENTIFIANT_DU_SERVEUR_DE_TEST
Le CLIENT_ID correspond à l’Application ID visible dans le Discord Developer Portal.
Pour obtenir le GUILD_ID, activez le mode développeur dans Discord, faites un clic droit sur votre serveur, puis sélectionnez Copier l’identifiant du serveur.
Ne publiez jamais votre token. Le
CLIENT_IDet leGUILD_IDne sont pas secrets, mais le token donne le contrôle de votre bot.
Enregistrement avec discord.js
Créez un fichier deploy-commands.js :
require("dotenv").config();
const {
REST,
Routes,
SlashCommandBuilder,
} = require("discord.js");
const token = process.env.DISCORD_TOKEN;
const clientId = process.env.CLIENT_ID;
const guildId = process.env.GUILD_ID;
if (!token || !clientId) {
throw new Error("DISCORD_TOKEN ou CLIENT_ID est absent.");
}
const commands = [
new SlashCommandBuilder()
.setName("ping")
.setDescription("Vérifie si le bot répond"),
new SlashCommandBuilder()
.setName("salut")
.setDescription("Salue un membre")
.addUserOption((option) =>
option
.setName("utilisateur")
.setDescription("Le membre à saluer")
.setRequired(true)
),
].map((command) => command.toJSON());
const rest = new REST({ version: "10" }).setToken(token);
async function deployCommands() {
const route = guildId
? Routes.applicationGuildCommands(clientId, guildId)
: Routes.applicationCommands(clientId);
await rest.put(route, { body: commands });
console.log(
guildId
? "Commandes enregistrées sur le serveur de test."
: "Commandes enregistrées globalement."
);
}
deployCommands().catch((error) => {
console.error("Échec de l'enregistrement :", error);
process.exitCode = 1;
});
Lancez l’enregistrement :
node deploy-commands.js
Avec GUILD_ID, les commandes sont enregistrées sur le serveur de test. Pour passer en global, retirez temporairement GUILD_ID de l’environnement, puis relancez le script.
N’exécutez le script de déploiement que lorsque la définition des commandes change. Il n’est pas nécessaire de réenregistrer les commandes à chaque démarrage du bot.
Répondre à une interaction avec discord.js
Dans votre fichier principal index.js, écoutez l’événement interactionCreate.
Exemple avec /ping et /salut :
require("dotenv").config();
const {
Client,
Events,
GatewayIntentBits,
} = require("discord.js");
const client = new Client({
intents: [GatewayIntentBits.Guilds],
});
client.once(Events.ClientReady, (readyClient) => {
console.log(`Bot connecté : ${readyClient.user.tag}`);
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) {
return;
}
try {
if (interaction.commandName === "ping") {
await interaction.reply("Pong !");
return;
}
if (interaction.commandName === "salut") {
const utilisateur = interaction.options.getUser(
"utilisateur",
true
);
await interaction.reply(`Bonjour ${utilisateur} !`);
}
} catch (error) {
console.error("Erreur pendant l'interaction :", error);
const message = {
content: "Une erreur est survenue.",
ephemeral: true,
};
if (interaction.replied || interaction.deferred) {
await interaction.followUp(message);
} else {
await interaction.reply(message);
}
}
});
client.login(process.env.DISCORD_TOKEN);
Une interaction doit recevoir rapidement une réponse. Pour un traitement long, utilisez :
await interaction.deferReply();
Puis envoyez le résultat :
await interaction.editReply("Traitement terminé.");
Répondre à une interaction avec discord.py
Avec discord.py, les commandes slash sont gérées par app_commands et l’arbre de commandes du bot.
Exemple limité à un serveur de test :
import os
import discord
from discord import app_commands
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
token = os.getenv("DISCORD_TOKEN")
guild_id = os.getenv("GUILD_ID")
if not token or not guild_id:
raise RuntimeError("DISCORD_TOKEN ou GUILD_ID est absent.")
test_guild = discord.Object(id=int(guild_id))
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)
@bot.tree.command(
name="ping",
description="Vérifie si le bot répond",
guild=test_guild,
)
async def ping(interaction: discord.Interaction) -> None:
await interaction.response.send_message("Pong !")
@bot.tree.command(
name="salut",
description="Salue un membre",
guild=test_guild,
)
@app_commands.describe(utilisateur="Le membre à saluer")
async def salut(
interaction: discord.Interaction,
utilisateur: discord.Member,
) -> None:
await interaction.response.send_message(
f"Bonjour {utilisateur.mention} !"
)
@bot.event
async def on_ready() -> None:
commandes = await bot.tree.sync(guild=test_guild)
print(
f"Bot connecté : {bot.user} — "
f"{len(commandes)} commande(s) synchronisée(s)"
)
bot.run(token)
Pour transformer ces commandes en commandes globales :
- retirez
guild=test_guilddes décorateurs ; - remplacez la synchronisation par :
await bot.tree.sync()
Évitez de synchroniser inutilement les commandes globales à chaque reconnexion. Dans un projet plus structuré, effectuez cette opération une seule fois au déploiement ou avec une commande réservée au propriétaire.
Ajouter des options aux commandes slash Discord
Discord propose plusieurs types d’options :
| Type | Exemple |
|---|---|
| String | Motif, texte ou identifiant |
| Integer | Quantité ou durée entière |
| Number | Valeur décimale |
| Boolean | Oui ou non |
| User | Membre ou utilisateur |
| Channel | Salon |
| Role | Rôle |
| Attachment | Fichier joint |
Dans discord.js, une option texte obligatoire s’ajoute ainsi :
new SlashCommandBuilder()
.setName("annonce")
.setDescription("Publie une annonce")
.addStringOption((option) =>
option
.setName("message")
.setDescription("Contenu de l'annonce")
.setRequired(true)
);
Récupérez ensuite sa valeur :
const message = interaction.options.getString("message", true);
Avec discord.py, les paramètres typés deviennent automatiquement des options :
@bot.tree.command(
name="addition",
description="Additionne deux nombres",
)
async def addition(
interaction: discord.Interaction,
nombre_a: int,
nombre_b: int,
) -> None:
resultat = nombre_a + nombre_b
await interaction.response.send_message(
f"Résultat : {resultat}"
)
Une option possédant une valeur par défaut devient facultative :
async def annonce(
interaction: discord.Interaction,
message: str,
silencieuse: bool = False,
) -> None:
...
Gérer les permissions et les réponses éphémères
Vous pouvez limiter une commande aux membres possédant une permission Discord précise.
Avec discord.js :
const {
PermissionFlagsBits,
SlashCommandBuilder,
} = require("discord.js");
const commande = new SlashCommandBuilder()
.setName("nettoyer")
.setDescription("Supprime des messages")
.setDefaultMemberPermissions(
PermissionFlagsBits.ManageMessages
);
Avec discord.py :
@app_commands.default_permissions(manage_messages=True)
@bot.tree.command(
name="nettoyer",
description="Supprime des messages",
)
async def nettoyer(
interaction: discord.Interaction,
) -> None:
await interaction.response.send_message(
"Commande autorisée.",
ephemeral=True,
)
Une réponse éphémère est visible uniquement par la personne ayant exécuté la commande. Elle est adaptée aux confirmations, erreurs et outils administratifs :
await interaction.reply({
content: "Action effectuée.",
ephemeral: true,
});
Les administrateurs du serveur peuvent également ajuster la visibilité des commandes depuis les paramètres d’intégration de l’application.
Les permissions par défaut améliorent l’interface, mais vérifiez aussi les autorisations dans votre code avant toute action sensible.
Déployer et garder le bot disponible
Une commande peut apparaître dans Discord alors que le bot est hors ligne. Dans ce cas, aucune réponse ne sera envoyée.
Votre processus doit donc fonctionner en continu. Pour préparer le projet, consultez le guide bot Discord en Node.js ou Python.
Pour une mise en production permanente, consultez également le guide pour héberger un bot Discord 24 h/24 et 7 j/7.
Des sauvegardes automatiques sont incluses pour vous aider à restaurer. Conservez aussi vos propres exports réguliers : vous restez responsable de vos données.
En résumé
- Les commandes slash Discord apparaissent dans l’interface lorsque l’utilisateur saisit
/. - Vérifiez que l’application est installée avec le scope
applications.commands. - Utilisez des commandes limitées à une guild pendant le développement.
- Enregistrez les commandes globalement lorsqu’elles sont prêtes pour la production.
- Avec discord.js, utilisez
SlashCommandBuilder,RESTetRoutes. - Écoutez
interactionCreateet répondez avecinteraction.reply(). - Avec discord.py, utilisez
@bot.tree.commandetinteraction.response.send_message(). - Synchronisez l’arbre avec
bot.tree.sync(). - Ajoutez des options typées pour les utilisateurs, chaînes, nombres, salons ou rôles.
- Limitez les commandes sensibles avec les permissions Discord.
- Utilisez les réponses éphémères pour les confirmations et erreurs privées.
- Gardez le bot en ligne afin qu’il puisse répondre aux interactions.
- Pour déployer vos commandes slash Discord sur un hébergement avec panel de gestion et support francophone, découvrez l’offre hébergement bot Discord TalCloud.