Discord Logging
Discord Logging
BUPA Chat has two independent Discord features. This page covers outgoing webhook logging (chat → Discord). The incoming channel bridge (Discord → chat), configured in shared/config/discord.lua, is a separate feature described at the end.
Webhook logging (chat → Discord)
Webhook URLs live in server/webhook.lua — an escrow_ignore file you edit directly. Three keys are defined:
local webhooks = {
chatMessage = "https://.../webhook-proxy/....",
emoteCommand = "https://.../webhook-proxy/....",
pmMessage = "https://.../webhook-proxy/....",
}Replace the placeholder proxy URLs with your own Discord webhook URLs. If a key's URL is empty, nothing is sent for it.
How messages map to webhooks
Config entries reference a webhook by its key via webhookKey:
- Categories — each category may set
webhookKey(see Chat Categories). - Private messages —
config.pm.webhookKey(defaults tochatMessage). - Emotes — each emote command may set
webhookKey(/meand/douseemoteCommand).
Every normal chat message is always logged to the chatMessage webhook. When a category also defines its own webhookKey, that category's messages are logged to both the category webhook and the chatMessage webhook.
Logging is handled by sendDiscordLog(webhookKey, message, src), which posts a standalone JSON payload to the mapped URL — no external Discord resource is required:
function sendDiscordLog(webhook, msg, src)
local url = webhooks[webhook]
if not url or url == "" then return end
local payload = type(msg) == "table" and { embeds = { msg } } or { content = tostring(msg) }
PerformHttpRequest(url, function() end, "POST", json.encode(payload),
{ ["Content-Type"] = "application/json" })
endTo add a new log target, add a key to the webhooks table and reference it from a category, PM or emote via webhookKey.
Channel bridge (Discord → chat)
Separately, shared/config/discord.lua (config.discord) can poll Discord channels and relay their messages into the game chat. It is disabled by default.
config.discord = {
active = false,
pollInterval = 15000, -- ms between polls
channels = {
{
channelId = "", -- Discord channel to read from
-- permissions = { "admin" }, -- optional: who can see these messages
-- jobs = { police = true },
-- gangs = { whiteGang = true },
tags = { { tag = "Discord", textColor = { 51, 51, 51 }, bgColor = { 88, 101, 242 } } },
color = { 200, 200, 200 },
},
-- more channels: Discord Admin / PD / EMS / Gang examples included
},
}Each channel entry can be gated by permissions, jobs or gangs, so a channel's messages only appear for the right players. The bridge reads messages through the Discord bot API and requires a bot token + guild ID — supplied either in config.discord or reused from config.adminChatName.discord in general.lua. Messages authored by bots are ignored.