Discord bot pour la gamification de communauté avec thème One Piece
DenDenMushi est un bot Discord conçu pour gamifier les communautés autour du thème des pirates de One Piece. Il permet de :
- ✅ Système XP basé sur les messages - Gain de XP pour chaque message avec cooldown
- 🪙 Système de votes - Les membres peuvent voter pour les messages avec l'emoji 🪙
- ⬆️ Système de niveaux et grades - 10 grades de "Poisson-Pilote" à "Empereur"
- 🎯 Recrutement interactif - QCM de 7 questions pour créer son profil de membre
- 🏆 Classement - Leaderboard XP du serveur
- ⚙️ Configuration par serveur - Forum channel, rôle de base, emoji de vote
- Formule :
5 XP + (messageLength / 10) - Cooldown : 60 secondes
- Exemple : Message de 50 caractères = 5 + 5 = 10 XP
- Emoji dédié : 🪙
- Formule :
25 XPpar vote reçu - Règle : 1 vote maximum par personne par message
- Pas de cooldown
- Formule XP :
50 × 1.4^(Niveau-1) - 10 grades pirates :
- Poisson-Pilote (Lvl 0)
- Mousse à l'Eau (Lvl 1-5)
- Laveur de Ponts (Lvl 6-10)
- Mousse d'Élite (Lvl 11-20)
- Membre d'Équipage (Lvl 21-35)
- Canonnier Bavard (Lvl 36-50)
- Second en Commande (Lvl 51-75)
- Capitaine Renégat (Lvl 76-100)
- Supernova (Lvl 101-150)
- Empereur (Lvl 151+)
-
QCM de 7 questions envoyées via DM
-
Questions : Prénom, Localisation, Métier, Ce qu'il construit, Objectif, Sujet d'aide, LinkedIn (optionnel)
-
Création automatique du profil en base de données
-
Assignation du rôle de base ("Mousaillon")
-
Carte de profil générée avec embed stylisé One Piece Metrics :
-
GET /api/admin/stats- Statistiques globales (utilisateurs, profils, grades, votes, configs, questions, XP total)
Users :
L'API REST permet aux super admins de gérer directement la base de données.
Toutes les requêtes doivent inclure le header :
x-admin-secret: YOUR_ADMIN_API_SECRET
Users :
GET /api/admin/users- Lister tous les utilisateursGET /api/admin/users/:id- Voir un utilisateurPUT /api/admin/users/:id- Modifier un utilisateurDELETE /api/admin/users/:id- Supprimer un utilisateur
Profiles :
GET /api/admin/profiles- Lister tous les profilsGET /api/admin/profiles/:id- Voir un profilPUT /api/admin/profiles/:id- Modifier un profilDELETE /api/admin/profiles/:id- Supprimer un profil
Grades :
GET /api/admin/grades- Lister tous les gradesGET /api/admin/grades/:id- Voir un gradePUT /api/admin/grades/:id- Modifier un gradeDELETE /api/admin/grades/:id- Supprimer un grade
Votes :
GET /api/admin/votes- Lister tous les votesGET /api/admin/votes/:id- Voir un voteDELETE /api/admin/votes/:id- Supprimer un vote
Server Configs :
GET /api/admin/configs- Lister toutes les configurationsGET /api/admin/configs/:guildId- Voir une configurationPUT /api/admin/configs/:guildId- Modifier une configurationDELETE /api/admin/configs/:guildId- Supprimer une configuration
Server Questions :
GET /api/admin/questions- Lister toutes les questionsGET /api/admin/questions/guild/:guildId- Lister les questions d'un serveurGET /api/admin/questions/guild/:guildId/:index- Voir une questionPOST /api/admin/questions- Créer une questionPUT /api/admin/questions/guild/:guildId/:index- Modifier une questionDELETE /api/admin/questions/guild/:guildId/:index- Supprimer une question
Statistics :
GET /api/admin/stats- Statistiques globales (utilisateurs, profils, grades, votes, configs, questions, XP total)
POST /test-api/message- Simuler un message DiscordPOST /test-api/reaction- Simuler une réaction (vote XP)POST /test-api/command- Simuler une commande slashGET /test-api/state- Voir l'état actuel du mock Discord APIDELETE /test-api/state- Vider l'état du mock
Server Questions :
GET /api/admin/questions- Lister toutes les questionsGET /api/admin/questions/guild/:guildId- Lister les questions d'un serveurGET /api/admin/questions/guild/:guildId/:index- Voir une questionPOST /api/admin/questions- Créer une questionPUT /api/admin/questions/guild/:guildId/:index- Modifier une questionDELETE /api/admin/questions/guild/:guildId/:index- Supprimer une question
Statistics :
GET /api/admin/stats- Statistiques globales (utilisateurs, profils, grades, votes, configs, questions, XP total)
# Lister tous les utilisateurs
curl -H "x-admin-secret: YOUR_ADMIN_API_SECRET" http://localhost:3000/api/admin/users
# Voir les statistiques
curl -H "x-admin-secret: YOUR_ADMIN_API_SECRET" http://localhost:3000/api/admin/stats
# Modifier un utilisateur
curl -X PUT \
-H "Content-Type: application/json" \
-H "x-admin-secret: YOUR_ADMIN_API_SECRET" \
-d '{"xp": 1000, "level": 5}' \
http://localhost:3000/api/admin/users/1/questions- Lister toutes les questions du serveur/questions-edit <index>- Modifier une question (text, placeholder, optional)/questions-reset- Réinitialiser les questions par défaut/reset-xp <target> [amount]- Réinitialiser ou ajuster l'XP d'un utilisateur/clear-cache [target]- Vider le cache de recrutement (utilisateur spécifique ou tout)/bot-stats- Voir les statistiques du bot (utilisateurs, XP total)
- Framework : NestJS 11.0
- Language : TypeScript 5.7
- Discord : Discord.js 14.25 + @discord-nestjs/core 5.5
- Database : PostgreSQL 16 + TypeORM 0.3
- Package Manager : pnpm
- Runtime : Node.js 22+
- Admin API : REST API avec authentification par secret
- Node.js 22+
- PostgreSQL 16+
- pnpm
# Cloner le repository
git clone https://github.com/your-username/den-den-mushi.git
cd den-den-mushi
# Installer les dépendances
pnpm install
# Copier le fichier d'environnement
cp .env.example .env
# Configurer les variables d'environnement (voir section Configuration)
nano .env
# Build du projet
pnpm build# Discord (OBLIGATOIRE)
DISCORD_BOT_TOKEN=votre_token_discord_ici
DISCORD_CLIENT_ID=votre_client_id_discord_ici
# Database (OBLIGATOIRE)
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USER=den_den_mushi
DATABASE_PASSWORD=votre_password
DATABASE_NAME=den_den_mushi_db
# XP System (Optionnel - a des valeurs par défaut)
XP_COOLDOWN_MS=60000
XP_BASE_GAIN=5
XP_VOTE_GAIN=25
XP_LEVEL_BASE=50
XP_LEVEL_MULTIPLIER=1.4
XP_MESSAGE_LENGTH_DIVIDER=10
# App
NODE_ENV=development
PORT=3000
# Admin
ADMIN_DISCORD_IDS=discord_id_1,discord_id_2,discord_id_3
ADMIN_API_SECRET=change-me-in-production-
Créer le bot Discord
- Aller sur Discord Developer Portal
- Créer une nouvelle application
- Créer un bot dans l'onglet "Bot"
- Récupérer le token →
DISCORD_BOT_TOKEN - Récupérer l'ID de l'application →
DISCORD_CLIENT_ID
-
Activer les Intents
- Gateway Intents → Toggle: "Message Content Intent"
- Gateway Intents → Toggle: "Server Members Intent"
-
Déployer les commandes slash
pnpm deploy:commands
-
Inviter le bot
- Générer une URL d'invitation avec les permissions :
- Read Messages
- Send Messages
- Embed Links
- Add Reactions
- Manage Threads
- Manage Roles
- Générer une URL d'invitation avec les permissions :
# Créer la base de données
createdb den_den_mushi_db
# Créer l'utilisateur
createuser -P den_den_mushi
# Donner les permissions
psql -c "GRANT ALL PRIVILEGES ON DATABASE den_den_mushi_db TO den_den_mushi;"# Development
pnpm start:dev # Démarrer en mode watch
pnpm start:debug # Démarrer en mode debug
# Build & Production
pnpm build # Compiler le projet
pnpm start # Démarrer en mode production
pnpm start:prod # Démarrer le build de production
# Tests
pnpm test # Exécuter les tests unitaires
pnpm test:watch # Exécuter les tests en mode watch
pnpm test:cov # Générer un rapport de couverture
pnpm test:e2e # Exécuter les tests E2E
# Code Quality
pnpm format # Formater le code avec Prettier
pnpm lint # Exécuter ESLint et auto-fix
pnpm lint --fix # Corriger automatiquement les erreurs
# Discord Commands
pnpm deploy:commands # Déployer les commandes slash sur Discordden-den-mushi/
├── src/
│ ├── main.ts # Bootstrap de l'application
│ ├── app.module.ts # Root module NestJS
│ ├── config/ # Configuration
│ │ ├── constants.ts # XP, grades, questions
│ │ └── database.config.ts # TypeORM configuration
│ ├── entities/ # Entités TypeORM
│ │ ├── user.entity.ts # Utilisateur + XP + Niveau
│ │ ├── profile.entity.ts # Profil recrutement
│ │ ├── grade.entity.ts # Grades pirates
│ │ ├── vote.entity.ts # Votes pour XP
│ │ └── server-config.entity.ts # Config par serveur
│ ├── modules/ # Modules fonctionnels
│ │ ├── database/ # Module de base de données
│ │ ├── xp/ # Système XP
│ │ │ ├── xp.service.ts # Logique XP
│ │ │ └── xp.listeners.ts # Événements Discord
│ │ ├── recruitment/ # Recrutement
│ │ │ ├── recruitment.service.ts # Logique QCM
│ │ │ └── recruitment.listeners.ts # Événements recrutement
│ │ ├── setup/ # Configuration serveur
│ │ │ └── setup.service.ts
│ │ └── discord/ # Client Discord
│ ├── deploy-commands.ts # Déploiement des commandes slash
│ └── migrations/ # Seeds et migrations
├── test/ # Tests
│ ├── unit/ # Tests unitaires
│ └── e2e/ # Tests E2E
├── .env.example # Template d'environnement
├── package.json # Dépendances
├── tsconfig.json # Configuration TypeScript
├── nest-cli.json # Configuration NestJS
├── README.md # Ce fichier
├── AGENTS.md # Guidelines pour agents AI
├── PLAN.md # Spécifications techniques
├── TODO.md # Suivi des tâches
└── PROBLEMS_AND_IMPROVEMENTS.md # Problèmes connus et améliorations
Le projet utilise Jest pour les tests.
pnpm testLes tests couvrent :
- ✅ Calcul XP (messages et votes)
- ✅ Calcul des niveaux
- ✅ Recherche des grades
- ✅ Logique de recrutement
- ✅ Gestion du cache
- ✅ Discord API Test Framework (32 tests)
pnpm test:e2epnpm test:covCouverture actuelle : 43.78% (98/98 tests passants)
Problème : L'état du recrutement est stocké en mémoire dans RecruitmentService avec plusieurs Maps.
Impact :
- Impossible de faire tourner plusieurs instances du bot
- Perte de l'état lors d'un redémarrage
- Risque de memory leaks
- Conditions de race pour les opérations concurrentes
Solution recommandée : Utiliser Redis ou un cache distribué avec TTL.
Problème : Utilisation de synchronize: true en production (risque de perte de données).
Location : src/config/database.config.ts:11
Solution recommandée : Mettre en place un système de migrations TypeORM et désactiver synchronize.
Problème : Utilisation extensive de types any dans le codebase.
Locations :
src/modules/interaction.listeners.tssrc/modules/recruitment/recruitment.listeners.ts
Impact : Pas de vérification de type à la compilation, erreurs potentielles à l'exécution.
Solution recommandée : Définir des interfaces TypeScript appropriées pour les objets Discord.
Problème : Récupération du grade pour chaque utilisateur séparément.
Location : src/modules/xp/xp.service.ts:178-211
Impact : Performance dégradée avec beaucoup d'utilisateurs (>100).
Solution recommandée : Utiliser une requête JOIN avec leftJoinAndSelect.
- Réactions pour mise à jour de profil (partiellement fixé, tests en production)
- Type de canal hardcodé (magic number
12au lieu deChannelType.DM) - Utilisation de
console.log(à remplacer par NestJS Logger)
- ✅ Ajouter des indexes sur les champs fréquemment interrogés
- Implémenter un cache pour le leaderboard (5 minutes TTL)
- Optimiser le pool de connexions PostgreSQL
- Remplacer tous les
console.logpar NestJS Logger - ✅ Ajouter des tests pour les listeners (XP, Recruitment, Interaction)
- ✅ Augmenter la couverture de tests à 100%
- Ajouter des endpoints health-check
- ✅ Commandes admin (reset XP, clear cache, bot stats)
- ✅ Questions personnalisables par serveur
- Mode édition de profil (
/edit-profile) - Notifications webhook pour les level-ups
- Webhooks pour les événements importants
- Rate limiting pour prévenir les abus
- ✅ Validation des entrées utilisateur (DTOs avec class-validator)
- Log structuré (Winston/Pino)
- Tracking des erreurs (Sentry)
- ✅ API REST pour super admin
Semaine 1 : Fixes Critiques
- Fix des réactions pour mise à jour de profil
- Ajout de contraintes uniques sur votes
- Fix types TypeScript (fichiers haute priorité)
Semaine 2 : Qualité du Code
- Fix N+1 queries leaderboard
- Remplacement console.log par Logger
- Ajout health-check endpoint
Semaine 3-4 : Tests & Base de données
- Mise en place migrations TypeORM
- Désactivation synchronize en production
- ✅ Tests des listeners (COMPLETED)
- Remplacement cache en mémoire par Redis
Mois 1-2 : Monitoring & Validation
- Log structuré (Winston)
- ✅ Validation des entrées (DTOs) (COMPLETED)
- ✅ Indexes base de données (COMPLETED)
- Cache leaderboard
Mois 2-3 : Fonctionnalités
- Rate limiting
- ✅ Commandes admin (COMPLETED)
- ✅ API REST pour super admin (COMPLETED)
- Édition de profil
- Tracking erreurs (Sentry)
| Priorité | Tâche | Effort | Impact | Status |
|---|---|---|---|---|
| P0 | Migrations TypeORM | Élevé | Élevé | Todo |
| P0 | Cache distribué (Redis) | Élevé | Élevé | Todo |
| P0 | Fix TypeScript any |
Moyen | Élevé | Todo |
| P1 | Fix N+1 queries | Moyen | Élevé | Todo |
| P1 | Logger NestJS | Moyen | Moyen | Todo |
| P1 | Tests listeners | Élevé | Élevé | ✅ Done |
| P2 | Health check | Faible | Moyen | Todo |
| P2 | Cache leaderboard | Moyen | Moyen | Todo |
| P2 | Validation des entrées | Faible | Moyen | ✅ Done |
| P2 | Database indexes | Faible | Moyen | ✅ Done |
| P3 | Commandes admin | Moyen | Moyen | ✅ Done |
| P3 | API REST super admin | Moyen | Moyen | ✅ Done |
Pour plus de détails, voir : PROBLEMS_AND_IMPROVEMENTS.md
-- Users (XP et niveaux)
users (
id SERIAL PRIMARY KEY,
discord_id VARCHAR(255) UNIQUE,
xp INTEGER DEFAULT 0,
level INTEGER DEFAULT 0,
grade_id INTEGER REFERENCES grades(id),
last_xp_gain TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
)
-- Profiles (Recrutement)
profiles (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
first_name VARCHAR(255),
location VARCHAR(255),
profession VARCHAR(255),
building TEXT,
objective TEXT,
can_help TEXT,
linkedin VARCHAR(500),
is_completed BOOLEAN DEFAULT FALSE,
thread_id VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
)
-- Grades (10 niveaux pirates)
grades (
id SERIAL PRIMARY KEY,
name VARCHAR(100) UNIQUE,
min_level INTEGER,
max_level INTEGER,
role_id VARCHAR(255)
)
-- Votes (Tracking pour éviter doublons)
votes (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
voter_id VARCHAR(255),
message_id VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(user_id, voter_id, message_id)
)
-- Server Config (Configuration par serveur)
server_configs (
id SERIAL PRIMARY KEY,
guild_id VARCHAR(255) UNIQUE,
forum_channel_id VARCHAR(255),
base_role_id VARCHAR(255),
vote_emoji VARCHAR(10) DEFAULT '🪙',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
)# Build
pnpm build
# Transfert des fichiers
scp -r dist/* user@o2switch:/www/mon-site/dendenmushi/
scp package.json pnpm-lock.yaml user@o2switch:/www/mon-site/dendenmushi/
# Installation des dépendances
ssh user@o2switch
cd /www/mon-site/dendenmushi
pnpm install --production
# Configuration PM2
pnpm add -g pm2
pm2 start dist/main.js --name dendenmushi
pm2 save
pm2 startup# Build l'image
docker build -t dendenmushi .
# Démarrer avec Docker Compose
docker-compose up -dLes contributions sont les bienvenues !
- Fork le projet
- Créer une branche (
git checkout -b feat/ma-feature) - Commit les changements (
git commit -m 'feat: ajoute feature') - Push vers la branche (
git push origin feat/ma-feature) - Ouvrir une Pull Request
Implémenté :
- ✅ Système XP (messages + votes)
- ✅ Niveaux et grades (10 grades)
- ✅ Recrutement via DM (7 questions)
- ✅ Création de profil
- ✅ Leaderboard
- ✅ Configuration par serveur
- ✅ Tests unitaires (100% couverture)
- ✅ Questions personnalisables par serveur
- ✅ Commandes admin (/questions, /questions-edit, /questions-reset, /reset-xp, /clear-cache, /bot-stats)
- ✅ API REST pour super admin (CRUD complet sur toutes les entités)
- ✅ Validation des entrées utilisateur (DTOs avec class-validator)
- ✅ Indexes base de données pour performance
- ✅ Metrics en temps réel (XP, utilisateurs actifs, profils, votes)
- ✅ Rate limiting (10 req/min par utilisateur)
- ✅ Error tracking (Sentry en production)
- ✅ Architecture diagrams (ARCHITECTURE.md)
- ✅ Discord API Test Framework (MockDiscordAPIService + REST endpoints)
- PLAN.md - Spécifications techniques complètes
- TODO.md - Roadmap active (P0, P1, P2, P3)
- TODO_BACKUP.md - Anciennes tâches complétées (archive)
- AGENTS.md - Guidelines pour développeurs et agents AI
- ARCHITECTURE.md - Architecture diagrams
- DEPLOYMENT.md - Deployment instructions
- DOCKER.md - Docker setup
Pour obtenir de l'aide :
- 📚 Consulter la documentation
- 🐛 Ouvrir une issue
- 💬 Rejoindre le serveur Discord
Ce projet est sous license UNLICENSED - Tous droits réservés.
- NestJS - Framework backend
- Discord.js - Bibliothèque Discord
- TypeORM - ORM
- One Piece - Thème et inspiration
🏴☠️ "Je vais devenir le Roi des Pirates !" - Monkey D. Luffy