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"
|
"flag"
|
||||||
"github.com/foxtrot/scuzzy/commands"
|
"github.com/foxtrot/scuzzy/commands"
|
||||||
"github.com/foxtrot/scuzzy/models"
|
"github.com/foxtrot/scuzzy/models"
|
||||||
"github.com/foxtrot/scuzzy/overwatch"
|
|
||||||
"github.com/foxtrot/scuzzy/permissions"
|
"github.com/foxtrot/scuzzy/permissions"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
@ -64,6 +63,9 @@ func main() {
|
||||||
log.Fatal("[!] Error: " + err.Error())
|
log.Fatal("[!] Error: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable Reconnect
|
||||||
|
bot.ShouldReconnectOnError = true
|
||||||
|
|
||||||
// Enable Message Caching (Last 1024 Events)
|
// Enable Message Caching (Last 1024 Events)
|
||||||
bot.State.MaxMessageCount = 1024
|
bot.State.MaxMessageCount = 1024
|
||||||
bot.State.TrackChannels = true
|
bot.State.TrackChannels = true
|
||||||
|
@ -93,17 +95,8 @@ func main() {
|
||||||
}
|
}
|
||||||
c.RegisterHandlers()
|
c.RegisterHandlers()
|
||||||
|
|
||||||
// Setup Overwatch
|
|
||||||
o := overwatch.Overwatch{
|
|
||||||
TotalMessages: 0,
|
|
||||||
UserMessages: make(map[string]*overwatch.UserMessageStat),
|
|
||||||
Commands: &c,
|
|
||||||
Config: &Config,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Handlers for Bot
|
// Add Handlers for Bot
|
||||||
bot.AddHandler(c.ProcessMessage)
|
bot.AddHandler(c.ProcessMessage)
|
||||||
bot.AddHandler(o.ProcessMessage)
|
|
||||||
|
|
||||||
log.Printf("[*] Bot Running.\n")
|
log.Printf("[*] Bot Running.\n")
|
||||||
|
|
||||||
|
@ -128,8 +121,6 @@ func main() {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
o.Run()
|
|
||||||
|
|
||||||
// Catch SIGINT
|
// Catch SIGINT
|
||||||
sc := make(chan os.Signal, 1)
|
sc := make(chan os.Signal, 1)
|
||||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGKILL)
|
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("saveconfig", "Save Configuration to Disk", true, c.handleSaveConfig)
|
||||||
c.RegisterCommand("reloadconfig", "Reload Configuration", true, c.handleReloadConfig)
|
c.RegisterCommand("reloadconfig", "Reload Configuration", true, c.handleReloadConfig)
|
||||||
c.RegisterCommand("addrole", "Add a joinable role", true, c.handleAddCustomRole)
|
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 {
|
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
|
currPos := channel.Position
|
||||||
s.ChannelEditComplex(channel.ID, &discordgo.ChannelEdit{
|
s.ChannelEditComplex(channel.ID, &discordgo.ChannelEdit{
|
||||||
Position: currPos,
|
Position: currPos,
|
||||||
RateLimitPerUser: &slowModeTime,
|
RateLimitPerUser: slowModeTime,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ func (c *Commands) handleSetSlowmode(s *discordgo.Session, m *discordgo.MessageC
|
||||||
currPos := currChan.Position
|
currPos := currChan.Position
|
||||||
_, err = s.ChannelEditComplex(m.ChannelID, &discordgo.ChannelEdit{
|
_, err = s.ChannelEditComplex(m.ChannelID, &discordgo.ChannelEdit{
|
||||||
Position: currPos,
|
Position: currPos,
|
||||||
RateLimitPerUser: &slowModeTime,
|
RateLimitPerUser: slowModeTime,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -78,7 +78,7 @@ func (c *Commands) handleUnsetSlowmode(s *discordgo.Session, m *discordgo.Messag
|
||||||
currPos := channel.Position
|
currPos := channel.Position
|
||||||
s.ChannelEditComplex(channel.ID, &discordgo.ChannelEdit{
|
s.ChannelEditComplex(channel.ID, &discordgo.ChannelEdit{
|
||||||
Position: currPos,
|
Position: currPos,
|
||||||
RateLimitPerUser: &secs,
|
RateLimitPerUser: secs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ func (c *Commands) handleUnsetSlowmode(s *discordgo.Session, m *discordgo.Messag
|
||||||
currPos := currChan.Position
|
currPos := currChan.Position
|
||||||
_, err = s.ChannelEditComplex(m.ChannelID, &discordgo.ChannelEdit{
|
_, err = s.ChannelEditComplex(m.ChannelID, &discordgo.ChannelEdit{
|
||||||
Position: currPos,
|
Position: currPos,
|
||||||
RateLimitPerUser: &secs,
|
RateLimitPerUser: secs,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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