MM-53924 - Implement push notifications plugin hook and plugin api method (#24350)
* Revert "MM-52804 - Implement SendPushNotification plugin api method (#24273)" This reverts commit8418eefb75. * Revert "MM-53924 - Implement NotificationWillBePushed plugin hook (#24263)" This reverts commitf13a531bca. * implement NotificationWillBePushed plugin hook * implement SendPushNotification plugin api method * move where we're setting post and channel type * fix comment --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
dad579daee
Коммит
69c11cfe14
@@ -81,6 +81,25 @@ func (a *App) sendPushNotificationSync(c request.CTX, post *model.Post, user *mo
|
||||
}
|
||||
|
||||
func (a *App) sendPushNotificationToAllSessions(msg *model.PushNotification, userID string, skipSessionId string) *model.AppError {
|
||||
rejectionReason := ""
|
||||
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||
var replacementNotification *model.PushNotification
|
||||
replacementNotification, rejectionReason = hooks.NotificationWillBePushed(msg, userID)
|
||||
if rejectionReason != "" {
|
||||
mlog.Info("Notification cancelled by plugin.", mlog.String("rejection reason", rejectionReason))
|
||||
return false
|
||||
}
|
||||
if replacementNotification != nil {
|
||||
msg = replacementNotification
|
||||
}
|
||||
return true
|
||||
}, plugin.NotificationWillBePushedID)
|
||||
|
||||
if rejectionReason != "" {
|
||||
// Notifications rejected by a plugin should not be considered errors
|
||||
return nil
|
||||
}
|
||||
|
||||
sessions, err := a.getMobileAppSessions(userID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -140,27 +159,6 @@ func (a *App) sendPushNotificationToAllSessions(msg *model.PushNotification, use
|
||||
}
|
||||
|
||||
func (a *App) sendPushNotification(notification *PostNotification, user *model.User, explicitMention, channelWideMention bool, replyToThreadType string) {
|
||||
cancelled := false
|
||||
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||
cancelled = hooks.NotificationWillBePushed(&model.PluginPushNotification{
|
||||
Post: notification.Post.ForPlugin(),
|
||||
Channel: notification.Channel,
|
||||
UserID: user.Id,
|
||||
ExplicitMention: explicitMention,
|
||||
ChannelWideMention: channelWideMention,
|
||||
ReplyToThreadType: replyToThreadType,
|
||||
})
|
||||
if cancelled {
|
||||
mlog.Info("Notification cancelled by plugin")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, plugin.NotificationWillBePushedID)
|
||||
|
||||
if cancelled {
|
||||
return
|
||||
}
|
||||
|
||||
cfg := a.Config()
|
||||
channel := notification.Channel
|
||||
post := notification.Post
|
||||
@@ -606,6 +604,10 @@ func (a *App) BuildPushNotificationMessage(c request.CTX, contentsConfig string,
|
||||
|
||||
msg.Badge = badgeCount
|
||||
|
||||
// Add post and channel types for plugins to use in the NotificationWillBePushed hook
|
||||
msg.PostType = post.Type
|
||||
msg.ChannelType = channel.Type
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1468,6 +1468,7 @@ func TestPushNotificationRace(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
s.products["channels"] = ch
|
||||
|
||||
app := New(ServerConnector(s.Channels()))
|
||||
require.NotPanics(t, func() {
|
||||
s.createPushNotificationsHub(th.Context)
|
||||
|
||||
@@ -1475,9 +1476,9 @@ func TestPushNotificationRace(t *testing.T) {
|
||||
|
||||
// Now we start sending messages after the PN hub is shut down.
|
||||
// We test all 3 notification types.
|
||||
th.App.clearPushNotification("currentSessionId", "userId", "channelId", "")
|
||||
app.clearPushNotification("currentSessionId", "userId", "channelId", "")
|
||||
|
||||
th.App.UpdateMobileAppBadge("userId")
|
||||
app.UpdateMobileAppBadge("userId")
|
||||
|
||||
notification := &PostNotification{
|
||||
Post: &model.Post{},
|
||||
@@ -1487,7 +1488,7 @@ func TestPushNotificationRace(t *testing.T) {
|
||||
},
|
||||
Sender: &model.User{},
|
||||
}
|
||||
th.App.sendPushNotification(notification, &model.User{}, true, false, model.CommentsNotifyAny)
|
||||
app.sendPushNotification(notification, &model.User{}, true, false, model.CommentsNotifyAny)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1267,30 +1267,7 @@ func (api *PluginAPI) GetUploadSession(uploadID string) (*model.UploadSession, e
|
||||
return fi, nil
|
||||
}
|
||||
|
||||
func (api *PluginAPI) SendPluginPushNotification(notification *model.PluginPushNotification) error {
|
||||
var profiles map[string]*model.User
|
||||
var err error
|
||||
if notification.Channel.Type == model.ChannelTypeGroup {
|
||||
if profiles, err = api.app.Srv().Store().User().GetAllProfilesInChannel(api.ctx.Context(), notification.Channel.Id, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
sender, appErr := api.app.GetUser(notification.Post.UserId)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
user, appErr := api.app.GetUser(notification.UserID)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
postNotification := &PostNotification{
|
||||
Post: notification.Post,
|
||||
Channel: notification.Channel,
|
||||
ProfileMap: profiles,
|
||||
Sender: sender,
|
||||
}
|
||||
api.app.sendPushNotification(postNotification, user, notification.ExplicitMention, notification.ChannelWideMention, notification.ReplyToThreadType)
|
||||
return nil
|
||||
func (api *PluginAPI) SendPushNotification(notification *model.PushNotification, userID string) *model.AppError {
|
||||
// Ignoring skipSessionId because it's only used internally to clear push notifications
|
||||
return api.app.sendPushNotificationToAllSessions(notification, userID, "")
|
||||
}
|
||||
|
||||
@@ -2266,13 +2266,22 @@ func TestSendPushNotification(t *testing.T) {
|
||||
defer wg.Done()
|
||||
post := th.CreatePost(th.BasicChannel)
|
||||
post.Message = "started a conversation"
|
||||
notification := &model.PluginPushNotification{
|
||||
Post: post,
|
||||
Channel: th.BasicChannel,
|
||||
UserID: user.Id,
|
||||
notification := &model.PushNotification{
|
||||
Category: model.CategoryCanReply,
|
||||
Version: model.PushMessageV2,
|
||||
Type: model.PushTypeMessage,
|
||||
TeamId: th.BasicChannel.TeamId,
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
PostId: post.Id,
|
||||
RootId: post.RootId,
|
||||
SenderId: post.UserId,
|
||||
SenderName: "Sender Name",
|
||||
PostType: post.Type,
|
||||
ChannelType: th.BasicChannel.Type,
|
||||
Message: "Custom message",
|
||||
}
|
||||
appErr := api.SendPluginPushNotification(notification)
|
||||
require.NoError(t, appErr)
|
||||
appErr := api.SendPushNotification(notification, user.Id)
|
||||
require.Nil(t, appErr)
|
||||
}(*data.user)
|
||||
}
|
||||
wg.Wait()
|
||||
@@ -2286,7 +2295,7 @@ func TestSendPushNotification(t *testing.T) {
|
||||
case model.PushTypeMessage:
|
||||
numMessages++
|
||||
assert.Equal(t, th.BasicChannel.Id, n.ChannelId)
|
||||
assert.Equal(t, fmt.Sprintf("@%s: started a conversation", th.BasicUser.GetDisplayName(model.ShowUsername)), n.Message)
|
||||
assert.Equal(t, "Custom message", n.Message)
|
||||
default:
|
||||
assert.Fail(t, "should not receive any other push notification types")
|
||||
}
|
||||
|
||||
@@ -1344,20 +1344,28 @@ func TestHookNotificationWillBePushed(t *testing.T) {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
testCode string
|
||||
expectedNotifications int
|
||||
name string
|
||||
testCode string
|
||||
expectedNotifications int
|
||||
expectedNotificationMessage string
|
||||
}{
|
||||
{
|
||||
name: "successfully pushed",
|
||||
testCode: `return false`,
|
||||
testCode: `return nil, ""`,
|
||||
expectedNotifications: 6,
|
||||
},
|
||||
{
|
||||
name: "push notification rejected",
|
||||
testCode: `return true`,
|
||||
testCode: `return nil, "rejected"`,
|
||||
expectedNotifications: 0,
|
||||
},
|
||||
{
|
||||
name: "push notification modified",
|
||||
testCode: `notification.Message = "brand new message"
|
||||
return notification, ""`,
|
||||
expectedNotifications: 6,
|
||||
expectedNotificationMessage: "brand new message",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -1440,7 +1448,11 @@ func TestHookNotificationWillBePushed(t *testing.T) {
|
||||
case model.PushTypeMessage:
|
||||
numMessages++
|
||||
assert.Equal(t, th.BasicChannel.Id, n.ChannelId)
|
||||
assert.Contains(t, n.Message, "mentioned you")
|
||||
if tt.expectedNotificationMessage != "" {
|
||||
assert.Equal(t, tt.expectedNotificationMessage, n.Message)
|
||||
} else {
|
||||
assert.Contains(t, n.Message, "mentioned you")
|
||||
}
|
||||
default:
|
||||
assert.Fail(t, "should not receive any other push notification types")
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost/server/public/plugin"
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/public/plugin"
|
||||
)
|
||||
|
||||
type MyPlugin struct {
|
||||
plugin.MattermostPlugin
|
||||
}
|
||||
|
||||
func (p *MyPlugin) NotificationWillBePushed(notification *model.PluginPushNotification) (cancel bool) {
|
||||
func (p *MyPlugin) NotificationWillBePushed(notification *model.PushNotification, userID string) (*model.PushNotification, string) {
|
||||
%s
|
||||
}
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user