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

Discord-Slash-Befehle erstellen (discord.js v14)

Einen Discord-Slash-Befehl zu erstellen ist der erste Schritt zum Schreiben eines modernen Discord-Bots. Die alten nachrichtenbasierten Befehle (wie !ping) wurden durch Discords native Slash-Command-Oberfläche ersetzt: Wenn ein Nutzer / eingibt, werden Befehle und ihre Optionen automatisch mit validierter Eingabe angezeigt. Das ist inzwischen der offizielle Weg. In diesem Tutorial bauen wir von Grund auf einen funktionierenden Slash-Command-Bot mit discord.js v14 und Node.js 18+: Projekteinrichtung, Befehle mit SlashCommandBuilder definieren, per REST-API deployen und über das interactionCreate-Event antworten.

Projekteinrichtung und Abhängigkeiten

Node.js 18 oder neuer ist erforderlich; discord.js v14 unterstützt ältere Versionen nicht. Initialisiere das Projekt in einem leeren Ordner und installiere die einzige Abhängigkeit, das Paket discord.js:

mkdir discord-bot && cd discord-bot
npm init -y
npm install discord.js

Wir verwenden CommonJS statt ESM, daher ist keine zusätzliche Konfiguration in package.json nötig; wenn du die moderne import-Syntax bevorzugst, kannst du "type": "module" hinzufügen. Dieser Leitfaden nutzt auf require basierendes (CommonJS) JavaScript. Codiere Geheimnisse wie deinen Token und IDs niemals fest in den Code; verwende eine config.json-Datei oder Umgebungsvariablen:

{
  "token": "DEIN_BOT_TOKEN",
  "clientId": "ANWENDUNGS_ID",
  "guildId": "TEST_SERVER_ID"
}
  • token: aus dem Discord Developer Portal → Reiter Bot.
  • clientId: die ID deiner Application.
  • guildId: die ID deines Testservers (aktiviere den Entwicklermodus und kopiere sie per Rechtsklick auf den Server).

Befehle mit SlashCommandBuilder definieren

Slash-Befehle werden mit der Klasse SlashCommandBuilder definiert. Diese Klasse ist Teil von discord.js (früher @discordjs/builders) und erlaubt es dir, Name, Beschreibung und Optionen eines Befehls typsicher festzulegen. Definieren wir einen einfachen ping- und einen begruessen-Befehl, der einen Parameter entgegennimmt. Jeden Befehl in eine eigene Datei innerhalb eines commands-Ordners zu legen ist gute Praxis, aber zur Übersicht verwenden wir hier ein einziges Array:

const { SlashCommandBuilder } = require('discord.js');

const commands = [
  new SlashCommandBuilder()
    .setName('ping')
    .setDescription('Misst die Latenz des Bots'),

  new SlashCommandBuilder()
    .setName('begruessen')
    .setDescription('Begrüßt einen Nutzer')
    .addUserOption(option =>
      option
        .setName('nutzer')
        .setDescription('Die zu begrüßende Person')
        .setRequired(true)
    ),
].map(command => command.toJSON());

module.exports = { commands };

Du kannst Parameter mit Methoden wie .addUserOption, .addStringOption und .addIntegerOption hinzufügen. setRequired(true) macht eine Option verpflichtend. Der abschließende toJSON()-Aufruf wandelt das Builder-Objekt in die rohe JSON-Struktur um, die die Discord-API erwartet.

Befehle mit REST deployen

Befehle zu definieren reicht nicht; du musst sie bei Discord registrieren. Dafür schreiben wir ein separates Deploy-Skript, das den REST-Client und die Routes-Helfer verwendet. Verwende während der Entwicklung Routes.applicationGuildCommands: Das registriert sofort auf einem einzelnen Server. Globale Befehle (Routes.applicationCommands) erscheinen auf jedem Server, ihre Verbreitung kann jedoch bis zu einer Stunde dauern.

const { REST, Routes } = require('discord.js');
const { token, clientId, guildId } = require('./config.json');
const { commands } = require('./commands');

const rest = new REST({ version: '10' }).setToken(token);

(async () => {
  try {
    console.log(`${commands.length} Befehle werden deployt...`);

    const data = await rest.put(
      Routes.applicationGuildCommands(clientId, guildId),
      { body: commands },
    );

    console.log(`${data.length} Befehle erfolgreich registriert.`);
  } catch (error) {
    console.error(error);
  }
})();

