From fb85ad85541badaa19563bdbc91e36a1390aa756 Mon Sep 17 00:00:00 2001 From: Carl Kittelberger Date: Wed, 6 Jul 2016 18:01:39 +0200 Subject: [PATCH] manager: Ignore users for 30 seconds after they join. This should be enough to at least prevent spammers from abusing the bot immediately. --- main.go | 8 ++++++++ manager/antiflood.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/main.go b/main.go index 9c541ff..f7940dc 100644 --- a/main.go +++ b/main.go @@ -129,6 +129,8 @@ func main() { conn.AddCallback("JOIN", func(e *irc.Event) { // Is this JOIN not about us? if !strings.EqualFold(e.Nick, conn.GetNick()) { + // Save this user's details for a temporary ignore + m.NotifyUserJoined(e.Arguments[0], e.Source) return } @@ -196,6 +198,12 @@ func main() { log.Printf("<%s @ %s> %s", event.Nick, target, msg) + // Ignore user if they just joined + if shouldIgnore := m.TrackUser(target, event.Source); shouldIgnore { + log.Print("This message will be ignored since the user just joined.") + return + } + urlStr := xurls.Relaxed.FindString(msg) switch { diff --git a/manager/antiflood.go b/manager/antiflood.go index 42d4692..9a100b2 100644 --- a/manager/antiflood.go +++ b/manager/antiflood.go @@ -17,6 +17,28 @@ func (m *Manager) initAntiflood() { m.cache = cache.New(1*time.Minute, 5*time.Second) } +func (m *Manager) TrackUser(target string, source string) (shouldIgnore bool) { + key := normalizeUserAntiflood(target, source) + + if _, ok := m.cache.Get(key); ok { + // User just joined here recently, ignore them + shouldIgnore = true + } + + return +} + +func (m *Manager) NotifyUserJoined(target string, source string) { + key := normalizeUserAntiflood(target, source) + + // When a user joins, he will be ignored for the first 30 seconds, + // enough to prevent parsing links from people who only join to spam their + // links immediately + if _, exists := m.cache.Get(key); !exists { + m.cache.Add(key, nil, 30*time.Second) + } +} + func (m *Manager) TrackUrl(target string, u *url.URL) (shouldIgnore bool) { key := normalizeUrlAntiflood(target, u) @@ -70,6 +92,17 @@ func normalizeTextAntiflood(target, text string) string { return fmt.Sprintf("TEXT/%s/%X", strings.ToUpper(target), s.Sum([]byte{})) } +func normalizeUserAntiflood(target, source string) string { + sourceSplitHost := strings.SplitN(source, "@", 2) + sourceSplitHostname := strings.Split(sourceSplitHost[1], ".") + if len(sourceSplitHostname) > 1 && + strings.EqualFold(sourceSplitHostname[len(sourceSplitHostname)-1], "IP") { + sourceSplitHostname[0] = "*" + } + source = fmt.Sprintf("%s!%s@%s", "*", "*", strings.Join(sourceSplitHostname, ".")) + return fmt.Sprintf("USER/%s/%s", strings.ToUpper(target), source) +} + // Proxies several methods of the IRC connection in order to drop repeated messages type ircConnectionProxy struct { *irc.Connection