Un bot de bienvenue Discord accueille automatiquement chaque nouveau membre qui rejoint ton serveur, mais il va plus loin qu'un simple message « bienvenue » : il génère une image personnalisée affichant l'avatar et le nom du membre. Un visuel sur mesure laisse une bien meilleure première impression qu'une ligne de texte. Dans ce tutoriel, nous construirons un bot fonctionnel de zéro avec discord.js et @napi-rs/canvas.
Paquets requis et mise en place du projet
Il te faut Node.js 18 ou plus récent. Dans un dossier vide, initialise le projet et installe deux paquets principaux : discord.js pour dialoguer avec Discord, et @napi-rs/canvas pour dessiner l'image. Je préfère ce dernier car, contrairement à l'ancien node-canvas, il n'exige pas de compiler de bibliothèques système (Cairo) — il s'installe proprement sur la plupart des systèmes d'exploitation et des VPS.
npm init -y
npm install discord.js @napi-rs/canvas
Crée ton bot sur le Discord Developer Portal, récupère le token dans l'onglet « Bot », et sous Privileged Gateway Intents active impérativement l'option SERVER MEMBERS INTENT. Sans cela, le bot ne voit jamais l'événement d'arrivée d'un membre.
Définir le client et ses intents
Lorsque tu crées le client avec discord.js v14, tu déclares quels événements recevoir via intents. Pour capter les nouveaux membres, l'intent GuildMembers est obligatoire.
const { Client, GatewayIntentBits, Events, AttachmentBuilder } = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
],
});
client.once(Events.ClientReady, (c) => {
console.log(`Connecté en tant que ${c.user.tag}`);
});
client.login(process.env.DISCORD_TOKEN);
Conserver le token dans une variable d'environnement (process.env.DISCORD_TOKEN) plutôt que de l'écrire en dur est essentiel pour la sécurité ; s'il fuite, quelqu'un d'autre prend le contrôle de ton bot.
Capter le nouveau membre : guildMemberAdd
Quand quelqu'un rejoint, l'événement GuildMemberAdd se déclenche. C'est là que nous générons l'image et l'envoyons dans un salon adapté. Trouver le salon par son ID est plus fiable que par son nom, mais je montre l'approche par nom pour l'exemple.
client.on(Events.GuildMemberAdd, async (member) => {
const channel = member.guild.channels.cache.find(
(c) => c.name === 'général'
);
if (!channel) return;
const attachment = await createWelcomeImage(member);
await channel.send({
content: `Bienvenue à bord <@${member.id}>! 🎉`,
files: [attachment],
});
});
L'expression <@${member.id}> mentionne l'utilisateur dans le message pour qu'il reçoive une notification. Nous écrirons ensuite la fonction createWelcomeImage qui produit le visuel.
Dessiner l'image de bienvenue avec Canvas
C'est ici que la magie opère. On crée un canvas et on dessine le fond, l'avatar découpé en cercle, puis le nom d'utilisateur par-dessus. Pour rendre l'avatar rond, on utilise un masque clip.
const { createCanvas, loadImage } = require('@napi-rs/canvas');
async function createWelcomeImage(member) {
const canvas = createCanvas(1024, 450);
const ctx = canvas.getContext('2d');
// Fond
const background = await loadImage('./assets/background.png');
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
// Dessiner l'avatar en cercle
const avatarURL = member.user.displayAvatarURL({
extension: 'png',
size: 256,
});
const avatar = await loadImage(avatarURL);
ctx.save();
ctx.beginPath();
ctx.arc(512, 150, 100, 0, Math.PI * 2);
ctx.closePath();
ctx.clip();
ctx.drawImage(avatar, 412, 50, 200, 200);
ctx.restore();
// Texte
ctx.textAlign = 'center';
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 52px Sans';
ctx.fillText('Bienvenue !', 512, 320);
ctx.font = '36px Sans';
ctx.fillText(member.user.username, 512, 375);
const buffer = await canvas.encode('png');
return new AttachmentBuilder(buffer, { name: 'welcome.png' });
}
Ici nous avons demandé l'extension de l'avatar en png ; le WebP par défaut peut parfois poser problème à loadImage. canvas.encode('png') renvoie un buffer, que l'on passe directement à AttachmentBuilder pour l'envoyer à Discord.
Utiliser une police personnalisée
La police « Sans » par défaut fonctionne, mais si tu en veux une assortie à ta marque, tu peux enregistrer un fichier .ttf. Fais-le une seule fois en haut du fichier, avant le démarrage du client.
const { GlobalFonts } = require('@napi-rs/canvas');
GlobalFonts.registerFromPath('./assets/Poppins-Bold.ttf', 'Poppins');
// Puis : ctx.font = 'bold 52px Poppins';
Les noms d'utilisateur longs peuvent déborder du bord de l'image. Une solution pratique consiste à réduire la taille de la police quand le nom dépasse une certaine longueur, ou à le tronquer en ajoutant ….
Erreurs fréquentes et astuces
- L'événement ne se déclenche jamais : généralement
SERVER MEMBERS INTENTn'est pas activé dans le portail, ou l'intentGuildMembersmanque dans ton code. - L'avatar ne se charge pas : demande l'extension en
pnget assure-toi que le bot a accès à Internet. - Salon introuvable : utilise l'ID du salon plutôt que le nom (
channels.cache.get('ID_SALON')) — les noms peuvent changer. - Mise en production : pour garder le bot en ligne 24h/24, lance-le sur un VPS avec un gestionnaire de processus comme
pm2.
Questions fréquentes
Un hébergement est-il vraiment nécessaire pour ce bot ?
Le bot doit rester connecté à Discord pour fonctionner, il s'arrête donc quand ton ordinateur s'éteint. Un VPS bon marché suffit à le garder en ligne en permanence ; avec pm2 il redémarre même automatiquement en cas de plantage.
Pourquoi @napi-rs/canvas plutôt que node-canvas ?
Leurs API sont presque identiques, mais @napi-rs/canvas est livré avec des binaires précompilés, donc tu n'as pas à installer de dépendances système comme Cairo. L'installation est bien plus simple, surtout sur un hébergement mutualisé et entre différents systèmes d'exploitation.
Puis-je ajouter le numéro du membre sur l'image ?
Oui. Utilise member.guild.memberCount pour obtenir le nombre actuel de membres et dessine-le sous forme de texte comme « Tu es notre 250e membre ! ». Avec la même logique ctx.fillText, tu peux ajouter autant d'informations dynamiques que tu veux.
Tu veux un bot de bienvenue sur mesure pour ta communauté ? Du design visuel à un système d'attribution de rôles, je peux développer un bot Discord adapté à tes besoins. Contacte-moi et discutons de ton projet.