Führe diese Datei einmal mit node deploy-commands.js aus. Du musst sie jedes Mal erneut ausführen, wenn du deine Befehle änderst. Die Methode rest.put ersetzt (überschreibt) den gesamten Satz vorhandener Befehle durch die Liste, die du sendest, sodass jeder aus der Liste entfernte Befehl gelöscht wird.

Client-Einrichtung und das interactionCreate-Event

Der Bot selbst lebt in einer separaten Datei (index.js). Beim Erstellen des Client-Objekts musst du mit GatewayIntentBits angeben, welche Events du empfangen möchtest. Für Slash-Befehle ist nur der Guilds-Intent nötig; du musst keinen Nachrichteninhalt lesen. Wir antworten auf Befehle im interactionCreate-Event und prüfen mit interaction.isChatInputCommand(), dass die eingehende Interaktion wirklich ein Befehl ist:

const { Client, GatewayIntentBits } = require('discord.js');
const { token } = require('./config.json');

const client = new Client({
  intents: [GatewayIntentBits.Guilds],
});

client.once('clientReady', () => {
  console.log(`Angemeldet als ${client.user.tag}`);
});

client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;

  if (interaction.commandName === 'ping') {
    await interaction.reply(`Pong! Latenz: ${client.ws.ping}ms`);
  }

  if (interaction.commandName === 'begruessen') {
    const user = interaction.options.getUser('nutzer');
    await interaction.reply(`Hallo ${user}! Willkommen.`);
  }
});

client.login(token);

Wichtige Punkte hier:

  • isChatInputCommand(): verarbeitet nur Slash-Befehle, keine Button- oder Menü-Interaktionen. Ohne diese Prüfung kann der Code beim Lesen von commandName einen Fehler werfen.
  • interaction.options.getUser('nutzer'): ruft den Wert der von dir definierten Option ab. Verwende getString, getInteger und getBoolean für diese Typen.
  • interaction.reply(): Du musst innerhalb von 3 Sekunden auf eine Interaktion antworten. Rufe bei länger laufenden Aufgaben zuerst interaction.deferReply() auf und sende dann das Ergebnis mit interaction.editReply().

Um den Bot zu starten, deploye zuerst die Befehle und starte dann den Client:

node deploy-commands.js
node index.js

Häufige Fehler

  • „Missing Access“-Fehler: Wenn du den Bot nicht mit dem applications.commands-Scope eingeladen hast, werden die Befehle nicht registriert. Wähle in der OAuth2-URL sowohl den bot- als auch den applications.commands-Scope aus.
  • Befehl erscheint nicht: Guild-Befehle erscheinen sofort, globale Befehle verbreiten sich mit Verzögerung. Verwende während der Entwicklung immer Guild-Befehle.
  • „Unknown interaction“: Die Antwort kam später als 3 Sekunden. Verwende deferReply().

Häufig gestellte Fragen

Was ist der Unterschied zwischen einem Slash-Befehl und einem alten Präfix-Befehl?

Präfix-Befehle (!befehl) erfordern das Lesen des Nachrichteninhalts und benötigen Discords privilegierten MessageContent-Intent. Slash-Befehle sind in die Discord-Oberfläche integriert, bieten Autovervollständigung und Eingabevalidierung und benötigen keine Berechtigung für Nachrichteninhalte. Für neue Bots sind Slash-Befehle die verpflichtende Wahl.

Warum erscheinen globale Befehle nicht sofort?

Discord cacht globale Befehle, während es sie an alle Server verteilt, und diese Verbreitung kann bis zu einer Stunde dauern. Registriere für Entwicklung und Tests mit Routes.applicationGuildCommands auf einem einzelnen Server, da Guild-Befehle sofort aktiv werden.

Welche Node.js-Version erfordert discord.js v14?

discord.js v14 erfordert Node.js 18 oder neuer. Auf älteren Versionen erhältst du während der Installation einen Inkompatibilitätsfehler. Prüfe deine Version mit node -v.

Möchtest du deinen Bot auf die nächste Stufe bringen? Wenn du Hilfe bei Unterbefehlen, Autovervollständigung, Buttons und einer maßgeschneiderten Bot-Architektur brauchst, nimm Kontakt mit mir auf und lass uns dein Projekt gemeinsam zum Leben erwecken.

Devamı için