MM-17071 Add mention counting when marking a post as unread (#11966)
* Add different types for different mentions * Remove redundant THREAD_ANY and THREAD_ROOT constants * Make PostStore.Get return thread in order * MM-17071 Add initial version of countMentionsFromPost * MM-17071 Refactor comment mention counting * MM-17071 Use mention counting when marking post as unread * Fix shadowing in tests * Remove repeated check of user count * Refactor code using MentionType * Update comments around -1 return value * Move inner functions out of countMentionsFromPost * Remove preconditions check as separate test case * Update comments * Add User.GetMentionKeys * Revert "Make PostStore.Get return thread in order" This reverts commit 22aa010cee359655fe75e1dc899cf0ffb0943c2a. * Fix tests * Fix merge conflict * Add store.MentionAllPosts
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
5f28ce9de0
Коммит
e6f67c664c
134
app/post.go
134
app/post.go
@@ -1178,3 +1178,137 @@ func (a *App) MaxPostSize() int {
|
||||
|
||||
return maxPostSize
|
||||
}
|
||||
|
||||
// countMentionsFromPost returns the number of posts in the post's channel that mention the user after and including the
|
||||
// given post. Returns the number of mentions or store.MentionAllPosts if the post is in a direct message channel.
|
||||
func (a *App) countMentionsFromPost(user *model.User, post *model.Post) (int, *model.AppError) {
|
||||
channel, err := a.GetChannel(post.ChannelId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if channel.Type == model.CHANNEL_DIRECT {
|
||||
return store.MentionAllPosts, nil
|
||||
}
|
||||
|
||||
channelMember, err := a.GetChannelMember(channel.Id, user.Id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
keywords := addMentionKeywordsForUser(
|
||||
map[string][]string{},
|
||||
user,
|
||||
channelMember.NotifyProps,
|
||||
&model.Status{Status: model.STATUS_ONLINE}, // Assume the user is online since they would've triggered this
|
||||
true, // Assume channel mentions are always allowed for simplicity
|
||||
)
|
||||
commentMentions := user.NotifyProps[model.COMMENTS_NOTIFY_PROP]
|
||||
checkForCommentMentions := commentMentions == model.COMMENTS_NOTIFY_ROOT || commentMentions == model.COMMENTS_NOTIFY_ANY
|
||||
|
||||
// A mapping of thread root IDs to whether or not a post in that thread mentions the user
|
||||
mentionedByThread := make(map[string]bool)
|
||||
|
||||
thread, err := a.GetPostThread(post.Id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
count := 0
|
||||
|
||||
if isPostMention(user, post, keywords, thread.Posts, mentionedByThread, checkForCommentMentions) {
|
||||
count += 1
|
||||
}
|
||||
|
||||
page := 0
|
||||
perPage := 200
|
||||
for {
|
||||
postList, err := a.GetPostsAfterPost(model.GetPostsOptions{
|
||||
ChannelId: post.ChannelId,
|
||||
PostId: post.Id,
|
||||
Page: page,
|
||||
PerPage: perPage,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for _, postId := range postList.Order {
|
||||
if isPostMention(user, postList.Posts[postId], keywords, postList.Posts, mentionedByThread, checkForCommentMentions) {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
|
||||
if len(postList.Order) < perPage {
|
||||
break
|
||||
}
|
||||
|
||||
page += 1
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func isCommentMention(user *model.User, post *model.Post, otherPosts map[string]*model.Post, mentionedByThread map[string]bool) bool {
|
||||
if post.RootId == "" {
|
||||
// Not a comment
|
||||
return false
|
||||
}
|
||||
|
||||
if mentioned, ok := mentionedByThread[post.RootId]; ok {
|
||||
// We've already figured out if the user was mentioned by this thread
|
||||
return mentioned
|
||||
}
|
||||
|
||||
// Whether or not the user was mentioned because they started the thread
|
||||
mentioned := otherPosts[post.RootId].UserId == user.Id
|
||||
|
||||
// Or because they commented on it before this post
|
||||
if !mentioned && user.NotifyProps[model.COMMENTS_NOTIFY_PROP] == model.COMMENTS_NOTIFY_ANY {
|
||||
for _, otherPost := range otherPosts {
|
||||
if otherPost.Id == post.Id {
|
||||
continue
|
||||
}
|
||||
|
||||
if otherPost.RootId != post.RootId {
|
||||
continue
|
||||
}
|
||||
|
||||
if otherPost.UserId == user.Id && otherPost.CreateAt < post.CreateAt {
|
||||
// Found a comment made by the user from before this post
|
||||
mentioned = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mentionedByThread[post.RootId] = mentioned
|
||||
return mentioned
|
||||
}
|
||||
|
||||
func isPostMention(user *model.User, post *model.Post, keywords map[string][]string, otherPosts map[string]*model.Post, mentionedByThread map[string]bool, checkForCommentMentions bool) bool {
|
||||
// Prevent the user from mentioning themselves
|
||||
if post.UserId == user.Id && post.Props["from_webhook"] != "true" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check for keyword mentions
|
||||
mentions := getExplicitMentions(post, keywords)
|
||||
if _, ok := mentions.Mentions[user.Id]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check for mentions caused by being added to the channel
|
||||
if post.Type == model.POST_ADD_TO_CHANNEL {
|
||||
if addedUserId, ok := post.Props[model.POST_PROPS_ADDED_USER_ID].(string); ok && addedUserId == user.Id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Check for comment mentions
|
||||
if checkForCommentMentions && isCommentMention(user, post, otherPosts, mentionedByThread) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user