mirror of https://github.com/hak5/scuzzy.git
commands: remove overwatch, enable auto reconnect to WS
parent
6ceb5be68d
commit
044ab7a79c
15
cmd/main.go
15
cmd/main.go
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
Loading…
Reference in New Issue