Repository navigation
v9.0
RELEASE NOTES & SPÉCIFICATIONS TECHNIQUES : KOTBO
Version : v9.0
Statut : Production Release / Major Milestone
Auteurs : Équipe Core Engineering Kotbo
Sujets Majeurs : Moteur d'Internationalisation (i18n), Composants Discord UI V2, Suite de Sécurité & Anti-Raid, Système de Clans Communautaires, Transcriptions HMAC
📑 Résumé Exécutif
La version v9.0 de Kotbo marque une refonte architecturale majeure de l'écosystème. Cette mise à jour transforme le bot d'un outil de gestion monolithique en une plateforme modulaire, internationale, hautement sécurisée et conforme aux derniers standards d'interface de Discord.
Points Clés de la Release
-
Moteur i18n Type-Safe : Intégration native de Paraglide-JS pour une prise en charge bilingue (FR/EN) compilée et sans surcoût au runtime.
-
Refonte Graphique Discord V2 : Transition complète des conteneurs d'affichage vers
@arcscord/componentssur plus de 25 commandes slash. -
Moteur Anti-Raid & Audit Automatisé : Déploiement de la suite de commande
/protection, du scanner/auditet du système de signalement/report. -
Écosystème de Clans & Saisons : Système complet de guildes rivales, distribution d'XP, annonces automatisées et classement public synchronisé en temps réel.
-
Transcriptions de Tickets Sécurisées : Implémentation d'URLs signées temporaires par HMAC pour éliminer tout risque de fuite d'informations ou d'énumération.
-
Optimisation DevOps & Runner : Isolation stricte des suites de tests unitaires (
bun test --isolate) et intégration des utilitaires PostgreSQL au conteneur principal.
📊 Matrice d'Impact & Matrice des Changements
| Module / Composant | Nature de la Modification | Impact Système | Compatibilité Descendante |
|---|---|---|---|
i18n Moteur (paraglide-js) |
Ajout du pipeline de compilation multilingue | Majeur (Cycle de build) | Totalement rétrocompatible |
| Interface Utilisateur (UI V2) | Refonte vers @arcscord/components |
Majeur (Rendu Visuel) | Rupture sur le formatage brut V1 |
Module Sécurité (/protection) |
Nouveaux services d'anti-raid, captcha & scam | Majeur (Pipeline d'événements) | Nouvelle configuration requise |
Module Clans (/clan & API) |
Nouvelles tables Prisma, routes API et commandes | Moyen (Base de données & API) | Totalement rétrocompatible |
Transcriptions (/api/public) |
Authentification HMAC et vérification RBAC | Moyen (API Publique) | Liens non signés dépréciés |
| Pipeline de Test (Bun Runner) | Isolation de processus via --isolate |
Mineur (DevOps & CI) | Transparent pour la production |
🏗️ Schémas d'Architecture & Flux de Traitement
1. Tunnel de Filtrage & Traitement d'un Membre Entrant (Anti-Raid & Captcha)
Le pipeline d'accueil évalue séquentiellement les verrous de sécurité avant d'accorder l'accès au serveur aux nouveaux utilisateurs :
[ Événement : GuildMemberAdd ]
│
v
┌─────────────────────────────────────────┐
│ Join Lock ou Mode Urgence Actif ? │
└────────────────────┬────────────────────┘
│
┌─────────────┴─────────────┐
▼ ▼
[ OUI ] [ NON ]
│ │
v v
┌──────────────────┐ ┌──────────────────────────┐
│ Expulsion / Ban │ │ Détection Anti-Raid │
│ Immédiat (Kick) │ │ (Arrivées Massives / Sec)│
└──────────────────┘ └────────────┬─────────────┘
│
┌─────────────┴─────────────┐
▼ ▼
[ Seuil ] [ Normal ]
│ │
v v
┌─────────────────────┐ ┌──────────────────────┐
│ Déclenchement Raid │ │ Captcha Requis ? │
│ Mode (Lock/Captcha) │ └──────────┬───────────┘
└─────────────────────┘ │
┌─────────────┴─────────────┐
▼ ▼
[ OUI ] [ NON ]
│ │
v v
┌──────────────────────┐ ┌──────────────────────┐
│ Assignation Rôle │ │ Accès Validé │
│ @Non-Vérifié + Modal │ │ (Attribution TagRole)│
└──────────────────────┘ └──────────────────────┘
2. Architecture de Compilations des Traductions (Paraglide-JS)
L'approche choisie évite le parsing JSON au runtime en compilant les clés de traduction sous forme de fonctions TypeScript pures :
┌──────────────────────────┐ ┌──────────────────────────┐
│ apps/bot/messages/fr.json│ │ apps/bot/messages/en.json│
└─────────────┬────────────┘ └─────────────┬────────────┘
│ │
└─────────────────┬────────────────┘
│
v
┌────────────────────────────────┐
│ bun run build:i18n │
│ (paraglide-js compile) │
└───────────────┬────────────────┘
│
v
┌────────────────────────────────┐
│ src/lib/paraglide/messages.js │
│ (Fonctions JS pure Type-Safe) │
└───────────────┬────────────────┘
│
v
┌────────────────────────────────┐
│ Import dans les commandes bot │
│ m.rpg_profile_title(..., loc) │
└────────────────────────────────┘
📄 Analyse Détaillée des Fonctionnalités & Code
🌐 1. Internationalisation (i18n) Native avec Paraglide-JS
Afin d'offrir une expérience utilisateur fluide pour les communautés francophones et anglophones, le bot embarque désormais un système de traduction type-safe.
Implémentation dans le module RPG (apps/bot/src/commands/fun/rpgEconomy.ts)
La résolution de la langue s'effectue via le helper getLocale, qui extrait la préférence de l'interaction :
import { getLocale } from '../../utils/i18n.js';
import * as m from '../../lib/paraglide/messages.js';
async function rpgProfileExecute(interaction: ChatInputCommandInteraction) {
const locale = getLocale(interaction);
if (!await checkEconomyEnabled(interaction, locale)) return;
const targetUser = interaction.options.getUser('membre') ?? interaction.user;
const profile = await getOrCreateRpgProfile(interaction.guildId!, targetUser.id);
const embed = new EmbedBuilder()
.setTitle(m.rpg_profile_title({ name: targetUser.displayName }, { locale }))
.setThumbnail(targetUser.displayAvatarURL({ size: 256 }))
.setColor(COLORS.primary)
.setDescription(
profile.isTraveling
? m.rpg_profile_traveling({ dest: profile.travelDestination }, { locale })
: m.rpg_profile_resting({}, { locale })
)
.addFields(
{
name: m.rpg_profile_field_wallet({ emoji: config.currencyEmoji }, { locale }),
value: `**${profile.balance}** ${config.currencyName}`,
inline: true
},
{
name: m.rpg_profile_field_level({}, { locale }),
value: m.rpg_profile_level_value({ level: profile.level }, { locale }),
inline: true
}
);
await interaction.reply({ embeds: [embed] });
}🎨 2. Standardisation des Composants Discord V2
Pour harmoniser l'affichage graphique sur mobile et desktop, Kotbo abandonne les anciens ContainerBuilder verbeux au profit du wrapper applicatif @arcscord/components.
Exemple de refonte sur la commande /backup (apps/bot/src/commands/admin/backup.ts)
import { separator, v2Message } from '@arcscord/components';
import { kotboContainer } from '../../utils/embeds.js';
// Rendu structuré et épuré avec gestion automatique du conteneur V2
await interaction.editReply(v2Message(
kotboContainer({
color: 'success',
title: `${E.success} Sauvegarde créée`,
fields: [
`Sauvegarde **${backupName}** créée avec succès!`,
separator({ divider: true, spacing: 'small' }),
`### ${E.stats} Statistiques`,
[
`${E.arrow} Rôles: ${backup.rolesCount}`,
`${E.arrow} Salons: ${backup.channelsCount}`,
`${E.arrow} Membres: ${backup.membersCount}`,
`${E.arrow} Taille: ${(backup.sizeBytes / 1024).toFixed(2)} KB`,
].join('\n'),
],
}),
));🛡️ 3. Panneau Anti-Raid, Audit & Signalements
La commande d'administration unifiée /protection offre un contrôle direct sur les modules de défense.
Configuration dynamique via les API Dashboard (apps/bot/src/api/routes/dashboard/raidProtection.ts)
// Champs modifiables à chaud depuis l'interface web d'administration
const PATCHABLE_FIELDS = [
'captchaEnabled', 'captchaChannelId', 'captchaUnverifiedRoleId', 'captchaTimeoutMinutes',
'antiRaidEnabled', 'antiRaidJoinThreshold', 'antiRaidJoinWindowSec', 'antiRaidAction',
'joinLockKick', 'joinLockMessage',
'reportsEnabled', 'reportsChannelId', 'reportsCooldownSec', 'reportsAnonymous',
'scamFilterEnabled', 'scamFilterAction', 'scamImageFilterEnabled',
'inviteGuardEnabled', 'inviteRequireUnitary', 'inviteValidationEnabled'
] as const;
export async function handleRaidProtectionRoutes(...) {
if (sub === 'raidmode' && method === 'POST') {
const body = await readJsonBody<{ active?: boolean }>(req);
const guild = client.guilds.cache.get(guildId);
const config = (await getRaidProtectionConfig(guildId)) ?? (await upsertRaidProtectionConfig(guildId, {}));
if (body?.active) {
await activateRaidMode(guild, config, true, user.userId);
pushAudit(client, guildId, auditUser, 'raid-protection', 'Mode raid activé manuellement');
} else {
await deactivateRaidMode(guild, config);
pushAudit(client, guildId, auditUser, 'raid-protection', 'Mode raid désactivé');
}
return json(res, 200, { config: await getRaidProtectionConfig(guildId) });
}
}🏰 4. Système de Clans Communautaires & REST API
Le module de Clans permet d'animer la communauté via des compétitions inter-groupes avec suivi de score en temps réel et réinitialisations saisonnières.
Structure d'une Réponse API Publique (GET /api/public/guilds/:guildId/clans)
{
"enabled": true,
"currentClanSeason": 2,
"guildName": "Server Support Kotbo",
"guildIcon": "https://cdn.discordapp.com/icons/123456789/a_123.png",
"clans": [
{
"id": "clan-uuid-01",
"name": "Guilde de l'Aube",
"description": "Les protecteurs du royaume",
"roleId": "987654321012345678",
"roleColor": "#3b82f6",
"totalXp": 15420,
"memberCount": 42,
"topParticipants": [
{
"userId": "223344556677889900",
"xp": 3400,
"displayName": "Arthur",
"avatarUrl": "https://cdn.discordapp.com/avatars/2233/abc.png"
}
]
}
],
"recentScores": [
{
"id": "evt-101",
"amount": 50,
"source": "XP",
"displayName": "Arthur",
"clanName": "Guilde de l'Aube",
"clanColor": "#3b82f6",
"createdAt": "2026-07-22T23:45:00.000Z"
}
]
}
🔐 5. Sécurisation des Transcriptions par Liens Signés HMAC
Pour éliminer les vulnérabilités de divulgation d'informations confidentielles via les transcriptions de tickets, les identifiants bruts ne permettent plus d'accéder au contenu. Une signature cryptographique d'une durée de validité limitée (TTL 1h) est générée à la demande.
// Extrait de validation des accès (`apps/bot/src/api/routes/public.ts`)
if (parts[2] === 'transcripts' && parts[3] && parts[4] === 'access' && method === 'GET') {
const transcriptId = parts[3];
const auth = await verifyAuth(req);
if (!auth) return json(res, 401, { error: 'Authentification requise.' });
const transcript = await prisma.transcript.findUnique({
where: { id: transcriptId },
select: { id: true, guildId: true },
});
if (!transcript) return json(res, 404, { error: 'Transcription introuvable' });
// Vérification des droits : Membre du Staff OU Auteur/Intervenant du ticket
const access = await resolveDashboardAccess(client, transcript.guildId, auth.userId).catch(() => null);
let authorized = !!access?.canViewDashboard;
if (!authorized) {
const ticket = await prisma.ticket.findFirst({
where: { transcriptId, guildId: transcript.guildId },
select: { userId: true, claimedById: true, closedById: true },
});
if (ticket && [ticket.userId, ticket.claimedById, ticket.closedById].includes(auth.userId)) {
authorized = true;
}
}
if (!authorized) return json(res, 403, { error: "Accès refusé." });
// Génération de l'URL signée temporaire (1 heure)
const { generateTranscriptSignature } = await import('@kotbo/core');
const { expires, signature } = generateTranscriptSignature(transcriptId, 3600);
json(res, 200, { signedUrl: `/api/public/transcripts/${transcriptId}?expires=${expires}&sig=${signature}` });
}🛠️ Infrastructure, Docker & Tests
1. Mise à Jour du DockerfileBot (DockerfileBot)
Ajout du paquet système postgresql-client afin d'autoriser l'exécution directe de l'utilitaire pg_dump pour le système de sauvegardes automatisées :
FROM oven/bun:1-alpine
# Canvas text rendering requires system fonts (Alpine ships with none)
# postgresql-client provides pg_dump, used by the daily database backup job
RUN apk add --no-cache fontconfig ttf-dejavu postgresql-client \
&& fc-cache -f
WORKDIR /app
2. Isolation des Tests Unitaires (apps/bot/package.json)
Correction d'un problème d'isolation au sein du test runner Bun où l'utilisation de mock.module polluait l'environnement d'exécution des tests suivants :
{
"scripts": {
"test:unit": "bun run build:i18n && bun test src/tests",
"test:watch": "bun test --isolate --watch src/tests"
}
}
What's Changed
- Make kotbo scale by @Klaynight-dev in #1
- feat(automod): add automatic nickname moderation system by @Intercalaire in #2
- e by @Klaynight-dev in #3
- feat(dashboard): implement real-time websocket sync for nickname mode by @Intercalaire in #6
- feat(automod): add undo option for deleted banned words and improve UI by @Intercalaire in #7
- Rate-limit and sanitize dashboard error reports by @Klaynight-dev in #26
- Harden dashboard API auth and security by @Klaynight-dev in #27
- fix(automod): overhaul nickname moderation detection to eliminate false positive by @Intercalaire in #33
- feat(dashboard/automod): add dynamic nickname whitelist and member bypass exceptions by @Intercalaire in #38
- feat(nickname-moderation): granular moderation toggles and real-time synchronization by @Intercalaire in #39
- Fix/nickname toggles by @Intercalaire in #41
- fix(dashboard): return created banned word payload in addBannedWord mutation by @Intercalaire in #42
- Optimisation du buffering I/O et du cache pour Prisma et le service de leveling by @sailingteam4 in #43
- refactor(bot): centralize command definitions by @Arcoz0308 in #44
- somes fixes by @Arcoz0308 in #45
- fix: éviter le spam de rappels et les crashs du dashboard by @sailingteam4 in #48
- A new bdd for username automod by @Intercalaire in #46
- Introducing mobile sidebar by @RevoIDE in #52
- Feat/prima clean by @Arcoz0308 in #51
- feat: intégration serveur MCP pour interaction IA avec le bot Discord by @sailingteam4 in #54
- feat: strengthen GDPR compliance and dashboard auth by @sailingteam4 in #55
- fix(rep): use mentions and shared vote limit by @Arcoz0308 in #59
- fix(security): CORS hardening + vulnerable dep bumps; remove dead code by @Klaynight-dev in #60
- Sync by @Klaynight-dev in #62
- Feat/clans Implementation clans by @Intercalaire in #58
- fix(dashboard): correction d'une balise fermante manquante dans Clans… by @Intercalaire in #63
- Feat/clans fix some issues by @Intercalaire in #65
- feat(clans): improve season planning UI, WS real-time, manual points fix, leader roles & leveling xp boost display by @Intercalaire in #67
- feat(clans): add season history, double accounts pooling, and dashboard administration tools by @Intercalaire in #69
- feat(clans): add season history, double accounts pooling, and dashboard by @Intercalaire in #70
- fix a gap by @Intercalaire in #71
- feat(clans): auto-assign clan on member join with DC exclusion by @Intercalaire in #72
- fix an issue, and this commit is a test by @Intercalaire in #73
- Feat/clans revert 2 commit by @Intercalaire in #74
- feat(clans): auto-assign new members to least populated clan on join by @Intercalaire in #75
-
- Fix member points endpoint using nonexistent prisma.member model by @Intercalaire in #76
- feat(leveling): add configurable message-length XP bonus by @Intercalaire in #77
- feat(clans): live public leaderboard — dynamic columns + recent score… by @Intercalaire in #78
- feat(clans): auto-assign new members to least populated clan on join by @Intercalaire in #79
- refactor(bot): adopt Arcscord component helpers by @Arcoz0308 in #61
- refactor(clans): replace dashboard emojis with Papicon icons by @Intercalaire in #80
- Feat ajoute de nouvelle fonctionnalité de raidprotection by @Klaynight-dev in #81
New Contributors
- @Klaynight-dev made their first contribution in #1
- @Arcoz0308 made their first contribution in #44
- @RevoIDE made their first contribution in #52
Full Changelog: https://github.com/Kotbo-Bot/Kotbo/commits/v9