commands: remove overwatch, enable auto reconnect to WS

master
Marc Egerton 2022-03-12 20:30:33 +00:00
parent 6ceb5be68d
commit 044ab7a79c
No known key found for this signature in database
GPG Key ID: 2038B084D50E858E
5 changed files with 7 additions and 258 deletions

View File

@ -5,7 +5,6 @@ import (
"flag"
"github.com/foxtrot/scuzzy/commands"
"github.com/foxtrot/scuzzy/models"
"github.com/foxtrot/scuzzy/overwatch"
"github.com/foxtrot/scuzzy/permissions"
"io/ioutil"
"log"
@ -64,6 +63,9 @@ func main() {
log.Fatal("[!] Error: " + err.Error())
}
// Enable Reconnect
bot.ShouldReconnectOnError = true
// Enable Message Caching (Last 1024 Events)
bot.State.MaxMessageCount = 1024
bot.State.TrackChannels = true
@ -93,17 +95,8 @@ func main() {
}
c.RegisterHandlers()
// Setup Overwatch
o := overwatch.Overwatch{
TotalMessages: 0,
UserMessages: make(map[string]*overwatch.UserMessageStat),
Commands: &c,
Config: &Config,
}
// Add Handlers for Bot
bot.AddHandler(c.ProcessMessage)
bot.AddHandler(o.ProcessMessage)
log.Printf("[*] Bot Running.\n")
@ -128,8 +121,6 @@ func main() {
}
}()
o.Run()
// Catch SIGINT
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGKILL)

View File

