aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Discord-bots

Een Discord reaction role (zelfrol) bot bouwen

Een Discord reaction role-systeem laat leden zichzelf een rol geven door op een bericht te reageren met een emoji of op een knop te klikken. In plaats van "kleurrollen", "meldingsrollen" of "game-interesse"-rollen één voor één uit te delen, laat je leden zelf kiezen; de server blijft netter en de moderatielast daalt. In deze gids bouwen we de zelfrol-logica vanaf nul: eerst met de klassieke emoji-reactie, daarna met de moderne knop-aanpak die vandaag wordt aanbevolen. De codevoorbeelden richten zich op discord.js v14 en Node.js.

Welke methode: emoji-reactie of knop?

Er zijn twee kernbenaderingen, en het loont om het verschil te kennen:

  • Reactie (emoji)-methode: het lid klikt op een emoji bij het bericht, de bot luistert naar de messageReactionAdd-gebeurtenis en kent de rol toe; de emoji weghalen verwijdert de rol. Klassiek en vertrouwd, maar de bot heeft een extra intent nodig om reacties te zien, en emojibeheer is broos.
  • Knop-methode: je voegt knoppen toe aan het bericht, het lid klikt, en de bot schakelt de rol om via interactionCreate. Schoner, betrouwbaarder op mobiel, en de moderne route die Discord aanmoedigt.

Voor nieuwe projecten raad ik de knop-methode aan. Toch laat ik de emoji-aanpak ook zien, omdat die op oudere servers nog erg gangbaar is.

Vereiste rechten en intents

De bot heeft het recht Manage Roles (Rollen beheren) nodig om rollen te beheren. Er is nog een gouden regel: de eigen rol van de bot moet boven de rollen staan die hij uitdeelt. Discord laat een bot alleen rollen toekennen die onder zijn hoogste rol staan. Sleep in Serverinstellingen > Rollen de botrol dus boven de doelrollen.

Kies de juiste intents bij het aanmaken van de client. Voor de knop-methode is Guilds genoeg; de emoji-methode vereist ook GuildMessageReactions:

const { Client, GatewayIntentBits, Partials } = require('discord.js');

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessageReactions, // alleen voor de emoji-methode
  ],
  partials: [Partials.Message, Partials.Channel, Partials.Reaction],
});

partials zijn belangrijk: ze laten de bot reacties op oudere berichten oppikken die zijn toegevoegd terwijl hij offline was, anders worden die reacties na een herstart genegeerd.

Zelfrollen opzetten met knoppen

Eerst sturen we een bericht met de rolknoppen. We zetten de ID van de doelrol in de customId van elke knop, zodat we bij een klik weten welke rol is gevraagd:

const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');

// Aangeroepen vanuit een command/handler
async function sendRolePanel(channel) {
  const row = new ActionRowBuilder().addComponents(
    new ButtonBuilder()
      .setCustomId('role:123456789012345678') // ID van de doelrol
      .setLabel('Evenement-meldingen')
      .setStyle(ButtonStyle.Primary),
    new ButtonBuilder()
      .setCustomId('role:987654321098765432')
      .setLabel('Aankondigingen')
      .setStyle(ButtonStyle.Secondary),
  );

  await channel.send({
    content: 'Klik op een knop om de rol te pakken of los te laten:',
    components: [row],
  });
}

Nu luisteren we naar kliks en schakelen de rol om. Heeft het lid de rol al, dan halen we hem weg; anders kennen we hem toe:

client.on('interactionCreate', async (interaction) => {
  if (!interaction.isButton()) return;
  if (!interaction.customId.startsWith('role:')) return;

  const roleId = interaction.customId.split(':')[1];
  const member = interaction.member;

  try {
    if (member.roles.cache.has(roleId)) {
      await member.roles.remove(roleId);
      await interaction.reply({ content: 'Rol verwijderd.', ephemeral: true });
    } else {
      await member.roles.add(roleId);
      await interaction.reply({ content: 'Rol toegekend!', ephemeral: true });
    }
  } catch (err) {
    console.error(err);
    await interaction.reply({
      content: 'Ik kon de rol niet instellen. Controleer mijn rechten en de rolvolgorde.',
      ephemeral: true,
    });
  }
});

