Faire un bot Discord
Comment faire un bot Discord ?
Formation ARISE - 18 Novembre 2025 - Fischer
Des indications arbitraires de temps sont communiquées à chaque étape de la forme : ~ 15 minutes
Lorsqu’un texte est souligné il contient un hyperlien
Serveur Discord temporaire pour la formation : https://discord.gg/WbqJAMxG
Discord c'est cool
Qu’est-ce qu’un bot Discord ?
(1 min, simple lecture)
Un bot Discord est un programme automatisé qui peut interagir avec les serveurs Discord.
Il peut effectuer diverses tâches comme :
Modérer des salons (supprimer des messages, bannir des utilisateurs, attribuer des rôles etc.)
Répondre à des commandes des utilisateurs
Jouer de la musique ou envoyer des images
Fournir des notifications ou informations en temps réel
Les bots utilisent l’API Discord pour communiquer avec les serveurs.
Un bot peut plus ou moins faire tout ce qu’un compte classique d’utilisateur sur discord peut faire, et même plus !
Comment créer son bot ?
Les seuls prérequis pour créer un bot Discord sont de posséder un compte Discord et des droits d’ajout de bot sur le serveur cible.
Création de l’app Discord ~ 20 min
Dans un premier temps :
Créer une application Discord
Rendez-vous sur le portail des développeurs Discord
Cliquez sur New Application, donnez-lui un nom, puis créez-la.
Il est possible de développer des bots à plusieurs à l’aide des teams. Chaque personne dans la team peut éditer le bot sur le portail développeur. Vous n’en aurez généralement pas besoin.
Configurer le bot de l’application
Dans le menu de l’application, allez sur l’onglet Bot
Vous pouvez le personnaliser (avatar, nom, etc.)
Le token est une clé secrète qui permet à votre programme de se connecter au bot.
Ne le partagez jamais !
Faites un reset token pour l’obtenir puis gardez-le précieusement.
Activer les “intents”
Les intents sont des permissions que vous donnez à votre bot. Il en existe trois :
Presence Intent : Pour tout ce qui est modification du statut du bot.
Member Intent : Pour tout ce qui est informations sur les utilisateurs.
Message Content Intent : Pour la lecture des messages.
Par défaut, votre bot n’en possède aucune. Il faut impérativement aller les cocher. Discord vous laisse les activer sans inspection de leur part tant que votre bot est présent sur moins de 100 serveurs.
Je vous conseille d’activer les 3 directement, surtout en cas de doutes sur la portée de ce que vous voulez que votre bot fasse.
A partir de maintenant, votre bot est prêt à être intégré à votre serveur.
Vous n’aurez normalement plus besoin de rentrer des informations dans le panel de contrôle de développeur, à moins de vouloir (re)personnaliser votre bot.
Invitation du Bot ~ 5 min
Dans un premier temps, vous pouvez vous rendre dans le menu Installation
Vous pouvez ici cocher ou décocher l’installation du bot en tant que bot personnel ou bot de serveur. Je vous conseille de laisser uniquement l’installation en tant que bot de serveur activée (Guild Install)
Rendez vous ensuite sur la page OAuth2.
→ OAuth2 est un standard d’authentification qu’utilise Discord mais aussi ARISE à l’aide de son implémentation d’OpenID, AriseID Connect.
Vous pouvez y trouver un générateur d’URL :
Un sacré foutoir quand on ne s'y connait pas
Dans Scopes, cochez simplement “bot” puis dans Bot Permissions vous pouvez renseignez toutes les permissions dont votre bot aura besoin. Pour la formation, vous pouvez garder “Administrator”
→ De manière générale, il est déconseillé de donner plus de permissions à votre bot que nécessaire. En cas de piratage de ce dernier, il ne pourra effectuer que les actions que vous lui avez donné l’autorisation de faire ici.
Gardez bien l’intégration Guild Install puis ouvrez le lien présent dans Generated URL. Vous avez alors un pop-up qui se lance pour inviter votre bot sur un serveur.
Félicitations, votre bot a rejoint le serveur !
Comment faire tourner son bot ?
Installation de l’environnement ~ 5 min
Il vous faut dans un premier temps choisir votre langage et bibliothèque.
Deux choix principaux s’offrent à vous :
JavaScript / Node.js → discord.js
Python → discord.py (plus simple que discord.js)
Pour le restant de la formation, nous partirons sur discord.py, en Python 🐍
Libre à vous de travailler en js, mais aucune aide sur le code ne vous sera fournie
Rien de plus simple pour installer discord.py :
python3 -m pip install discord.pyVous voilà prêt à coder votre bot et à le lancer !
→ Il est possible d’installer discord.py dans un venv. Nous aborderons ça lors de l’hébergement sur Perso3, où c’est obligatoire.
Lancer son bot ~ 5 min
Afin de lancer son bot, il est nécessaire d’écrire quelques lignes de code.
import discord
from discord import app_commands # Pas nécessaire ici mais conseillé pour la suite
from discord.ext import commands # Pas nécessaire ici mais conseillé pour la suite
from discord import interactions # Pas nécessaire ici mais conseillé pour la suite
# On vient charger nos intents
intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)
bot = commands.Bot(command_prefix="/", intents=intents, case_insensitive=False) # On définit ici le prefix de nos commandes textuels (sans slash)
bot.run(VOTRE_TOKEN) # On lance le bot. Il faut changer son token.Félicitations, votre bot apparait désormais comme étant en ligne !
Malheureusement, il ne fait pas encore grand chose… (en fait, il ne fait rien du tout)
On verra comment il peut agir après !
Plutôt que d’écrire votre token dans le code, il est conseillé de faire un fichier .env ou un autre fichier .py qui définit toutes les informations sensibles de votre code. Il faut bien penser à l’inclure dans votre .gitignore ensuite, si vous travaillez sur git.
Hébergement sur Perso3 ~ 20 min
Vous avez la possibilité de faire tourner votre bot en continu sur le serveur Perso3. Pour ce faire on commence par s’y connecter :
ssh ariseid20xx@perso3.iiens.netPuis on vient créer un “virtual environment”.
→ En Python, un “virtual environment” (venv) permet d’installer des bibliothèques à l’échelle d’un projet plutôt que de toute la machine. Cela permet de séparer les différents environnements Python.
→ Souvent, lorsque vous n’avez pas les permissions d’administrateur sur une machine, c’est le seul moyen d’installer des bibliothèques. Cela garantit que vous n’agissez que pour vous, et pas à l’échelle de la distribution Python de la machine.
Pour créer son venv, il suffit de lancer :
python3 -m venv <dossier>Où <dossier> correspond naturellement à l’emplacement où vous voulez installer votre venv.
Une fois fait, il vous suffira d’activer votre venv avec :
source <lien vers le venv>/bin/activateVous pouvez également le désactiver, si besoin, avec la commande deactivate.
Une fois votre venv activé, vous pouvez lancer pip install discord.py sans que cela soit installé sur la machine mais simplement dans votre environnement local.
Lorsque vous lancez Python3 avec un venv activé, votre installation locale est automatiquement utilisée.
Pour héberger votre code sur Perso3, il est recommandé de passer par le git d’ARISE afin de pouvoir éditer le code localement sur votre machine et déployer ensuite le code proprement sur Perso3.
→ Veillez néanmoins à ne pas mettre de mots de passes et/ou tokens sur git.
Afin de lancer son bot, les utilisateurs utilisent généralement la commande tmux.
→ tmux permet d’accéder à une session indépendante de la connexion ssh. Cette dernière tournera même lorsque vous ne serez plus connecté. Il est également possible à d’autres utilisateurs de se connecter sur votre tmux.
Pour ce faire, lancez tmux, qui va vous ouvrir un nouveau terminal, puis lancez votre bot avec python3 et faites ctrl + b puis d afin de sortir de votre tmux.
→ Si vous avez besoin de retourner dans votre tmux pour fermer votre bot ou le relancer, vous pouvez faire tmux a pour retourner dans votre terminal.
Faire ctrl + d ou exit va tuer votre tmux.
Vous devez impérativement en sortir avec ctrl + b puis appuyer sur d pour sortir et que votre session soit préservée.
→ Votre bot est lancé et tournera de manière permanente !
Que faire avec son bot ?
Tout le reste de votre temps
La partie la plus intéressante ! Maintenant que vous avez votre bot fonctionnel : “Qu’est-ce qu’on en fait ?”
Discord events
En anglais, les serveurs Discord ne s’appellent pas “server” mais “guild”.
Gardez ça en tête lorsque vous parcourez les documentations !
Il existe une panoplie d’événements (events) qui peuvent déclencher une action pour votre bot.
La liste entière est dispo ici.
Une liste non exhaustive d’événements utiles :
on_message(message) → Permet de lancer une fonction dès qu’un message est envoyé par quelqu’un
on_reaction_add(reaction, user) → Permet de lancer une fonction dès qu’une réaction est ajoutée par quelqu’un
on_member_join(member) → Exécutée dès qu’un utilisateur rejoint le serveur
on_member_remove(member) → Pareil qu’avant, mais dès qu’il quitte le serveur
on_typing(channel, user, when) → Enregistre dès qu’un utilisateur commence à écrire
Il existe des events qui concernent le bot également (on_guild_join, et on_ready, qui sont trigger dès que le bot rejoint un serveur ou à chaque fois qu’il est lancé).
Notez que la doc indique, pour chaque event, quel intent doit être activé.
→ Sinon, cela ne fonctionnera pas.
Il existe des dizaines et dizaines d’autres events qui couvrent plus ou moins toute possibilité.
Regardons plus en détail avec un petit exemple :
@bot.event
async def on_typing(channel, user, when):
print(f"{user} est en train d'écrire dans {channel}")→ Cet exemple vient écrire dans la console du bot dès qu’un utilisateur commence à écrire sur un serveur où le bot est présent et peut lire les messages du channel.
On vient utiliser un décorateur “@bot.event” suivi d’une fonction async comportant le nom de l’event en question, puis les bons arguments.
Vous remarquerez que les fonctions utilisent async def et non pas def.
→ Un bot Discord utilise de la programmation dite “asynchrone”, permettant de ne pas exécuter linéairement le code.
→ Retenez simplement que cela change la manière de définir les fonctions d’event et que certains appels de fonctions devront utiliser await. Dans le doute, Google ou une IA pourra vous renseigner sur l’appel que vous tentez d’utiliser.
Vous êtes cependant limités à une fonction pour chaque type d’event.
Il faudra donc gérer vos différents cas dans des sous-fonctions et avoir une seule fonction on_message par exemple.
Fonctions pratiques
Jusqu’à maintenant votre bot est capable d’enregistrer des événements mais vous ne l’avez pas fait interagir avec Discord. Pour cela, les schémas de model Discord sont disponibles ici.
@bot.event
async def on_message(message):
# On ignore les messages envoyés par le bot lui-même
if message.author == bot.user:
return
# Si le contenu du message est "ping"
if message.content.lower() == "ping":
await message.channel.send("pong")→ Le comportement de cet event est de répondre “pong” lorsqu’un utilisateur écrit “ping”.
On remarque l’utilisation nécessaire d’await car cette fonction send va nécessiter un petit temps de process du bot, et il doit pouvoir continuer à tourner le temps qu’il envoie le message.
Les models intéressants sont notamment, de manière non exhaustive :
Embed → Ce n’est pas à proprement parler un model mais ça permet d’envoyer des messages très stylés que seuls les bots peuvent envoyer.
@bot.event
async def on_message(message):
# On ignore les messages envoyés par le bot lui-même
if message.author == bot.user:
return
# Si le contenu du message est "ping2"
if message.content.lower() == "ping2":
# Création de l'embed
embed = discord.Embed(
title="🏓 Pong !",
description="Voici une réponse sous forme d'embed.",
color=discord.Color.blue() # couleur de la barre latérale
)
embed.set_author(name=message.author.name, icon_url=message.author.avatar.url if message.author.avatar else None)
embed.add_field(name="Commande", value="ping", inline=True)
embed.add_field(name="Réponse", value="pong", inline=True)
embed.set_footer(text="Exemple d'embed avec discord.py")
# Envoi de l'embed
await message.channel.send(embed=embed)→ Exemple qui se sert d’un embed lorsqu’on envoie le message “ping2”
Il ne tient désormais qu’à vous de fouiller dans les docs, sur internet ou avec une IA pour réaliser toutes vos envies.
Ci-joint un exemple qui récupère le texte :
@bot.event
async def on_message(message):
if message.author == bot.user:
return
# Vérifie si le message commence par "repeat"
if message.content.lower().startswith("repeat"):
# On enlève le mot "repeat" et on découpe le reste
suite = message.content[len("repeat"):].strip()
mots = suite.split()
if mots:
# On formate en "mot1, mot2, mot3 ..."
resultat = ", ".join(mots)
await message.channel.send(resultat)
else:
async def on_message(message):
if message.author == bot.user:
return
# Vérifie si le message commence par "repeat"
if message.content.lower().startswith("repeat"):
# On enlève le mot "repeat" et on découpe le reste
suite = message.content[len("repeat"):].strip()
mots = suite.split()
if mots:
# On formate en "mot1, mot2, mot3 ..."
resultat = ", ".join(mots)
await message.channel.send(resultat)
else:
await message.channel.send("Tu n'as rien écrit après 'repeat' !")Il existe également bot.commands qui permet de faire un event on_message qui ne s’active que si le message commence par “/” (ou un autre préfixe configurable au tout début).
→ Je n’ai pas décidé de les présenter ici afin de ne pas alourdir la formation, le comportement est entièrement reproductible avec on_message.
Slash commands
Dernière fonctionnalité sympa qui a été introduite récemment dans Discord : les commandes slash.
Ces dernières permettent d’interagir plus facilement avec les bots en utilisant des commandes.
Le nouveau décorateur est @bot.tree.command(name="<nom de la commande>", description="<description de la commande>").
Il suffit ensuite de définir une fonction et Discord se chargera tout seul des arguments etc…
Un seul argument est nécessaire : l’argument d’interaction, dont le modèle de données est dispo ici.
@bot.tree.command(name="repeat", description="Répète tes deux messages")
async def repeat(interaction: discord.Interaction, texte: str, texte2: str):
async def repeat(interaction: discord.Interaction, texte: str, texte2: str):
await interaction.response.send_message(f"Tu as dit : {texte} et {texte2}")Il est également possible de faire en sorte que la réponse ne soit visible que par la personne qui a lancé la commande, grâce au mot clé ephemeral :
@bot.tree.command(name="secret", description="Réponse visible uniquement par toi")
async def secret(interaction: discord.Interaction):
await interaction.response.send_message(
"Ceci est un message secret 👀",
ephemeral=True
)On n’est pas limité au nombre de @bot.tree.comand, comparé aux events où un seul peut être déclaré, forçant à regrouper toute la logique sous une seule fonction qui appelle des sous-fonctions.
Les slash commands sont bien plus pratiques, mais nécessitent juste d’être synchronisées lorsque le bot est lancé. La synchronisation n’est pas forcément immédiate et il faut des fois attendre plusieurs minutes et redémarrer Discord (ctrl + R) avant que la commande apparaisse bien sur Discord.
Pour ce faire :
@bot.event
async def on_ready():
print(f"Bot connecté en tant que {bot.user}")
try:
await bot.tree.sync()
print("Slash commands synchronisées")
except Exceptiéon as e:
print(e)→ Lorsque le bot est lancé, il l’indique dans le terminal et tente de synchroniser ses commandes avec les serveurs de Discord, pour que les utilisateurs voient les commandes apparaitre.
Les serveurs de Discord sont très sensibles aux demandes de synchronisations.
→ Plus vous en lancez, moins Discord les effectuera rapidement, estimant que vous spammez.
Pour aller plus loin
Pour mes kiffeurs de bots
Développer un bot c’est bien, mais il y a moyen de faire d’autres petites intégrations pour améliorer ses fonctionnalités !
Bot d’assignation de rôles
Vous voulez assigner automatiquement un rôle lorsque les gens répondent à votre message avec un emoji ?
Le bot d’ARISE est dispo en open source ici.
Utilisations de bases de données
En général si vous voulez faire un bot assez avancé, l’utilisation d’une base de données peut être justifiée.
→ Si vous comptez stocker uniquement deux ou trois infos, un .json et/ou un fichier .db de sqlite devraient suffire.
Les bibliothèques que vous pouvez utiliser sont :
sqlite3pour interagir avec sqlite, petite implémentation de bases de données en local sans aucune configuration à faire côté machinepsycopg2pour interagir avec postgresql, mysql, mariadb par exemple. C’est ceci qu’il faut utiliser pour une base de données distante d’ARISESQLAlchemysi vous comptez utiliser un ORM qui permet de faire du SQL en restant sur la syntaxe Python (je vous laisse vous renseigner)
On peut imaginer un bot de gatcha qui possède des milliers d’objets stockés dans une base de données.
Se connecter à une API / Ecouter un websocket
Il peut être pertinent de faire des appels API avec votre bot si vous voulez le connecter à d’autres services, ou vous connecter à un websocket pour obtenir des informations en temps réel d’une source externe.
Pour ce faire, vous pouvez directement le développer en asynchrone.
Les bibliothèques que vous pouvez utiliser sont :
aiohttp & asynciopour faire des requêtes asynchrones aux API REST.websockets & asynciopour se connecter aux websockets en asynchrone.
On imagine bien un bot avec une commande /weather qui vient donner en temps réel les prévisions météos grâce à une API Météo
import discord
from discord import app_commands
import aiohttp
import asyncio
# Crée une instance de bot
intents = discord.Intents.default()
bot = discord.Client(intents=intents)
tree = app_commands.CommandTree(bot)
# Slash command météo
@tree.command(name="meteo", description="Donne la température d'une ville")
async def meteo(interaction: discord.Interaction, ville: str = "Paris"):
async with aiohttp.ClientSession() as session:
# API simple wttr.in (renvoie juste la température)
url = f"https://wttr.in/{ville}?format=%t"
async with session.get(url) as resp:
if resp.status == 200:
data = await resp.text()
await interaction.response.send_message(
f"🌡️ Température à {ville} : {data}"
)
else:
await interaction.response.send_message(
f"Impossible de récupérer la météo pour {ville}."
)
# Quand le bot est prêt
@bot.event
async def on_ready():
print(f"Connecté en tant que {bot.user}")
# Synchronise les slash commands avec Discord
await tree.sync()
# Démarrage du bot
bot.run("TON_TOKEN_ICI")→ Exemple du bot météo. Ca marche moyen parce que wttr.in répond difficilement aux requêtes.