Nathan Retour au site
Projet · avril → août 2026

Soulbot

Un bot Discord de modération et de protection, mené seul pendant quatre mois et demi. Parti d’une base existante, il n’en reste aujourd’hui presque rien : l’interface, l’architecture, les protections et les tests ont été réécrits.

4,5 moisd’avril à août 2026 Seul, du premier au dernier commit.
3 613tests automatisés 204 fichiers, dont une part de garde-fous : des tests qui échouent si une erreur déjà corrigée revient.
276commandes
788fichiers JavaScript
16serveurs
avrilmaijuinjuil.août
538 commits sur 38 jours · record le 30 juillet avec 78

D’où ça part

Le premier commit date du 18 avril 2026. Le projet ne part pas de rien : il reprend une base de bot existante, avec ses commandes et sa structure. Le deuxième commit est un audit de sécurité — avant d’ajouter quoi que ce soit, savoir ce qu’on a hérité.

Il a trouvé, entre autres, que les commandes réservées au propriétaire portaient bien la mention « propriétaire uniquement », mais que rien ne la lisait : le routeur de messages exécutait la commande sans jamais vérifier qui la tapait. Dans la même journée : une permission sensible réclamée à Discord sans jamais servir, et une commande déclarée sous le nom d’une autre — donc injoignable. Tout est corrigé le jour même, avant la première ligne de fonctionnalité.

Quatre mois et demi plus tard, il ne reste quasiment rien de cette base. Les commandes ont été réécrites une par une, l’interface a été refondue deux fois, et le socle technique — journalisation, permissions, protections, tests — a été construit entièrement.

C’est la partie de l’histoire qui compte : ce n’est pas un projet démarré, c’est un projet repris. Reprendre du code qu’on n’a pas écrit, le comprendre, décider quoi garder et quoi jeter, c’est le travail qu’on fait vraiment en entreprise.

Les six phases

  1. Reprise et structure

    Réorganisation en seize catégories de commandes, mise en place de la base SQLite et du système de permissions à trois niveaux.

  2. Le creux

    12 commits en mai, 22 en juin. Le projet ralentit sans s’arrêter. C’est le passage le moins spectaculaire et le plus honnête : un projet personnel qui survit à son premier essoufflement.

  3. Components V2

    Toutes les commandes migrent vers le format d’interface moderne de Discord. Les embeds classiques disparaissent. Un kit d’interface commun remplace le copier-coller entre fichiers. Le rouge devient la couleur du produit.

    Migration incomplète, et on ne s’en apercevra qu’en août : le panneau qui marche a été refait, les messages d’erreur non. Une interface soignée qui répond par une ligne de texte brut dès que quelque chose échoue — c’est-à-dire au seul moment où l’utilisateur a vraiment besoin qu’on lui parle.

  4. Le mois où tout accélère

    Le mois le plus dense du projet : 39 % des commits en un seul mois. Journaux de nouvelle génération, détection de comptes multiples, capture réseau, audit de serveur, journal vidéo, contrôle vocal, console de santé dessinée au canvas.

    Ce n’est pas de l’énergie retrouvée : c’est juillet qui paie. Une fois le kit d’interface écrit, une commande neuve se pose dessus au lieu de se réécrire entièrement. Le mois spectaculaire est la conséquence du mois ingrat.

  5. L’IA entre dans le produit

    Trois fournisseurs de modèles, un catalogue à deux étages — gratuit pour tous, payant réservé au propriétaire qui paie la clé. Et surtout deux consentements distincts : envoyer des statistiques n’est pas envoyer les propos des membres. Le second ne s’allume jamais tout seul.

  6. Reprendre la main quand tout brûle

    Un mode de secours permet de reprendre le contrôle du bot depuis un message privé authentifié, quand il est devenu incontrôlable sur les serveurs. TOTP écrit à la main d’après la RFC 6238, anti-rejeu, codes de secours, et une mise en veille qui coupe les cinquante événements et les seize tâches planifiées.

La console de santé
Les panneaux
Les journaux
L’audit de serveur
Le mode sans échec

Glisse le présentoir, clique une pochette, ou utilise les flèches.

Les décisions qui ont façonné le projet

Des commandes à préfixe, pas des slash commands

À contre-courant de ce que fait Discord depuis 2020. Le choix tient à la densité : deux cent soixante-seize commandes en slash commands, c’est un menu déroulant illisible et une limite d’API atteinte. Le préfixe reste immédiat pour ceux qui connaissent, et un panneau d’aide guide les autres.

Zéro emoji Unicode

