Logs de webhook Discord depuis un serveur FiveM : guide PerformHttpRequest
Envoyez des logs à Discord depuis FiveM avec PerformHttpRequest et des embeds JSON. Côté serveur seulement, URL dans une convar, une queue pour les limites de débit, et quoi logger.
Vous voulez savoir qui a acheté quoi, qui a donné de l'argent, qui a exécuté une commande admin et qui a rejoint, sans regarder la console toute la journée. Un webhook Discord le fait : votre serveur poste un message à un canal. Ce guide montre le Lua côté serveur avec PerformHttpRequest, comment construire des embeds, comment garder l'URL sûre et comment éviter la limite de débit.
Créer le webhook
Dans Discord, ouvrez les paramètres du canal, puis Intégrations, puis Webhooks, créez un et copiez son URL. Elle ressemble à https://discord.com/api/webhooks/<id>/<token>. N'importe qui avec cette URL peut poster dans votre canal, donc traitez-la comme un mot de passe.
Garder l'URL dans une convar
Mettez-la dans server.cfg :
set discord_webhook_logs "https://discord.com/api/webhooks/ID/TOKEN"Utilisez set, pas setr ou sets. Une convar répliquée est envoyée à chaque client, ce qui fuirait l'URL. Lisez-la sur le serveur :
local WEBHOOK = GetConvar('discord_webhook_logs', '')Si la convar est vide, sautez l'envoi au lieu de faire une erreur. Vous pouvez garder une convar par type de log (argent, admin, joins) pour les envoyer à différents canaux.
Envoyer un message
local function sendLog(title, description, color, fields)
if WEBHOOK == '' then return end
local embed = {
title = title,
description = description,
color = color or 3447003,
fields = fields,
timestamp = os.date('!%Y-%m-%dT%H:%M:%SZ'),
}
PerformHttpRequest(WEBHOOK, function(status, body, headers)
if status ~= 204 and status ~= 200 then
print(('webhook failed: %s'):format(status))
end
end, 'POST', json.encode({ username = 'Server logs', embeds = { embed } }), {
['Content-Type'] = 'application/json',
})
endPoints à savoir :
colorest un nombre décimal, pas une chaîne hex.3447003est bleu et15158332est rouge. Convertissez hex avectonumber('FF0000', 16).timestampdoit être une date ISO 8601 en UTC. Le!dans le format fait queos.dateutilise UTC.fieldsest une liste de{ name = '...', value = '...', inline = true }. Une valeur de champ ne peut pas être vide.- Un appel webhook réussi retourne le statut 204, avec un corps vide.
- Discord limite les tailles. Les titres sont courts (256 caractères), les descriptions sont longues mais plafonnées (4096), et un message contient un nombre limité de champs et d'embeds. Coupez le texte long avant de l'envoyer.
Un exemple d'appel, pour un joueur qui a envoyé de l'argent :
sendLog('Money transfer', 'A player sent money', 3066993, {
{ name = 'From', value = ('%s (id %d)'):format(GetPlayerName(src), src), inline = true },
{ name = 'To', value = ('%s (id %d)'):format(GetPlayerName(target), target), inline = true },
{ name = 'Amount', value = ('$%d'):format(amount), inline = false },
})Côté serveur seulement, jamais depuis le client
Attention : n'appelez pas
PerformHttpRequestpour un webhook dans un script client, et n'envoyez pas l'URL au client. Les fichiers clients peuvent être lus par chaque joueur, donc l'URL fuit et n'importe qui peut inonder votre canal.
Si un événement sur le client doit être loggé, envoyez un événement au serveur, et laissez le serveur décider quoi logger à partir de données en lesquelles il fait confiance. Un client qui peut déclencher « loggez ce texte » peut aussi déclencher de faux logs. Pour la sécurité des événements en général, lisez événements sécurisés dans FiveM. Loggez ce que le serveur a fait, pas ce que le client dit qu'il a fait.
Limites de débit : utilisez une queue
Discord rejette les appels webhook qui arrivent trop vite, avec une réponse 429. Une rafale de logs, comme 50 joueurs déclenchant le même événement, peut le faire. Envoyez les messages d'une queue à un rythme régulier :
local queue = {}
local function enqueue(payload)
queue[#queue + 1] = payload
end
CreateThread(function()
while true do
local item = table.remove(queue, 1)
if item then
PerformHttpRequest(WEBHOOK, function(status, _, headers)
if status == 429 then
-- put it back and wait a bit longer
table.insert(queue, 1, item)
Wait(5000)
end
end, 'POST', json.encode(item), { ['Content-Type'] = 'application/json' })
end
Wait(2000)
end
end)Attendre deux secondes entre les messages reste sous la limite. Si vous en avez besoin de plus, groupez plusieurs embeds en un message : une requête peut contenir jusqu'à 10 embeds dans sa liste embeds. Pour l'utilisation de Wait, voir Wait expliqué.
Quoi logger
Loggez les événements que vous voudriez quand quelque chose va mal :
- Argent : grands transferts, achats, n'importe quoi qui crée de l'argent. C'est où l'abus se montre en premier.
- Actions administrateur : qui a utilisé quelle commande admin sur qui, bans, avertissements, téléports. Voir bans et avertissements de joueurs.
- Joins et leaves, avec les identifiants du joueur, ce qui aide aux différends et aux bans.
- Génération d'objets et utilisation d'armes, si vous les autorisez.
Ne loggez pas tout. Un canal avec un message chaque seconde est un canal que personne ne lit. Choisissez quelques canaux, mettez les importants où le staff regarde, et gardez le reste court. Gardez les données personnelles à ce dont vous avez besoin, et ne loggez pas le chat privé.
Conseil : mettez votre fonction de logging dans une petite ressource et appelez-la avec un export depuis vos autres scripts, pour que l'URL du webhook et la queue de limite de débit vivent au même endroit. Voir exports dans FiveM.
Checklist
| Problème | Solution |
|---|---|
| Rien n'arrive | Vérifiez le nom de la convar, que l'URL est complète et que l'appel s'exécute sur le serveur |
| Statut 400 | Le JSON est invalide : valeur de champ vide, texte trop long, ou couleur chaîne hex |
| Statut 429 | Envoyez par une queue avec une pause entre les messages |
| Timestamp ignoré | Utilisez UTC ISO 8601 : os.date('!%Y-%m-%dT%H:%M:%SZ') |
| URL fuie | Supprimez le webhook dans Discord, créez-en un nouveau, et gardez-le dans une convar set |
| Trop de messages | Loggez seulement l'argent, les actions administrateur et les joins |
Réponses rapides
Puis-je envoyer un webhook Discord depuis le client ?
Non. N'importe qui peut lire le code client et voler l'URL du webhook, puis spammer votre canal. Déclenchez le log sur le serveur et envoyez-le de là.
Combien de messages webhook puis-je envoyer ?
Discord limite les webhooks, et à peu près 30 messages par minute par webhook est un plafond sûr. Au-delà de cela, vous obtenez une réponse 429, donc mettez vos messages en queue et envoyez-les à un rythme régulier.
Où dois-je garder l'URL du webhook ?
Dans une convar de serveur définie avec set dans server.cfg, lue avec GetConvar. Ne la mettez jamais dans un fichier client ou dans une convar définie avec setr ou sets.
Des scripts sans ce problème
Advanced BoostingDu boosting de véhicules piloté par tablette : contrats de classe D à S+, crews et file d’attente en direct.Voir le script →
Crypto MiningAchetez un entrepôt, montez vos rigs pièce par pièce et minez sur un marché qui bouge.Voir le script →
Shop CreatorCréez un magasin en moins d’une minute — propriétaires, employés, coffres et braquages inclus.Voir le script →