GH-15624: Added plugin hooks for ReationHasBeenAdded and ReactionHasBeenRemoved (#15765)

Этот коммит содержится в:
Jared Shields
2020-10-31 02:06:43 -04:00
коммит произвёл GitHub
родитель 71c371509b
Коммит 3515b4d6c9
6 изменённых файлов: 234 добавлений и 19 удалений

Просмотреть файл

@@ -1131,3 +1131,89 @@ func TestHookMetrics(t *testing.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"
"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) {
@@ -51,6 +52,16 @@ func (a *App) SaveReactionForPost(reaction *model.Reaction) (*model.Reaction, *m
// The post is always modified since the UpdateAt always changes
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.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
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.sendReactionEvent(model.WEBSOCKET_EVENT_REACTION_REMOVED, reaction, post, hasReactions)
})

Просмотреть файл

@@ -464,6 +464,74 @@ func (s *hooksRPCServer) UserHasLeftTeam(args *Z_UserHasLeftTeamArgs, returns *Z
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 {
A *model.Command
}

Просмотреть файл

@@ -15,25 +15,27 @@ import (
// 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.
const (
OnActivateId = 0
OnDeactivateId = 1
ServeHTTPId = 2
OnConfigurationChangeId = 3
ExecuteCommandId = 4
MessageWillBePostedId = 5
MessageWillBeUpdatedId = 6
MessageHasBeenPostedId = 7
MessageHasBeenUpdatedId = 8
UserHasJoinedChannelId = 9
UserHasLeftChannelId = 10
UserHasJoinedTeamId = 11
UserHasLeftTeamId = 12
ChannelHasBeenCreatedId = 13
FileWillBeUploadedId = 14
UserWillLogInId = 15
UserHasLoggedInId = 16
UserHasBeenCreatedId = 17
TotalHooksId = iota
OnActivateId = 0
OnDeactivateId = 1
ServeHTTPId = 2
OnConfigurationChangeId = 3
ExecuteCommandId = 4
MessageWillBePostedId = 5
MessageWillBeUpdatedId = 6
MessageHasBeenPostedId = 7
MessageHasBeenUpdatedId = 8
UserHasJoinedChannelId = 9
UserHasLeftChannelId = 10
UserHasJoinedTeamId = 11
UserHasLeftTeamId = 12
ChannelHasBeenCreatedId = 13
FileWillBeUploadedId = 14
UserWillLogInId = 15
UserHasLoggedInId = 16
UserHasBeenCreatedId = 17
ReactionHasBeenAddedId = 18
ReactionHasBeenRemovedId = 19
TotalHooksId = iota
)
const (
@@ -191,4 +193,20 @@ type Hooks interface {
//
// Minimum server version: 5.2
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)
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
}
// 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
func (_m *Hooks) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
_m.Called(c, w, r)