From 80cbf0eada620db8cbd1de686252abb4ef60ea69 Mon Sep 17 00:00:00 2001 From: mlvzk Date: Tue, 16 Feb 2021 16:41:01 +0100 Subject: [PATCH] spam protection --- command/mute.go | 71 +++++++++++++++++++++++++++---------------------- main.go | 50 ++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 32 deletions(-) diff --git a/command/mute.go b/command/mute.go index 813610f..0bfc1a5 100644 --- a/command/mute.go +++ b/command/mute.go @@ -8,10 +8,47 @@ import ( "trup/db" "github.com/bwmarrin/discordgo" + "github.com/dustin/go-humanize" ) const muteUsage = "mute <@user> [reason]" +func MuteMember(env *Env, session *discordgo.Session, moderator *discordgo.User, userId string, duration time.Duration, reason string) error { + w := db.NewMute(env.Guild, moderator.ID, userId, reason, time.Now(), time.Now().Add(duration)) + err := w.Save() + if err != nil { + return fmt.Errorf("Failed to save your mute. Error: %w", err) + } + + err = session.GuildMemberRoleAdd(env.Guild, userId, env.RoleMute) + if err != nil { + return fmt.Errorf("Error adding role %w", err) + } + + reasonText := "" + if reason != "" { + reasonText = " with reason: " + reason + } + durationText := humanize.RelTime(time.Now(), time.Now().Add(duration), "", "") + err = db.NewNote(moderator.ID, userId, "User was muted for "+durationText+reasonText, db.ManualNote).Save() + if err != nil { + return fmt.Errorf("Failed to set note about the user %w", err) + } + + r := "" + if reason != "" { + r = " with reason: " + reason + } + if _, err = session.ChannelMessageSend( + env.ChannelModlog, + fmt.Sprintf("User <@%s> was muted by %s for %s%s.", userId, moderator.Username, durationText, r), + ); err != nil { + log.Println("Failed to send mute message: " + err.Error()) + } + + return nil +} + func mute(ctx *Context, args []string) { if len(args) < 3 { ctx.Reply("Usage: " + muteUsage) @@ -22,7 +59,6 @@ func mute(ctx *Context, args []string) { user := m.User.ID var ( duration = args[2] - start = time.Now() reason = "" ) if len(args) > 3 { @@ -35,41 +71,12 @@ func mute(ctx *Context, args []string) { return nil } - end := start.Add(i) - w := db.NewMute(ctx.Message.GuildID, ctx.Message.Author.ID, user, reason, start, end) - err = w.Save() - if err != nil { - ctx.ReportError("Failed to save your mute", err) + if err := MuteMember(ctx.Env, ctx.Session, ctx.Message.Author, user, i, reason); err != nil { + ctx.Reply("Failed to mute user. Error: " + err.Error()) return nil } - err = ctx.Session.GuildMemberRoleAdd(ctx.Message.GuildID, user, ctx.Env.RoleMute) - if err != nil { - ctx.ReportError("Error adding role", err) - return nil - } - - reasonText := "" - if reason != "" { - reasonText = " with reason: " + reason - } - err = db.NewNote(ctx.Message.Author.ID, user, "User was muted for "+duration+reasonText, db.ManualNote).Save() - if err != nil { - ctx.ReportError("Failed to set note about the user", err) - } ctx.Reply("User successfully muted. ") - - r := "" - if reason != "" { - r = " with reason: " + reason - } - - if _, err = ctx.Session.ChannelMessageSend( - ctx.Env.ChannelModlog, - fmt.Sprintf("User <@%s> was muted by %s for %s%s.", user, ctx.Message.Author.Username, duration, r), - ); err != nil { - log.Println("Failed to send mute message: " + err.Error()) - } return nil }) if err != nil { diff --git a/main.go b/main.go index a9d6245..ab4ee6b 100644 --- a/main.go +++ b/main.go @@ -154,6 +154,10 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { return } + if wasDeleted := spamProtection(s, m.Message); wasDeleted { + return + } + cache.add(m.ID, *m.Message) if wasDeleted := runMessageFilter(s, m.Message); wasDeleted { @@ -501,3 +505,49 @@ func initializeRoles(s *discordgo.Session, r *discordgo.Ready) { } } } + +func spamProtection(s *discordgo.Session, m *discordgo.Message) (deleted bool) { + accountAge, err := discordgo.SnowflakeTimestamp(m.Author.ID) + if err != nil { + return + } + if time.Since(accountAge) > time.Hour*24 { + return + } + + messageHasMention := len(m.Mentions) > 0 + if !messageHasMention { + return + } + + var sameMessages []discordgo.Message + for _, msg := range cache.m { + if msg.Author.ID != m.Author.ID || msg.ChannelID != m.ChannelID || msg.Content != m.Content { + continue + } + + timestamp, err := msg.Timestamp.Parse() + if err != nil { + continue + } + + if time.Since(timestamp) > time.Minute { + continue + } + + sameMessages = append(sameMessages, msg) + } + + if len(sameMessages) > 2 { + _, err := s.ChannelMessageSend(env.ChannelAutoMod, "Detected spam. Message: "+m.ID) + log.Println("spamProtection err:", err) + // err := command.MuteMember(&env, s, s.State.User, m.Author.ID, time.Minute*24, "Spam") + // if err != nil { + // log.Printf("Failed to mute spammer(ID: %s). Error: %v\n", m.Author.ID, err) + // return false + // } + // return true + } + + return false +}