Aucun emoji du clavier dans les réponses du bot : uniquement des emojis dessinés sur mesure, ou rien. Un emoji Unicode s’affiche différemment sur chaque système, casse l’alignement des colonnes, et fait ressembler un bot professionnel à un message de forum.

Le rouge ne sert qu’à ce qui ne va pas

Règle posée après un premier essai raté où tout était en couleur d’accent — donc tout était rouge, et plus rien ne signalait un incident. Une donnée sans seuil n’est jamais colorée. C’est ce qui rend le rouge crédible quand il apparaît.

Chaque décision non évidente est écrite en haut du fichier

Pas un commentaire qui répète le code, mais la raison du choix et ce qu’on a essayé avant. Six mois plus tard, c’est la seule chose qui empêche de refaire l’erreur qu’on avait déjà corrigée.

Ce qu’il y a dessous

788
fichiers JavaScript

Node.js et discord.js, aucun framework. Ce qui manquait a été écrit plutôt qu’installé.

Une base, en local

SQLite, accès synchrone, migrations de schéma versionnées. Rien à joindre par le réseau pour lire une sanction.

Ce qui se lit mieux dessiné

Classements, statistiques, santé du bot, calendriers : rendus au canvas, avec un repli texte si le dessin échoue.

3 613 tests, 204 fichiers

Une pastille par fichier. Beaucoup sont des garde-fous : ils échouent si quelqu’un réintroduit une erreur déjà corrigée.

Journalisation maison

Un logger, trois destinations, corrélation par identifiant de requête, limitation du flot. Et les secrets masqués avant d’atteindre le disque.

Les galères

Ce sont elles qui ont le plus appris. Chacune a laissé un commentaire dans le code et, souvent, un test qui l’empêche de revenir.

01Tout devenait magenta, sans que personne ne l’ait demandé

Une valeur par défaut dans le schéma SQLite imposait une couleur héritée d’une ancienne identité, en écrasant le thème choisi. Le bug ne se voyait que sur les serveurs qui n’avaient jamais touché à leurs réglages — donc presque tous.

La leçon : une valeur par défaut en base est une décision de produit déguisée en détail technique.

02Les tests effaçaient les emojis du bot

Un fichier de test supprimait le cache d’identifiants d’emojis — le vrai, celui de production. Après chaque exécution de la suite, le bot repartait avec des emojis Unicode, c’est-à-dire exactement ce que le projet s’interdit.

La leçon : une suite de tests qui touche aux fichiers de production n’est pas une suite de tests, c’est un risque.

03Une commande d’urgence rendue injoignable par un alias

La commande de secours ne répondait jamais. Cause : une autre commande, écrite des mois plus tôt, déclarait le même mot dans ses alias — et la table des alias est consultée avant celle des noms. La commande existait, se chargeait, apparaissait dans l’aide, et n’était atteignable par personne.

La leçon : un test balaie désormais les 276 commandes et échoue si un alias masque le nom d’une autre.

04Discord ne livrait aucun message privé

Le mode de secours se pilote en message privé. Il ne recevait rien — aucune erreur, aucun message : les événements n’arrivaient tout simplement pas. Il a fallu une sonde posée avant toute logique, un témoin de contrôle sur les messages de serveur, et la lecture directe de l’API pour établir que Discord stockait bien les messages sans les transmettre.

La leçon : un relais lit désormais ces messages par l’API. Un mode de secours qui dépend d’un canal qu’on ne contrôle pas n’est pas un mode de secours.

05La mise en veille ne coupait pas ce qu’elle prétendait couper

La garde chargée de faire taire le bot ne voyait que le nom de l’événement, jamais qui l’écoutait. Comme un événement devait passer pour répondre « maintenance », tout ce qui écoutait ce même événement passait avec lui : anti-spam, journaux, compteurs. Un commentaire dans le code affirmait le contraire.

La leçon : un commentaire n’est pas une preuve. La garde reçoit maintenant l’identité de l’appelant, et des tests vérifient que les autres sont bien coupés.

Les fondateurs

Un projet mené seul n’est pas un projet mené sans personne.

Où ça en est

Le bot tourne sur seize serveurs. La suite de tests passe entièrement. Le chantier ouvert est le découpage en bots spécialisés — un premier satellite de modération autonome existe déjà, trois autres sont amorcés.

Ce qui reste le plus utile, avec le recul, n’est aucune des fonctionnalités : c’est l’habitude d’écrire pourquoi, de tester ce qui a déjà cassé, et de refuser une explication tant qu’elle n’est pas vérifiée.