Ein Discord temporärer Sprachkanal (Temp Voice) System räumt mit den Dutzenden leeren, festen Sprachräumen auf, die sich auf gut besuchten Servern ansammeln: Ein Nutzer betritt einen einzigen "Raum erstellen"-Kanal, der Bot baut ihm sofort einen privaten Sprachkanal und verschiebt ihn hinein, und der Kanal löscht sich selbst, sobald er leer ist. In dieser Anleitung bauen wir dieses System von Grund auf mit discord.js v14. Im Kern dreht sich alles um ein einziges Ereignis: voiceStateUpdate.
Wie das System funktioniert
Die Idee ist einfach, aber es hilft, den Ablauf klar zu benennen:
- Der Server hat einen "Lobby"-Sprachkanal (z. B. "➕ Raum erstellen"). Niemand bleibt hier; er ist nur ein Auslöser.
- Wenn ein Nutzer diesen Kanal betritt, erstellt der Bot einen neuen Sprachkanal für ihn unter derselben Kategorie und verschiebt den Nutzer hinein.
- Der Raumbesitzer erhält Verwaltungsrechte über den Kanal (umbenennen, kicken, ein Limit setzen).
- Wenn die letzte Person geht, löscht der Bot den Kanal, sodass keine Müllkanäle im Hintergrund übrig bleiben.
Voraussetzungen und Intents
Um Sprachstatus-Ereignisse zu empfangen, benötigt der Bot den GuildVoiceStates-Intent. Um Kanäle zu erstellen und Mitglieder zu verschieben, muss die Rolle des Bots die Berechtigungen Kanäle verwalten und Mitglieder verschieben besitzen. Richten wir zuerst den Client ein:
// index.js
const {
Client, GatewayIntentBits, ChannelType, PermissionFlagsBits,
} = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
],
});
// ID des "Raum erstellen"-Lobbykanals
const LOBBY_ID = '123456789012345678';
// Temporaere Kanaele, die wir erstellt haben: channelId -> ownerId
const tempChannels = new Map();
client.login(process.env.TOKEN);
Die tempChannels-Map ist entscheidend: Der Bot darf nur Kanäle löschen, die er selbst erstellt hat. Dieser Eintrag verhindert, dass er andere Sprachkanäle auf dem Server anrührt.
Beim Beitritt einen Raum erstellen
Das Ereignis voiceStateUpdate wird bei jeder Sprachstatusänderung mit zwei Parametern ausgelöst: oldState (der vorherige Status) und newState (der neue). Wir wissen, dass ein Nutzer die Lobby betreten hat, wenn newState.channelId der Lobby-ID entspricht:
client.on('voiceStateUpdate', async (oldState, newState) => {
// Hat der Nutzer den Lobbykanal betreten?
if (newState.channelId !== LOBBY_ID) return;
const { guild, member } = newState;
const channel = await guild.channels.create({
name: `Raum von ${member.displayName}`,
type: ChannelType.GuildVoice,
parent: newState.channel.parentId, // gleiche Kategorie wie die Lobby
permissionOverwrites: [
{
id: member.id,
allow: [
PermissionFlagsBits.ManageChannels,
PermissionFlagsBits.MoveMembers,
],
},
],
});
tempChannels.set(channel.id, member.id);
await member.voice.setChannel(channel);
});
Hier übergeben wir die Kategorie der Lobby als parent, damit die neuen Räume ordentlich unter demselben Ordner gruppiert bleiben. Mit permissionOverwrites geben wir dem Besitzer das Recht, seinen eigenen Kanal zu verwalten. Die letzte Zeile, member.voice.setChannel, zieht den Nutzer in den neuen Raum.
Den leeren Raum automatisch löschen
Ein zweiter voiceStateUpdate-Listener fängt den Moment ab, in dem jemand einen Kanal verlässt. Wenn oldState.channel existiert und niemand mehr darin ist (members.size === 0) und dieser Kanal einer unserer erfassten temporären Kanäle ist, löschen wir ihn:
client.on('voiceStateUpdate', async (oldState) => {
const left = oldState.channel;
if (!left) return;
// Ist es einer von uns und jetzt leer?
if (tempChannels.has(left.id) && left.members.size === 0) {
await left.delete().catch(() => {});
tempChannels.delete(left.id);
}
});
Das .catch(() => {}) ist wichtig: Falls der Kanal aus einem anderen Grund bereits weg ist (manuelles Löschen, eine Rechteänderung), verhindert es, dass der Bot abstürzt. Der Aufruf tempChannels.delete hält die Map sauber.
Feinschliff und Robustheit
Das Grundsystem funktioniert; ein paar Ergänzungen, die es auf einem echten Server brauchbar machen:
- Nutzerlimit: Füge
userLimit: 5zucreatehinzu, um die Räume klein zu halten. - Spam-Schutz: Wenn ein Nutzer schnell beitritt und wieder geht, können viele Kanäle entstehen. Füge einen Cooldown pro Nutzer hinzu.
- Neustarts: Bei einem Neustart des Bots wird die
tempChannels-Map zurückgesetzt. Es ist ratsam, beim Start die Kategorie zu durchsuchen und übrig gebliebene leere temporäre Kanäle aufzuräumen. - Namens-/Limit-Befehle: Mit Slash-Befehlen kannst du dem Besitzer erlauben, seinen Kanal umzubenennen oder zu sperren.
Häufige Fragen
Der Bot erstellt keine Kanäle, warum?
Die zwei häufigsten Ursachen: Der Rolle des Bots fehlen Kanäle verwalten und Mitglieder verschieben, oder du hast vergessen, den GuildVoiceStates-Intent hinzuzufügen. Außerdem muss die Rolle des Bots gemäß den Berechtigungsüberschreibungen in dieser Kategorie Kanäle erstellen dürfen.
Wird die Leistung auf einem Server mit Hunderten von Mitgliedern zum Problem?
Nein. Da es ereignisgesteuert ist, wird es nur ausgelöst, wenn jemand die Lobby betritt oder einen Kanal verlässt. Die Erstell-/Lösch-Anfragen unterliegen den Rate Limits der Discord-API, aber normale Nutzung bleibt deutlich darunter.
Brauche ich eine Datenbank?
Für kleine Server nicht — eine Map im Arbeitsspeicher reicht. Für sehr große oder Multi-Bot-Setups sorgt das Speichern der temporären Kanal-IDs in einer leichten Datenbank wie SQLite dafür, dass das System Neustarts übersteht.
Möchtest du ein fertiges, robustes Temp-Voice-System für deine Community? Ich baue maßgeschneiderte Discord-Bots mit temporären Sprachkanälen, einem Raum-Steuerungspanel und Moderationsintegration — kontaktiere mich.