summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2016-08-31 12:52:14 -0400
committerGitHub <noreply@github.com>2016-08-31 12:52:14 -0400
commit26f96b240ddc8cf8c56decea72102b10238e0a43 (patch)
tree7eda509038de3d6b95a02b95bee2ad72e2e3a063 /api
parentb0b39ce71cd77fbffbf23d56b20db1927f0c6cb1 (diff)
downloadchat-26f96b240ddc8cf8c56decea72102b10238e0a43.tar.gz
chat-26f96b240ddc8cf8c56decea72102b10238e0a43.tar.bz2
chat-26f96b240ddc8cf8c56decea72102b10238e0a43.zip
PLT-3462 Add the ability to clear push notifications after channel is viewed (#3834)
* Add the ability to clear push notifications after channel is viewed * Fix race condition between updating the mention count and reading it when sending push notifications
Diffstat (limited to 'api')
-rw-r--r--api/channel.go16
-rw-r--r--api/post.go162
2 files changed, 113 insertions, 65 deletions
diff --git a/api/channel.go b/api/channel.go
index faa39e13c..e2c67f18b 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -846,8 +846,24 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
+ doClearPush := false
+ if *utils.Cfg.EmailSettings.SendPushNotifications && !c.Session.IsMobileApp() {
+ if result := <-Srv.Store.User().GetUnreadCountForChannel(c.Session.UserId, id); result.Err != nil {
+ l4g.Error(utils.T("api.channel.update_last_viewed_at.get_unread_count_for_channel.error"), c.Session.UserId, id, result.Err.Error())
+ } else {
+ if result.Data.(int64) > 0 {
+ doClearPush = true
+ }
+ }
+ }
+
Srv.Store.Channel().UpdateLastViewedAt(id, c.Session.UserId)
+ // Must be after update so that unread count is correct
+ if doClearPush {
+ go clearPushNotification(c.Session.UserId, id)
+ }
+
preference := model.Preference{
UserId: c.Session.UserId,
Category: model.PREFERENCE_CATEGORY_LAST,
diff --git a/api/post.go b/api/post.go
index 8639938e2..bfd22084b 100644
--- a/api/post.go
+++ b/api/post.go
@@ -711,6 +711,15 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
}
}
+ // Make sure all mention updates are complete to prevent race
+ // Probably better to batch these DB updates in the future
+ // MUST be completed before push notifications send
+ for _, uchan := range updateMentionChans {
+ if result := <-uchan; result.Err != nil {
+ l4g.Warn(utils.T("api.post.update_mention_count_and_forget.update_error"), post.Id, post.ChannelId, result.Err)
+ }
+ }
+
sendPushNotifications := false
if *utils.Cfg.EmailSettings.SendPushNotifications {
pushServer := *utils.Cfg.EmailSettings.PushNotificationServer
@@ -773,14 +782,6 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
message.Add("mentions", model.ArrayToJson(mentionedUsersList))
}
- // Make sure all mention updates are complete to prevent race
- // Probably better to batch these DB updates in the future
- for _, uchan := range updateMentionChans {
- if result := <-uchan; result.Err != nil {
- l4g.Warn(utils.T("api.post.update_mention_count_and_forget.update_error"), post.Id, post.ChannelId, result.Err)
- }
- }
-
go Publish(message)
}
@@ -888,12 +889,10 @@ func getMessageForNotification(post *model.Post, translateFunc i18n.TranslateFun
}
func sendPushNotification(post *model.Post, user *model.User, channel *model.Channel, senderName string, wasMentioned bool) {
- var sessions []*model.Session
- if result := <-Srv.Store.Session().GetSessions(user.Id); result.Err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.sessions.error"), user.Id, result.Err)
+ session := getMobileAppSession(user.Id)
+
+ if session == nil {
return
- } else {
- sessions = result.Data.([]*model.Session)
}
var channelName string
@@ -906,65 +905,98 @@ func sendPushNotification(post *model.Post, user *model.User, channel *model.Cha
userLocale := utils.GetUserTranslations(user.Locale)
- for _, session := range sessions {
- if len(session.DeviceId) > 0 &&
- (strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") || strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")) {
+ msg := model.PushNotification{}
+ if badge := <-Srv.Store.User().GetUnreadCount(user.Id); badge.Err != nil {
+ msg.Badge = 1
+ l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), user.Id, badge.Err)
+ } else {
+ msg.Badge = int(badge.Data.(int64))
+ }
+ msg.Type = model.PUSH_TYPE_MESSAGE
+ msg.ChannelId = channel.Id
+ msg.ChannelName = channel.Name
- msg := model.PushNotification{}
- if badge := <-Srv.Store.User().GetUnreadCount(user.Id); badge.Err != nil {
- msg.Badge = 1
- l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), user.Id, badge.Err)
- } else {
- msg.Badge = int(badge.Data.(int64))
- }
- msg.ServerId = utils.CfgDiagnosticId
- msg.ChannelId = channel.Id
- msg.ChannelName = channel.Name
-
- if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") {
- msg.Platform = model.PUSH_NOTIFY_APPLE
- msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":")
- } else if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":") {
- msg.Platform = model.PUSH_NOTIFY_ANDROID
- msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")
- }
+ msg.SetDeviceIdAndPlatform(session.DeviceId)
- if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
- if channel.Type == model.CHANNEL_DIRECT {
- msg.Category = model.CATEGORY_DM
- msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
- } else {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(post.Message)
- }
- } else {
- if channel.Type == model.CHANNEL_DIRECT {
- msg.Category = model.CATEGORY_DM
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
- } else if wasMentioned {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
- } else {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName
- }
- }
+ if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
+ if channel.Type == model.CHANNEL_DIRECT {
+ msg.Category = model.CATEGORY_DM
+ msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
+ } else {
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(post.Message)
+ }
+ } else {
+ if channel.Type == model.CHANNEL_DIRECT {
+ msg.Category = model.CATEGORY_DM
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
+ } else if wasMentioned {
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
+ } else {
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName
+ }
+ }
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
- }
- httpClient := &http.Client{Transport: tr}
- request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
+ l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
+ sendToPushProxy(msg)
+}
- l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
- if resp, err := httpClient.Do(request); err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), user.Id, err)
- } else {
- ioutil.ReadAll(resp.Body)
- resp.Body.Close()
- }
+func clearPushNotification(userId string, channelId string) {
+ session := getMobileAppSession(userId)
+
+ if session == nil {
+ return
+ }
+
+ msg := model.PushNotification{}
+ msg.Type = model.PUSH_TYPE_CLEAR
+ msg.ChannelId = channelId
+ msg.ContentAvailable = 0
+ if badge := <-Srv.Store.User().GetUnreadCount(userId); badge.Err != nil {
+ msg.Badge = 0
+ l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), userId, badge.Err)
+ } else {
+ msg.Badge = int(badge.Data.(int64))
+ }
+
+ msg.SetDeviceIdAndPlatform(session.DeviceId)
- // notification sent, don't need to check other sessions
- break
+ l4g.Debug(utils.T("api.post.send_notifications_and_forget.clear_push_notification.debug"), msg.DeviceId, msg.ChannelId)
+ sendToPushProxy(msg)
+}
+
+func sendToPushProxy(msg model.PushNotification) {
+ msg.ServerId = utils.CfgDiagnosticId
+
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
+ }
+ httpClient := &http.Client{Transport: tr}
+ request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
+
+ if resp, err := httpClient.Do(request); err != nil {
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), msg.DeviceId, err)
+ } else {
+ ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ }
+}
+
+func getMobileAppSession(userId string) *model.Session {
+ var sessions []*model.Session
+ if result := <-Srv.Store.Session().GetSessions(userId); result.Err != nil {
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.sessions.error"), userId, result.Err)
+ return nil
+ } else {
+ sessions = result.Data.([]*model.Session)
+ }
+
+ for _, session := range sessions {
+ if session.IsMobileApp() {
+ return session
}
}
+
+ return nil
}
func sendOutOfChannelMentions(c *Context, post *model.Post, profiles map[string]*model.User, outOfChannelMentions map[string]bool) {