Ce bot Discord, prénommé Marvin, a été développé en Python par curiosité et par amusement. Son nom est une référence à Marvin le robot dépressif de H2G2 (Le Guide du voyageur galactique) de Douglas Adams : un robot cynique et blasé, doté d’un cerveau gigantesque, condamné à supporter l’univers et toutes ses absurdités.
Il faut créer une application, lui donner un nom, entre autres, et vous obtiendrez un token.
Hébergement
Soit en local, soit sur un serveur en ligne.
Avec le local, vous aurez moins de problèmes si vous voulez faire du random d’affichage d’images de sites tels que Reddit, Imgur, etc.
Sur un serveur en ligne par contre, il va falloir utiliser les API des sites en question - j’avoue ne pas avoir eu le courage de m’inscrire juste pour ça (afficher des images rigolotes…).
Base OS
Mon bot, Marvin, un robot dépressif (et parfois extrêment grossier), est hébergé sur une Debian, avec du Python3.
Marvin est un utilisateur du système (pour l’ajouter : adduser marvin).
Arboressence
Sur le serveur en ligne, Python 3 est installé.
Si, en lançant le bot, des messages d’erreur (Python) s’affichent, ils sont généralement assez parlants : Python aura besoin de tels ou tels paquets supplémentaires.
Liste des fichiers pour le bot Marvin (non, je n’utilise pas Git ¯|(ツ)/¯ et heuresement peut-être…) :
marvin@marvin:~$ ls -l total 72 drwxr-xr-x 2 marvin marvin 4 28 déc. images # Répertoire des images (Appel) drwxr-xr-x 6 marvin marvin 4 28 déc. venv # Environnement, lorsque des paquets utiles sont installés -rw-r--r-- 1 marvin marvin 2 28 déc. anniv_react.py # Anniv de mes potes Discord (Timer) -rw-r--r-- 1 marvin marvin 3 28 déc. blague_react.py # Blagues de mes potes Discord (Déclencheur) -rw-r--r-- 1 marvin marvin 2 28 déc. destin_react.py # Avenir de mes potes Discord (Déclencheur) -rw-r--r-- 1 marvin marvin 18 28 déc. event_react.py # Événements importants (Timer) -rw-r--r-- 1 marvin marvin 2 28 déc. list_react.py # Liste des commandes de Marvin (Déclencheur) -rw-r--r-- 1 marvin marvin 2 28 déc. main.py # Programme principal (Main) -rw-r--r-- 1 marvin marvin 2 30 déc. meteo_react.py # Affiche la météo (Déclencheur) -rw-r--r-- 1 marvin marvin 2 28 déc. porn_react.py # Affiche des images (Déclencheur – photos de serveurs, hein) -rw-r--r-- 1 marvin marvin 2 28 déc. potins_react.py # Potins entre potes Discord (Déclencheur) -rw-r--r-- 1 marvin marvin 2 30 déc. wiki_react # Demander à wikipedia (Déclencheur) -rw-r--r-- 1 marvin marvin 2 28 déc. words_react.py # Mots déclencheurs (Déclencheur)
Le codes de chaque fichiers
Pour un bot “rigolo” et relativement basique, voici le code en Python dans les chapitres suivants.
Code main.py
Le main, qui fait tous les appels des autres classes :
# main.py
import discord from discord.ext import commands import words_react import potins_react import destin_react import anniv_react import blague_react import event_react import list_react import porn_react import wtf_react import boobs_react import wiki_react import meteo_react import os from dotenv import load_dotenv from anniv_react import BirthdayManager from event_react import EventManager
# Charger le token depuis .env load_dotenv() TOKEN = os.getenv("DISCORD_TOKEN")
CHANNEL_ID_Test = 9xxxxxxxxxxxxx98 # Salon Test CHANNEL_ID_Gene = 6xxxxxxxxxxxxx26 # Salon Genéral CHANNEL_ID_Parl = 1xxxxxxxxxxxxx67 # Salon Envie de parler
@bot.event asyncdefon_ready(): print(f"Bot connecté en tant que {bot.user}")
channel = bot.get_channel(CHANNEL_ID_Test) if channel: await channel.send("🤖 Je viens d'être mis à jour 🤖")
# Commandes "rapides", un /bonjour fera répondre le bot et pingera le user @bot.command(name="bonjour") asyncdefbonjour_command(ctx): await ctx.send(f"Bonjour, {ctx.author.mention}!")
# Exécuter le bot avec le jeton bot.run("xxxVotreJetonRécupéréenEnChapitre1xxx")
Code anniv_react.py
Ce script permet à votre bot de souhaiter l’anniversaire de vos potes sur votre Discord.
Certains diront que c’est totalement impersonnel, il est donc possible de régler l’heure. Comme ça, les vrais humains, s’ils y pensent, l’auront souhaité avant le bot (ici réglé sur 16 h 54).
# anniv_react.py
from datetime import datetime from discord.ext import tasks import random
asyncdefreact_to_specific_word(bot, message):
# Mot spécifique à détecter mots_specifiques = ['/anniv']
message.content = message.content.lower()
# Vérifier si le mot spécifique est présent dans le message ifany(mot in message.content for mot in mots_specifiques): # Messages possibles messages_possibles = [ """MM-DD - Month - Day 03-07 - Potame 03-27 - Berger 04-10 - Syst3m 07-06 - Chat Je n\'ai oublié personne ? PS : Si je ne me déclenche pas au bon moment c'est pas ma faute""" ]
# Choisir un message au hasard message_choisi = random.choice(messages_possibles)
# Envoyer le message choisi await message.channel.send(f"```\n{message_choisi}\n```")
classBirthdayManager: def__init__(self, bot, channel_id): """ bot : instance de commands.Bot channel_id : ID du canal où envoyer les messages """ self.bot = bot self.channel_id = channel_id
@tasks.loop(minutes=1) # vérifie toutes les minutes asyncdefbirthday_check(self):
now = datetime.now() ifnot (now.hour == 16and now.minute == 00): # ne fait rien si ce n'est pas 16h00 return
channel = self.bot.get_channel(self.channel_id) if channel isNone: print(f"Impossible de trouver le channel {self.channel_id}") return
today = now.strftime("%m-%d") for user_id, date in self.birthdays.items(): if date == today: await channel.send(f"🎉 🎁 Joyeux Anniversaire <@{user_id}> ! 🎂 🥳")
@birthday_check.before_loop asyncdefbefore_birthday_check(self): # Attend que le bot soit prêt avant de démarrer la tâche await self.bot.wait_until_ready()
Code blague_react.py
Ce script permet à votre bot de dire des blagues :
# blagues_react.py
import random import discord from discord import app_commands
defsetup(bot):
@bot.tree.command(name="blague", description="Marvin a beaucoup d'humour") asyncdefblague(interaction: discord.Interaction):
# Messages possibles messages_possibles = [ 'Halloween et Noël c\'est la meme chose car Oct 31 == Dec 25', 'Les devs détestent la nature car y\'a trop de bugs', 'Un SQL arrive à l\'improviste et demande : Puis-je vous joindre', 'Un dev ne descend pas du métro, il libère la RAM', 'Un dev ne vieillis pas il level up' ]' # Choisir un message au hasard message_choisi = random.choice(messages_possibles) # Envoyer le message choisi await interaction.response.send_message(message_choisi) # Récupérer le message réel pour ajouter des réactions msg = await interaction.original_response() msg = await msg.channel.fetch_message(msg.id) await msg.add_reaction("🤣") await msg.add_reaction("🥁")
Code destin_react.py
Ce script permet à votre bot de LIRE L’AVENIR !
# destin_react.py
import random import discord from discord import app_commands
defsetup(bot):
@bot.tree.command(name="destin", description="Marvin est de bon conseil") asyncdefblague(interaction: discord.Interaction):
# Messages possibles messages_possibles = [ '🔮 Si tu vois un oiseau blanc sur un lac. C\'est un cygne.', '🔮 Ton chausson gauche te portera chance demain.', '🔮 Si tu trouves un caillou rond, fais un vœu.', '🔮 Une fourmi te rendra visite ce soir. Elle sera de bon conseil', '🔮 Les chaussures oubliées sous le lit te surveillent en secret.', '🔮 Les escargots sont des messagers du destin. Observe-les.' ]
# Choisir un message au hasard message_choisi = random.choice(messages_possibles)
# Envoyer le message choisi await interaction.response.send_message(message_choisi)
Code event_react.py
Ce script permet à votre bot de rappeler des dates importantes :
# event_react.py
from datetime import datetime from discord.ext import tasks
# Dictionnaire des dates spéciales : ""MM-DD" -> (heure, minute, message) self.events = { "01-01": "🎉 Bonne année ! 🥳", "01-08": "🛁 Journée Internationale du bain moussant", "03-14": "🥧 Happy Pi Day !", "04-09": "🦄🪽🌈 Journée Mondiale de la licorne", "04-25": "🐧 Journée Mondiale des Manchots", "05-25": "🏖️ Journée Mondiale de la serviette", "07-25": "😎 Journée Mondiale des administrateurs système 😎", "08-04": "🍺 Journée Mondiale de la bière 🍺", "08-08": "🐱 Journée Internationale du chat 🐱", "09-13": "👨💻 Journée Mondiale des programmeurs et développeurs 👩💻", "09-22": [ """ 🌰🍂🍁🍄🍁🍂🌰🍄🍁🍂 JOYEUX ÉQUINOXE D'AUTOMNE 🌰🍂🍁🍄🍁🍂🌰🍄🍁🍂 """, "🦏 Journée Mondiale du rhinocéros 🦏" ], "11-01": "🌿 Journée Mondiale Végane", "11-19": "🚽 Journée Mondiale des toilettes 🚽", "12-05": "🥷 Journée Internationale du Ninja 🥷", "12-12": "🎸🤘 Journée Internationale de la musique Métal 🤘 🎸", }
self.sent_today = set() self.events_check.start()
@tasks.loop(minutes=1) asyncdefevents_check(self): now = datetime.now()
ifnot (now.hour == 9and now.minute == 00): return
channel = self.bot.get_channel(self.channel_id) if channel isNone: print(f"Impossible de trouver le channel {self.channel_id}") return
today = now.strftime("%m-%d")
if today in self.events and today notin self.sent_today: messages = self.events[today]
# Cas 1 : un seul message ifisinstance(messages, str): await channel.send(f"{message}")
# Cas 2 : plusieurs messages elifisinstance(messages, list): for message in messages: await channel.send(f"{message}")
Pas de code, c’est un répertoire. Juste des images de ce que vous voulez.
Elles sont en lien avec le fichier porn_react.py. Et je tiens à préciser qu’il s’agit de /cableporn, c’est-à-dire des administrateurs réseau qui font (pour une fois) extrêmement bien leur travail - merci à eux.
Code meteo_react.py
Ce script permet à votre bot d’afficher la mété d’une ville donnée.
Obtenir une API est facile en allant sur http://openweathermap.org. Il suffit de créer un compte et de valider son adresse mail.
# meteo_react
import discord from discord import app_commands from discord.ext import commands import aiohttp
API_KEY = "xXxxxXxxxXxxxXxxxXxxxXxxxXxxxXxx"# Clé API OpenWeatherMap
@app_commands.command( name="meteo", description="Je suis aussi M. Météo" ) @app_commands.describe( ville="Nom de la ville à rechercher" ) asyncdefmeteo(self, interaction: discord.Interaction, ville: str): await interaction.response.defer() # évite le timeout
asyncwith aiohttp.ClientSession() as session: asyncwith session.get(url) as resp: if resp.status != 200: await interaction.followup.send(f"❌ Impossible de récupérer la météo pour **{ville}**.") return data = await resp.json()
Ce script permet à votre bot d’afficher une image aléatoire contenue dans le répertoire /images.
Note : En local, il est extrêmement facile de faire appel à un site de type Reddit, Imgur, etc., pour afficher des images aléatoires en fonction d’une thématique. Pour un bot hébergé sur un serveur, il sera nécessaire de passer par une API.
Code sans API (et donc auto-hébergement d’images) :
# porn_react.py
import random import os import discord from discord import app_commands
# Messages possibles messages_possibles = [ 'Apparemment Potame a défoncé son mur.', 'Apparemment Warman a de très beaux avocats.', 'Apparemment Potame préfère le mot "popotin" à "potin".', 'Va lire Gala si tu veux des potins.', 'Apparemment Chat veut juste emprunter les 2 moutons de Berger.', 'Apparemment Potame kiffe les hippopotames.' ]
# Choisir un message au hasard message_choisi = random.choice(messages_possibles)
# Envoyer le message choisi await interaction.response.send_message(message_choisi)
Code wiki_react.py
Ce script permet à votre bot d’afficher les information trouvées sur Wikipedia en fonction de certains mots :
# wiki_react.py
import discord from discord.ext import commands from discord import app_commands import wikipedia
except Exception as e: await interaction.followup.send( "⚠️ Erreur lors de la requête Wikipédia." ) print(e)
asyncdefsetup(bot): await bot.add_cog(Wiki(bot))
Code words_react.py
Ce script permet à votre bot de réagir en fonction de certains mots :
# Code words_react.py
import re import unicodedata import random
defstrip_accents(text: str) -> str: """Supprime les accents d'une chaîne""" return"".join( c for c in unicodedata.normalize("NFD", text) if unicodedata.category(c) != "Mn" )
asyncdefreact_to_specific_word(bot, message):
# Mise en forme du message content = message.content.lower() content = strip_accents(content)
# Remplace la ponctuation par des espaces content = re.sub(r"[^\w\s']", " ", content)
responses_99 = [ "Intéressant comme sujet", "On part sur de la philosophie là ?", "Hmm... fascinant", "Je note ça dans ma base de données mentale", "Rien à voir mais hier je suis allé voir mes potes les T-1000, ils leur manquent des MAJ...", "Oh vous savez quoi ? Ce matin j'ai vu 1 pixel mort... pas beau à voir...", "Oh les gars, j'ai fait un cauchemar atroce cette nuit, y avait plein de 0 et de 1 mais le pire c'est q "Je me fais chier, je peux rester avec vous ?", "Hier j'ai mangé une pomme", "C'est pas faux", "Je vois pas de quoi tu parles en fait" ] if any(word in words for word in specific_words1): await message.add_reaction('🖕') if any(word in words for word in specific_words2): await message.add_reaction('😙') if any(word in words for word in specific_words3): await message.add_reaction('🐱') if any(word in words for word in specific_words4): await message.add_reaction('🥦') if any(word in words for word in specific_words5): await message.add_reaction('🍺') if any(word in words for word in specific_words6): await message.channel.send("Des photos compromettantes ?") if any(word in words for word in specific_words7): await message.channel.send("Sans sucre pour moi.") # 🎲 Réponses aléatoires (liste 99) if any(word in words for word in specific_words99): reply = random.choice(responses_99) await message.channel.send(reply)
Code list_react.py
Ce script permet à votre bot lister ce qu’il sait faire. Certains salons ne sont pas accessibles par le bot de par leur sérieux et leurs thématiques. Les droits ont été directement configurés sur le Discord en lui-même.
# list_react.py
import random import discord from discord import app_commands
defsetup(bot):
@bot.tree.command(name="help", description="Tous les secrets de Marvin") asyncdefblague(interaction: discord.Interaction):
# Messages possibles messages_possibles = [ """ # ▷ ▷ ▷ Marvin V1337.1 ◁ ◁ ◁ > Je suis Marvin, un *Robot dépressif* ## ▷ Commandes et réactions SI j'en ai envie, je réagis à certains appels : /help # Ce que je sais faire - si j'en ai envie - /wiki [Mot] # Je sais lire wikipedia. /meteo [ville] # Je suis aussi M. Météo. /blague # Parce que j'ai de l'humour, moi. /potin # Des histoires croustillantes d'Humains (/popotin fonctionne aussi). /destin # Parce que les Humains aiment être guidés par des suites de mots aléatoires. Marvin # Parce que je suis poli, je réponds. Certains mots me font réagir. Je ne sais pas pourquoi : Bisou, Brocoli, merde, ect. Ah, et **parfois**, quand *j'y pense*, je gère certaines dates : - Je te souhaite ton anniversaire. Si je ne dors pas. - je rapelle des journées mondiales/internationnales. Quand j'y pense. ## ▷ Salons où je peux venir t'emmerder **TOUS** sauf que je constate que je n'ai pas accès à certains salons (... et je m'en branle. Démerdez-vous entre Humains 🖕) : - La totalité de la catégorie "Salons sérieux" (soi-disant "sérieux") - Le salon : 🤬 13NRV - Le salon : 🚑 Blessures - Le salon : 💔 HELP M3 PLZ.... """ ]
# Choisir un message au hasard message_choisi = random.choice(messages_possibles)
# Envoyer le message choisi await interaction.response.send_message(message_choisi)
Lancer le bot (Pour du dev)
Sur votre serveur, connectez-vous sous l’utilisateur de votre bot ici, Marvin et entrez dans l’environement Python pour ensuite lancer votre main.py.
(venv) marvin@marvin:~$ python3 main.py 2025-12-28 23:20:31 INFO discord.client logging in using static token 2025-12-28 23:20:31 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: dxxxxxxxxxxxxxxxxxxxxxxxxbe). Bot connecté en tant que Marvin#1337
Lancer le bot en tant que service
Créer le fichier /etc/systemd/system/marvin.service et ajouter :