Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pkg/connector/chatinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ import (

const ChatInfoCacheExpiry = 1 * time.Hour

func (s *SlackClient) invalidateChatInfoCache(channelID string) {
s.chatInfoCacheLock.Lock()
defer s.chatInfoCacheLock.Unlock()
delete(s.chatInfoCache, channelID)
}

func (s *SlackClient) fetchChatInfoWithCache(ctx context.Context, channelID string, onlyIfNotAttempted bool) (*slack.Channel, error) {
s.chatInfoCacheLock.Lock()
defer s.chatInfoCacheLock.Unlock()
Expand Down
55 changes: 49 additions & 6 deletions pkg/connector/handleslack.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ func (s *SlackClient) handleUserInvalidated(ctx context.Context, userID string)
}
}

func isChannelInfoChangeSubtype(subType string) bool {
switch subType {
case slack.MsgSubTypeChannelTopic, slack.MsgSubTypeChannelPurpose, slack.MsgSubTypeChannelName,
slack.MsgSubTypeGroupTopic, slack.MsgSubTypeGroupPurpose, slack.MsgSubTypeGroupName:
return true
default:
return false
}
}

func (s *SlackClient) wrapEvent(ctx context.Context, rawEvt any) (bridgev2.RemoteEvent, error) {
var meta SlackEventMeta
var metaErr error
Expand All @@ -185,6 +195,23 @@ func (s *SlackClient) wrapEvent(ctx context.Context, rawEvt any) (bridgev2.Remot
if evt.SubType == slack.MsgSubTypeMessageChanged && evt.SubMessage.SubType == "huddle_thread" {
return nil, nil
}
switch evt.SubType {
case slack.MsgSubTypeChannelName, slack.MsgSubTypeGroupName:
// The room name is formatted from the channel type/privacy, which
// the rename message doesn't include, so resync the full info.
// Drop the cache first so GetChatInfo fetches the new name.
s.invalidateChatInfoCache(evt.Channel)
meta, metaErr = s.makeEventMeta(ctx, evt.Channel, nil, "", evt.Timestamp)
meta.Type = bridgev2.RemoteEventChatResync
return &SlackChatResync{
SlackEventMeta: &meta,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we know exactly which field changed, it'd be more appropriate to send a targeted ChatInfoChange event than a full resync

Client: s,
ShouldSyncInfo: true,
}, metaErr
case slack.MsgSubTypeChannelTopic, slack.MsgSubTypeGroupTopic:
meta, metaErr = s.makeEventMeta(ctx, evt.Channel, nil, "", evt.Timestamp)
return wrapTopicChange(&meta, evt.Topic), metaErr
}
sender := evt.User
if sender == "" {
sender = evt.BotID
Expand Down Expand Up @@ -261,10 +288,14 @@ func (s *SlackClient) wrapEvent(ctx context.Context, rawEvt any) (bridgev2.Remot
wrapped = wrapMemberChange(&meta, meta.Sender, event.MembershipLeave, event.MembershipJoin)

case *slack.ChannelUpdateEvent:
s.invalidateChatInfoCache(evt.Channel)
meta, metaErr = s.makeEventMeta(ctx, evt.Channel, nil, "", evt.Timestamp)
meta.Type = bridgev2.RemoteEventChatResync
//meta.CreatePortal = true
wrapped = &meta
wrapped = &SlackChatResync{
SlackEventMeta: &meta,
Client: s,
ShouldSyncInfo: true,
}
}
return wrapped, metaErr
}
Expand Down Expand Up @@ -315,6 +346,18 @@ func wrapReadReceipt(meta *SlackEventMeta) *SlackReadReceipt {
return &SlackReadReceipt{SlackEventMeta: meta}
}

func wrapTopicChange(meta *SlackEventMeta, topic string) *SlackChatInfoChange {
meta.Type = bridgev2.RemoteEventChatInfoChange
return &SlackChatInfoChange{
SlackEventMeta: meta,
Change: &bridgev2.ChatInfoChange{
ChatInfo: &bridgev2.ChatInfo{
Topic: &topic,
},
},
}
}

func wrapMemberChange(meta *SlackEventMeta, sender bridgev2.EventSender, newMembership, prevMembership event.Membership) *SlackChatInfoChange {
meta.Type = bridgev2.RemoteEventChatInfoChange
meta.LogContext = func(c zerolog.Context) zerolog.Context {
Expand Down Expand Up @@ -545,15 +588,15 @@ var (
)

func (s *SlackMessage) GetType() bridgev2.RemoteEventType {
if isChannelInfoChangeSubtype(s.Data.SubType) {
// These shouldn't end up as SlackMessage events
return bridgev2.RemoteEventUnknown
}
switch s.Data.SubType {
case slack.MsgSubTypeMessageChanged:
return bridgev2.RemoteEventEdit
case slack.MsgSubTypeMessageDeleted:
return bridgev2.RemoteEventMessageRemove
case slack.MsgSubTypeChannelTopic, slack.MsgSubTypeChannelPurpose, slack.MsgSubTypeChannelName,
slack.MsgSubTypeGroupTopic, slack.MsgSubTypeGroupPurpose, slack.MsgSubTypeGroupName:
// TODO implement deltas instead of full resync
return bridgev2.RemoteEventChatResync
case slack.MsgSubTypeMessageReplied, slack.MsgSubTypeGroupJoin, slack.MsgSubTypeGroupLeave,
slack.MsgSubTypeChannelJoin, slack.MsgSubTypeChannelLeave:
return bridgev2.RemoteEventUnknown
Expand Down
Loading