Security: tune the Join Gate, raid mode, anti-nuke and heat with commands

- /security settings, joingate check|account-age, words add|remove|list, raid, antinuke set|limit, heat, alert-dms
- Same rule as the rest of the configuration: owner or trusted, validated in the engine
- schema.sql was missing security_settings.alert_dm, so the bot couldn't read security settings on a database built from it. Fixed, with an ALTER for existing installs
- A test checks every command against Discord's limits

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
FernandoJVideiraandClaude Sonnet 5.5 committed 2026-10-23 02:03:03 +01:00
1 parent 5657d0789a
commit d95ebf473e
10 files changed
+1020 -4

No files matched your search

+55
View File
@@ -153,6 +153,61 @@ func (f *fakeStore) SetJoinLock(_ context.Context, g int64, mode string) error {
f.set(g).JoinLock = mode
return nil
}
func (f *fakeStore) UpdateTuning(_ context.Context, g int64, t securityrepo.Tuning) error {
s := f.set(g)
str := func(dst *string, v *string) {
if v != nil {
*dst = *v
}
}
num := func(dst *int, v *int) {
if v != nil {
*dst = *v
}
}
flag := func(dst *bool, v *bool) {
if v != nil {
*dst = *v
}
}
if t.AlertDM != nil {
s.AlertDM = *t.AlertDM
}
str(&s.NoAvatar, t.NoAvatar)
str(&s.NewAccount, t.NewAccount)
num(&s.MinAccountAgeDays, t.MinAccountAgeDays)
str(&s.AdvertisingName, t.AdvertisingName)
str(&s.UsernameFilter, t.UsernameFilter)
if t.UsernamePatterns != nil {
s.UsernamePatterns = *t.UsernamePatterns
}
str(&s.UnverifiedBot, t.UnverifiedBot)
str(&s.UnauthorizedBot, t.UnauthorizedBot)
num(&s.RaidJoinCount, t.RaidJoinCount)
num(&s.RaidJoinSeconds, t.RaidJoinSeconds)
str(&s.RaidAction, t.RaidAction)
flag(&s.RaidPauseInvites, t.RaidPauseInvites)
num(&s.RaidQuietMinutes, t.RaidQuietMinutes)
num(&s.AntiNukeWindowSeconds, t.AntiNukeWindowSeconds)
if s.AntiNukeLimits == nil {
s.AntiNukeLimits = securityrepo.DefaultLimits()
}
for k, v := range t.AntiNukeLimits {
s.AntiNukeLimits[k] = v
}
flag(&s.AntiNukeLockServer, t.AntiNukeLockServer)
flag(&s.AntiNukeAutoRestore, t.AntiNukeAutoRestore)
str(&s.HeatStrictness, t.HeatStrictness)
str(&s.HeatAction, t.HeatAction)
num(&s.HeatTimeoutMinutes, t.HeatTimeoutMinutes)
flag(&s.HeatEscalate, t.HeatEscalate)
if t.HeatBlockedWords != nil {
s.HeatBlockedWords = *t.HeatBlockedWords
}
num(&s.HeatPanicMembers, t.HeatPanicMembers)
num(&s.HeatLockdownMentions, t.HeatLockdownMentions)
return nil
}
func (f *fakeStore) ListTrusted(_ context.Context, g int64) ([]securityrepo.Trusted, error) {
f.mu.Lock()
defer f.mu.Unlock()