Discord-Whitelist für FiveM: Erlaube Spieler nach Discord-Rolle
Erstelle eine Discord-Rollen-Whitelist für deinen FiveM-Server: playerConnecting mit deferrals, der Discord-Kennung, eine Bot-Rollen-Überprüfung über die REST-API und einen sicheren Token.
Du möchtest, dass nur Spieler mit einer bestimmten Discord-Rolle beitreten: Mitglieder, Unterstützer, Whitelist. FiveM hat keine eingebaute Discord-Überprüfung, daher fügst du eine in playerConnecting hinzu: Lese die Discord-Kennung des Spielers, frage Discord nach ihren Rollen über einen Bot und akzeptiere oder lehne die Verbindung ab.
Du brauchst drei Dinge: einen Discord-Bot in deinem Server, ein Skript auf dem FiveM-Server und einen sicheren Platz für den Token.
Wie es funktioniert
- Ein Spieler verbindet sich. FiveM triggert
playerConnectingund gibt dir ihre Kennungen. - Du pausierst die Verbindung mit deferrals (siehe playerConnecting und deferrals).
- Dein Server fragt die Discord REST-API: Ist dieser Benutzer in der Gilde und welche Rollen haben sie?
- Du rufst
deferrals.done()auf, um sie einzulassen, oderdeferrals.done('reason')um abzulehnen.
Erstelle den Bot
- Öffne das Discord-Entwicklerportal und erstelle eine Anwendung, dann füge einen Bot hinzu.
- Kopiere den Bot-Token. Behandle ihn wie ein Passwort.
- Keine privilegierte Intent ist nötig, um einen Mitglied nach ID zu suchen. (Die Server Members Intent ist nur wichtig, wenn ein Bot jeden Mitglied auflistet oder auf Mitglied-Events hört.)
- Laden den Bot zu deinem Discord-Server ein. Er braucht keine Admin-Rechte, er muss nur ein Mitglied sein.
- In Discord schalte den Developer Mode ein, kopiere dann die Server (Guild) ID und die Rollen-ID der Whitelist-Rolle.
Halte den Token aus dem Code
Stelle ihn als Convar in server.cfg oder in einer cfg-Datei, die du exec und nie teilst:
set discord_bot_token "paste-token-here"
set discord_guild_id "123456789012345678"
set discord_whitelist_role "123456789012345679"Verwende set, nicht setr. Eine setr-Convar wird an jeden Client repliziert, was den Token für Spieler lecken würde.
Lese sie im Skript:
local TOKEN = GetConvar('discord_bot_token', '')
local GUILD = GetConvar('discord_guild_id', '')
local ROLE = GetConvar('discord_whitelist_role', '')Achtung: Falls der Token jemals in einem Screenshot, einer Support-Nachricht oder einem öffentlichen Repository endet, setze ihn im Entwicklerportal sofort zurück.
Lese die Discord-Kennung
Die Kennungen eines Spielers sehen wie discord:123456789012345678 aus. Schleife über sie und entferne das Präfix:
local function getDiscordId(src)
for _, id in ipairs(GetPlayerIdentifiers(src)) do
if id:sub(1, 8) == 'discord:' then
return id:sub(9)
end
end
endFrage Discord nach den Rollen
Der Endpunkt ist GET https://discord.com/api/v10/guilds/{guild.id}/members/{user.id}, autorisiert mit Authorization: Bot <token>. Die Antwort enthält ein roles-Array von Rollen-IDs.
local function hasWhitelistRole(discordId, cb)
PerformHttpRequest(
('https://discord.com/api/v10/guilds/%s/members/%s'):format(GUILD, discordId),
function(status, body)
if status == 200 then
local member = json.decode(body)
for _, role in ipairs(member.roles or {}) do
if role == ROLE then return cb(true) end
end
return cb(false)
elseif status == 404 then
return cb(false, 'not_in_guild')
end
cb(nil, status) -- rate limit or Discord error
end,
'GET', '',
{ ['Authorization'] = 'Bot ' .. TOKEN }
)
endEin 404 bedeutet, dass der Benutzer kein Mitglied deines Discord-Servers ist. Jeder andere Status, wie 429 oder 5xx, ist ein Problem auf dem Weg, kein „Nein".
Der Verbindungs-Handler
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
local src = source
deferrals.defer()
Wait(0)
deferrals.update('Checking your Discord role...')
local discordId = getDiscordId(src)
if not discordId then
return deferrals.done('Open the Discord app on your PC, then reconnect.')
end
hasWhitelistRole(discordId, function(ok, info)
if ok then
deferrals.done()
elseif ok == false and info == 'not_in_guild' then
deferrals.done('Join our Discord server first.')
elseif ok == false then
deferrals.done('You do not have the whitelist role.')
else
deferrals.done('Could not reach Discord (' .. tostring(info) .. '). Try again in a moment.')
end
end)
end)Speichere source in einem Local zuerst: Nach Wait zeigt das globale source nicht mehr auf diesen Spieler.
Raten-Limits und Caching
Discord begrenzt API-Anfragen pro Route und global. Bei einem Neustart verbinden sich viele Spieler auf einmal und jeder triggert eine Anforderung. Zwei einfache Schutzmaßnahmen:
- Cache-Ergebnisse für ein paar Minuten pro Discord-ID, daher ruft ein Spieler, der erneut versucht, die API nicht erneut auf.
- Behandle
429. Discord antwortet mit einemRetry-After-Header. Zeige eine „Versuchen Sie es später"-Nachricht und loope nicht darauf.
local cache = {}
local TTL = 5 * 60 * 1000
local function cachedCheck(discordId, cb)
local hit = cache[discordId]
if hit and GetGameTimer() - hit.at < TTL then
return cb(hit.ok)
end
hasWhitelistRole(discordId, function(ok, info)
if ok ~= nil then cache[discordId] = { ok = ok, at = GetGameTimer() } end
cb(ok, info)
end)
endVerwende cachedCheck im Handler anstelle von hasWhitelistRole. Ein gecachtes „Ja" bedeutet, dass eine entfernte Rolle bis zu fünf Minuten länger funktioniert, was für eine Whitelist in Ordnung ist.
Andere Punkte
- Scheitere nicht offen. Falls Discord unten ist, lehne mit einer klaren Nachricht ab, anstatt alle einzulassen, es sei denn, du hast entschieden, dass es akzeptabel ist.
- Staff-Bypass. Falls du möchtest, dass Admins ohne die Rolle beitreten, überprüfe ihre Kennungen gegen eine Liste, bevor du Discord aufrufst.
- Spieler ohne Discord bekommen keine Kennung. Deine Nachricht oben sagt ihnen, was zu tun ist.
- Um einen Cheater für immer zu blockieren, bannen ihn statt eine Rolle zu entfernen. Siehe Moderieren mit txAdmin.
Checkliste
| Symptom | Behebung |
|---|---|
Keine discord:-Kennung |
Die Discord-App des Spielers muss laufen und angemeldet sein |
401 von Discord |
Falscher oder zurückgesetzter Bot-Token oder fehlendes Bot -Präfix |
403 von Discord |
Der Bot ist nicht in diesem Server oder der Token gehört einem anderen Bot |
404 von Discord |
Der Benutzer ist nicht in deinem Discord-Server |
429 von Discord |
Raten-Limit: cache Ergebnisse und zeige eine Wiederholungs-Nachricht |
| Token für Spieler sichtbar | Verwende set, nicht setr, und halte ihn aus gemeinsamen Dateien |
| Spieler hängt auf „Checking" | Jeder Code-Pfad muss mit deferrals.done enden |
Kurze Antworten
Muss der Spieler Discord offen haben, um beizutreten?
Ja. FiveM sendet den discord:-Identifier nur, wenn die Discord-Desktop-App auf dem PC des Spielers läuft und angemeldet ist. Ohne ihn fehlt der Identifier und dein Skript sollte eine klare Nachricht zeigen.
Wohin lege ich den Bot-Token?
In eine Convar, die in server.cfg oder einer separaten cfg-Datei gesetzt wird, gelesen mit GetConvar. Lege ihn nie in eine Lua-Datei, die geteilt, hochgeladen oder in einem Repository gespeichert ist.
Rufe ich die Discord-API bei jedem Beitritt auf?
Du kannst, aber cache das Ergebnis ein paar Minuten lang. Discord begrenzt Anfragen und ein Neustart mit vielen Spielern, die sich wieder verbinden, kann die Grenze treffen.

