(feature) New MessagesWillBeConsumed Server Plugin Hook (#23305)
* feature: implemented basic MessageWillBeConsumed hook and applied on GetSinglePost method. * use hook in get methods * chore: refactored hook usage and created utils functions to apply hook * bugfix: single post not updating * chore: adjusted hook to return post * chore: reverted some uneeded changes * chore: updated hook to accept slice of posts * bugfix: slice filled with niil values * chore: MessageWillBeConsumed ranamed to MessagesWillBeConsumed * Update plugin/hooks.go Co-authored-by: Jesse Hallam <jesse@thehallams.ca> * Add feature flag * Update min version * update tests to account for feature flag * fix linting issues --------- Co-authored-by: Matej Topolovac <> Co-authored-by: mtopolovac <43346061+mtopolovac@users.noreply.github.com> Co-authored-by: Jesse Hallam <jesse@thehallams.ca> Co-authored-by: Kevin Hsieh <kevinh@qrypt.com> Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>
Этот коммит содержится в:
@@ -698,6 +698,43 @@ func (s *hooksRPCServer) MessageWillBeUpdated(args *Z_MessageWillBeUpdatedArgs,
|
||||
return nil
|
||||
}
|
||||
|
||||
// MessagesWillBeConsumed is in this file because of the difficulty of identifying which fields need special behaviour.
|
||||
// The special behaviour needed is decoding the returned post into the original one to avoid the unintentional removal
|
||||
// of fields by older plugins.
|
||||
func init() {
|
||||
hookNameToId["MessagesWillBeConsumed"] = MessagesWillBeConsumedID
|
||||
}
|
||||
|
||||
type Z_MessagesWillBeConsumedArgs struct {
|
||||
A []*model.Post
|
||||
}
|
||||
|
||||
type Z_MessagesWillBeConsumedReturns struct {
|
||||
A []*model.Post
|
||||
}
|
||||
|
||||
func (g *hooksRPCClient) MessagesWillBeConsumed(posts []*model.Post) []*model.Post {
|
||||
_args := &Z_MessagesWillBeConsumedArgs{posts}
|
||||
_returns := &Z_MessagesWillBeConsumedReturns{}
|
||||
if g.implemented[MessagesWillBeConsumedID] {
|
||||
if err := g.client.Call("Plugin.MessagesWillBeConsumed", _args, _returns); err != nil {
|
||||
g.log.Error("RPC call MessagesWillBeConsumed to plugin failed.", mlog.Err(err))
|
||||
}
|
||||
}
|
||||
return _returns.A
|
||||
}
|
||||
|
||||
func (s *hooksRPCServer) MessagesWillBeConsumed(args *Z_MessagesWillBeConsumedArgs, returns *Z_MessagesWillBeConsumedReturns) error {
|
||||
if hook, ok := s.impl.(interface {
|
||||
MessagesWillBeConsumed(posts []*model.Post) []*model.Post
|
||||
}); ok {
|
||||
returns.A = hook.MessagesWillBeConsumed(args.A)
|
||||
} else {
|
||||
return encodableError(fmt.Errorf("hook MessagesWillBeConsumed called but not implemented"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_LogDebugArgs struct {
|
||||
A string
|
||||
B []any
|
||||
|
||||
@@ -53,6 +53,7 @@ const (
|
||||
NotificationWillBePushedID = 35
|
||||
UserHasBeenDeactivatedID = 36
|
||||
MessageHasBeenDeletedID = 37
|
||||
MessagesWillBeConsumedID = 38
|
||||
TotalHooksID = iota
|
||||
)
|
||||
|
||||
@@ -170,6 +171,15 @@ type Hooks interface {
|
||||
// Minimum server version: 5.2
|
||||
MessageHasBeenUpdated(c *Context, newPost, oldPost *model.Post)
|
||||
|
||||
// MessagesWillBeConsumed is invoked when a message is requested by a client before it is returned
|
||||
// to the client
|
||||
//
|
||||
// Note that this method will be called for posts created by plugins, including the plugin that
|
||||
// created the post.
|
||||
//
|
||||
// Minimum server version: 9.3
|
||||
MessagesWillBeConsumed(posts []*model.Post) []*model.Post
|
||||
|
||||
// MessageHasBeenDeleted is invoked after the message has been deleted from the database.
|
||||
// Note that this method will be called for posts deleted by plugins, including the plugin that
|
||||
// deleted the post.
|
||||
|
||||
@@ -113,6 +113,13 @@ func (hooks *hooksTimerLayer) MessageHasBeenUpdated(c *Context, newPost, oldPost
|
||||
hooks.recordTime(startTime, "MessageHasBeenUpdated", true)
|
||||
}
|
||||
|
||||
func (hooks *hooksTimerLayer) MessagesWillBeConsumed(posts []*model.Post) []*model.Post {
|
||||
startTime := timePkg.Now()
|
||||
_returnsA := hooks.hooksImpl.MessagesWillBeConsumed(posts)
|
||||
hooks.recordTime(startTime, "MessagesWillBeConsumed", true)
|
||||
return _returnsA
|
||||
}
|
||||
|
||||
func (hooks *hooksTimerLayer) MessageHasBeenDeleted(c *Context, post *model.Post) {
|
||||
startTime := timePkg.Now()
|
||||
hooks.hooksImpl.MessageHasBeenDeleted(c, post)
|
||||
|
||||
@@ -32,6 +32,7 @@ var excludedPluginHooks = []string{
|
||||
"LogWarn",
|
||||
"MessageWillBePosted",
|
||||
"MessageWillBeUpdated",
|
||||
"MessagesWillBeConsumed",
|
||||
"OnActivate",
|
||||
"PluginHTTP",
|
||||
"ServeHTTP",
|
||||
|
||||
@@ -198,6 +198,22 @@ func (_m *Hooks) MessageWillBeUpdated(c *plugin.Context, newPost *model.Post, ol
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MessagesWillBeConsumed provides a mock function with given fields: posts
|
||||
func (_m *Hooks) MessagesWillBeConsumed(posts []*model.Post) []*model.Post {
|
||||
ret := _m.Called(posts)
|
||||
|
||||
var r0 []*model.Post
|
||||
if rf, ok := ret.Get(0).(func([]*model.Post) []*model.Post); ok {
|
||||
r0 = rf(posts)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Post)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// NotificationWillBePushed provides a mock function with given fields: pushNotification, userID
|
||||
func (_m *Hooks) NotificationWillBePushed(pushNotification *model.PushNotification, userID string) (*model.PushNotification, string) {
|
||||
ret := _m.Called(pushNotification, userID)
|
||||
|
||||
@@ -50,6 +50,10 @@ type MessageHasBeenUpdatedIFace interface {
|
||||
MessageHasBeenUpdated(c *Context, newPost, oldPost *model.Post)
|
||||
}
|
||||
|
||||
type MessagesWillBeConsumedIFace interface {
|
||||
MessagesWillBeConsumed(posts []*model.Post) []*model.Post
|
||||
}
|
||||
|
||||
type MessageHasBeenDeletedIFace interface {
|
||||
MessageHasBeenDeleted(c *Context, post *model.Post)
|
||||
}
|
||||
@@ -224,6 +228,15 @@ func NewAdapter(productHooks any) (*HooksAdapter, error) {
|
||||
return nil, errors.New("hook has MessageHasBeenUpdated method but does not implement plugin.MessageHasBeenUpdated interface")
|
||||
}
|
||||
|
||||
// Assessing the type of the productHooks if it individually implements MessagesWillBeConsumed interface.
|
||||
tt = reflect.TypeOf((*MessagesWillBeConsumedIFace)(nil)).Elem()
|
||||
|
||||
if ft.Implements(tt) {
|
||||
a.implemented[MessagesWillBeConsumedID] = struct{}{}
|
||||
} else if _, ok := ft.MethodByName("MessagesWillBeConsumed"); ok {
|
||||
return nil, errors.New("hook has MessagesWillBeConsumed method but does not implement plugin.MessagesWillBeConsumed interface")
|
||||
}
|
||||
|
||||
// Assessing the type of the productHooks if it individually implements MessageHasBeenDeleted interface.
|
||||
tt = reflect.TypeOf((*MessageHasBeenDeletedIFace)(nil)).Elem()
|
||||
|
||||
@@ -488,6 +501,15 @@ func (a *HooksAdapter) MessageHasBeenUpdated(c *Context, newPost, oldPost *model
|
||||
|
||||
}
|
||||
|
||||
func (a *HooksAdapter) MessagesWillBeConsumed(posts []*model.Post) []*model.Post {
|
||||
if _, ok := a.implemented[MessagesWillBeConsumedID]; !ok {
|
||||
panic("product hooks must implement MessagesWillBeConsumed")
|
||||
}
|
||||
|
||||
return a.productHooks.(MessagesWillBeConsumedIFace).MessagesWillBeConsumed(posts)
|
||||
|
||||
}
|
||||
|
||||
func (a *HooksAdapter) MessageHasBeenDeleted(c *Context, post *model.Post) {
|
||||
if _, ok := a.implemented[MessageHasBeenDeletedID]; !ok {
|
||||
panic("product hooks must implement MessageHasBeenDeleted")
|
||||
|
||||
Ссылка в новой задаче
Block a user