From 15bb7c34e5b41d2b9886316508a211ae2c49af22 Mon Sep 17 00:00:00 2001 From: Chris Sexton Date: Mon, 18 Feb 2019 18:45:23 -0500 Subject: [PATCH] slackApp: add dedupe --- connectors/slackapp/slackApp.go | 33 ++++++++++++++++ connectors/slackapp/slackApp_test.go | 58 ++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 connectors/slackapp/slackApp_test.go diff --git a/connectors/slackapp/slackApp.go b/connectors/slackapp/slackApp.go index a252037..45d3b0d 100644 --- a/connectors/slackapp/slackApp.go +++ b/connectors/slackapp/slackApp.go @@ -2,6 +2,7 @@ package slackapp import ( "bytes" + "container/ring" "encoding/json" "fmt" "html" @@ -23,6 +24,8 @@ import ( "github.com/velour/catbase/config" ) +const DEFAULT_RING = 5 + type SlackApp struct { bot bot.Bot config *config.Config @@ -40,6 +43,8 @@ type SlackApp struct { emoji map[string]string event bot.Callback + + msgIDBuffer *ring.Ring } func New(c *config.Config) *SlackApp { @@ -50,6 +55,12 @@ func New(c *config.Config) *SlackApp { api := slack.New(token, slack.OptionDebug(false)) + idBuf := ring.New(c.GetInt("ringSize", DEFAULT_RING)) + for i := 0; i < idBuf.Len(); i++ { + idBuf.Value = "" + idBuf = idBuf.Next() + } + return &SlackApp{ api: api, config: c, @@ -60,6 +71,7 @@ func New(c *config.Config) *SlackApp { lastRecieved: time.Now(), users: make(map[string]string), emoji: make(map[string]string), + msgIDBuffer: idBuf, } } @@ -106,7 +118,28 @@ func (s *SlackApp) Serve() error { return nil } +// checkRingOrAdd returns true if it finds the ts value +// or false if the ts isn't yet in the ring (and adds it) +func (s *SlackApp) checkRingOrAdd(ts string) bool { + found := false + s.msgIDBuffer.Do(func(p interface{}) { + if p.(string) == ts { + found = true + } + }) + if found { + return true + } + s.msgIDBuffer.Value = ts + s.msgIDBuffer = s.msgIDBuffer.Next() + return false +} + func (s *SlackApp) msgReceivd(msg *slackevents.MessageEvent) { + if s.checkRingOrAdd(msg.TimeStamp) { + log.Printf("Got a duplicate message from server: %s", msg.TimeStamp) + return + } isItMe := msg.BotID != "" && msg.BotID == s.myBotID if !isItMe && msg.ThreadTimeStamp == "" { m := s.buildMessage(msg) diff --git a/connectors/slackapp/slackApp_test.go b/connectors/slackapp/slackApp_test.go new file mode 100644 index 0000000..939f1fa --- /dev/null +++ b/connectors/slackapp/slackApp_test.go @@ -0,0 +1,58 @@ +package slackapp + +import ( + "container/ring" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDedupeNoDupes(t *testing.T) { + buf := ring.New(3) + for i := 0; i < 3; i++ { + buf.Value = "" + buf = buf.Next() + } + s := SlackApp{msgIDBuffer: buf} + expected := []bool{ + false, + false, + false, + false, + false, + } + + actuals := []bool{} + actuals = append(actuals, s.checkRingOrAdd("a")) + actuals = append(actuals, s.checkRingOrAdd("b")) + actuals = append(actuals, s.checkRingOrAdd("c")) + actuals = append(actuals, s.checkRingOrAdd("d")) + actuals = append(actuals, s.checkRingOrAdd("e")) + + assert.ElementsMatch(t, expected, actuals) +} + +func TestDedupeWithDupes(t *testing.T) { + buf := ring.New(3) + for i := 0; i < 3; i++ { + buf.Value = "" + buf = buf.Next() + } + s := SlackApp{msgIDBuffer: buf} + expected := []bool{ + false, + false, + true, + false, + true, + } + + actuals := []bool{} + actuals = append(actuals, s.checkRingOrAdd("a")) + actuals = append(actuals, s.checkRingOrAdd("b")) + actuals = append(actuals, s.checkRingOrAdd("a")) + actuals = append(actuals, s.checkRingOrAdd("d")) + actuals = append(actuals, s.checkRingOrAdd("d")) + + assert.ElementsMatch(t, expected, actuals) +}