fix(slack): resolve mention race condition and unify chatID logic
This commit is contained in:
parent
76cd7f8ad5
commit
4079cb9080
1 changed files with 23 additions and 6 deletions
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/slack-go/slack"
|
"github.com/slack-go/slack"
|
||||||
"github.com/slack-go/slack/slackevents"
|
"github.com/slack-go/slack/slackevents"
|
||||||
|
|
@ -29,6 +30,7 @@ type SlackChannel struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
pendingAcks sync.Map
|
pendingAcks sync.Map
|
||||||
|
seenMessages sync.Map // "channel_id:ts" -> true (dedup message/app_mention race)
|
||||||
}
|
}
|
||||||
|
|
||||||
type slackMessageRef struct {
|
type slackMessageRef struct {
|
||||||
|
|
@ -279,6 +281,14 @@ func (c *SlackChannel) handleMessageEvent(ev *slackevents.MessageEvent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deduplicate against app_mention events which Slack often sends in parallel.
|
||||||
|
dedupKey := ev.Channel + ":" + ev.TimeStamp
|
||||||
|
if _, loaded := c.seenMessages.LoadOrStore(dedupKey, true); loaded {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Simple TTL: clean up from map after 1 minute (sufficient for Slack race)
|
||||||
|
time.AfterFunc(1*time.Minute, func() { c.seenMessages.Delete(dedupKey) })
|
||||||
|
|
||||||
// check allowlist to avoid downloading attachments for rejected users
|
// check allowlist to avoid downloading attachments for rejected users
|
||||||
sender := bus.SenderInfo{
|
sender := bus.SenderInfo{
|
||||||
Platform: "slack",
|
Platform: "slack",
|
||||||
|
|
@ -307,12 +317,13 @@ func (c *SlackChannel) handleMessageEvent(ev *slackevents.MessageEvent) {
|
||||||
Timestamp: messageTS,
|
Timestamp: messageTS,
|
||||||
})
|
})
|
||||||
|
|
||||||
content := ev.Text
|
rawContent := ev.Text
|
||||||
content = c.stripBotMention(content)
|
content := c.stripBotMention(rawContent)
|
||||||
|
isMentioned := rawContent != content // Detect if bot was @mentioned
|
||||||
|
|
||||||
// In non-DM channels, apply group trigger filtering
|
// In non-DM channels, apply group trigger filtering
|
||||||
if !strings.HasPrefix(channelID, "D") {
|
if !strings.HasPrefix(channelID, "D") {
|
||||||
respond, cleaned := c.ShouldRespondInGroup(false, content)
|
respond, cleaned := c.ShouldRespondInGroup(isMentioned, content)
|
||||||
if !respond {
|
if !respond {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -385,6 +396,14 @@ func (c *SlackChannel) handleAppMention(ev *slackevents.AppMentionEvent) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deduplicate against message events which Slack often sends in parallel.
|
||||||
|
dedupKey := ev.Channel + ":" + ev.TimeStamp
|
||||||
|
if _, loaded := c.seenMessages.LoadOrStore(dedupKey, true); loaded {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Simple TTL: clean up from map after 1 minute (sufficient for Slack race)
|
||||||
|
time.AfterFunc(1*time.Minute, func() { c.seenMessages.Delete(dedupKey) })
|
||||||
|
|
||||||
if !c.IsAllowedSender(bus.SenderInfo{
|
if !c.IsAllowedSender(bus.SenderInfo{
|
||||||
Platform: "slack",
|
Platform: "slack",
|
||||||
PlatformID: ev.User,
|
PlatformID: ev.User,
|
||||||
|
|
@ -406,11 +425,9 @@ func (c *SlackChannel) handleAppMention(ev *slackevents.AppMentionEvent) {
|
||||||
threadTS := ev.ThreadTimeStamp
|
threadTS := ev.ThreadTimeStamp
|
||||||
messageTS := ev.TimeStamp
|
messageTS := ev.TimeStamp
|
||||||
|
|
||||||
var chatID string
|
chatID := channelID
|
||||||
if threadTS != "" {
|
if threadTS != "" {
|
||||||
chatID = channelID + "/" + threadTS
|
chatID = channelID + "/" + threadTS
|
||||||
} else {
|
|
||||||
chatID = channelID + "/" + messageTS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.pendingAcks.Store(chatID, slackMessageRef{
|
c.pendingAcks.Store(chatID, slackMessageRef{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue