Discord Whitelist Bot: Bewerbungsformular und Auto-Whitelist für SMP
Wenn der SMP jeden reinlässt, ist der Chat in einer Woche Chaos: Griefer, Kinder ohne Mikrofon und ein paar Handelsbots. Eine Discord-Bewerbungsform filtert zufällige Leute aus und sammelt Infos über jeden Spieler. Hier: welche fertigen Bots du nutzen kannst, wie man einen eigenen mit discord.js baut, und wie alles mit RCON oder DiscordSRV verknüpft wird.
Warum ein Bewerbungsformular statt einfach /whitelist
Eine offene Whitelist über /whitelist add nick funktioniert nur, solange der Server klein ist. Sobald das Projekt in Toplisten oder auf Reddit auftaucht, wird die Flut unkontrollierbar. Eine Discord-Form löst drei Probleme auf einmal.
Erstens: Filter gegen Zufallsleute. Wer nicht bereit ist, fünf Sätze über sich zu schreiben, bleibt selten länger als zwei Tage. Das ist natürliche Auslese.
Zweitens: Datensammlung. Nickname, Alter, bisherige SMP-Erfahrung, wie sie den Server gefunden haben, was sie in Minecraft mögen. Diese Infos helfen Admins später, das Publikum zu verstehen, und Staff-Mitglieder können Konflikte klären.
Drittens: ein einziger Eingangspunkt. Alle Bewerbungen landen in einem Kanal #applications, mit Accept/Deny-Buttons und Entscheidungshistorie. Wenn ein Spieler später die Regeln bricht, kannst du seine ursprüngliche Form ansehen und prüfen, ob er anfangs gelogen hat.
In den meisten Fällen ist ein Discord-Bot in ein paar Stunden eingerichtet und läuft jahrelang ohne Anpassungen.
Architektur: wie es funktioniert
Grundablauf:
- Spieler tritt dem Discord-Server des Projekts bei.
- Schreibt den Slash-Befehl
/applyin einem beliebigen Kanal. - Bot öffnet ein Modal mit Feldern: Minecraft username, age, experience, why join.
- Nach dem Submit postet der Bot die Bewerbung in einen privaten Kanal
#applicationsmit zwei ButtonsAcceptundDeny. - Ein Moderator klickt
Accept, der Bot sendetwhitelist add <username>per RCON oder REST an den Server und vergibt die Discord-Rolle@Member. - Bei
Denyschreibt der Bot dem Spieler eine DM mit Grund und loggt das Event.
Die Verbindung zum Minecraft-Server läuft über einen von drei Kanälen: RCON (TCP auf Port 25575), das DiscordSRV-Plugin mit seiner API, oder REST über ein dünnes eigenes Plugin. Am zuverlässigsten ist DiscordSRV, weil es selbst neu verbindet und Server-Restarts übersteht.
Fertige Bots: WhitelistBot, ApplicationBot, DraftBot
Wer keinen Code schreiben will, hat funktionierende Out-of-the-box-Optionen.
DraftBot ist ein großer Bot mit einem Bewerbungsmodul. Custom Forms und Webhook-Integration gibt es im Bezahltarif. Passt zu Communities, in denen Discord eh die Hauptbühne ist. Nachteil: die Minecraft-Seite braucht ein eigenes Webhook-Handler-Plugin.
ApplyBot (apply-bot.com) ist ein dedizierter Bewerbungsbot. Unterstützt Modal-Forms, Aufteilung nach Kategorien (whitelist, staff, builder) und benutzerdefinierte Fragen. Der Free-Tarif limitiert die Zahl aktiver Forms.
WhitelistBot ist ein einfacher Open-Source-Bot in discord.py, auf GitHub unter dem Namen zu finden. Out of the box: eine Form, RCON-Integration, Accept/Deny-Buttons. Nachteil: nicht aktiv gepflegt, neuere discord.py-Versionen werfen Deprecation-Warnings.
Für die meisten SMPs unter 200 Spielern reicht ApplyBot oder DraftBot ohne eigenen Code. Wenn das Projekt größer ist oder ungewöhnliche Logik braucht (zum Beispiel automatische Prüfung des Discord-Account-Alters), bau einen eigenen.
Günstiger Weg: DiscordSRV-Apply
Wenn du DiscordSRV für Chat-Sync schon laufen hast, installier das Addon DiscordSRV-Apply. Die Form öffnet sich direkt in Discord über einen Slash-Befehl, Antworten gehen in den gewählten Kanal, Accept/Deny-Buttons sind direkt dabei. Kein separater Bot, kein Hosting, kein VPS.
Der Addon-Config sieht so aus:
applications:
default:
questions:
- "Dein Minecraft-Nickname?"
- "Wie alt bist du?"
- "Beschreibe deine SMP-Erfahrung"
- "Warum willst du zu uns?"
- "Wie hast du den Server gefunden?"
review-channel: "1234567890"
on-accept:
- "whitelist add %username%"
- "lp user %username% parent set member"
- "discord-role-add %discord_id% Member"
on-deny:
- "discord-dm %discord_id% Bewerbung abgelehnt. Grund: %reason%"
Es funktioniert sofort, DiscordSRV ersetzt %username% und %discord_id% selbst. In der Praxis ist das der schnellste Weg, eine Whitelist-Form auf einem SMP bis 500 Spieler zu starten.
Eigener Bot mit discord.js: 100-Zeilen-Skelett
Wenn du eigene Logik brauchst, hier ein Skelett für discord.js v14. Es implementiert /apply, öffnet ein Modal, postet in den Kanal, behandelt die Buttons.
const { Client, GatewayIntentBits, SlashCommandBuilder,
ModalBuilder, TextInputBuilder, TextInputStyle,
ActionRowBuilder, ButtonBuilder, ButtonStyle,
EmbedBuilder } = require('discord.js');
const { Rcon } = require('rcon-client');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const APPLICATIONS_CHANNEL = '1234567890';
const COOLDOWN = new Map();
client.on('interactionCreate', async (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'apply') {
const last = COOLDOWN.get(interaction.user.id) || 0;
if (Date.now() - last < 24 * 3600 * 1000) {
return interaction.reply({ content: 'Du hast in den letzten 24 Stunden bereits eingereicht.', ephemeral: true });
}
const accountAge = Date.now() - interaction.user.createdTimestamp;
if (accountAge < 7 * 24 * 3600 * 1000) {
return interaction.reply({ content: 'Discord-Account zu neu (mindestens 7 Tage erforderlich).', ephemeral: true });
}
const modal = new ModalBuilder().setCustomId('apply_modal').setTitle('SMP-Bewerbung');
const fields = ['username', 'age', 'experience', 'why'];
const labels = ['Minecraft-Nickname', 'Alter', 'SMP-Erfahrung', 'Warum zu uns?'];
fields.forEach((id, i) => {
const input = new TextInputBuilder()
.setCustomId(id).setLabel(labels[i])
.setStyle(i >= 2 ? TextInputStyle.Paragraph : TextInputStyle.Short)
.setRequired(true).setMaxLength(i >= 2 ? 500 : 50);
modal.addComponents(new ActionRowBuilder().addComponents(input));
});
return interaction.showModal(modal);
}
if (interaction.isModalSubmit() && interaction.customId === 'apply_modal') {
const data = {
username: interaction.fields.getTextInputValue('username'),
age: interaction.fields.getTextInputValue('age'),
experience: interaction.fields.getTextInputValue('experience'),
why: interaction.fields.getTextInputValue('why'),
};
COOLDOWN.set(interaction.user.id, Date.now());
const embed = new EmbedBuilder()
.setTitle(`Bewerbung von ${interaction.user.tag}`)
.addFields(
{ name: 'Nickname', value: data.username, inline: true },
{ name: 'Alter', value: data.age, inline: true },
{ name: 'Erfahrung', value: data.experience },
{ name: 'Warum', value: data.why },
).setFooter({ text: `discord_id: ${interaction.user.id}` });
const buttons = new ActionRowBuilder().addComponents(
new ButtonBuilder().setCustomId(`accept_${interaction.user.id}_${data.username}`)
.setLabel('Accept').setStyle(ButtonStyle.Success),
new ButtonBuilder().setCustomId(`deny_${interaction.user.id}`)
.setLabel('Deny').setStyle(ButtonStyle.Danger),
);
const channel = await client.channels.fetch(APPLICATIONS_CHANNEL);
await channel.send({ embeds: [embed], components: [buttons] });
return interaction.reply({ content: 'Bewerbung gesendet. Warte auf Moderation.', ephemeral: true });
}
if (interaction.isButton()) {
const [action, userId, username] = interaction.customId.split('_');
if (action === 'accept') {
const rcon = await Rcon.connect({ host: 'mc.example.com', port: 25575, password: process.env.RCON });
await rcon.send(`whitelist add ${username}`);
await rcon.send(`lp user ${username} parent set member`);
await rcon.end();
const member = await interaction.guild.members.fetch(userId);
await member.roles.add('ROLE_ID_MEMBER');
await member.send(`Bewerbung angenommen. Verbinde dich: mc.example.com`).catch(() => {});
await interaction.update({ content: `Angenommen von ${interaction.user.tag}`, components: [] });
} else if (action === 'deny') {
const member = await interaction.guild.members.fetch(userId);
await member.send('Bewerbung abgelehnt.').catch(() => {});
await interaction.update({ content: `Abgelehnt von ${interaction.user.tag}`, components: [] });
}
}
});
client.login(process.env.TOKEN);
Die Slash-Command-Registrierung läuft in einem separaten Skript register.js über die Discord-REST-API, die Doku liegt auf discord.js.guide. Danach Deploy auf jeden günstigen VPS oder sogar einen Raspberry Pi.
Verbindung mit Minecraft: RCON, DiscordSRV oder REST
RCON ist Standard. Aktivieren in server.properties:
enable-rcon=true
rcon.port=25575
rcon.password=langes_zufaelliges_passwort_hier
Aus dem Bot schickst du Befehle per rcon-client (Node) oder mcrcon (Python). RCON-Nachteil: der Port muss per Firewall nur auf die Bot-IP beschränkt sein, sonst bekommt jeder Brute-Forcer eine Konsolen-Shell.
DiscordSRV stellt eine API über seinen Plugin-Channel bereit, du kannst Befehle per dsrv:execute senden. Sicherer, weil keine zusätzlichen Ports. Nachteil: braucht DiscordSRV mit dem ganzen Abhängigkeits-Stack.
REST-Plugin heißt: du schreibst ein winziges Paper-Plugin (etwa 50 Zeilen), das HTTP auf localhost lauscht und einen Token im Header akzeptiert. Der Bot ruft per curl oder fetch auf. Das ist der sauberste Weg für Production: keine extern offenen Ports, Token im Header, beliebig loggbar.
LinkAccount: Discord an Minecraft binden
Wer Discord-Account fest mit Minecraft-Nick koppeln will (für Auto-Rollen, Shop, Statistik), nutzt das Link-Code-Pattern.
Spieler joint den Server, schreibt /link, das Plugin gibt einen Code wie A7K2-9XQ8. In Discord schreibt er dem Bot /link A7K2-9XQ8, der Bot sendet den Code per RCON, das Plugin verifiziert ihn, bindet discord_id an UUID und speichert das Paar in der Datenbank.
DiscordSRV macht das ab Werk mit /discord link. Wer eigenes baut, speichert eine Tabelle linked_accounts(uuid, discord_id, linked_at) in SQLite oder MySQL.
Anti-Spam und Schutz vor Fakes
Ohne Schutz füllt sich der #applications-Kanal in einer Woche mit Müll. Mindestens:
- Cooldown pro discord_id: eine Bewerbung pro 24 Stunden, oder eine pro Woche bei vorheriger Ablehnung.
- Mindestalter des Discord-Accounts: 7 bis 30 Tage. Frisch erstellte Accounts sind fast immer Alts oder Bots.
- Captcha-Rolle: vor
/applymuss der Spieler eine Basis-Verifizierung über Bots wie Wick oder Captcha.bot bestehen. - Mindestlänge der Antworten: für das "warum"-Feld 100+ Zeichen verlangen, sonst gibt es Ein-Wort-Antworten.
- Quellen-Logging: läuft der Bot hinter einem Reverse Proxy, kann man Bots an verdächtigen Mustern erkennen.
Größere Projekte verifizieren zusätzlich den Nickname über die Mojang-API: existiert der Minecraft-Account, ist er auf VPN-Servern gebannt.
Fragenvorlage für SMP
Mach keine 20 Fragen, niemand schließt das ab. Optimum sind 4 bis 6 Felder:
- Minecraft-Nickname (exakte Schreibweise).
- Alter (Zahl, ohne Echtheitsprüfung, aber Fakes gehen zurück).
- SMP-Erfahrung: welche Server, was gebaut.
- Was du in Minecraft magst: Bauen, Redstone, Farmen, PvP.
- Warum gerade zu uns, was hat dich gepackt.
- Wie hast du den Server gefunden: Toplisten, Reddit, Freund, YouTube.
Frage sechs ist nützlich für Marketing-Analytics. Wenn 80% "von einem Freund" schreiben, dominiert organisches Wachstum und du kannst bezahlte Kanäle pausieren.
Auto-Rollen nach Accept
Nach dem Annehmen einer Bewerbung gleichzeitig:
- Rolle
@Memberin Discord vergeben. - An LuckPerms-Gruppe
memberauf dem Server binden. - Rolle
@Applicantentfernen, falls vorhanden. - Entscheidung in
#mod-logmit Modname und Zeitstempel loggen.
Über DiscordSRV ist das eine Zeile im Group-Sync-Config. Über eigenen Bot drei API-Calls hintereinander.
GroupRoleSynchronizationGroupsAndRolesToSync:
member: "1234567890"
vip: "9876543210"
staff: "5555555555"
DiscordSRV beobachtet Rollenänderungen in Discord und Gruppenänderungen in LuckPerms, der Sync läuft beidseitig.
FAQ
Geht ein Bewerbungsformular ohne Programmieren?
Ja, über DiscordSRV-Apply Addon oder das kostenpflichtige ApplyBot. DiscordSRV-Apply installiert sich wie ein normales Paper-Plugin, Konfiguration per yaml, kein Code nötig. Passt für Server bis 500 aktive Spieler. ApplyBot konfigurierst du direkt in Discord per Slash-Befehlen.
Wie blockiere ich Fake-Bewerbungen und Bots?
Mindestens: 24-Stunden-Cooldown pro discord_id, Account-Alter-Limit (7+ Tage), Captcha-Verifizierung bevor /apply erlaubt ist. Größere Projekte validieren den Minecraft-Nick zusätzlich über die Mojang-API und moderieren die ersten 24 Stunden nach Discord-Registrierung manuell.
Soll der Bot in Discord laufen oder ein Minecraft-Plugin sein?
Hängt vom Ansatz ab. Discord-Bot (discord.js, discord.py) wird separat gehostet und spricht per RCON mit dem Server. Plugin-Variante ist DiscordSRV plus Addon, alles läuft auf dem Minecraft-Server. Plugin-Weg ist einfacher für kleine SMPs, Bot-Weg flexibler für große.
Was macht man mit abgelehnten Bewerbungen?
Ablehnungen in einen separaten Kanal mit Grund loggen. Nach 30 Tagen automatisch erneute Einreichung erlauben. Abgelehnte Nachrichten nicht sofort löschen, Mods brauchen die Entscheidungshistorie. Wenn die Ablehnungsrate über 50% geht, Fragen überarbeiten, sie sind wahrscheinlich zu hart.
Wie macht man, dass Accept automatisch Minecraft-Rollen vergibt?
Per RCON lp user <username> parent set member nach whitelist add. Mit DiscordSRV konfigurierst du den Group Sync, die Discord-Rolle wird automatisch auf eine LuckPerms-Gruppe gemappt.
Soll man echtes Alter abfragen?
Rechtlich nicht prüfbar, aber selbst eine selbstgemeldete Angabe schreckt einen Teil der Trolle ab. Mindestalter 13 (Discord-ToS-Vorgabe) ist Pflicht. Für SMPs mit erwachsenem Publikum 16+ oder 18+ in der Beschreibung schreiben und im Formular klar nennen.
Kann ein Bot mehrere Server bedienen?
Ja, im Bot-Config listest du mehrere RCON-Endpunkte, und das Formular fragt "für welchen Server bewirbst du dich". Jede Bewerbung läuft in den eigenen Kanal #apps-survival, #apps-creative und so weiter. Ein Prozess für alle.
Was als Nächstes
Wenn du DiscordSRV schon laufen hast, probier zuerst das DiscordSRV-Apply Addon, es deckt 90% der Bedürfnisse in einer Stunde ab. Brauchst du eigene Logik (Linked Accounts, Multi-Server, ungewöhnliche Checks), nimm discord.js und bau einen eigenen Bot. RCON nie ins offene Internet stellen, immer per Firewall auf die Bot-IP beschränken oder REST-Plugin auf localhost laufen lassen.
Eine Discord-Bewerbungsform spart Stunden Moderationsarbeit pro Woche und hebt die Community-Qualität deutlich. Hauptregel: keine 15-Fragen-Form, fast niemand schließt das ab.
Schützen Sie Ihren Server vor DDoS-Angriffen
Kostenloser Schutz mit 5-Minuten-Einrichtung. 1 TB Traffic inklusive.
Kostenlos testenWeitere Artikel
DDoS-Schutz für Minecraft-Server in Russland - Warum lokale Filterung wichtig ist
Warum die Verkehrsfilterung über Europa 30-40ms für jeden GUS-Spieler hinzufügt und was ein lokaler Filterknoten in Moskau verändert.
Proxy Protocol für Minecraft: Wozu es nötig ist und wie man es einrichtet
Proxy Protocol bewahrt die echten IP-Adressen der Spieler, wenn der Server hinter einem Reverse Proxy oder DDoS-Schutz läuft.
SMP Wirtschaft ohne Pay-to-Win: faire Monetarisierung & EULA
Wie man SMP ohne P2W monetarisiert: was die EULA erlaubt, was verboten ist, Ränge, Tebex, Vote-Belohnungen und reale Umsätze.