@ -67,8 +67,6 @@ func (c *Commands) RegisterHandlers() {
c.RegisterCommand("saveconfig", "Save Configuration to Disk", true, c.handleSaveConfig)
c.RegisterCommand("reloadconfig", "Reload Configuration", true, c.handleReloadConfig)
c.RegisterCommand("addrole", "Add a joinable role", true, c.handleAddCustomRole)
c.RegisterCommand("enforcement", "Configure Overwatch enforcement", true, c.handleSetOverwatchEnforcement)
c.RegisterCommand("wordfilter", "Configure Overwatch word filtering", true, c.handleSetWordFilter)
}
func (c *Commands) ProcessCommand(s *discordgo.Session, m *discordgo.MessageCreate) error {

View File

@ -33,7 +33,7 @@ func (c *Commands) handleSetSlowmode(s *discordgo.Session, m *discordgo.MessageC
currPos := channel.Position
s.ChannelEditComplex(channel.ID, &discordgo.ChannelEdit{
Position: currPos,
RateLimitPerUser: &slowModeTime,
RateLimitPerUser: slowModeTime,
})
}
}
@ -46,7 +46,7 @@ func (c *Commands) handleSetSlowmode(s *discordgo.Session, m *discordgo.MessageC
currPos := currChan.Position
_, err = s.ChannelEditComplex(m.ChannelID, &discordgo.ChannelEdit{
Position: currPos,
RateLimitPerUser: &slowModeTime,
RateLimitPerUser: slowModeTime,
})
if err != nil {
return err
@ -78,7 +78,7 @@ func (c *Commands) handleUnsetSlowmode(s *discordgo.Session, m *discordgo.Messag
currPos := channel.Position
s.ChannelEditComplex(channel.ID, &discordgo.ChannelEdit{
Position: currPos,
RateLimitPerUser: &secs,
RateLimitPerUser: secs,
})
}
}
@ -91,7 +91,7 @@ func (c *Commands) handleUnsetSlowmode(s *discordgo.Session, m *discordgo.Messag
currPos := currChan.Position
_, err = s.ChannelEditComplex(m.ChannelID, &discordgo.ChannelEdit{
Position: currPos,
RateLimitPerUser: &secs,
RateLimitPerUser: secs,
})
if err != nil {
return err

View File

@ -1,47 +0,0 @@
package commands
import (
"errors"
"github.com/bwmarrin/discordgo"
"strings"
)
func (c *Commands) handleSetOverwatchEnforcement(s *discordgo.Session, m *discordgo.MessageCreate) error {
args := strings.Split(m.Content, " ")
if len(args) != 2 {
return errors.New("Invalid arguments supplied. Usage: " + c.Config.CommandKey + "enforcement [on/off]")
}
mode := strings.ToLower(args[1])
if mode == "on" {
c.Config.EnforceMode = true
} else {
c.Config.EnforceMode = false
}
err := c.handleSaveConfig(s, m)
return err
}
func (c *Commands) handleSetWordFilter(s *discordgo.Session, m *discordgo.MessageCreate) error {
args := strings.Split(m.Content, " ")
if len(args) != 2 {
return errors.New("Invalid arguments supplied. Usage: " + c.Config.CommandKey + "wordfilter [on/off]")
}
mode := strings.ToLower(args[1])
if mode == "on" {
c.Config.FilterLanguage = true
} else {
c.Config.FilterLanguage = false
}
err := c.handleSaveConfig(s, m)
return err
}

View File

@ -1,193 +0,0 @@
package overwatch
import (
"log"
"time"
"github.com/bwmarrin/discordgo"
"github.com/foxtrot/scuzzy/commands"
"github.com/foxtrot/scuzzy/models"
)
type UserMessageStat struct {
UserID string
Username string
MessagesLastDay int
MessagesLastHour int
MessagesLastFiveMins int
MessagesLastTenSecs int
LastActiveChannel string
Warnings int
Kicks int
}
type ServerStat struct {
JoinsLastTenMins int
SlowmodeFlood bool
SlowmodeFloodStartTime time.Time
}
type Overwatch struct {
TotalMessages uint64
TotalJoins uint64
UserMessages map[string]*UserMessageStat
ServerStats ServerStat
Commands *commands.Commands
Config *models.Configuration
}
func (o *Overwatch) ProcessMessage(s *discordgo.Session, m interface{}) {
switch m.(type) {
case *discordgo.MessageCreate:
o.TotalMessages++
err := o.handleUserStat(s, m.(*discordgo.MessageCreate))
if err != nil {
log.Printf("[!] Error handling Overwatch user stat: %s\n", err.Error())
}
err = o.filterUserMessage(s, m.(*discordgo.MessageCreate))
if err != nil {
log.Printf("[!] Error handling Overwatch user message filter: %s\n", err.Error())
}
break
case *discordgo.GuildMemberAdd:
o.TotalJoins++
err := o.handleServerJoin(s, m.(*discordgo.GuildMemberAdd))
if err != nil {
log.Printf("[!] Error handling Overwatch server join: %s\n", err.Error())
}
break
}
}
func (o *Overwatch) filterUserMessage(s *discordgo.Session, m *discordgo.MessageCreate) error {
if o.Config.FilterLanguage {
// load regex from config?
}
return nil
}
func (o *Overwatch) handleUserStat(s *discordgo.Session, m *discordgo.MessageCreate) error {
userID := m.Author.ID
if userID == s.State.User.ID {
// Ignore bots own actions
return nil
}
user, ok := o.UserMessages[userID]
if !ok {
o.UserMessages[userID] = &UserMessageStat{
UserID: userID,
Username: m.Author.Username,
}
user = o.UserMessages[userID]
}
user.MessagesLastDay++
user.MessagesLastHour++
user.MessagesLastFiveMins++
user.MessagesLastTenSecs++
user.LastActiveChannel = m.ChannelID
return nil
}
func (o *Overwatch) handleServerJoin(s *discordgo.Session, m *discordgo.GuildMemberAdd) error {
o.ServerStats.JoinsLastTenMins++
// json value
if o.ServerStats.JoinsLastTenMins > o.Config.JoinFloodThreshold {
log.Printf("[*] User flood detected, enforcing slow mode on all channels for 30 minutes\n")
// Set slow mode on all channels
o.ServerStats.SlowmodeFlood = true
o.ServerStats.SlowmodeFloodStartTime = time.Now()
o.ServerStats.JoinsLastTenMins = 0
}
return nil
}
// this is fucking amazing code
func (o *Overwatch) Run() {
// State of the art anti-spam loop
go func() {
for range time.Tick(5 * time.Second) {
for _, user := range o.UserMessages {
if user.MessagesLastTenSecs > o.Config.UserMessageThreshold {
// Set slow mode, kick user? add kick count?
if user.Warnings > o.Config.MaxUserWarnings {
if user.Kicks > o.Config.MaxUserKicks {
// ban that sucker
delete(o.UserMessages, user.UserID)
log.Printf("[*] User %s (%s) was banned due to previous spam-related kicks\n", user.Username, user.UserID)
} else {
user.Kicks++
// kick user
user.MessagesLastTenSecs = 0
log.Printf("[*] User %s (%s) has been kicked for message spam\n", user.Username, user.UserID)
}
} else {
user.Warnings++
log.Printf("[*] User %s (%s) was warned for spamming\n", user.Username, user.UserID)
}
}
}
}
}()
// State of the art anti-join-flood loop
go func() {
for range time.Tick(30 * time.Second) {
if o.ServerStats.SlowmodeFlood {
// json value
if o.ServerStats.JoinsLastTenMins > 10 {
if time.Since(o.ServerStats.SlowmodeFloodStartTime) > time.Minute*30 {
log.Printf("[*] Removing Slowmode for all channels after flood\n")
o.ServerStats.SlowmodeFlood = false
// remove slow mode
}
} else {
log.Printf("[*] Exending Slowmode due to sustained join flood\n")
o.ServerStats.SlowmodeFloodStartTime = time.Now()
}
}
}
}()
// Clear Server Counters
go func() {
for range time.Tick(10 * time.Minute) {
o.ServerStats.JoinsLastTenMins = 0
}
}()
// Clear User Counters
go func() {
for range time.Tick(24 * time.Hour) {
for _, user := range o.UserMessages {
if user.MessagesLastDay == 0 {
delete(o.UserMessages, user.UserID)
} else {
user.MessagesLastDay = 0
}
}
}
for range time.Tick(1 * time.Hour) {
for _, user := range o.UserMessages {
user.MessagesLastHour = 0
}
}
for range time.Tick(5 * time.Minute) {
for _, user := range o.UserMessages {
user.MessagesLastFiveMins = 0
}
}
for range time.Tick(10 * time.Second) {
for _, user := range o.UserMessages {
user.MessagesLastTenSecs = 0
}
}
}()
}