fix(channels): collect contacts for DM and group-mentioned messages (#271)

* fix(channels): collect contacts for DM and group-mentioned messages

Previously, EnsureContact was only called inside the "not mentioned →
record history → return" branch, so contacts were never saved for
messages that the bot actually processed (DMs and group @mentions).
This caused the contacts list to show empty names ("—") for active
users across all channels.

Move contact collection to the main processing path (before
PublishInbound / HandleMessage) so every processed message upserts
the sender's display name. The existing ContactCollector 30-minute
cache prevents redundant DB writes.

Affected channels: Feishu, Telegram, Discord, Slack, Zalo, WhatsApp.

* fix(slack): use clean userID for EnsureContact cache key

The senderID param in HandleMessage is the compound "U123|DisplayName"
form, which produces a different cache key than the clean "U123" used
in the group-history path (handlers.go:178). Use userID (extracted
clean ID) to ensure cache dedup works correctly.

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
Co-authored-by: viettranx <viettranx@gmail.com>
This commit is contained in:
Luan Vu
2026-03-19 14:02:19 +07:00
committed by GitHub
co-authored by Luvu182 viettranx
parent a38d972438
commit 0dd4ebd6e6
6 changed files with 35 additions and 0 deletions
+5
View File
@@ -247,6 +247,11 @@ func (c *Channel) handleMessage(_ *discordgo.Session, m *discordgo.MessageCreate
}
}
// Collect contact for processed messages (DM + group-mentioned).
if cc := c.ContactCollector(); cc != nil {
cc.EnsureContact(context.Background(), c.Type(), c.Name(), senderID, senderID, senderName, m.Author.Username, peerKind)
}
// Publish directly to bus (to preserve MediaFile MIME types)
c.Bus().PublishInbound(bus.InboundMessage{
Channel: c.Name(),
+5
View File
@@ -131,6 +131,11 @@ func (c *Channel) handleMessageEvent(ctx context.Context, event *MessageEvent) {
peerKind = "group"
}
// Collect contact for processed messages (DM + group-mentioned).
if cc := c.ContactCollector(); cc != nil {
cc.EnsureContact(ctx, c.Type(), c.Name(), mc.SenderID, mc.SenderID, senderName, "", peerKind)
}
metadata := map[string]string{
"message_id": messageID,
"chat_type": mc.ChatType,
+5
View File
@@ -30,6 +30,11 @@ func (c *Channel) HandleMessage(senderID, chatID, content string, mediaPaths []s
mediaFiles = append(mediaFiles, bus.MediaFile{Path: p})
}
// Collect contact for processed messages (DM + group-mentioned).
if cc := c.ContactCollector(); cc != nil {
cc.EnsureContact(context.Background(), c.Type(), c.Name(), userID, userID, metadata["username"], "", peerKind)
}
c.Bus().PublishInbound(bus.InboundMessage{
Channel: c.Name(),
SenderID: senderID,
+5
View File
@@ -482,6 +482,11 @@ func (c *Channel) handleMessage(ctx context.Context, update telego.Update) {
}
}
// Collect contact for processed messages (DM + group-mentioned).
if cc := c.ContactCollector(); cc != nil {
cc.EnsureContact(ctx, c.Type(), c.Name(), senderID, userID, user.FirstName, user.Username, peerKind)
}
c.Bus().PublishInbound(bus.InboundMessage{
Channel: c.Name(),
SenderID: senderID,
+5
View File
@@ -267,6 +267,11 @@ func (c *Channel) handleIncomingMessage(msg map[string]any) {
"preview", channels.Truncate(content, 50),
)
// Collect contact for processed messages.
if cc := c.ContactCollector(); cc != nil {
cc.EnsureContact(context.Background(), c.Type(), c.Name(), senderID, senderID, metadata["user_name"], "", peerKind)
}
c.HandleMessage(senderID, chatID, content, media, metadata, peerKind)
}
@@ -59,6 +59,11 @@ func (c *Channel) handleDM(msg protocol.UserMessage) {
c.startTyping(threadID, protocol.ThreadTypeUser)
// Collect contact for DM messages.
if cc := c.ContactCollector(); cc != nil {
cc.EnsureContact(context.Background(), c.Type(), c.Name(), senderID, senderID, senderName, "", "direct")
}
metadata := map[string]string{
"message_id": msg.Data.MsgID,
"platform": channels.TypeZaloPersonal,
@@ -131,6 +136,11 @@ func (c *Channel) handleGroupMessage(msg protocol.GroupMessage) {
histMedia := c.groupHistory.CollectMedia(threadID)
allMedia := append(histMedia, media...)
// Collect contact for group-mentioned messages.
if cc := c.ContactCollector(); cc != nil {
cc.EnsureContact(context.Background(), c.Type(), c.Name(), senderID, senderID, senderName, "", "group")
}
metadata := map[string]string{
"message_id": msg.Data.MsgID,
"platform": channels.TypeZaloPersonal,