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

Discord Reaction Role (Selbstrollen) Bot erstellen

Ein Discord reaction role-System lässt Mitglieder sich selbst eine Rolle geben, indem sie auf eine Nachricht mit einem Emoji reagieren oder auf einen Button klicken. Statt "Farbrollen", "Benachrichtigungsrollen" oder "Spiel-Interesse"-Rollen einzeln zu vergeben, überlässt du den Mitgliedern die Wahl; der Server bleibt aufgeräumter und die Moderationslast sinkt. In dieser Anleitung bauen wir die Selbstrollen-Logik von Grund auf: zuerst mit der klassischen Emoji-Reaktion, dann mit dem heute empfohlenen modernen Button-Ansatz. Die Codebeispiele zielen auf discord.js v14 und Node.js.

Welche Methode: Emoji-Reaktion oder Button?

Es gibt zwei grundlegende Ansätze, und es lohnt sich, den Unterschied zu kennen:

  • Reaktions-Methode (Emoji): Das Mitglied klickt ein Emoji unter der Nachricht an, der Bot lauscht auf das Ereignis messageReactionAdd und vergibt die Rolle; wird das Emoji entfernt, wird auch die Rolle entzogen. Klassisch und vertraut, aber der Bot braucht einen zusätzlichen intent, um Reaktionen zu sehen, und die Emoji-Verwaltung ist anfällig.
  • Button-Methode: Du hängst Buttons an die Nachricht, das Mitglied klickt einen davon, und der Bot schaltet die Rolle per interactionCreate um (Toggle). Sauberer, auf dem Handy zuverlässiger und der moderne Weg, zu dem Discord dich lenkt.

Für neue Projekte empfehle ich die Button-Methode. Da der Emoji-Ansatz auf älteren Servern aber noch sehr verbreitet ist, zeige ich auch diesen.

Benötigte Berechtigungen und Intents

Der Bot braucht die Berechtigung Manage Roles (Rollen verwalten), um Rollen zu verwalten. Es gibt noch eine goldene Regel: die eigene Rolle des Bots muss über den Rollen stehen, die er vergibt. Discord erlaubt einem Bot nur, Rollen zuzuweisen, die unterhalb seiner höchsten Rolle liegen. Ziehe daher in den Servereinstellungen > Rollen die Bot-Rolle über die Zielrollen.

Wähle beim Erstellen des Clients die richtigen Intents. Für die Button-Methode genügt Guilds; die Emoji-Methode benötigt zusätzlich GuildMessageReactions:

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

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessageReactions, // nur für die Emoji-Methode
  ],
  partials: [Partials.Message, Partials.Channel, Partials.Reaction],
});

partials sind wichtig: Sie erlauben dem Bot, Reaktionen auf älteren Nachrichten zu erfassen, die hinzugefügt wurden, während er offline war. Andernfalls werden diese Reaktionen nach einem Neustart ignoriert.

Selbstrollen mit Buttons einrichten

Zuerst senden wir eine Nachricht mit den Rollen-Buttons. Wir betten die ID der Zielrolle in den customId jedes Buttons ein, damit wir beim Klick wissen, welche Rolle angefordert wurde:

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

// Aus einem Befehl/Handler aufgerufen
async function sendRolePanel(channel) {
  const row = new ActionRowBuilder().addComponents(
    new ButtonBuilder()
      .setCustomId('role:123456789012345678') // ID der Zielrolle
      .setLabel('Event-Pings')
      .setStyle(ButtonStyle.Primary),
    new ButtonBuilder()
      .setCustomId('role:987654321098765432')
      .setLabel('Ankündigungen')
      .setStyle(ButtonStyle.Secondary),
  );

  await channel.send({
    content: 'Klicke auf einen Button, um die Rolle zu nehmen oder abzulegen:',
    components: [row],
  });
}

Jetzt lauschen wir auf Klicks und schalten die Rolle um (Toggle). Hat das Mitglied die Rolle bereits, entfernen wir sie, sonst fügen wir sie hinzu:

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: 'Rolle entfernt.', ephemeral: true });
    } else {
      await member.roles.add(roleId);
      await interaction.reply({ content: 'Rolle vergeben!', ephemeral: true });
    }
  } catch (err) {
    console.error(err);
    await interaction.reply({
      content: 'Ich konnte die Rolle nicht setzen. Prüfe meine Berechtigungen und die Rollenreihenfolge.',
      ephemeral: true,
    });
  }
});

ephemeral: true zeigt die Antwort nur dem Mitglied, das geklickt hat, sodass der Kanal nicht zugespammt wird. Das try/catch liefert eine saubere Fehlermeldung, falls die Rollenhierarchie nicht stimmt, und informiert den Nutzer, statt still zu scheitern.

Klassische Selbstrollen mit Emoji-Reaktionen

Wenn du die Emoji-Methode bevorzugst, musst du die ID der Panel-Nachricht und die Emoji-zu-Rolle-Zuordnung irgendwo speichern. Für kleine Server reicht ein einfaches Objekt; bei größeren Projekten verlagerst du das in eine Datenbank (z. B. SQLite):

const PANEL_MESSAGE_ID = '111111111111111111';
const map = {
  '🔴': '123456789012345678', // rote Rolle
  '🟢': '987654321098765432', // grüne Rolle
};

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);
});

Hinweis: Bei benutzerdefinierten (custom) Emojis solltest du über reaction.emoji.id statt reaction.emoji.name abgleichen, denn Namen können sich ändern, die ID bleibt aber konstant.

Sicherheit und häufige Fehler

  • Rollenreihenfolge: Das ist das häufigste Problem. Liegt die Bot-Rolle unterhalb der Zielrolle, bekommst du einen "Missing Permissions"-Fehler.
  • Verwaltete (managed) Rollen: Bot-/Integrationsrollen oder die Nitro-Booster-Rolle lassen sich nicht manuell vergeben; setze sie nicht ins Panel.
  • Rechteausweitung: Setze niemals Rollen mit gefährlichen Berechtigungen wie Manage Roles oder Administrator ins Panel, sonst kann sich jeder selbst zum Team machen.
  • Nachrichten-ID festlegen: Vergiss die Prüfung nicht, die nur auf die Panel-Nachricht reagiert, sonst reagiert der Bot auf jede Nachricht.

Häufige Fragen

Welche Intents braucht ein Reaction-Role-Bot?

Die Button-Methode braucht nur Guilds. Die Emoji-Methode erfordert zusätzlich den Intent GuildMessageReactions sowie die partials-Einstellung, um Reaktionen zu erfassen, die hinzugefügt wurden, während der Bot offline war.

Warum muss die Bot-Rolle über der Zielrolle stehen?

Aufgrund einer Discord-Sicherheitsregel kann ein Bot nur Rollen hinzufügen oder entfernen, die unterhalb seiner eigenen höchsten Rolle liegen. Ziehst du die Bot-Rolle in den Servereinstellungen > Rollen nicht über die vergebenen Rollen, erhältst du einen "Missing Permissions"-Fehler.

Was passiert, wenn ein Mitglied reagiert, während der Bot offline ist?

Bei der Button-Methode gibt es kein Problem, da die Interaktion verarbeitet wird, sobald der Bot wieder online ist. Bei der Emoji-Methode verpasst du diese Reaktion, sofern du keine partials definiert hast — genau deshalb ist die Button-Methode zuverlässiger.

Möchtest du ein sauberes, sicheres Selbstrollen-System für deinen Server? Ich kann einen button-basierten, datenbankgestützten Discord-Bot mit solider Fehlerbehandlung bauen. Nimm Kontakt mit mir auf für dein Projekt.

Devamı için