Make GM behave as DM (#24289)
* Make GM behave as DM * Fix lint * Add desktop notification special behavior * Change notification preferences menu * Make changes to the GM channel intro * Fix tests * Fix i18n and style lint * Add system notice and update style * Fix style and fix tests * Fix tests * Handle push notifications as desktop notifications * Fix tests * Add test and default GMs to none when user level config is none * Fix test * Update only for mentions text * Add tests * Fix lint * Fix lint
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
39d6cb8008
Коммит
88d043a971
@@ -50,8 +50,8 @@ func TestGetPreferences(t *testing.T) {
|
||||
prefs, _, err := client.GetPreferences(context.Background(), user1.Id)
|
||||
require.NoError(t, err)
|
||||
|
||||
// 5 because we have 2 initial preferences tutorial_step and recommended_next_steps added when creating a new user
|
||||
require.Equal(t, len(prefs), 5, "received the wrong number of preferences")
|
||||
// 6 because we have 3 initial preferences tutorial_step, recommended_next_steps and system_notification are added when creating a new user
|
||||
require.Equal(t, len(prefs), 6, "received the wrong number of preferences")
|
||||
|
||||
for _, preference := range prefs {
|
||||
require.Equal(t, preference.UserId, th.BasicUser.Id, "user id does not match")
|
||||
|
||||
@@ -387,7 +387,9 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
|
||||
status = &model.Status{UserId: id, Status: model.StatusOffline, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
|
||||
}
|
||||
|
||||
if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], true, status, post) {
|
||||
isExplicitlyMentioned := mentions.Mentions[id] > GMMention
|
||||
isGM := channel.Type == model.ChannelTypeGroup
|
||||
if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], isExplicitlyMentioned, status, post, isGM) {
|
||||
mentionType := mentions.Mentions[id]
|
||||
|
||||
replyToThreadType := ""
|
||||
@@ -428,7 +430,8 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
|
||||
status = &model.Status{UserId: id, Status: model.StatusOffline, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
|
||||
}
|
||||
|
||||
if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], false, status, post) {
|
||||
isGM := channel.Type == model.ChannelTypeGroup
|
||||
if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], false, status, post, isGM) {
|
||||
a.sendPushNotification(
|
||||
notification,
|
||||
profileMap[id],
|
||||
@@ -770,6 +773,14 @@ func (a *App) getExplicitMentionsAndKeywords(c request.CTX, post *model.Post, ch
|
||||
keywords = a.getMentionKeywordsInChannel(profileMap, allowChannelMentions, channelMemberNotifyPropsMap)
|
||||
|
||||
mentions = getExplicitMentions(post, keywords, groups)
|
||||
|
||||
// Add a GM mention to all members of a GM channel
|
||||
if channel.Type == model.ChannelTypeGroup {
|
||||
for id := range channelMemberNotifyPropsMap {
|
||||
mentions.addMention(id, GMMention)
|
||||
}
|
||||
}
|
||||
|
||||
// Add an implicit mention when a user is added to a channel
|
||||
// even if the user has set 'username mentions' to false in account settings.
|
||||
if post.Type == model.PostTypeAddToChannel {
|
||||
@@ -1063,6 +1074,9 @@ const (
|
||||
// A placeholder that should never be used in practice
|
||||
NoMention MentionType = iota
|
||||
|
||||
// The post is in a GM
|
||||
GMMention
|
||||
|
||||
// The post is in a thread that the user has commented on
|
||||
ThreadMention
|
||||
|
||||
|
||||
@@ -512,12 +512,12 @@ func (a *App) getMobileAppSessions(userID string) ([]*model.Session, *model.AppE
|
||||
return sessions, nil
|
||||
}
|
||||
|
||||
func ShouldSendPushNotification(user *model.User, channelNotifyProps model.StringMap, wasMentioned bool, status *model.Status, post *model.Post) bool {
|
||||
return DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, wasMentioned) &&
|
||||
func ShouldSendPushNotification(user *model.User, channelNotifyProps model.StringMap, wasMentioned bool, status *model.Status, post *model.Post, isGM bool) bool {
|
||||
return DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, wasMentioned, isGM) &&
|
||||
DoesStatusAllowPushNotification(user.NotifyProps, status, post.ChannelId)
|
||||
}
|
||||
|
||||
func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps model.StringMap, post *model.Post, wasMentioned bool) bool {
|
||||
func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps model.StringMap, post *model.Post, wasMentioned, isGM bool) bool {
|
||||
userNotifyProps := user.NotifyProps
|
||||
userNotify := userNotifyProps[model.PushNotifyProp]
|
||||
channelNotify, ok := channelNotifyProps[model.PushNotifyProp]
|
||||
@@ -525,6 +525,14 @@ func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps m
|
||||
channelNotify = model.ChannelNotifyDefault
|
||||
}
|
||||
|
||||
notify := channelNotify
|
||||
if channelNotify == model.ChannelNotifyDefault {
|
||||
notify = userNotify
|
||||
if isGM && userNotify == model.UserNotifyMention {
|
||||
notify = model.ChannelNotifyAll
|
||||
}
|
||||
}
|
||||
|
||||
// If the channel is muted do not send push notifications
|
||||
if channelNotifyProps[model.MarkUnreadNotifyProp] == model.ChannelMarkUnreadMention {
|
||||
return false
|
||||
@@ -534,28 +542,19 @@ func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps m
|
||||
return false
|
||||
}
|
||||
|
||||
if channelNotify == model.UserNotifyNone {
|
||||
if notify == model.ChannelNotifyNone {
|
||||
return false
|
||||
}
|
||||
|
||||
if channelNotify == model.ChannelNotifyMention && !wasMentioned {
|
||||
if notify == model.ChannelNotifyMention && !wasMentioned {
|
||||
return false
|
||||
}
|
||||
|
||||
if userNotify == model.UserNotifyMention && channelNotify == model.ChannelNotifyDefault && !wasMentioned {
|
||||
return false
|
||||
}
|
||||
|
||||
if (userNotify == model.UserNotifyAll || channelNotify == model.ChannelNotifyAll) &&
|
||||
if (notify == model.ChannelNotifyAll) &&
|
||||
(post.UserId != user.Id || post.GetProp("from_webhook") == "true") {
|
||||
return true
|
||||
}
|
||||
|
||||
if userNotify == model.UserNotifyNone &&
|
||||
channelNotify == model.ChannelNotifyDefault {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned bool
|
||||
isMuted bool
|
||||
expected bool
|
||||
isGM bool
|
||||
}{
|
||||
{
|
||||
name: "When post is a System Message and has no mentions",
|
||||
@@ -45,6 +46,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When post is a System Message and has mentions",
|
||||
@@ -54,6 +56,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, no channel props is set and has no mentions",
|
||||
@@ -63,6 +66,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, no channel props is set and has mentions",
|
||||
@@ -72,6 +76,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, no channel props is set and has no mentions",
|
||||
@@ -81,6 +86,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, no channel props is set and has mentions",
|
||||
@@ -90,6 +96,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, no channel props is set and has no mentions",
|
||||
@@ -99,6 +106,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, no channel props is set and has mentions",
|
||||
@@ -108,6 +116,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, channel is DEFAULT and has no mentions",
|
||||
@@ -117,6 +126,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, channel is DEFAULT and has mentions",
|
||||
@@ -126,6 +136,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, channel is DEFAULT and has no mentions",
|
||||
@@ -135,6 +146,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, channel is DEFAULT and has mentions",
|
||||
@@ -144,6 +156,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, channel is DEFAULT and has no mentions",
|
||||
@@ -153,6 +166,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, channel is DEFAULT and has mentions",
|
||||
@@ -162,6 +176,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, channel is ALL and has no mentions",
|
||||
@@ -171,6 +186,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, channel is ALL and has mentions",
|
||||
@@ -180,6 +196,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, channel is ALL and has no mentions",
|
||||
@@ -189,6 +206,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, channel is ALL and has mentions",
|
||||
@@ -198,6 +216,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, channel is ALL and has no mentions",
|
||||
@@ -207,6 +226,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, channel is ALL and has mentions",
|
||||
@@ -216,6 +236,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, channel is MENTION and has no mentions",
|
||||
@@ -225,6 +246,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, channel is MENTION and has mentions",
|
||||
@@ -234,6 +256,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, channel is MENTION and has no mentions",
|
||||
@@ -243,6 +266,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, channel is MENTION and has mentions",
|
||||
@@ -252,6 +276,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, channel is MENTION and has no mentions",
|
||||
@@ -261,6 +286,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, channel is MENTION and has mentions",
|
||||
@@ -270,6 +296,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, channel is NONE and has no mentions",
|
||||
@@ -279,6 +306,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, channel is NONE and has mentions",
|
||||
@@ -288,6 +316,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, channel is NONE and has no mentions",
|
||||
@@ -297,6 +326,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is MENTION, channel is NONE and has mentions",
|
||||
@@ -306,6 +336,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, channel is NONE and has no mentions",
|
||||
@@ -315,6 +346,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is NONE, channel is NONE and has mentions",
|
||||
@@ -324,6 +356,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "When default is ALL, and channel is MUTED",
|
||||
@@ -333,6 +366,47 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
wasMentioned: false,
|
||||
isMuted: true,
|
||||
expected: false,
|
||||
isGM: false,
|
||||
},
|
||||
{
|
||||
name: "For GM default for NONE is NONE",
|
||||
userNotifySetting: model.UserNotifyNone,
|
||||
channelNotifySetting: model.ChannelNotifyDefault,
|
||||
withSystemPost: false,
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: true,
|
||||
},
|
||||
{
|
||||
name: "For GM, mentioned is only called if explicitly mentioned",
|
||||
userNotifySetting: model.UserNotifyNone,
|
||||
channelNotifySetting: model.ChannelNotifyMention,
|
||||
withSystemPost: false,
|
||||
wasMentioned: true,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: true,
|
||||
},
|
||||
{
|
||||
name: "For GM default for MENTION is ALL",
|
||||
userNotifySetting: model.UserNotifyMention,
|
||||
channelNotifySetting: model.ChannelNotifyDefault,
|
||||
withSystemPost: false,
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: true,
|
||||
isGM: true,
|
||||
},
|
||||
{
|
||||
name: "For GM, mentioned is only called if explicitly mentioned",
|
||||
userNotifySetting: model.UserNotifyNone,
|
||||
channelNotifySetting: model.ChannelNotifyMention,
|
||||
withSystemPost: false,
|
||||
wasMentioned: false,
|
||||
isMuted: false,
|
||||
expected: false,
|
||||
isGM: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -352,7 +426,7 @@ func TestDoesNotifyPropsAllowPushNotification(t *testing.T) {
|
||||
if tc.isMuted {
|
||||
channelNotifyProps[model.MarkUnreadNotifyProp] = model.ChannelMarkUnreadMention
|
||||
}
|
||||
assert.Equal(t, tc.expected, DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, tc.wasMentioned))
|
||||
assert.Equal(t, tc.expected, DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, tc.wasMentioned, tc.isGM))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,19 +38,21 @@ func TestSendNotifications(t *testing.T) {
|
||||
|
||||
th.App.AddUserToChannel(th.Context, th.BasicUser2, th.BasicChannel, false)
|
||||
|
||||
post1, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
|
||||
post1, createPostErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "@" + th.BasicUser2.Username,
|
||||
Type: model.PostTypeAddToChannel,
|
||||
Props: map[string]any{model.PostPropsAddedUserId: "junk"},
|
||||
}, true, true)
|
||||
require.Nil(t, appErr)
|
||||
require.Nil(t, createPostErr)
|
||||
|
||||
mentions, err := th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
require.True(t, pUtils.Contains(mentions, th.BasicUser2.Id), "mentions", mentions)
|
||||
t.Run("Basic channel", func(t *testing.T) {
|
||||
mentions, err := th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
require.True(t, pUtils.Contains(mentions, th.BasicUser2.Id), "mentions", mentions)
|
||||
})
|
||||
|
||||
t.Run("license is required for group mention", func(t *testing.T) {
|
||||
group := th.CreateGroup()
|
||||
@@ -70,7 +72,7 @@ func TestSendNotifications(t *testing.T) {
|
||||
groupMentionPost, createPostErr := th.App.CreatePost(th.Context, groupMentionPost, th.BasicChannel, false, true)
|
||||
require.Nil(t, createPostErr)
|
||||
|
||||
mentions, err = th.App.SendNotifications(th.Context, groupMentionPost, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
|
||||
mentions, err := th.App.SendNotifications(th.Context, groupMentionPost, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
require.Len(t, mentions, 0)
|
||||
@@ -83,40 +85,83 @@ func TestSendNotifications(t *testing.T) {
|
||||
require.Len(t, mentions, 1)
|
||||
})
|
||||
|
||||
dm, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
|
||||
require.Nil(t, appErr)
|
||||
t.Run("message in DM generate mention", func(t *testing.T) {
|
||||
dm, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
post2, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: dm.Id,
|
||||
Message: "dm message",
|
||||
}, true, true)
|
||||
require.Nil(t, appErr)
|
||||
post2, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: dm.Id,
|
||||
Message: "dm message",
|
||||
}, true, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
mentions, err = th.App.SendNotifications(th.Context, post2, th.BasicTeam, dm, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
mentions, err := th.App.SendNotifications(th.Context, post2, th.BasicTeam, dm, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
|
||||
_, appErr = th.App.UpdateActive(th.Context, th.BasicUser2, false)
|
||||
require.Nil(t, appErr)
|
||||
appErr = th.App.Srv().InvalidateAllCaches()
|
||||
require.Nil(t, appErr)
|
||||
_, appErr = th.App.UpdateActive(th.Context, th.BasicUser2, false)
|
||||
require.Nil(t, appErr)
|
||||
appErr = th.App.Srv().InvalidateAllCaches()
|
||||
require.Nil(t, appErr)
|
||||
|
||||
post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: dm.Id,
|
||||
Message: "dm message",
|
||||
}, true, true)
|
||||
require.Nil(t, appErr)
|
||||
post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: dm.Id,
|
||||
Message: "dm message",
|
||||
}, true, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
mentions, err = th.App.SendNotifications(th.Context, post3, th.BasicTeam, dm, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
mentions, err = th.App.SendNotifications(th.Context, post3, th.BasicTeam, dm, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
|
||||
th.BasicChannel.DeleteAt = 1
|
||||
mentions, err = th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, mentions)
|
||||
th.BasicChannel.DeleteAt = 1
|
||||
mentions, err = th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, mentions)
|
||||
})
|
||||
|
||||
t.Run("message in GM generate mention", func(t *testing.T) {
|
||||
users := []*model.User{}
|
||||
for i := 0; i < 2; i++ {
|
||||
user := th.CreateUser()
|
||||
users = append(users, user)
|
||||
}
|
||||
channel := th.CreateGroupChannel(th.Context, users[0], users[1])
|
||||
|
||||
post2, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
|
||||
UserId: users[0].Id,
|
||||
ChannelId: channel.Id,
|
||||
Message: "gm message",
|
||||
}, true, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
mentions, err := th.App.SendNotifications(th.Context, post2, th.BasicTeam, channel, users[0], nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
|
||||
_, appErr = th.App.UpdateActive(th.Context, users[1], false)
|
||||
require.Nil(t, appErr)
|
||||
appErr = th.App.Srv().InvalidateAllCaches()
|
||||
require.Nil(t, appErr)
|
||||
|
||||
post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
|
||||
UserId: users[0].Id,
|
||||
ChannelId: channel.Id,
|
||||
Message: "gm message",
|
||||
}, true, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
mentions, err = th.App.SendNotifications(th.Context, post3, th.BasicTeam, channel, users[0], nil, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mentions)
|
||||
|
||||
th.BasicChannel.DeleteAt = 1
|
||||
mentions, err = th.App.SendNotifications(th.Context, post1, th.BasicTeam, th.BasicChannel, users[0], nil, true)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, mentions)
|
||||
})
|
||||
|
||||
t.Run("replies to post created by OAuth bot should not notify user", func(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
@@ -129,7 +174,7 @@ func TestSendNotifications(t *testing.T) {
|
||||
Props: model.StringInterface{"from_webhook": "true", "override_username": "a bot"},
|
||||
}
|
||||
|
||||
rootPost, appErr = th.App.CreatePostMissingChannel(th.Context, rootPost, false, true)
|
||||
rootPost, appErr := th.App.CreatePostMissingChannel(th.Context, rootPost, false, true)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
childPost := &model.Post{
|
||||
@@ -145,11 +190,12 @@ func TestSendNotifications(t *testing.T) {
|
||||
Order: []string{rootPost.Id, childPost.Id},
|
||||
Posts: map[string]*model.Post{rootPost.Id: rootPost, childPost.Id: childPost},
|
||||
}
|
||||
mentions, err = th.App.SendNotifications(th.Context, childPost, th.BasicTeam, th.BasicChannel, th.BasicUser2, &postList, true)
|
||||
mentions, err := th.App.SendNotifications(th.Context, childPost, th.BasicTeam, th.BasicChannel, th.BasicUser2, &postList, true)
|
||||
require.NoError(t, err)
|
||||
require.False(t, pUtils.Contains(mentions, user.Id))
|
||||
}
|
||||
|
||||
var appErr *model.AppError
|
||||
th.BasicUser.NotifyProps[model.CommentsNotifyProp] = model.CommentsNotifyAny
|
||||
th.BasicUser, appErr = th.App.UpdateUser(th.Context, th.BasicUser, false)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
@@ -179,17 +179,19 @@ func TestPluginAPIGetUserPreferences(t *testing.T) {
|
||||
|
||||
preferences, err := api.GetPreferencesForUser(user1.Id)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 2, len(preferences))
|
||||
assert.Equal(t, 3, len(preferences))
|
||||
|
||||
assert.Equal(t, user1.Id, preferences[0].UserId)
|
||||
assert.Equal(t, model.PreferenceRecommendedNextSteps, preferences[0].Category)
|
||||
assert.Equal(t, "hide", preferences[0].Name)
|
||||
assert.Equal(t, "false", preferences[0].Value)
|
||||
|
||||
assert.Equal(t, user1.Id, preferences[1].UserId)
|
||||
assert.Equal(t, model.PreferenceCategoryTutorialSteps, preferences[1].Category)
|
||||
assert.Equal(t, user1.Id, preferences[1].Name)
|
||||
assert.Equal(t, "0", preferences[1].Value)
|
||||
assert.Equal(t, model.PreferenceCategorySystemNotice, preferences[1].Category)
|
||||
|
||||
assert.Equal(t, user1.Id, preferences[2].UserId)
|
||||
assert.Equal(t, model.PreferenceCategoryTutorialSteps, preferences[2].Category)
|
||||
assert.Equal(t, user1.Id, preferences[2].Name)
|
||||
assert.Equal(t, "0", preferences[2].Value)
|
||||
}
|
||||
|
||||
func TestPluginAPIDeleteUserPreferences(t *testing.T) {
|
||||
@@ -207,7 +209,7 @@ func TestPluginAPIDeleteUserPreferences(t *testing.T) {
|
||||
|
||||
preferences, err := api.GetPreferencesForUser(user1.Id)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 2, len(preferences))
|
||||
assert.Equal(t, 3, len(preferences))
|
||||
|
||||
err = api.DeletePreferencesForUser(user1.Id, preferences)
|
||||
require.Nil(t, err)
|
||||
@@ -234,16 +236,16 @@ func TestPluginAPIDeleteUserPreferences(t *testing.T) {
|
||||
|
||||
preferences, err = api.GetPreferencesForUser(user2.Id)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 3, len(preferences))
|
||||
assert.Equal(t, 4, len(preferences))
|
||||
|
||||
err = api.DeletePreferencesForUser(user2.Id, []model.Preference{preference})
|
||||
require.Nil(t, err)
|
||||
preferences, err = api.GetPreferencesForUser(user2.Id)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 2, len(preferences))
|
||||
assert.Equal(t, 3, len(preferences))
|
||||
assert.ElementsMatch(t,
|
||||
[]string{model.PreferenceRecommendedNextSteps, model.PreferenceCategoryTutorialSteps},
|
||||
[]string{preferences[0].Category, preferences[1].Category},
|
||||
[]string{model.PreferenceRecommendedNextSteps, model.PreferenceCategoryTutorialSteps, model.PreferenceCategorySystemNotice},
|
||||
[]string{preferences[0].Category, preferences[1].Category, preferences[2].Category},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -262,16 +264,17 @@ func TestPluginAPIUpdateUserPreferences(t *testing.T) {
|
||||
|
||||
preferences, err := api.GetPreferencesForUser(user1.Id)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 2, len(preferences))
|
||||
assert.Equal(t, 3, len(preferences))
|
||||
|
||||
assert.Equal(t, user1.Id, preferences[0].UserId)
|
||||
assert.Equal(t, model.PreferenceRecommendedNextSteps, preferences[0].Category)
|
||||
assert.Equal(t, "hide", preferences[0].Name)
|
||||
assert.Equal(t, "false", preferences[0].Value)
|
||||
assert.Equal(t, user1.Id, preferences[1].UserId)
|
||||
assert.Equal(t, model.PreferenceCategoryTutorialSteps, preferences[1].Category)
|
||||
assert.Equal(t, user1.Id, preferences[1].Name)
|
||||
assert.Equal(t, "0", preferences[1].Value)
|
||||
assert.Equal(t, model.PreferenceCategorySystemNotice, preferences[1].Category)
|
||||
assert.Equal(t, user1.Id, preferences[2].UserId)
|
||||
assert.Equal(t, model.PreferenceCategoryTutorialSteps, preferences[2].Category)
|
||||
assert.Equal(t, user1.Id, preferences[2].Name)
|
||||
assert.Equal(t, "0", preferences[2].Value)
|
||||
|
||||
preference := model.Preference{
|
||||
Name: user1.Id,
|
||||
@@ -286,8 +289,8 @@ func TestPluginAPIUpdateUserPreferences(t *testing.T) {
|
||||
preferences, err = api.GetPreferencesForUser(user1.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 3, len(preferences))
|
||||
expectedCategories := []string{model.PreferenceCategoryTutorialSteps, model.PreferenceCategoryTheme, model.PreferenceRecommendedNextSteps}
|
||||
assert.Equal(t, 4, len(preferences))
|
||||
expectedCategories := []string{model.PreferenceCategoryTutorialSteps, model.PreferenceCategoryTheme, model.PreferenceRecommendedNextSteps, model.PreferenceCategorySystemNotice}
|
||||
for _, pref := range preferences {
|
||||
assert.Contains(t, expectedCategories, pref.Category)
|
||||
assert.Equal(t, user1.Id, pref.UserId)
|
||||
|
||||
@@ -275,9 +275,9 @@ func (a *App) channelTeamMapsForPosts(posts []*model.Post) (map[string]*model.Ch
|
||||
|
||||
func (a *App) sendPersistentNotifications(post *model.Post, channel *model.Channel, team *model.Team, mentions *ExplicitMentions, profileMap model.UserMap, channelNotifyProps map[string]map[string]model.StringMap) error {
|
||||
mentionedUsersList := make(model.StringArray, 0, len(mentions.Mentions))
|
||||
for id := range mentions.Mentions {
|
||||
// Don't send notification to post owner
|
||||
if id != post.UserId {
|
||||
for id, v := range mentions.Mentions {
|
||||
// Don't send notification to post owner nor GM mentions
|
||||
if id != post.UserId && v > GMMention {
|
||||
mentionedUsersList = append(mentionedUsersList, id)
|
||||
}
|
||||
}
|
||||
@@ -307,7 +307,8 @@ func (a *App) sendPersistentNotifications(post *model.Post, channel *model.Chann
|
||||
status = &model.Status{UserId: userID, Status: model.StatusOffline, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
|
||||
}
|
||||
|
||||
if ShouldSendPushNotification(profileMap[userID], channelNotifyProps[channel.Id][userID], true, status, post) {
|
||||
isGM := channel.Type == model.ChannelTypeGroup
|
||||
if ShouldSendPushNotification(profileMap[userID], channelNotifyProps[channel.Id][userID], true, status, post, isGM) {
|
||||
a.sendPushNotification(
|
||||
notification,
|
||||
user,
|
||||
|
||||
@@ -282,8 +282,9 @@ func (a *App) createUserOrGuest(c request.CTX, user *model.User, guest bool) (*m
|
||||
|
||||
recommendedNextStepsPref := model.Preference{UserId: ruser.Id, Category: model.PreferenceRecommendedNextSteps, Name: "hide", Value: "false"}
|
||||
tutorialStepPref := model.Preference{UserId: ruser.Id, Category: model.PreferenceCategoryTutorialSteps, Name: ruser.Id, Value: "0"}
|
||||
gmASdmPref := model.Preference{UserId: ruser.Id, Category: model.PreferenceCategorySystemNotice, Name: "GMasDM", Value: "true"}
|
||||
|
||||
preferences := model.Preferences{recommendedNextStepsPref, tutorialStepPref}
|
||||
preferences := model.Preferences{recommendedNextStepsPref, tutorialStepPref, gmASdmPref}
|
||||
if err := a.Srv().Store().Preference().Save(preferences); err != nil {
|
||||
c.Logger().Warn("Encountered error saving user preferences", mlog.Err(err))
|
||||
}
|
||||
|
||||
@@ -1825,6 +1825,11 @@ func TestCreateUserWithInitialPreferences(t *testing.T) {
|
||||
assert.Equal(t, model.PreferenceRecommendedNextSteps, recommendedNextStepsPref[0].Category)
|
||||
assert.Equal(t, "hide", recommendedNextStepsPref[0].Name)
|
||||
assert.Equal(t, "false", recommendedNextStepsPref[0].Value)
|
||||
|
||||
gmASdmNoticeViewedPref, appErr := th.App.GetPreferenceByCategoryAndNameForUser(testUser.Id, model.PreferenceCategorySystemNotice, "GMasDM")
|
||||
require.Nil(t, appErr)
|
||||
assert.Equal(t, "GMasDM", gmASdmNoticeViewedPref.Name)
|
||||
assert.Equal(t, "true", gmASdmNoticeViewedPref.Value)
|
||||
})
|
||||
|
||||
t.Run("successfully create a guest user with initial tutorial and recommended steps preferences", func(t *testing.T) {
|
||||
@@ -1842,6 +1847,11 @@ func TestCreateUserWithInitialPreferences(t *testing.T) {
|
||||
assert.Equal(t, model.PreferenceRecommendedNextSteps, recommendedNextStepsPref[0].Category)
|
||||
assert.Equal(t, "hide", recommendedNextStepsPref[0].Name)
|
||||
assert.Equal(t, "false", recommendedNextStepsPref[0].Value)
|
||||
|
||||
gmASdmNoticeViewedPref, appErr := th.App.GetPreferenceByCategoryAndNameForUser(testUser.Id, model.PreferenceCategorySystemNotice, "GMasDM")
|
||||
require.Nil(t, appErr)
|
||||
assert.Equal(t, "GMasDM", gmASdmNoticeViewedPref.Name)
|
||||
assert.Equal(t, "true", gmASdmNoticeViewedPref.Value)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ const (
|
||||
PreferenceNameUseMilitaryTime = "use_military_time"
|
||||
PreferenceRecommendedNextSteps = "recommended_next_steps"
|
||||
|
||||
PreferenceCategorySystemNotice = "system_notice"
|
||||
|
||||
PreferenceCategoryTheme = "theme"
|
||||
// the name for theme props is the team id
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user