summaryrefslogtreecommitdiffstats
path: root/api/post.go
diff options
context:
space:
mode:
Diffstat (limited to 'api/post.go')
-rw-r--r--api/post.go145
1 files changed, 56 insertions, 89 deletions
diff --git a/api/post.go b/api/post.go
index 498f5b363..5ae5f60db 100644
--- a/api/post.go
+++ b/api/post.go
@@ -35,18 +35,18 @@ const (
func InitPost() {
l4g.Debug(utils.T("api.post.init.debug"))
- BaseRoutes.NeedTeam.Handle("/posts/search", ApiUserRequired(searchPosts)).Methods("POST")
- BaseRoutes.NeedTeam.Handle("/posts/flagged/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequiredActivity(getFlaggedPosts, false)).Methods("GET")
+ BaseRoutes.NeedTeam.Handle("/posts/search", ApiUserRequiredActivity(searchPosts, true)).Methods("POST")
+ BaseRoutes.NeedTeam.Handle("/posts/flagged/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequired(getFlaggedPosts)).Methods("GET")
BaseRoutes.NeedTeam.Handle("/posts/{post_id}", ApiUserRequired(getPostById)).Methods("GET")
BaseRoutes.NeedTeam.Handle("/pltmp/{post_id}", ApiUserRequired(getPermalinkTmp)).Methods("GET")
- BaseRoutes.Posts.Handle("/create", ApiUserRequired(createPost)).Methods("POST")
- BaseRoutes.Posts.Handle("/update", ApiUserRequired(updatePost)).Methods("POST")
- BaseRoutes.Posts.Handle("/page/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequiredActivity(getPosts, false)).Methods("GET")
- BaseRoutes.Posts.Handle("/since/{time:[0-9]+}", ApiUserRequiredActivity(getPostsSince, false)).Methods("GET")
+ BaseRoutes.Posts.Handle("/create", ApiUserRequiredActivity(createPost, true)).Methods("POST")
+ BaseRoutes.Posts.Handle("/update", ApiUserRequiredActivity(updatePost, true)).Methods("POST")
+ BaseRoutes.Posts.Handle("/page/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequired(getPosts)).Methods("GET")
+ BaseRoutes.Posts.Handle("/since/{time:[0-9]+}", ApiUserRequired(getPostsSince)).Methods("GET")
BaseRoutes.NeedPost.Handle("/get", ApiUserRequired(getPost)).Methods("GET")
- BaseRoutes.NeedPost.Handle("/delete", ApiUserRequired(deletePost)).Methods("POST")
+ BaseRoutes.NeedPost.Handle("/delete", ApiUserRequiredActivity(deletePost, true)).Methods("POST")
BaseRoutes.NeedPost.Handle("/before/{offset:[0-9]+}/{num_posts:[0-9]+}", ApiUserRequired(getPostsBefore)).Methods("GET")
BaseRoutes.NeedPost.Handle("/after/{offset:[0-9]+}/{num_posts:[0-9]+}", ApiUserRequired(getPostsAfter)).Methods("GET")
BaseRoutes.NeedPost.Handle("/get_file_infos", ApiUserRequired(getFileInfosForPost)).Methods("GET")
@@ -154,7 +154,7 @@ func CreatePost(c *Context, post *model.Post, triggerWebhooks bool) (*model.Post
}
}
- go handlePostEvents(c, rpost, triggerWebhooks)
+ handlePostEvents(c, rpost, triggerWebhooks)
return rpost, nil
}
@@ -250,7 +250,7 @@ func handlePostEvents(c *Context, post *model.Post, triggerWebhooks bool) {
channel = result.Data.(*model.Channel)
}
- go sendNotifications(c, post, team, channel)
+ sendNotifications(c, post, team, channel)
var user *model.User
if result := <-uchan; result.Err != nil {
@@ -441,40 +441,31 @@ func handleWebhookEvents(c *Context, post *model.Post, team *model.Team, channel
}
}
-// Given a map of user IDs to profiles and a map of user IDs of channel members, returns a list of mention
-// keywords for all users on the team. Users that are members of the channel will have all their mention
-// keywords returned while users that aren't in the channel will only have their @mentions returned.
-func getMentionKeywords(profiles map[string]*model.User, members map[string]string) map[string][]string {
+// Given a map of user IDs to profiles, returns a list of mention
+// keywords for all users in the channel.
+func getMentionKeywordsInChannel(profiles map[string]*model.User) map[string][]string {
keywords := make(map[string][]string)
for id, profile := range profiles {
- _, inChannel := members[id]
-
- if inChannel {
- if len(profile.NotifyProps["mention_keys"]) > 0 {
- // Add all the user's mention keys
- splitKeys := strings.Split(profile.NotifyProps["mention_keys"], ",")
- for _, k := range splitKeys {
- // note that these are made lower case so that we can do a case insensitive check for them
- key := strings.ToLower(k)
- keywords[key] = append(keywords[key], id)
- }
+ if len(profile.NotifyProps["mention_keys"]) > 0 {
+ // Add all the user's mention keys
+ splitKeys := strings.Split(profile.NotifyProps["mention_keys"], ",")
+ for _, k := range splitKeys {
+ // note that these are made lower case so that we can do a case insensitive check for them
+ key := strings.ToLower(k)
+ keywords[key] = append(keywords[key], id)
}
+ }
- // If turned on, add the user's case sensitive first name
- if profile.NotifyProps["first_name"] == "true" {
- keywords[profile.FirstName] = append(keywords[profile.FirstName], profile.Id)
- }
+ // If turned on, add the user's case sensitive first name
+ if profile.NotifyProps["first_name"] == "true" {
+ keywords[profile.FirstName] = append(keywords[profile.FirstName], profile.Id)
+ }
- // Add @channel and @all to keywords if user has them turned on
- if profile.NotifyProps["channel"] == "true" {
- keywords["@channel"] = append(keywords["@channel"], profile.Id)
- keywords["@all"] = append(keywords["@all"], profile.Id)
- }
- } else {
- // user isn't in channel, so just look for @mentions
- key := "@" + strings.ToLower(profile.Username)
- keywords[key] = append(keywords[key], id)
+ // Add @channel and @all to keywords if user has them turned on
+ if profile.NotifyProps["channel"] == "true" {
+ keywords["@channel"] = append(keywords["@channel"], profile.Id)
+ keywords["@all"] = append(keywords["@all"], profile.Id)
}
}
@@ -482,9 +473,11 @@ func getMentionKeywords(profiles map[string]*model.User, members map[string]stri
}
// Given a message and a map mapping mention keywords to the users who use them, returns a map of mentioned
-// users and whether or not @here was mentioned.
-func getExplicitMentions(message string, keywords map[string][]string) (map[string]bool, bool) {
+// users and a slice of potencial mention users not in the channel and whether or not @here was mentioned.
+func getExplicitMentions(message string, keywords map[string][]string) (map[string]bool, []string, bool) {
mentioned := make(map[string]bool)
+ potentialOthersMentioned := make([]string, 0)
+ systemMentions := map[string]bool{"@here": true, "@channel": true, "@all": true}
hereMentioned := false
addMentionedUsers := func(ids []string) {
@@ -510,6 +503,9 @@ func getExplicitMentions(message string, keywords map[string][]string) (map[stri
if ids, match := keywords[word]; match {
addMentionedUsers(ids)
isMention = true
+ } else if _, ok := systemMentions[word]; !ok && strings.HasPrefix(word, "@") {
+ potentialOthersMentioned = append(potentialOthersMentioned, word[1:])
+ continue
}
if !isMention {
@@ -532,19 +528,19 @@ func getExplicitMentions(message string, keywords map[string][]string) (map[stri
// Case-sensitive check for first name
if ids, match := keywords[splitWord]; match {
addMentionedUsers(ids)
+ } else if _, ok := systemMentions[word]; !ok && strings.HasPrefix(word, "@") {
+ username := word[1:len(splitWord)]
+ potentialOthersMentioned = append(potentialOthersMentioned, username)
}
}
}
}
- return mentioned, hereMentioned
+ return mentioned, potentialOthersMentioned, hereMentioned
}
func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *model.Channel) {
- // get profiles for all users we could be mentioning
- pchan := Srv.Store.User().GetProfiles(c.TeamId)
- dpchan := Srv.Store.User().GetDirectProfiles(c.Session.UserId)
- mchan := Srv.Store.Channel().GetMembers(post.ChannelId)
+ pchan := Srv.Store.User().GetProfilesInChannel(channel.Id, -1, -1, true)
fchan := Srv.Store.FileInfo().GetForPost(post.Id)
var profileMap map[string]*model.User
@@ -555,30 +551,11 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
profileMap = result.Data.(map[string]*model.User)
}
- if result := <-dpchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.profiles.error"), c.TeamId, result.Err)
- return
- } else {
- dps := result.Data.(map[string]*model.User)
- for k, v := range dps {
- profileMap[k] = v
- }
- }
-
+ // If the user who made the post is mention don't send a notification
if _, ok := profileMap[post.UserId]; !ok {
l4g.Error(utils.T("api.post.send_notifications_and_forget.user_id.error"), post.UserId)
return
}
- // using a map as a pseudo-set since we're checking for containment a lot
- members := make(map[string]string)
- if result := <-mchan; result.Err != nil {
- l4g.Error(utils.T("api.post.handle_post_events_and_forget.members.error"), post.ChannelId, result.Err)
- return
- } else {
- for _, member := range result.Data.([]model.ChannelMember) {
- members[member.UserId] = member.UserId
- }
- }
mentionedUserIds := make(map[string]bool)
allActivityPushUserIds := []string{}
@@ -595,11 +572,11 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
mentionedUserIds[otherUserId] = true
} else {
- keywords := getMentionKeywords(profileMap, members)
+ keywords := getMentionKeywordsInChannel(profileMap)
- // get users that are explicitly mentioned
var mentioned map[string]bool
- mentioned, hereNotification = getExplicitMentions(post.Message, keywords)
+ var potentialOtherMentions []string
+ mentioned, potentialOtherMentions, hereNotification = getExplicitMentions(post.Message, keywords)
// get users that have comment thread mentions enabled
if len(post.RootId) > 0 {
@@ -623,25 +600,15 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
delete(mentioned, post.UserId)
}
- outOfChannelMentions := make(map[string]bool)
- for id := range mentioned {
- if _, inChannel := members[id]; inChannel {
- mentionedUserIds[id] = true
- } else {
- outOfChannelMentions[id] = true
+ if len(potentialOtherMentions) > 0 {
+ if result := <-Srv.Store.User().GetProfilesByUsernames(potentialOtherMentions, team.Id); result.Err == nil {
+ outOfChannelMentions := result.Data.(map[string]*model.User)
+ go sendOutOfChannelMentions(c, post, outOfChannelMentions)
}
}
- go sendOutOfChannelMentions(c, post, profileMap, outOfChannelMentions)
-
// find which users in the channel are set up to always receive mobile notifications
- for id := range members {
- profile := profileMap[id]
- if profile == nil {
- l4g.Warn(utils.T("api.post.notification.member_profile.warn"), id)
- continue
- }
-
+ for _, profile := range profileMap {
if profile.NotifyProps["push"] == model.USER_NOTIFY_ALL &&
(post.UserId != profile.Id || post.Props["from_webhook"] == "true") &&
!post.IsSystemMessage() {
@@ -699,10 +666,9 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
}
_, profileFound := profileMap[status.UserId]
- _, isChannelMember := members[status.UserId]
_, alreadyMentioned := mentionedUserIds[status.UserId]
- if status.Status == model.STATUS_ONLINE && profileFound && isChannelMember && !alreadyMentioned {
+ if status.Status == model.STATUS_ONLINE && profileFound && !alreadyMentioned {
mentionedUsersList = append(mentionedUsersList, status.UserId)
updateMentionChans = append(updateMentionChans, Srv.Store.Channel().IncrementMentionCount(post.ChannelId, status.UserId))
}
@@ -787,7 +753,8 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
message.Add("mentions", model.ArrayToJson(mentionedUsersList))
}
- go Publish(message)
+ Publish(message)
+ return
}
func sendNotificationEmail(c *Context, post *model.Post, user *model.User, channel *model.Channel, team *model.Team, senderName string, sender *model.User) {
@@ -1045,14 +1012,14 @@ func getMobileAppSession(userId string) *model.Session {
return nil
}
-func sendOutOfChannelMentions(c *Context, post *model.Post, profiles map[string]*model.User, outOfChannelMentions map[string]bool) {
- if len(outOfChannelMentions) == 0 {
+func sendOutOfChannelMentions(c *Context, post *model.Post, profiles map[string]*model.User) {
+ if len(profiles) == 0 {
return
}
var usernames []string
- for id := range outOfChannelMentions {
- usernames = append(usernames, profiles[id].Username)
+ for _, user := range profiles {
+ usernames = append(usernames, user.Username)
}
sort.Strings(usernames)