Ein Discord-Bot kann einen Server moderieren, den Support automatisieren, Benachrichtigungen posten oder eine Community mit einer API verbinden. Ein moderner Bot ist aber kein einfaches Skript mehr, das Nachrichten mit ! am Anfang ausliest. Heute besteht die solide Grundlage darin, Slash-Befehle zu verwenden, möglichst wenige Intents und Berechtigungen anzufordern, das Token außerhalb des Codes zu halten und die Registrierung der Befehle vom Start des Bots zu trennen.
Dieses Tutorial baut ein echtes Node.js-Projekt mit:
/ping, um Verfügbarkeit und Latenz zu prüfen;/server, um einige Informationen über den Server anzuzeigen;/sagen, nur für Mitglieder mit dem Recht, Nachrichten zu verwalten;- einem Token außerhalb des Codes;
- einem Schutz gegen über
/sageneingeschleuste Erwähnungen; - sauberen Fehlerantworten und einem kontrollierten Beenden des Prozesses;
- einer Testbereitstellung pro Server und anschließend einer globalen Bereitstellung in der Produktion.
Der Code folgt discord.js 14.27.0, veröffentlicht im Juli 2026, und Node.js 24 LTS. Node.js empfiehlt für die Produktion die Zweige Active LTS oder Maintenance LTS, und der Zweig 20 erhält keine neuen Versionen mehr. Prüfen Sie vor einer neuen Installation stets die gepflegten Node.js-Versionen und die veröffentlichten discord.js-Versionen.
Was ein Discord-Bot wirklich ist
Eine Discord-Anwendung kann zwei sich ergänzende Wege nutzen:
- das Gateway, eine dauerhafte WebSocket-Verbindung, die Ereignisse in Echtzeit überträgt, etwa eine Interaktion oder den Beitritt eines Mitglieds;
- die HTTP-API, mit der ein Befehl registriert, eine Nachricht gesendet oder eine Ressource geändert wird.
discord.js bietet eine JavaScript-Abstraktion über diesen APIs. Der Client hält die Gateway-Verbindung; das REST-Objekt führt die HTTP-Aufrufe aus. Die offizielle Einführung zu Discord-Bots beschreibt diese Architektur.
Ein wichtiger Hinweis: Automatisieren Sie ausschließlich ein im Developer Portal erstelltes Bot-Konto. Discord verbietet „Self-Bots", also die Automatisierung eines normalen Nutzerkontos, und weist darauf hin, dass dies zur Sperrung des Kontos führen kann. Siehe die offizielle Richtlinie zu Self-Bots.
Voraussetzungen
Sie brauchen ein Discord-Konto, einen Discord-Testserver, auf dem Sie Anwendungen verwalten dürfen, Node.js 24 LTS, einen Editor wie Visual Studio Code, ein Terminal sowie JavaScript-Grundlagen: Variablen, Funktionen und async/await.
Prüfen Sie Ihre Umgebung:
node --version
npm --version
discord.js 14.27.0 gibt offiziell Node.js 18 oder höher als Voraussetzung an. Wir wählen in diesem Leitfaden dennoch Node.js 24 LTS, aus einem einfachen Grund: Der Zweig 20 erhält keine neuen Versionen mehr, und einen dem Internet ausgesetzten Bot auf einem Zweig ohne Sicherheitsupdates zu betreiben ist nicht sinnvoll. Jede aktuelle 24er-Version genügt.
1. Die Anwendung im Discord Developer Portal erstellen
Öffnen Sie das Discord Developer Portal und dann:
- klicken Sie auf New Application;
- geben Sie der Anwendung einen Namen;
- akzeptieren Sie die Bedingungen und bestätigen Sie;
- kopieren Sie unter General Information die Application ID;
- passen Sie unter Bot bei Bedarf Name und Avatar an;
- erzeugen Sie unter Bot mit Reset Token das Token und kopieren Sie es einmalig.
Discord erstellt heute mit jeder neuen Anwendung einen Bot-Benutzer. Der offizielle Ablauf ist in Building your first Discord Bot beschrieben.
Das Token ist keine öffentliche Kennung
Mit dem Token kann man sich als der Bot verbinden. Wer es erhält, kann dessen Rechte auf allen Servern nutzen, auf denen er installiert ist.
Legen Sie dieses Token niemals in index.js, in einen Screenshot, in ein Ticket oder eine Discord-Nachricht, in Git auch nicht in einem privaten Repository, und nicht in ein auf einem Blog veröffentlichtes Beispiel.
Bei einem Leck gehen Sie sofort zurück zu Bot > Reset Token und ersetzen den Wert auf dem Hosting. Einen alten Commit zu löschen genügt nicht: Das Geheimnis muss widerrufen werden.
2. Installation und Berechtigungen konfigurieren
Auf der Seite Installation des Developer Portals:
- aktivieren Sie Guild Install;
- verwenden Sie vorzugsweise den Discord Provided Link;
- fügen Sie die Scopes
applications.commandsundbothinzu; - gewähren Sie für dieses Projekt nur View Channels und Send Messages;
- öffnen Sie den Link, wählen Sie Ihren Testserver und autorisieren Sie die Anwendung.
Gewähren Sie nicht Administrator, „damit es funktioniert": Diese Berechtigung umgeht Kanalbeschränkungen und gibt weit mehr Macht als nötig.
Die Berechtigung zur Nutzung von /sagen wird auf Befehlsebene über ManageMessages gesteuert. Der Bot selbst muss nur den Kanal sehen und dort eine Nachricht senden können. Diese Unterscheidung setzt das Prinzip der geringsten Rechte um.
Discord-Berechtigungen und Rollenhierarchie
Die Berechtigungen des Bots genügen nicht immer. Um eine Rolle zu verwalten, ein Mitglied zu entfernen oder einen Spitznamen zu ändern, muss die höchste Rolle des Bots außerdem über dem Ziel in der Hierarchie stehen. Discord beschreibt diesen Mechanismus in seiner offiziellen Berechtigungsreferenz.
3. Intents verstehen, bevor man programmiert
Die Gateway Intents bestimmen, welche Ereigniskategorien Discord an den Bot sendet. Sie reduzieren die empfangenen Daten und den Zugriff auf sensible Informationen.
Dieses Tutorial verwendet nur GatewayIntentBits.Guilds. Dieser nicht privilegierte Intent genügt, um die Interaktionen der auf den Servern installierten Slash-Befehle zu empfangen. Wir müssen weder alle Nachrichten lesen noch die vollständige Mitgliederliste laden.
Drei Intents sind privilegiert: GuildPresences, GuildMembers und MessageContent. Sie müssen im Developer Portal aktiviert und im Code deklariert werden. Discord kann die Verbindung mit dem Code 4014 schließen, wenn ein Bot einen nicht zugelassenen privilegierten Intent anfordert.
Seit dem 10. Juni 2026 beruht die Prüfung privilegierter Intents nicht mehr auf der Zahl der Server, sondern auf der Zahl der eindeutigen Nutzer, die Ihre Anwendung sehen können, über alle Server hinweg. Ab 10 000 wird ein Antrag auf Zugang nötig. Ein Bot auf fünfzig großen Servern kann diese Schwelle also erreichen. Die aktuellen Regeln stehen in der Gateway-Dokumentation und im Leitfaden zur Prüfung privilegierter Intents.
Für einen neuen Bot vermeiden Slash-Befehle in der Regel MessageContent. Discord empfiehlt sie als Alternative zu den alten Textbefehlen mit Präfix.
4. Das Node.js-Projekt initialisieren
Legen Sie den Projektordner an:
mkdir mein-discord-bot
cd mein-discord-bot
npm init -y
npm install discord.js@14.27.0
mkdir src
Wir legen die discord.js-Version hier fest, um eine reproduzierbare Installation zu erhalten. Behalten Sie die Datei package-lock.json: Auf dem Server kann npm ci damit exakt die geprüften Versionen installieren.
Die endgültige Struktur sieht so aus:
mein-discord-bot/
├── src/
│ ├── commands.js
│ ├── deploy-commands.js
│ └── index.js
├── .env
├── .env.example
├── .gitignore
├── package-lock.json
└── package.json
package.json
Ersetzen Sie den Inhalt durch:
{
"name": "mein-discord-bot",
"version": "1.0.0",
"private": true,
"type": "module",
"engines": {
"node": ">=24.0.0"
},
"scripts": {
"deploy:guild": "node --env-file=.env src/deploy-commands.js",
"deploy:global": "node --env-file=.env src/deploy-commands.js --global",
"start": "node --env-file=.env src/index.js"
},
"dependencies": {
"discord.js": "14.27.0"
}
}
Das Feld engines ist hier unsere eigene Wahl, keine Vorgabe von discord.js: Es dokumentiert den Node-Zweig, auf dem das Projekt laufen soll, und lässt die Installation auf einer älteren Version fehlschlagen.
"type": "module" aktiviert die moderne import-Syntax. Node.js kann .env mit --env-file nativ laden, was eine zusätzliche Abhängigkeit erspart. Syntax und Vorrang der Variablen sind in der Node.js-Kommandozeilenreferenz dokumentiert.
.gitignore
node_modules/
.env
npm-debug.log*
.env.example
Diese Datei beschreibt die nötigen Variablen, ohne ein Geheimnis zu enthalten:
DISCORD_TOKEN=
DISCORD_CLIENT_ID=
DISCORD_GUILD_ID=
.env
Erstellen Sie anschließend Ihre lokale Kopie:
DISCORD_TOKEN=hier_das_bot_token_einfuegen
DISCORD_CLIENT_ID=hier_die_application_id_einfuegen
DISCORD_GUILD_ID=hier_die_id_des_testservers_einfuegen
Um die Server-ID zu kopieren, aktivieren Sie Benutzereinstellungen > Erweitert > Entwicklermodus, klicken dann mit der rechten Maustaste auf das Serversymbol und wählen Server-ID kopieren.
Veröffentlichen Sie niemals die echte .env. Führen Sie vor dem ersten Commit git status aus: Die Datei .env darf nicht unter den verfolgten Dateien erscheinen.
5. Die Slash-Befehle definieren
Erstellen Sie src/commands.js:
import {
PermissionFlagsBits,
SlashCommandBuilder,
} from 'discord.js';
export const commands = [
new SlashCommandBuilder()
.setName('ping')
.setDescription('Misst die Latenz des Bots'),
new SlashCommandBuilder()
.setName('server')
.setDescription('Zeigt die Serverinformationen an'),
new SlashCommandBuilder()
.setName('sagen')
.setDescription('Veröffentlicht eine Nachricht über den Bot')
.addStringOption((option) =>
option
.setName('text')
.setDescription('Zu veröffentlichende Nachricht')
.setRequired(true)
.setMaxLength(1000),
)
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
];
export const commandsJSON = commands.map((command) => command.toJSON());
SlashCommandBuilder erzeugt ein mit der API kompatibles JSON-Objekt. Die Einschränkung von /sagen ist also keine bloße Sichtprüfung in unserem Code: Discord setzt ManageMessages auch als Standardberechtigung des Befehls. Siehe die Regeln für Application Commands.
6. Die Befehle bei Discord registrieren
Der Bot-Code und die Befehlsliste sind zwei verschiedene Ressourcen. commands.js zu ändern aktualisiert die Discord-Oberfläche nicht automatisch: Die neue Definition muss an die API gesendet werden.
Erstellen Sie src/deploy-commands.js:
import { REST, Routes } from 'discord.js';
import { commandsJSON } from './commands.js';
const token = process.env.DISCORD_TOKEN;
const clientId = process.env.DISCORD_CLIENT_ID;
const guildId = process.env.DISCORD_GUILD_ID;
const deployGlobally = process.argv.includes('--global');
if (!token || !clientId || (!deployGlobally && !guildId)) {
throw new Error(
'Erforderliche Variablen: DISCORD_TOKEN, DISCORD_CLIENT_ID' +
(deployGlobally ? '' : ' und DISCORD_GUILD_ID'),
);
}
const rest = new REST({ version: '10' }).setToken(token);
const route = deployGlobally
? Routes.applicationCommands(clientId)
: Routes.applicationGuildCommands(clientId, guildId);
try {
console.log(
`Registrierung von ${commandsJSON.length} Befehl(en) ` +
(deployGlobally ? 'global' : `auf Server ${guildId}`),
);
const result = await rest.put(route, { body: commandsJSON });
console.log(`${result.length} Befehl(e) registriert.`);
} catch (error) {
console.error('Registrierung der Befehle fehlgeschlagen:', error);
process.exitCode = 1;
}
Registrieren Sie die Befehle während der Entwicklung nur auf Ihrem Testserver:
npm run deploy:guild
Die PUT-Anfrage ersetzt alle Befehle auf dieser Route. Legen Sie diese Bereitstellung nicht in index.js: Die Befehle bei jedem Neustart neu zu schreiben ist unnötig und vermischt zwei getrennte Vorgänge.
Wenn der Bot geprüft und bereit für mehrere Server ist:
npm run deploy:global
Führen Sie nach jeder Änderung an Name, Beschreibung, Option oder Berechtigung den passenden Bereitstellungsbefehl erneut aus.
7. Den Client programmieren und Interaktionen verarbeiten
Erstellen Sie src/index.js:
import {
Client,
Events,
GatewayIntentBits,
MessageFlags,
} from 'discord.js';
const token = process.env.DISCORD_TOKEN;
if (!token) {
throw new Error('Die Variable DISCORD_TOKEN fehlt.');
}
const client = new Client({
intents: [GatewayIntentBits.Guilds],
});
client.once(Events.ClientReady, (readyClient) => {
console.log(
`Verbunden als ${readyClient.user.tag} ` +
`auf ${readyClient.guilds.cache.size} Server(n).`,
);
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
try {
switch (interaction.commandName) {
case 'ping': {
const gatewayLatency = Math.round(client.ws.ping);
const interactionLatency = Date.now() - interaction.createdTimestamp;
await interaction.reply({
content:
`Pong! Gateway: ${gatewayLatency} ms · ` +
`Interaktion: ${interactionLatency} ms`,
flags: MessageFlags.Ephemeral,
});
break;
}
case 'server': {
if (!interaction.inGuild()) {
await interaction.reply({
content: 'Dieser Befehl funktioniert nur in einem Server.',
flags: MessageFlags.Ephemeral,
});
break;
}
await interaction.reply({
content:
`Server: **${interaction.guild.name}**\n` +
`Mitglieder: **${interaction.guild.memberCount}**\n` +
`ID: \`${interaction.guild.id}\``,
flags: MessageFlags.Ephemeral,
});
break;
}
case 'sagen': {
if (!interaction.inGuild() || !interaction.channel?.isTextBased()) {
await interaction.reply({
content: 'Kein nutzbarer Textkanal.',
flags: MessageFlags.Ephemeral,
});
break;
}
const text = interaction.options.getString('text', true);
await interaction.channel.send({
content: text,
allowedMentions: { parse: [] },
});
await interaction.reply({
content: 'Nachricht veröffentlicht.',
flags: MessageFlags.Ephemeral,
});
break;
}
default:
await interaction.reply({
content: 'Unbekannter Befehl.',
flags: MessageFlags.Ephemeral,
});
}
} catch (error) {
console.error(
`Fehler bei /${interaction.commandName} ` +
`(Interaktion ${interaction.id}):`,
error,
);
const response = {
content: 'Ein interner Fehler ist aufgetreten. Bitte später erneut versuchen.',
flags: MessageFlags.Ephemeral,
};
if (interaction.replied || interaction.deferred) {
await interaction.followUp(response).catch(console.error);
} else {
await interaction.reply(response).catch(console.error);
}
}
});
client.on(Events.Error, (error) => {
console.error('Fehler des Discord-Clients:', error);
});
async function shutdown(signal) {
console.log(`${signal} empfangen: Bot wird beendet.`);
await client.destroy();
process.exit(0);
}
process.once('SIGINT', () => void shutdown('SIGINT'));
process.once('SIGTERM', () => void shutdown('SIGTERM'));
await client.login(token);
Warum diese technischen Entscheidungen?
GatewayIntentBits.Guildsist der einzige Intent, den diese Befehle brauchen.interaction.isChatInputCommand()ignoriert andere Interaktionstypen sauber.getString('text', true)kennzeichnet die Option als Pflichtfeld und liefert eine Zeichenkette.allowedMentions: { parse: [] }verhindert, dass ein Nutzer über/sageneine ausgewertete Erwähnung wie@everyone, eine Rolle oder einen Nutzer einschleust.MessageFlags.Ephemeralmacht Bestätigungen und Fehler nur für die ausführende Person sichtbar.SIGINTundSIGTERMerlauben dem Terminal oder dem Hoster, die Verbindung sauber zu schließen.- die Meldung an den Nutzer bleibt allgemein; die Fehlerdetails landen in den Logs, ohne den Stacktrace auf Discord offenzulegen.
8. Die Drei-Sekunden-Grenze der Interaktionen einhalten
Discord verwirft die Interaktion, wenn der Bot nicht innerhalb von drei Sekunden eine erste Antwort sendet. Das Interaktions-Token bleibt danach fünfzehn Minuten nutzbar, um die Antwort zu ändern oder Folgenachrichten zu senden. Diese Fristen stehen in Receiving and Responding to Interactions.
Bestätigen Sie bei einer Datenbank oder API, die länger als drei Sekunden brauchen kann, sofort den Empfang:
await interaction.deferReply({
flags: MessageFlags.Ephemeral,
});
const result = await langsameOperation();
await interaction.editReply({
content: `Ergebnis: ${result}`,
});
Verwenden Sie nach deferReply() nicht reply(): Schließen Sie mit editReply() oder followUp() ab.
9. Den Bot lokal starten und testen
Registrieren Sie zuerst die Befehle und starten Sie dann den Prozess:
npm run deploy:guild
npm start
Die Konsole sollte etwa Folgendes anzeigen:
Verbunden als MeinBot#0000 auf 1 Server(n).
Testen Sie in Discord:
/ping: Die Antwort ist privat;/server: Name, Mitgliederzahl und ID erscheinen;/sagen text:Hallomit einem berechtigten Konto;/sagenmit einem Konto ohneManageMessages: Der Befehl sollte standardmäßig nicht verfügbar sein;/sagen text:@everyone test: Der Text kann erscheinen, es darf aber keine Erwähnung ausgelöst werden.
Testen Sie vor der Produktion auf einem separaten Server. Prüfen Sie außerdem die Berechtigungen Kanal für Kanal: Eine Rolle kann Send Messages global erlauben und in einem bestimmten Kanal verweigert sein.
10. Eine Willkommensnachricht hinzufügen, nur wenn nötig
Der Beitritt eines Mitglieds wird vom Intent Guilds nicht abgedeckt. Um guildMemberAdd zu empfangen, müssen Sie Server Members Intent unter Bot > Privileged Gateway Intents aktivieren, GatewayIntentBits.GuildMembers im Client ergänzen, die Kanal-ID in WELCOME_CHANNEL_ID hinterlegen und prüfen, dass der Bot den Kanal sehen und dort schreiben kann.
Änderung am Client:
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
],
});
Fügen Sie dann das Ereignis hinzu:
client.on(Events.GuildMemberAdd, async (member) => {
const channelId = process.env.WELCOME_CHANNEL_ID;
if (!channelId) return;
const channel = await member.guild.channels
.fetch(channelId)
.catch(() => null);
if (!channel?.isTextBased()) return;
await channel.send({
content: `Willkommen ${member} auf **${member.guild.name}**!`,
allowedMentions: { users: [member.id] },
});
});
Eine Kanal-ID ist zuverlässiger als eine Suche nach Namen: Mehrere Kanäle können ähnliche Namen tragen, und eine Umbenennung zerstört die Konfiguration nicht.
Aktivieren Sie MessageContent, GuildMembers oder GuildPresences nicht „für alle Fälle". Jeder Intent erhöht die empfangenen Daten und die Reichweite einer möglichen Kompromittierung.
11. Den Bot rund um die Uhr auf OuiPanel hosten
Ein auf Ihrem Rechner gestarteter Bot endet mit dem Terminal, dem Ruhezustand oder der Internetverbindung. Für einen durchgehenden Dienst nutzen Sie eine überwachte Node.js-Umgebung.
Die Seite Discord-Bot-Hosting von OuiHeberg nennt unter anderem Node.js, automatischen Neustart, Backups, Aufgabenplanung und den Versionswechsel über das Panel. Die OuiPanel-Dokumentation zu discord.js beschreibt den Upload über den Dateimanager oder SFTP, die Auswahl der Startdatei und die Installation der Abhängigkeiten beim ersten Start.
Den Upload vorbereiten
Laden Sie src/, package.json, package-lock.json und optional .env.example ohne echte Werte hoch.
Laden Sie nicht node_modules/ hoch, das für das System des Servers neu erzeugt wird, ebenso wenig den Ordner .git/ oder Ihre lokale .env, wenn Sie sie lieber direkt im Panel anlegen.
Empfohlene Konfiguration
- wählen Sie Node.js 24 LTS;
- laden Sie die Dateien über den Manager oder SFTP hoch;
- erstellen Sie
.envdirekt auf dem Server mit den drei Variablen; - legen Sie
src/index.jsals Hauptdatei fest, falls das Panel nach einer „Main File" fragt; - lassen Sie die npm-Installation beim ersten Start durchlaufen;
- starten Sie den Server und prüfen Sie die Logs;
- aktivieren Sie ein Backup, sobald die Konfiguration bestätigt ist.
Das start-Skript dieses Projekts lädt .env. Slash-Befehle müssen nur nach einer Änderung ihres Schemas bereitgestellt werden: Führen Sie beim Testen npm run deploy:guild oder für die Veröffentlichung npm run deploy:global aus.
Aktuelle Preise und Merkmale finden Sie auf der Seite der Node.js-Angebote.
12. Sicherheit und Betrieb in der Produktion
Rechte reduzieren
- gewähren Sie niemals standardmäßig
Administrator; - aktivieren Sie nur die Intents, die der Code verwendet;
- beschränken Sie sensible Befehle mit
setDefaultMemberPermissions(); - prüfen Sie bei kritischen Vorgängen auch die serverseitigen Berechtigungen;
- vermeiden Sie es, Tokens, HTTP-Header oder unnötige personenbezogene Daten zu protokollieren.
Abhängigkeiten verwalten
Behalten Sie package-lock.json und installieren Sie in der Produktion mit:
npm ci --omit=dev
Vor einem Update:
npm outdated
npm audit
npm audit ist ein nützliches Signal, keine absolute Garantie. Lesen Sie die Änderungshinweise, testen Sie auf einem separaten Discord-Server und stellen Sie dann bereit. Ein Backup ersetzt kein sauberes Git-Repository.
Rate Limits einhalten
Discord wendet Limits pro Route und ein globales HTTP-Limit an. Eine 429-Antwort bedeutet, dass Sie die von Retry-After oder retry_after genannte Dauer abwarten müssen. discord.js reiht gängige Aufrufe in eine Warteschlange ein; umgehen Sie diesen Mechanismus nicht mit Schleifen paralleler Anfragen. Discord nennt in seiner Dokumentation zu Rate Limits ein globales Limit von 50 HTTP-Anfragen pro Sekunde und Bot.
Protokollieren, was wirklich hilft
Protokollieren Sie für jeden Befehlsfehler mindestens die Uhrzeit, den Namen des Befehls, die Interaktions-ID, den Fehlertyp und einen serverseitigen Stacktrace.
Vermeiden Sie es, Nachrichteninhalte aufzubewahren, wenn es nicht nötig ist. Legen Sie eine Aufbewahrungsdauer für Logs fest und beschränken Sie den Zugriff darauf.
Den Prozess überwachen
Ein Bot, der „online" ist, funktioniert nicht zwangsläufig. Prüfen Sie, dass der Prozess nach einem kontrollierten Absturz neu startet, dass /ping antwortet, dass die Latenz nicht dauerhaft abdriftet, dass Fehler und Verbindungsabbrüche in den Logs sichtbar sind und dass Backups tatsächlich wiederhergestellt werden können.
13. Fehlerbehebung: häufige Fehler
| Symptom oder Fehler | Wahrscheinliche Ursache | Behebung |
|---|---|---|
An invalid token was provided | Token fehlt, ist veraltet oder falsch kopiert | prüfen Sie .env; setzen Sie das Token bei Bedarf im Developer Portal zurück |
Used disallowed intents oder Schließcode 4014 | privilegierter Intent angefordert, aber nicht aktiviert oder nicht zugelassen | entfernen Sie den unnötigen Intent oder aktivieren Sie ihn unter Bot und prüfen Sie die Berechtigung |
Cannot find package 'discord.js' | Abhängigkeiten nicht installiert | führen Sie npm ci aus oder starten Sie die Installation im Panel neu |
| Die Befehle erscheinen nicht | falsche Application ID, falsche Guild ID oder Befehle nicht bereitgestellt | prüfen Sie .env und führen Sie npm run deploy:guild erneut aus |
Interaction failed | keine erste Antwort innerhalb von drei Sekunden | verwenden Sie deferReply() und danach editReply() |
Missing Permissions oder API-Code 50013 | fehlende Bot- oder Kanalberechtigung | prüfen Sie Rolle, Kanalberechtigungen und Hierarchie |
/sagen ist für ein Mitglied nicht sichtbar | das Mitglied hat kein ManageMessages | das ist das erwartete Verhalten; passen Sie die Befehlsberechtigung bei Bedarf an |
| Der Bot ist auf dem Hosting offline | Prozess gestoppt, falsche Node-Version oder falsche Hauptdatei | wählen Sie Node.js 24 und src/index.js und lesen Sie den ersten Fehler in den Logs |
| Alte Befehle weiterhin sichtbar | Schema nicht auf der richtigen Route neu bereitgestellt | führen Sie die passende Guild- oder Global-Bereitstellung erneut aus |
| Antworten werden doppelt gesendet | mehrere Prozesse nutzen dasselbe Token | stoppen Sie doppelte Instanzen und behalten Sie einen Prozess pro Bot, außer bei bewusst eingerichtetem Sharding |
Beginnen Sie immer beim ersten Fehler der Konsole. Die folgenden Meldungen sind oft Folgen desselben ursprünglichen Fehlschlags.
14. Das Projekt weiterentwickeln, ohne es brüchig zu machen
Der switch-Router ist für drei Befehle bewusst gut lesbar. Wenn das Projekt wächst:
- legen Sie jeden Befehl in ein eigenes Modul mit
dataundexecute; - laden Sie die Module beim Start in eine
Collection; - validieren Sie alle Eingaben vor einem Aufruf an eine API oder Datenbank;
- verwenden Sie parametrisierte Abfragen für SQL;
- ergänzen Sie Unit-Tests für die Fachlogik;
- trennen Sie Entwicklungs- und Produktionsumgebung;
- planen Sie Datenbankmigrationen und deren Rücknahme;
- erwägen Sie Sharding erst, wenn die Größe des Bots es rechtfertigt.
Gute Architektur bedeutet nicht, am ersten Tag Ordner zu vervielfachen. Sie bedeutet, Verantwortlichkeiten dann zu trennen, wenn sie schwer testbar oder wartbar werden.
Häufige Fragen
Kann man einen Discord-Bot kostenlos erstellen?
Ja. Das Developer Portal, die Discord-API, Node.js und discord.js lassen sich kostenlos nutzen. Die lokale Ausführung kostet nichts, hängt aber von Ihrem Rechner ab. Ein dauerhaftes Hosting wird nützlich, sobald der Bot ohne Ihre Maschine verfügbar bleiben soll.
Muss man programmieren können?
Man muss die Grundlagen von JavaScript und asynchroner Programmierung verstehen, um einen Bot zuverlässig zu betreiben. Ein Token in ein Beispiel zu kopieren kann reichen, um „online" anzuzeigen, aber nicht, um den Dienst abzusichern, zu diagnostizieren oder weiterzuentwickeln.
Warum Slash-Befehle statt eines Präfixes?
Sie sind in der Discord-Oberfläche nativ, validieren Optionen, zeigen automatisch Hilfe an und vermeiden oft den privilegierten Intent MessageContent. Zudem lassen sich Berechtigungen pro Befehl konfigurieren.
Warum ist der Bot online, antwortet aber nicht?
Die Gateway-Verbindung kann funktionieren, während die Befehle nicht registriert wurden, der Bot keinen Zugriff auf den Kanal hat oder der Interaktionshandler einen Fehler wirft. Prüfen Sie die Konsole, testen Sie /ping und kontrollieren Sie dann Bereitstellungsroute und Kanalberechtigungen.
Muss ich die Befehle bei jedem Start neu bereitstellen?
Nein. Stellen Sie sie nur neu bereit, wenn sich Name, Beschreibung, Optionen oder Berechtigungen ändern. Der Hauptprozess soll sich nur verbinden und Interaktionen verarbeiten.
Brauche ich den Message-Content-Intent?
Für die Slash-Befehle dieses Leitfadens nicht. Er wird erst relevant, wenn eine Funktion wirklich den Inhalt gewöhnlicher Nachrichten lesen muss und die Bedingungen von Discord erfüllt.
Welches Hosting soll ich für den Anfang wählen?
Eine verwaltete Node.js-Umgebung eignet sich für einen ersten Bot: Installation der Abhängigkeiten, wählbare Node-Version, Konsole und Neustart sind zentral verfügbar. Ein VPS gibt mehr Kontrolle, verlangt aber die Administration von System, Updates, Diensten und Sicherheit.
Fazit
Sie verfügen jetzt über einen modernen Discord-Bot: getrennt registrierte Slash-Befehle, ein einziger nicht privilegierter Intent, minimale Berechtigungen, ein Token außerhalb des Codes, behandelte Fehler und ein sauberes Beenden. Diese Basis ist einfach genug, um verstanden zu werden, und gründlich genug, um eine Datenbank, eine externe API, ein Ticketsystem oder Moderationsfunktionen aufzunehmen.
Führen Sie vor dem Produktivbetrieb drei Kontrollen erneut durch: Die .env wird nicht von Git verfolgt, der Bot hat keine unnötige Berechtigung, und die Befehle wurden mit einem Nicht-Administrator-Konto getestet. Stellen Sie dann auf einer überwachten Node.js-Umgebung bereit und beobachten Sie die Logs tatsächlich.
Quellen und Referenzdokumentation
- Discord: Building your first Discord Bot
- Discord: Bots and apps overview
- Discord: Application Commands
- Discord: Receiving and Responding to Interactions
- Discord: Gateway und Gateway Intents
- Discord: Getting Started with Privileged Intent Review
- Discord: Permissions
- Discord: Rate Limits
- Discord Support: Self-Bots
- discord.js: Dokumentation 14.27.0
- discord.js: veröffentlichte Versionen
- Node.js: Versionsplan
- Node.js: Option --env-file
- OuiHeberg: Discord-Bot-Hosting
- OuiPanel: einen discord.js-Bot hosten
