MM-56201, MM-56280: Suppress typing and emoji events (#25794)
We do not send the typing event when the originating channel is not the active channel or active channel thread. https://mattermost.atlassian.net/browse/MM-56201 ```release-note NONE ``` Co-authored-by: harshil Sharma <harshilsharma63@gmail.com> Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
38bbf04e48
Коммит
f5ee5463e4
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
||||
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
||||
"github.com/mattermost/mattermost/server/public/shared/request"
|
||||
"github.com/mattermost/mattermost/server/public/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -48,6 +49,10 @@ const (
|
||||
|
||||
const websocketMessagePluginPrefix = "custom_"
|
||||
|
||||
// UnsetPresenceIndicator is the value that gets set initially for active channel/
|
||||
// thread/team. This is done to differentiate it from an explicitly set empty value.
|
||||
const UnsetPresenceIndicator = "<>"
|
||||
|
||||
type pluginWSPostedHook struct {
|
||||
connectionID string
|
||||
userID string
|
||||
@@ -105,17 +110,19 @@ type WebConn struct {
|
||||
// a reused connection.
|
||||
// It's theoretically possible for this number to wrap around. But we
|
||||
// leave that as an edge-case.
|
||||
reuseCount int
|
||||
sessionToken atomic.Value
|
||||
session atomic.Pointer[model.Session]
|
||||
connectionID atomic.Value
|
||||
reuseCount int
|
||||
sessionToken atomic.Value
|
||||
session atomic.Pointer[model.Session]
|
||||
connectionID atomic.Value
|
||||
|
||||
activeChannelID atomic.Value
|
||||
activeTeamID atomic.Value
|
||||
activeRHSThreadChannelID atomic.Value
|
||||
activeThreadViewThreadChannelID atomic.Value
|
||||
endWritePump chan struct{}
|
||||
pumpFinished chan struct{}
|
||||
pluginPosted chan pluginWSPostedHook
|
||||
|
||||
endWritePump chan struct{}
|
||||
pumpFinished chan struct{}
|
||||
pluginPosted chan pluginWSPostedHook
|
||||
|
||||
// These counters are to suppress spammy websocket.slow
|
||||
// and websocket.full logs which happen continuously, if they
|
||||
@@ -236,10 +243,12 @@ func (ps *PlatformService) NewWebConn(cfg *WebConnConfig, suite SuiteIFace, runn
|
||||
wc.SetSessionToken(cfg.Session.Token)
|
||||
wc.SetSessionExpiresAt(cfg.Session.ExpiresAt)
|
||||
wc.SetConnectionID(cfg.ConnectionID)
|
||||
wc.SetActiveChannelID("")
|
||||
wc.SetActiveTeamID("")
|
||||
wc.SetActiveRHSThreadChannelID("")
|
||||
wc.SetActiveThreadViewThreadChannelID("")
|
||||
// <> means unset. This is to differentiate from empty value.
|
||||
// Because we need to support mobile clients where the value might be unset.
|
||||
wc.SetActiveChannelID(UnsetPresenceIndicator)
|
||||
wc.SetActiveTeamID(UnsetPresenceIndicator)
|
||||
wc.SetActiveRHSThreadChannelID(UnsetPresenceIndicator)
|
||||
wc.SetActiveThreadViewThreadChannelID(UnsetPresenceIndicator)
|
||||
|
||||
ps.Go(func() {
|
||||
runner.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||
@@ -305,6 +314,9 @@ func (wc *WebConn) SetActiveChannelID(id string) {
|
||||
|
||||
// GetActiveChannelID returns the active channel id of the connection.
|
||||
func (wc *WebConn) GetActiveChannelID() string {
|
||||
if wc.activeChannelID.Load() == nil {
|
||||
return UnsetPresenceIndicator
|
||||
}
|
||||
return wc.activeChannelID.Load().(string)
|
||||
}
|
||||
|
||||
@@ -315,11 +327,17 @@ func (wc *WebConn) SetActiveTeamID(id string) {
|
||||
|
||||
// GetActiveTeamID returns the active team id of the connection.
|
||||
func (wc *WebConn) GetActiveTeamID() string {
|
||||
if wc.activeTeamID.Load() == nil {
|
||||
return UnsetPresenceIndicator
|
||||
}
|
||||
return wc.activeTeamID.Load().(string)
|
||||
}
|
||||
|
||||
// GetActiveRHSThreadChannelID returns the channel id of the active thread of the connection.
|
||||
func (wc *WebConn) GetActiveRHSThreadChannelID() string {
|
||||
if wc.activeRHSThreadChannelID.Load() == nil {
|
||||
return UnsetPresenceIndicator
|
||||
}
|
||||
return wc.activeRHSThreadChannelID.Load().(string)
|
||||
}
|
||||
|
||||
@@ -330,6 +348,9 @@ func (wc *WebConn) SetActiveRHSThreadChannelID(id string) {
|
||||
|
||||
// GetActiveThreadViewThreadChannelID returns the channel id of the active thread of the connection.
|
||||
func (wc *WebConn) GetActiveThreadViewThreadChannelID() string {
|
||||
if wc.activeThreadViewThreadChannelID.Load() == nil {
|
||||
return UnsetPresenceIndicator
|
||||
}
|
||||
return wc.activeThreadViewThreadChannelID.Load().(string)
|
||||
}
|
||||
|
||||
@@ -338,6 +359,11 @@ func (wc *WebConn) SetActiveThreadViewThreadChannelID(id string) {
|
||||
wc.activeThreadViewThreadChannelID.Store(id)
|
||||
}
|
||||
|
||||
// isSet is a helper to check if a value is unset or not.
|
||||
func (wc *WebConn) isSet(val string) bool {
|
||||
return val != UnsetPresenceIndicator
|
||||
}
|
||||
|
||||
// areAllInactive returns whether all of the connections
|
||||
// are inactive or not.
|
||||
func areAllInactive(conns []*WebConn) bool {
|
||||
@@ -847,7 +873,18 @@ func (wc *WebConn) ShouldSendEvent(msg *model.WebSocketEvent) bool {
|
||||
}
|
||||
|
||||
// Only report events to users who are in the channel for the event
|
||||
if msg.GetBroadcast().ChannelId != "" {
|
||||
if chID := msg.GetBroadcast().ChannelId; chID != "" {
|
||||
// For typing events, we don't send them to users who don't have
|
||||
// that channel or thread opened.
|
||||
if wc.Platform.Config().FeatureFlags.WebSocketEventScope &&
|
||||
utils.Contains([]model.WebsocketEventType{
|
||||
model.WebsocketEventTyping,
|
||||
model.WebsocketEventReactionAdded,
|
||||
model.WebsocketEventReactionRemoved,
|
||||
}, msg.EventType()) && wc.notInChannel(chID) && wc.notInThread(chID) {
|
||||
return false
|
||||
}
|
||||
|
||||
if model.GetMillis()-wc.lastAllChannelMembersTime > webConnMemberCacheTime {
|
||||
wc.allChannelMembers = nil
|
||||
wc.lastAllChannelMembersTime = 0
|
||||
@@ -863,7 +900,7 @@ func (wc *WebConn) ShouldSendEvent(msg *model.WebSocketEvent) bool {
|
||||
wc.lastAllChannelMembersTime = model.GetMillis()
|
||||
}
|
||||
|
||||
if _, ok := wc.allChannelMembers[msg.GetBroadcast().ChannelId]; ok {
|
||||
if _, ok := wc.allChannelMembers[chID]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -881,6 +918,15 @@ func (wc *WebConn) ShouldSendEvent(msg *model.WebSocketEvent) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (wc *WebConn) notInChannel(val string) bool {
|
||||
return (wc.isSet(wc.GetActiveChannelID()) && val != wc.GetActiveChannelID())
|
||||
}
|
||||
|
||||
func (wc *WebConn) notInThread(val string) bool {
|
||||
return (wc.isSet(wc.GetActiveRHSThreadChannelID()) && val != wc.GetActiveRHSThreadChannelID()) &&
|
||||
(wc.isSet(wc.GetActiveThreadViewThreadChannelID()) && val != wc.GetActiveThreadViewThreadChannelID())
|
||||
}
|
||||
|
||||
// IsMemberOfTeam returns whether the user of the WebConn
|
||||
// is a member of the given teamID or not.
|
||||
func (wc *WebConn) isMemberOfTeam(teamID string) bool {
|
||||
|
||||
Ссылка в новой задаче
Block a user