Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
5. Discord-Integration
Updated a week agoDiscord Integration
ServerGuard supports two independent Discord webhooks: a public channel and an admin channel. Either, both, or neither may be set.
What each channel receives
Public channel (discordWebhookUrl)
Player-facing events only. Safe to share with your whole community.
| Event | Example |
|---|---|
| Player joined | ✅ Erik (76561198064360681) joined |
| Player left | 👋 Erik (76561198064360681) left |
| Player kicked | 🚪 Erik (76561198064360681) was kicked — wrong password |
| Player auto-banned | ⛔ Erik (76561198064360681) was auto-banned — too many strikes |
| Player died | 💀 Erik (76561198064360681) died at [-1234, 567] — killed by a Troll |
Admins are hidden from this channel. Their joins, leaves, deaths, and kicks all route to the admin channel instead. Players never see admins coming and going.
Admin channel (discordWebhookUrlAdmin)
Curated moderation events. Use a private channel that only moderators can see.
| Event | Example |
|---|---|
| Server boot | 🚀 ServerGuard online v1.4.0 enforce=ON requireHmac=ON req/allow/ban=1/29/0 modset=8ce8906e |
| Hot-reload | 🔄 allowed_mods.yaml reloaded — req=1 allow=29 ban=0 |
| Counted violation | ⚠️ Erik (765…) violated DevcommandAttempt (1/3) — fly |
| Informational rule | 👁 Erik (765…) triggered HashMismatch (informational — not counted) — Jotunn |
| Auto-ban | ⛔ Auto-banned Erik (765…) (threshold reached) |
| Manual kick | 🚪 Disconnected Erik (765…) — Kicked by admin. |
| Admin command | 🛠 Erik (765…) ran sg kick someone |
| Admin player events | 🛡 Erik (765…) joined as admin |
| First ping (if enabled) | 🛰 Erik (765…) first ping: 42 ms |
| Session avg ping | 🛰 Erik (765…) session ping avg: 38 ms (24 samples) |
| Daily summary | A one-paragraph digest at the configured UTC hour |
Verbose mirror (optional, discordVerboseMirror: true)
Forwards every ServerGuard log line to the admin channel. Very noisy — debug only.
Creating webhooks
In Discord:
- Open your server settings → Integrations → Webhooks.
- Create a new webhook in the channel where you want events to appear.
- Copy the URL.
- Paste into
settings.yaml:
discordWebhookUrl: 'https://discord.com/api/webhooks/...' # public
discordWebhookUrlAdmin: 'https://discord.com/api/webhooks/...' # admin
- Save. Hot-reload picks it up — no restart needed.
If only one URL is configured, all events that would route to the other channel are silently suppressed.
Daily summary
A coroutine fires once per UTC day and posts a digest:
📊 Daily summary
2026-05-29 00:00 UTC → 2026-05-30 00:00 UTC
• Joins: 14
• Leaves: 12
• Kicks: 3
• Auto-bans: 1
Top kick reasons:
– wrong password (2)
– had a mod that isn't allowed (BiggerBackpack) (1)
Configure:
dailySummaryEnabled: true
dailySummaryHourUtc: 0 # 0..23 - hour at which the post fires
dailySummaryChannel: admin # public | admin | both
If no events occurred, the scheduled post is silently skipped (no spam).
Friendly reason wording
The public channel uses non-technical language. Internal rule names like HmacInvalid, DisallowedMod, ChallengeMismatch are translated:
HmacInvalid→ "wrong password"CompanionMissing→ "missing the required companion mod"RequiredModMissing→ "missing a required mod (Name)"DisallowedMod→ "had a mod that isn't allowed (Name)"BannedMod→ "had a banned mod (Name)"HashMismatch→ "mod file doesn't match the server's copy (Name)"CharacterNameLimitExceeded→ "tried to use too many characters"
The admin channel keeps the technical rule name so moderators can correlate to log lines.
Stopping a noisy channel
If you accidentally point both URLs at the same channel and don't want duplicates: set dailySummaryChannel: admin (or public) instead of both, and don't enable discordVerboseMirror.
See also
- Configuration — all webhook settings.
- Anti-Cheat Features — rules that fire Discord events.
- Admin Commands —
sgevents that post to admin channel.