From 2a43d7a0388d7e68d5c87a1f0de8642b2005753e Mon Sep 17 00:00:00 2001 From: avasconcelos114 Date: Mon, 9 Mar 2026 18:41:44 +0200 Subject: [PATCH 1/5] Added missing checks for muted notifications in webhook handlers --- server/plugin/webhook.go | 24 +++++++++++++++++------ server/plugin/webhook_test.go | 36 +++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go index 90d62ac4d..b84183d5e 100644 --- a/server/plugin/webhook.go +++ b/server/plugin/webhook.go @@ -594,6 +594,10 @@ func (p *Plugin) handlePRDescriptionMentionNotification(event *github.PullReques continue } + if p.senderMutedByReceiver(userID, event.GetSender().GetLogin()) { + continue + } + channel, err := p.client.Channel.GetDirect(userID, p.BotUserID) if err != nil { continue @@ -1103,6 +1107,10 @@ func (p *Plugin) handleCommentMentionNotification(event *github.IssueCommentEven continue } + if p.senderMutedByReceiver(userID, event.GetSender().GetLogin()) { + continue + } + channel, err := p.client.Channel.GetDirect(userID, p.BotUserID) if err != nil { continue @@ -1300,12 +1308,12 @@ func (p *Plugin) handlePullRequestNotification(event *github.PullRequestEvent) { return } - if len(requestedUserID) > 0 { + if len(requestedUserID) > 0 && !p.senderMutedByReceiver(requestedUserID, sender) { p.CreateBotDMPost(requestedUserID, message, "custom_git_review_request") p.sendRefreshEvent(requestedUserID) } - p.postIssueNotification(message, authorUserID, assigneeUserID) + p.postIssueNotification(message, sender, authorUserID, assigneeUserID) } func (p *Plugin) handleIssueNotification(event *github.IssuesEvent) { @@ -1352,16 +1360,16 @@ func (p *Plugin) handleIssueNotification(event *github.IssuesEvent) { return } - p.postIssueNotification(message, authorUserID, assigneeUserID) + p.postIssueNotification(message, sender, authorUserID, assigneeUserID) } -func (p *Plugin) postIssueNotification(message, authorUserID, assigneeUserID string) { - if len(authorUserID) > 0 { +func (p *Plugin) postIssueNotification(message, sender, authorUserID, assigneeUserID string) { + if len(authorUserID) > 0 && !p.senderMutedByReceiver(authorUserID, sender) { p.CreateBotDMPost(authorUserID, message, "custom_git_author") p.sendRefreshEvent(authorUserID) } - if len(assigneeUserID) > 0 { + if len(assigneeUserID) > 0 && !p.senderMutedByReceiver(assigneeUserID, sender) { p.CreateBotDMPost(assigneeUserID, message, "custom_git_assigned") p.sendRefreshEvent(assigneeUserID) } @@ -1386,6 +1394,10 @@ func (p *Plugin) handlePullRequestReviewNotification(event *github.PullRequestRe return } + if p.senderMutedByReceiver(authorUserID, event.GetSender().GetLogin()) { + return + } + message, err := renderTemplate("pullRequestReviewNotification", event) if err != nil { p.client.Log.Warn("Failed to render template", "error", err.Error()) diff --git a/server/plugin/webhook_test.go b/server/plugin/webhook_test.go index 1f3ef60a2..445f9d88b 100644 --- a/server/plugin/webhook_test.go +++ b/server/plugin/webhook_test.go @@ -487,8 +487,8 @@ func TestHandleCommentMentionNotification(t *testing.T) { _, ok := val.(*[]uint8) return ok })).DoAndReturn(setByteValue("otherUserID")).Times(1) - mockKVStore.EXPECT().Get("otherUserID_githubtoken", mock.MatchedBy(func(val any) bool { - _, ok := val.(**GitHubUserInfo) + mockKVStore.EXPECT().Get("otherUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) return ok })).Return(nil).Times(1) mockAPI.On("GetDirectChannel", "otherUserID", "mockBotID").Return(nil, &model.AppError{Message: "error getting channel"}).Times(1) @@ -502,6 +502,10 @@ func TestHandleCommentMentionNotification(t *testing.T) { _, ok := val.(*[]uint8) return ok })).DoAndReturn(setByteValue("otherUserID")).Times(1) + mockKVStore.EXPECT().Get("otherUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).Return(nil).Times(1) mockKVStore.EXPECT().Get("otherUserID_githubtoken", mock.MatchedBy(func(val any) bool { _, ok := val.(**GitHubUserInfo) return ok @@ -519,6 +523,10 @@ func TestHandleCommentMentionNotification(t *testing.T) { _, ok := val.(*[]uint8) return ok })).DoAndReturn(setByteValue("otherUserID")).Times(1) + mockKVStore.EXPECT().Get("otherUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).Return(nil).Times(1) mockKVStore.EXPECT().Get("otherUserID_githubtoken", mock.MatchedBy(func(val any) bool { _, ok := val.(**GitHubUserInfo) return ok @@ -764,6 +772,10 @@ func TestHandlePullRequestNotification(t *testing.T) { _, ok := val.(*[]uint8) return ok })).DoAndReturn(setByteValue("authorUserID")).Times(1) + mockKVStore.EXPECT().Get("authorUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).Return(nil).Times(1) mockKVStore.EXPECT().Get("authorUserID_githubtoken", mock.MatchedBy(func(val any) bool { _, ok := val.(**GitHubUserInfo) return ok @@ -795,12 +807,16 @@ func TestHandlePullRequestNotification(t *testing.T) { _, ok := val.(*[]uint8) return ok })).DoAndReturn(setByteValue("assigneeUserID")).Times(1) - mockAPI.On("GetDirectChannel", "assigneeUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockKVStore.EXPECT().Get("assigneeUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).Return(nil).Times(1) mockKVStore.EXPECT().Get("assigneeUserID_githubtoken", mock.MatchedBy(func(val any) bool { _, ok := val.(**GitHubUserInfo) return ok })).Return(nil).Times(1) + mockAPI.On("GetDirectChannel", "assigneeUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) }, }, { @@ -811,12 +827,16 @@ func TestHandlePullRequestNotification(t *testing.T) { _, ok := val.(*[]uint8) return ok })).DoAndReturn(setByteValue("requestedUserID")).Times(1) - mockAPI.On("GetDirectChannel", "requestedUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil) - mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) + mockKVStore.EXPECT().Get("requestedUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).Return(nil).Times(1) mockKVStore.EXPECT().Get("requestedUserID_githubtoken", mock.MatchedBy(func(val any) bool { _, ok := val.(**GitHubUserInfo) return ok })).Return(nil).Times(1) + mockAPI.On("GetDirectChannel", "requestedUserID", "mockBotID").Return(&model.Channel{Id: "mockChannelID"}, nil) + mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) }, }, { @@ -977,6 +997,10 @@ func TestHandlePullRequestReviewNotification(t *testing.T) { _, ok := val.(*[]uint8) return ok })).DoAndReturn(setByteValue("authorUserID")).Times(1) + mockKvStore.EXPECT().Get("authorUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).Return(nil).Times(1) mockAPI.On("GetDirectChannel", "authorUserID", "mockBotID").Return(nil, &model.AppError{Message: "error getting channel"}).Times(1) mockAPI.On("LogWarn", "Couldn't get bot's DM channel", "userID", "authorUserID", "error", "error getting channel") mockKvStore.EXPECT().Get("authorUserID_githubtoken", mock.MatchedBy(func(val any) bool { From 9acfd73c568b7d3e4e9642ce9058d003dd553990 Mon Sep 17 00:00:00 2001 From: avasconcelos114 Date: Mon, 9 Mar 2026 19:14:54 +0200 Subject: [PATCH 2/5] Fixing issue with possible false positives returned by string evalutation --- server/plugin/webhook.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go index b84183d5e..a4841bbe3 100644 --- a/server/plugin/webhook.go +++ b/server/plugin/webhook.go @@ -919,7 +919,10 @@ func (p *Plugin) senderMutedByReceiver(userID string, sender string) bool { } mutedUsernames := string(mutedUsernameBytes) - return strings.Contains(mutedUsernames, sender) + if len(mutedUsernames) == 0 { + return false + } + return slices.Contains(strings.Split(mutedUsernames, ","), sender) } func (p *Plugin) postPullRequestReviewEvent(event *github.PullRequestReviewEvent) { From 7569303e2b06a224629d29d25c63e6c5e8ba06c3 Mon Sep 17 00:00:00 2001 From: avasconcelos114 Date: Mon, 9 Mar 2026 19:44:39 +0200 Subject: [PATCH 3/5] Added test cases for muted flows --- server/plugin/webhook_test.go | 196 +++++++++++++++++++++++++++++++--- 1 file changed, 184 insertions(+), 12 deletions(-) diff --git a/server/plugin/webhook_test.go b/server/plugin/webhook_test.go index 445f9d88b..5131e350e 100644 --- a/server/plugin/webhook_test.go +++ b/server/plugin/webhook_test.go @@ -450,9 +450,10 @@ func TestPostPullRequestReviewCommentEvent(t *testing.T) { func TestHandleCommentMentionNotification(t *testing.T) { tests := []struct { - name string - event *github.IssueCommentEvent - setup func(*plugintest.API, *mocks.MockKvStore) + name string + event *github.IssueCommentEvent + setup func(*plugintest.API, *mocks.MockKvStore) + assertDMs func(*testing.T, *plugintest.API) }{ { name: "Unsupported action", @@ -535,6 +536,28 @@ func TestHandleCommentMentionNotification(t *testing.T) { mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) }, }, + { + name: "Muted sender suppresses mention notification", + event: GetMockIssueCommentEvent(actionCreated, "mention @otherUser", "mockUser"), + setup: func(_ *plugintest.API, mockKVStore *mocks.MockKvStore) { + mockKVStore.EXPECT().Get("otherUser_githubusername", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(setByteValue("otherUserID")).Times(1) + mockKVStore.EXPECT().Get("otherUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(func(key string, value any) error { + *value.(*[]byte) = []byte("mockUser,anotherUser") + return nil + }).Times(1) + }, + assertDMs: func(t *testing.T, mockAPI *plugintest.API) { + t.Helper() + mockAPI.AssertNotCalled(t, "GetDirectChannel", mock.Anything, mock.Anything) + mockAPI.AssertNotCalled(t, "CreatePost", mock.Anything) + }, + }, } for _, tc := range tests { mockKVStore, mockAPI, _, _, _ := GetTestSetup(t) @@ -545,6 +568,9 @@ func TestHandleCommentMentionNotification(t *testing.T) { p.handleCommentMentionNotification(tc.event) + if tc.assertDMs != nil { + tc.assertDMs(t, mockAPI) + } mockAPI.AssertExpectations(t) }) } @@ -740,9 +766,10 @@ func TestHandleCommentAssigneeNotification(t *testing.T) { func TestHandlePullRequestNotification(t *testing.T) { tests := []struct { - name string - event *github.PullRequestEvent - setup func(*plugintest.API, *mocks.MockKvStore) + name string + event *github.PullRequestEvent + setup func(*plugintest.API, *mocks.MockKvStore) + assertDMs func(*testing.T, *plugintest.API) }{ { name: "Review requested by sender", @@ -839,6 +866,72 @@ func TestHandlePullRequestNotification(t *testing.T) { mockAPI.On("CreatePost", mock.Anything).Return(&model.Post{}, nil).Times(1) }, }, + { + name: "Muted sender suppresses PR closed notification to author", + event: GetMockPullRequestEvent(actionClosed, "mockRepo", false, "senderUser", "prAuthor", ""), + setup: func(_ *plugintest.API, mockKVStore *mocks.MockKvStore) { + mockKVStore.EXPECT().Get("prAuthor_githubusername", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(setByteValue("prAuthorUserID")).Times(1) + mockKVStore.EXPECT().Get("prAuthorUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(func(key string, value any) error { + *value.(*[]byte) = []byte("senderUser,otherBot") + return nil + }).Times(1) + }, + assertDMs: func(t *testing.T, mockAPI *plugintest.API) { + t.Helper() + mockAPI.AssertNotCalled(t, "GetDirectChannel", mock.Anything, mock.Anything) + mockAPI.AssertNotCalled(t, "CreatePost", mock.Anything) + }, + }, + { + name: "Muted sender suppresses PR assigned notification to assignee", + event: GetMockPullRequestEvent(actionAssigned, "mockRepo", false, "senderUser", "prAuthor", "assigneeUser"), + setup: func(_ *plugintest.API, mockKVStore *mocks.MockKvStore) { + mockKVStore.EXPECT().Get("assigneeUser_githubusername", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(setByteValue("assigneeUserID")).Times(1) + mockKVStore.EXPECT().Get("assigneeUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(func(key string, value any) error { + *value.(*[]byte) = []byte("senderUser") + return nil + }).Times(1) + }, + assertDMs: func(t *testing.T, mockAPI *plugintest.API) { + t.Helper() + mockAPI.AssertNotCalled(t, "GetDirectChannel", mock.Anything, mock.Anything) + mockAPI.AssertNotCalled(t, "CreatePost", mock.Anything) + }, + }, + { + name: "Muted sender suppresses PR review requested notification", + event: GetMockPullRequestEvent("review_requested", "mockRepo", false, "senderUser", "requestedReviewer", ""), + setup: func(_ *plugintest.API, mockKVStore *mocks.MockKvStore) { + mockKVStore.EXPECT().Get("requestedReviewer_githubusername", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(setByteValue("requestedUserID")).Times(1) + mockKVStore.EXPECT().Get("requestedUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(func(key string, value any) error { + *value.(*[]byte) = []byte("senderUser") + return nil + }).Times(1) + }, + assertDMs: func(t *testing.T, mockAPI *plugintest.API) { + t.Helper() + mockAPI.AssertNotCalled(t, "GetDirectChannel", mock.Anything, mock.Anything) + mockAPI.AssertNotCalled(t, "CreatePost", mock.Anything) + }, + }, { name: "Unhandled event action", event: GetMockPullRequestEvent( @@ -858,6 +951,9 @@ func TestHandlePullRequestNotification(t *testing.T) { p.handlePullRequestNotification(tc.event) + if tc.assertDMs != nil { + tc.assertDMs(t, mockAPI) + } mockAPI.AssertExpectations(t) }) } @@ -868,9 +964,10 @@ func TestHandleIssueNotification(t *testing.T) { p := getPluginTest(mockAPI, mockKvStore) tests := []struct { - name string - event *github.IssuesEvent - setup func() + name string + event *github.IssuesEvent + setup func() + assertDMs func(*testing.T) }{ { name: "issue closed by author", @@ -926,6 +1023,50 @@ func TestHandleIssueNotification(t *testing.T) { })).DoAndReturn(setByteValue("assigneeUserID")).Times(1) }, }, + { + name: "muted sender suppresses issue closed notification to author", + event: GetMockIssuesEvent(actionClosed, MockRepo, false, "authorUser", "senderUser", ""), + setup: func() { + mockKvStore.EXPECT().Get("authorUser_githubusername", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(setByteValue("authorUserID")).Times(1) + mockKvStore.EXPECT().Get("authorUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(func(key string, value any) error { + *value.(*[]byte) = []byte("senderUser,otherBot") + return nil + }).Times(1) + }, + assertDMs: func(t *testing.T) { + t.Helper() + mockAPI.AssertNotCalled(t, "GetDirectChannel", mock.Anything, mock.Anything) + mockAPI.AssertNotCalled(t, "CreatePost", mock.Anything) + }, + }, + { + name: "muted sender suppresses issue assigned notification to assignee", + event: GetMockIssuesEvent(actionAssigned, MockRepo, false, "authorUser", "senderUser", "assigneeUser"), + setup: func() { + mockKvStore.EXPECT().Get("assigneeUser_githubusername", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(setByteValue("assigneeUserID")).Times(1) + mockKvStore.EXPECT().Get("assigneeUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(func(key string, value any) error { + *value.(*[]byte) = []byte("senderUser") + return nil + }).Times(1) + }, + assertDMs: func(t *testing.T) { + t.Helper() + mockAPI.AssertNotCalled(t, "GetDirectChannel", mock.Anything, mock.Anything) + mockAPI.AssertNotCalled(t, "CreatePost", mock.Anything) + }, + }, { name: "unhandled event action", event: GetMockIssuesEvent("unsupported_action", MockRepo, false, "senderUser", "", ""), @@ -937,10 +1078,14 @@ func TestHandleIssueNotification(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { mockAPI.ExpectedCalls = nil + mockAPI.Calls = nil tc.setup() p.handleIssueNotification(tc.event) + if tc.assertDMs != nil { + tc.assertDMs(t) + } mockAPI.AssertExpectations(t) }) } @@ -951,9 +1096,10 @@ func TestHandlePullRequestReviewNotification(t *testing.T) { p := getPluginTest(mockAPI, mockKvStore) tests := []struct { - name string - event *github.PullRequestReviewEvent - setup func() + name string + event *github.PullRequestReviewEvent + setup func() + assertDMs func(*testing.T) }{ { name: "review submitted by author", @@ -1009,14 +1155,40 @@ func TestHandlePullRequestReviewNotification(t *testing.T) { })).Return(nil).Times(1) }, }, + { + name: "muted sender suppresses review notification to PR author", + event: GetMockPullRequestReviewEvent(actionSubmitted, "approved", MockRepo, false, "reviewerUser", "authorUser"), + setup: func() { + mockKvStore.EXPECT().Get("authorUser_githubusername", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(setByteValue("authorUserID")).Times(1) + mockKvStore.EXPECT().Get("authorUserID-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).DoAndReturn(func(key string, value any) error { + *value.(*[]byte) = []byte("reviewerUser,otherBot") + return nil + }).Times(1) + }, + assertDMs: func(t *testing.T) { + t.Helper() + mockAPI.AssertNotCalled(t, "GetDirectChannel", mock.Anything, mock.Anything) + mockAPI.AssertNotCalled(t, "CreatePost", mock.Anything) + }, + }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { mockAPI.ExpectedCalls = nil + mockAPI.Calls = nil tc.setup() p.handlePullRequestReviewNotification(tc.event) + if tc.assertDMs != nil { + tc.assertDMs(t) + } mockAPI.AssertExpectations(t) }) } From ae5a8406a860f5ac067ed3b5574691f621bf1a40 Mon Sep 17 00:00:00 2001 From: avasconcelos114 Date: Mon, 9 Mar 2026 19:58:36 +0200 Subject: [PATCH 4/5] Ensuring muting is case insensitive --- server/plugin/webhook.go | 8 +++++++- server/plugin/webhook_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go index a4841bbe3..b79c9195b 100644 --- a/server/plugin/webhook.go +++ b/server/plugin/webhook.go @@ -922,7 +922,13 @@ func (p *Plugin) senderMutedByReceiver(userID string, sender string) bool { if len(mutedUsernames) == 0 { return false } - return slices.Contains(strings.Split(mutedUsernames, ","), sender) + senderLower := strings.ToLower(sender) + for _, muted := range strings.Split(mutedUsernames, ",") { + if strings.ToLower(muted) == senderLower { + return true + } + } + return false } func (p *Plugin) postPullRequestReviewEvent(event *github.PullRequestReviewEvent) { diff --git a/server/plugin/webhook_test.go b/server/plugin/webhook_test.go index 5131e350e..886c0ff3a 100644 --- a/server/plugin/webhook_test.go +++ b/server/plugin/webhook_test.go @@ -303,6 +303,38 @@ func TestSenderMutedByReceiver(t *testing.T) { assert.False(t, muted, "Expected sender to not be muted") }, }, + { + name: "Sender is muted with different casing", + userID: "user1", + sender: "Sender1", + setup: func(mockKVStore *mocks.MockKvStore, _ *plugintest.API) { + mockKVStore.EXPECT().Get("user1-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).Return(nil).Do(func(key string, value any) { + *value.(*[]byte) = []byte("sender1,sender2") + }).Times(1) + }, + assert: func(t *testing.T, muted bool) { + assert.True(t, muted, "Expected sender to be muted regardless of casing") + }, + }, + { + name: "Empty muted users list", + userID: "user1", + sender: "sender1", + setup: func(mockKVStore *mocks.MockKvStore, _ *plugintest.API) { + mockKVStore.EXPECT().Get("user1-muted-users", mock.MatchedBy(func(val any) bool { + _, ok := val.(*[]uint8) + return ok + })).Return(nil).Do(func(key string, value any) { + *value.(*[]byte) = []byte("") + }).Times(1) + }, + assert: func(t *testing.T, muted bool) { + assert.False(t, muted, "Expected sender to not be muted when mute list is empty") + }, + }, { name: "Error fetching muted users", userID: "user1", From e5659714cfb1c35f3becd559d67215c424ffb191 Mon Sep 17 00:00:00 2001 From: avasconcelos114 Date: Mon, 9 Mar 2026 20:09:52 +0200 Subject: [PATCH 5/5] Fixing linter errors --- server/plugin/webhook.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go index b79c9195b..4808d1fa2 100644 --- a/server/plugin/webhook.go +++ b/server/plugin/webhook.go @@ -923,7 +923,7 @@ func (p *Plugin) senderMutedByReceiver(userID string, sender string) bool { return false } senderLower := strings.ToLower(sender) - for _, muted := range strings.Split(mutedUsernames, ",") { + for muted := range strings.SplitSeq(mutedUsernames, ",") { if strings.ToLower(muted) == senderLower { return true }