ephemeral: true toont het antwoord alleen aan het lid dat klikte, zodat het kanaal niet wordt gespamd. De try/catch geeft een net foutbericht als de rolhiërarchie verkeerd is, en informeert de gebruiker in plaats van stil te falen.

Klassieke zelfrollen met emoji-reacties

Geef je de voorkeur aan de emoji-methode, dan moet je de ID van het paneelbericht en de emoji-naar-rol-koppeling ergens bewaren. Een eenvoudig object volstaat voor kleine servers; bij grotere projecten verplaats je dit naar een database (bijvoorbeeld SQLite):

const PANEL_MESSAGE_ID = '111111111111111111';
const map = {
  '🔴': '123456789012345678', // rode rol
  '🟢': '987654321098765432', // groene rol
};

client.on('messageReactionAdd', async (reaction, user) => {
  if (user.bot) return;
  if (reaction.message.id !== PANEL_MESSAGE_ID) return;
  if (reaction.partial) await reaction.fetch();

  const roleId = map[reaction.emoji.name];
  if (!roleId) return;

  const member = await reaction.message.guild.members.fetch(user.id);
  await member.roles.add(roleId).catch(console.error);
});

client.on('messageReactionRemove', async (reaction, user) => {
  if (user.bot) return;
  if (reaction.message.id !== PANEL_MESSAGE_ID) return;
  if (reaction.partial) await reaction.fetch();

  const roleId = map[reaction.emoji.name];
  if (!roleId) return;

  const member = await reaction.message.guild.members.fetch(user.id);
  await member.roles.remove(roleId).catch(console.error);
});

Let op: voor aangepaste (custom) emoji's matcht je op reaction.emoji.id in plaats van reaction.emoji.name, want namen kunnen veranderen maar de ID blijft stabiel.

Beveiliging en veelgemaakte fouten

  • Rolvolgorde: dit is het meest voorkomende probleem. Staat de botrol onder de doelrol, dan krijg je een "Missing Permissions"-fout.
  • Beheerde (managed) rollen: bot-/integratierollen of de Nitro Booster-rol kunnen niet handmatig worden toegekend; zet ze niet op het paneel.
  • Rechtenescalatie: zet nooit rollen met gevaarlijke rechten zoals Manage Roles of Administrator op het paneel, anders kan iedereen zichzelf staff maken.
  • Zet de bericht-ID vast: vergeet de controle niet die alleen op het paneelbericht reageert, anders reageert de bot op elk bericht.

Veelgestelde vragen

Welke intents heeft een reaction role-bot nodig?

De knop-methode heeft alleen Guilds nodig. De emoji-methode vereist daarnaast de GuildMessageReactions-intent, plus de partials-instelling om reacties op te vangen die zijn toegevoegd terwijl de bot offline was.

Waarom moet de botrol boven de doelrol staan?

Door een beveiligingsregel van Discord kan een bot alleen rollen toevoegen of verwijderen die onder zijn eigen hoogste rol staan. Sleep je de botrol in Serverinstellingen > Rollen niet boven de uitgedeelde rollen, dan krijg je een "Missing Permissions"-fout.

Wat gebeurt er als een lid reageert terwijl de bot offline is?

Bij de knop-methode is er geen probleem, want de interactie wordt verwerkt zodra de bot terugkomt. Bij de emoji-methode mis je die reactie als je partials niet hebt ingesteld — precies daarom is de knop-methode betrouwbaarder.

Wil je een net en veilig zelfrolsysteem voor je server? Ik kan een knopgebaseerde, database-ondersteunde Discord-bot bouwen met degelijke foutafhandeling. Neem contact met me op voor je project.

Devamı için