GH-15624: Added plugin hooks for ReationHasBeenAdded and ReactionHasBeenRemoved (#15765)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
71c371509b
Коммит
3515b4d6c9
@@ -1131,3 +1131,89 @@ func TestHookMetrics(t *testing.T) {
|
|||||||
metricsMock.AssertExpectations(t)
|
metricsMock.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHookReactionHasBeenAdded(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
var mockAPI plugintest.API
|
||||||
|
mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil)
|
||||||
|
mockAPI.On("LogDebug", "smile").Return(nil)
|
||||||
|
|
||||||
|
tearDown, _, _ := SetAppEnvironmentWithPlugins(t,
|
||||||
|
[]string{
|
||||||
|
`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mattermost/mattermost-server/v5/plugin"
|
||||||
|
"github.com/mattermost/mattermost-server/v5/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MyPlugin struct {
|
||||||
|
plugin.MattermostPlugin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MyPlugin) ReactionHasBeenAdded(c *plugin.Context, reaction *model.Reaction) {
|
||||||
|
p.API.LogDebug(reaction.EmojiName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
plugin.ClientMain(&MyPlugin{})
|
||||||
|
}
|
||||||
|
`}, th.App, func(*model.Manifest) plugin.API { return &mockAPI })
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
reaction := &model.Reaction{
|
||||||
|
UserId: th.BasicUser.Id,
|
||||||
|
PostId: th.BasicPost.Id,
|
||||||
|
EmojiName: "smile",
|
||||||
|
CreateAt: model.GetMillis() - 10000,
|
||||||
|
}
|
||||||
|
_, err := th.App.SaveReactionForPost(reaction)
|
||||||
|
require.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHookReactionHasBeenRemoved(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
var mockAPI plugintest.API
|
||||||
|
mockAPI.On("LoadPluginConfiguration", mock.Anything).Return(nil)
|
||||||
|
mockAPI.On("LogDebug", "star").Return(nil)
|
||||||
|
|
||||||
|
tearDown, _, _ := SetAppEnvironmentWithPlugins(t,
|
||||||
|
[]string{
|
||||||
|
`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mattermost/mattermost-server/v5/plugin"
|
||||||
|
"github.com/mattermost/mattermost-server/v5/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MyPlugin struct {
|
||||||
|
plugin.MattermostPlugin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MyPlugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.Reaction) {
|
||||||
|
p.API.LogDebug(reaction.EmojiName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
plugin.ClientMain(&MyPlugin{})
|
||||||
|
}
|
||||||
|
`}, th.App, func(*model.Manifest) plugin.API { return &mockAPI })
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
reaction := &model.Reaction{
|
||||||
|
UserId: th.BasicUser.Id,
|
||||||
|
PostId: th.BasicPost.Id,
|
||||||
|
EmojiName: "star",
|
||||||
|
CreateAt: model.GetMillis() - 10000,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := th.App.DeleteReactionForPost(reaction)
|
||||||
|
|
||||||
|
require.Nil(t, err)
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/v5/model"
|
"github.com/mattermost/mattermost-server/v5/model"
|
||||||
|
"github.com/mattermost/mattermost-server/v5/plugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) SaveReactionForPost(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
func (a *App) SaveReactionForPost(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
||||||
@@ -51,6 +52,16 @@ func (a *App) SaveReactionForPost(reaction *model.Reaction) (*model.Reaction, *m
|
|||||||
// The post is always modified since the UpdateAt always changes
|
// The post is always modified since the UpdateAt always changes
|
||||||
a.invalidateCacheForChannelPosts(post.ChannelId)
|
a.invalidateCacheForChannelPosts(post.ChannelId)
|
||||||
|
|
||||||
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
|
a.Srv().Go(func() {
|
||||||
|
pluginContext := a.PluginContext()
|
||||||
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
|
hooks.ReactionHasBeenAdded(pluginContext, reaction)
|
||||||
|
return true
|
||||||
|
}, plugin.ReactionHasBeenAddedId)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_ADDED, reaction, post, true)
|
a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_ADDED, reaction, post, true)
|
||||||
})
|
})
|
||||||
@@ -132,6 +143,16 @@ func (a *App) DeleteReactionForPost(reaction *model.Reaction) *model.AppError {
|
|||||||
// The post is always modified since the UpdateAt always changes
|
// The post is always modified since the UpdateAt always changes
|
||||||
a.invalidateCacheForChannelPosts(post.ChannelId)
|
a.invalidateCacheForChannelPosts(post.ChannelId)
|
||||||
|
|
||||||
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
|
a.Srv().Go(func() {
|
||||||
|
pluginContext := a.PluginContext()
|
||||||
|
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
|
hooks.ReactionHasBeenRemoved(pluginContext, reaction)
|
||||||
|
return true
|
||||||
|
}, plugin.ReactionHasBeenRemovedId)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_REMOVED, reaction, post, hasReactions)
|
a.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_REMOVED, reaction, post, hasReactions)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -464,6 +464,74 @@ func (s *hooksRPCServer) UserHasLeftTeam(args *Z_UserHasLeftTeamArgs, returns *Z
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["ReactionHasBeenAdded"] = ReactionHasBeenAddedId
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_ReactionHasBeenAddedArgs struct {
|
||||||
|
A *Context
|
||||||
|
B *model.Reaction
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_ReactionHasBeenAddedReturns struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) ReactionHasBeenAdded(c *Context, reaction *model.Reaction) {
|
||||||
|
_args := &Z_ReactionHasBeenAddedArgs{c, reaction}
|
||||||
|
_returns := &Z_ReactionHasBeenAddedReturns{}
|
||||||
|
if g.implemented[ReactionHasBeenAddedId] {
|
||||||
|
if err := g.client.Call("Plugin.ReactionHasBeenAdded", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call ReactionHasBeenAdded to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) ReactionHasBeenAdded(args *Z_ReactionHasBeenAddedArgs, returns *Z_ReactionHasBeenAddedReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
ReactionHasBeenAdded(c *Context, reaction *model.Reaction)
|
||||||
|
}); ok {
|
||||||
|
hook.ReactionHasBeenAdded(args.A, args.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook ReactionHasBeenAdded called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["ReactionHasBeenRemoved"] = ReactionHasBeenRemovedId
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_ReactionHasBeenRemovedArgs struct {
|
||||||
|
A *Context
|
||||||
|
B *model.Reaction
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_ReactionHasBeenRemovedReturns struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) ReactionHasBeenRemoved(c *Context, reaction *model.Reaction) {
|
||||||
|
_args := &Z_ReactionHasBeenRemovedArgs{c, reaction}
|
||||||
|
_returns := &Z_ReactionHasBeenRemovedReturns{}
|
||||||
|
if g.implemented[ReactionHasBeenRemovedId] {
|
||||||
|
if err := g.client.Call("Plugin.ReactionHasBeenRemoved", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call ReactionHasBeenRemoved to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) ReactionHasBeenRemoved(args *Z_ReactionHasBeenRemovedArgs, returns *Z_ReactionHasBeenRemovedReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
ReactionHasBeenRemoved(c *Context, reaction *model.Reaction)
|
||||||
|
}); ok {
|
||||||
|
hook.ReactionHasBeenRemoved(args.A, args.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook ReactionHasBeenRemoved called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Z_RegisterCommandArgs struct {
|
type Z_RegisterCommandArgs struct {
|
||||||
A *model.Command
|
A *model.Command
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,25 +15,27 @@ import (
|
|||||||
// Feel free to add more, but do not change existing assignments. Follow the naming convention of
|
// Feel free to add more, but do not change existing assignments. Follow the naming convention of
|
||||||
// <HookName>Id as the autogenerated glue code depends on that.
|
// <HookName>Id as the autogenerated glue code depends on that.
|
||||||
const (
|
const (
|
||||||
OnActivateId = 0
|
OnActivateId = 0
|
||||||
OnDeactivateId = 1
|
OnDeactivateId = 1
|
||||||
ServeHTTPId = 2
|
ServeHTTPId = 2
|
||||||
OnConfigurationChangeId = 3
|
OnConfigurationChangeId = 3
|
||||||
ExecuteCommandId = 4
|
ExecuteCommandId = 4
|
||||||
MessageWillBePostedId = 5
|
MessageWillBePostedId = 5
|
||||||
MessageWillBeUpdatedId = 6
|
MessageWillBeUpdatedId = 6
|
||||||
MessageHasBeenPostedId = 7
|
MessageHasBeenPostedId = 7
|
||||||
MessageHasBeenUpdatedId = 8
|
MessageHasBeenUpdatedId = 8
|
||||||
UserHasJoinedChannelId = 9
|
UserHasJoinedChannelId = 9
|
||||||
UserHasLeftChannelId = 10
|
UserHasLeftChannelId = 10
|
||||||
UserHasJoinedTeamId = 11
|
UserHasJoinedTeamId = 11
|
||||||
UserHasLeftTeamId = 12
|
UserHasLeftTeamId = 12
|
||||||
ChannelHasBeenCreatedId = 13
|
ChannelHasBeenCreatedId = 13
|
||||||
FileWillBeUploadedId = 14
|
FileWillBeUploadedId = 14
|
||||||
UserWillLogInId = 15
|
UserWillLogInId = 15
|
||||||
UserHasLoggedInId = 16
|
UserHasLoggedInId = 16
|
||||||
UserHasBeenCreatedId = 17
|
UserHasBeenCreatedId = 17
|
||||||
TotalHooksId = iota
|
ReactionHasBeenAddedId = 18
|
||||||
|
ReactionHasBeenRemovedId = 19
|
||||||
|
TotalHooksId = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -191,4 +193,20 @@ type Hooks interface {
|
|||||||
//
|
//
|
||||||
// Minimum server version: 5.2
|
// Minimum server version: 5.2
|
||||||
FileWillBeUploaded(c *Context, info *model.FileInfo, file io.Reader, output io.Writer) (*model.FileInfo, string)
|
FileWillBeUploaded(c *Context, info *model.FileInfo, file io.Reader, output io.Writer) (*model.FileInfo, string)
|
||||||
|
|
||||||
|
// ReactionHasBeenAdded is invoked after the reaction has been committed to the database.
|
||||||
|
//
|
||||||
|
// Note that this method will be called for reactions added by plugins, including the plugin that
|
||||||
|
// added the reaction.
|
||||||
|
//
|
||||||
|
// Minimum server version: 5.30
|
||||||
|
ReactionHasBeenAdded(c *Context, reaction *model.Reaction)
|
||||||
|
|
||||||
|
// ReactionHasBeenRemoved is invoked after the removal of the reaction has been committed to the database.
|
||||||
|
//
|
||||||
|
// Note that this method will be called for reactions removed by plugins, including the plugin that
|
||||||
|
// removed the reaction.
|
||||||
|
//
|
||||||
|
// Minimum server version: 5.30
|
||||||
|
ReactionHasBeenRemoved(c *Context, reaction *model.Reaction)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,3 +150,15 @@ func (hooks *hooksTimerLayer) FileWillBeUploaded(c *Context, info *model.FileInf
|
|||||||
hooks.recordTime(startTime, "FileWillBeUploaded", true)
|
hooks.recordTime(startTime, "FileWillBeUploaded", true)
|
||||||
return _returnsA, _returnsB
|
return _returnsA, _returnsB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) ReactionHasBeenAdded(c *Context, reaction *model.Reaction) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
hooks.hooksImpl.ReactionHasBeenAdded(c, reaction)
|
||||||
|
hooks.recordTime(startTime, "ReactionHasBeenAdded", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) ReactionHasBeenRemoved(c *Context, reaction *model.Reaction) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
hooks.hooksImpl.ReactionHasBeenRemoved(c, reaction)
|
||||||
|
hooks.recordTime(startTime, "ReactionHasBeenRemoved", true)
|
||||||
|
}
|
||||||
|
|||||||
@@ -194,6 +194,16 @@ func (_m *Hooks) OnDeactivate() error {
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReactionHasBeenAdded provides a mock function with given fields: c, reaction
|
||||||
|
func (_m *Hooks) ReactionHasBeenAdded(c *plugin.Context, reaction *model.Reaction) {
|
||||||
|
_m.Called(c, reaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReactionHasBeenRemoved provides a mock function with given fields: c, reaction
|
||||||
|
func (_m *Hooks) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.Reaction) {
|
||||||
|
_m.Called(c, reaction)
|
||||||
|
}
|
||||||
|
|
||||||
// ServeHTTP provides a mock function with given fields: c, w, r
|
// ServeHTTP provides a mock function with given fields: c, w, r
|
||||||
func (_m *Hooks) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
func (_m *Hooks) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
||||||
_m.Called(c, w, r)
|
_m.Called(c, w, r)
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user