This repository was archived by the owner on Feb 28, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathpost.go
334 lines (278 loc) · 9.99 KB
/
post.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
package pluginapi
import (
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/pkg/errors"
)
// PostService exposes methods to manipulate posts.
type PostService struct {
api plugin.API
}
// CreatePost creates a post.
//
// Minimum server version: 5.2
func (p *PostService) CreatePost(post *model.Post) error {
createdPost, appErr := p.api.CreatePost(post)
if appErr != nil {
return normalizeAppErr(appErr)
}
err := createdPost.ShallowCopy(post)
if err != nil {
return err
}
return nil
}
// DM sends a post as a direct message
//
// Minimum server version: 5.2
func (p *PostService) DM(senderUserID, receiverUserID string, post *model.Post) error {
channel, appErr := p.api.GetDirectChannel(senderUserID, receiverUserID)
if appErr != nil {
return normalizeAppErr(appErr)
}
post.ChannelId = channel.Id
post.UserId = senderUserID
return p.CreatePost(post)
}
// GetPost gets a post.
//
// Minimum server version: 5.2
func (p *PostService) GetPost(postID string) (*model.Post, error) {
post, appErr := p.api.GetPost(postID)
return post, normalizeAppErr(appErr)
}
// UpdatePost updates a post.
//
// Minimum server version: 5.2
func (p *PostService) UpdatePost(post *model.Post) error {
updatedPost, appErr := p.api.UpdatePost(post)
if appErr != nil {
return normalizeAppErr(appErr)
}
err := updatedPost.ShallowCopy(post)
if err != nil {
return err
}
return nil
}
// DeletePost deletes a post.
//
// Minimum server version: 5.2
func (p *PostService) DeletePost(postID string) error {
return normalizeAppErr(p.api.DeletePost(postID))
}
// SendEphemeralPost creates an ephemeral post.
//
// Minimum server version: 5.2
func (p *PostService) SendEphemeralPost(userID string, post *model.Post) {
*post = *p.api.SendEphemeralPost(userID, post)
}
// UpdateEphemeralPost updates an ephemeral message previously sent to the user.
// EXPERIMENTAL: This API is experimental and can be changed without advance notice.
//
// Minimum server version: 5.2
func (p *PostService) UpdateEphemeralPost(userID string, post *model.Post) {
*post = *p.api.UpdateEphemeralPost(userID, post)
}
// DeleteEphemeralPost deletes an ephemeral message previously sent to the user.
// EXPERIMENTAL: This API is experimental and can be changed without advance notice.
//
// Minimum server version: 5.2
func (p *PostService) DeleteEphemeralPost(userID, postID string) {
p.api.DeleteEphemeralPost(userID, postID)
}
// GetPostThread gets a post with all the other posts in the same thread.
//
// Minimum server version: 5.6
func (p *PostService) GetPostThread(postID string) (*model.PostList, error) {
postList, appErr := p.api.GetPostThread(postID)
return postList, normalizeAppErr(appErr)
}
// GetPostsSince gets posts created after a specified time as Unix time in milliseconds.
//
// Minimum server version: 5.6
func (p *PostService) GetPostsSince(channelID string, time int64) (*model.PostList, error) {
postList, appErr := p.api.GetPostsSince(channelID, time)
return postList, normalizeAppErr(appErr)
}
// GetPostsAfter gets a page of posts that were posted after the post provided.
//
// Minimum server version: 5.6
func (p *PostService) GetPostsAfter(channelID, postID string, page, perPage int) (*model.PostList, error) {
postList, appErr := p.api.GetPostsAfter(channelID, postID, page, perPage)
return postList, normalizeAppErr(appErr)
}
// GetPostsBefore gets a page of posts that were posted before the post provided.
//
// Minimum server version: 5.6
func (p *PostService) GetPostsBefore(channelID, postID string, page, perPage int) (*model.PostList, error) {
postList, appErr := p.api.GetPostsBefore(channelID, postID, page, perPage)
return postList, normalizeAppErr(appErr)
}
// GetPostsForChannel gets a list of posts for a channel.
//
// Minimum server version: 5.6
func (p *PostService) GetPostsForChannel(channelID string, page, perPage int) (*model.PostList, error) {
postList, appErr := p.api.GetPostsForChannel(channelID, page, perPage)
return postList, normalizeAppErr(appErr)
}
// SearchPostsInTeam returns a list of posts in a specific team that match the given params.
//
// Minimum server version: 5.10
func (p *PostService) SearchPostsInTeam(teamID string, paramsList []*model.SearchParams) ([]*model.Post, error) {
postList, appErr := p.api.SearchPostsInTeam(teamID, paramsList)
return postList, normalizeAppErr(appErr)
}
// AddReaction add a reaction to a post.
//
// Minimum server version: 5.3
func (p *PostService) AddReaction(reaction *model.Reaction) error {
addedReaction, appErr := p.api.AddReaction(reaction)
if appErr != nil {
return normalizeAppErr(appErr)
}
*reaction = *addedReaction
return nil
}
// GetReactions get the reactions of a post.
//
// Minimum server version: 5.3
func (p *PostService) GetReactions(postID string) ([]*model.Reaction, error) {
reactions, appErr := p.api.GetReactions(postID)
return reactions, normalizeAppErr(appErr)
}
// RemoveReaction remove a reaction from a post.
//
// Minimum server version: 5.3
func (p *PostService) RemoveReaction(reaction *model.Reaction) error {
return normalizeAppErr(p.api.RemoveReaction(reaction))
}
type ShouldProcessMessageOption func(*shouldProcessMessageOptions)
type shouldProcessMessageOptions struct {
AllowSystemMessages bool
AllowBots bool
AllowWebhook bool
FilterChannelIDs []string
FilterUserIDs []string
OnlyBotDMs bool
BotID string
}
// AllowSystemMessages configures a call to ShouldProcessMessage to return true for system messages.
//
// As it is typically desirable only to consume messages from users of the system, ShouldProcessMessage ignores system messages by default.
func AllowSystemMessages() ShouldProcessMessageOption {
return func(options *shouldProcessMessageOptions) {
options.AllowSystemMessages = true
}
}
// AllowBots configures a call to ShouldProcessMessage to return true for bot posts.
//
// As it is typically desirable only to consume messages from human users of the system, ShouldProcessMessage ignores bot messages by default.
// When allowing bots, take care to avoid a loop where two plugins respond to each others posts repeatedly.
func AllowBots() ShouldProcessMessageOption {
return func(options *shouldProcessMessageOptions) {
options.AllowBots = true
}
}
// AllowWebhook configures a call to ShouldProcessMessage to return true for posts from webhook.
//
// As it is typically desirable only to consume messages from human users of the system, ShouldProcessMessage ignores webhook messages by default.
func AllowWebhook() ShouldProcessMessageOption {
return func(options *shouldProcessMessageOptions) {
options.AllowWebhook = true
}
}
// FilterChannelIDs configures a call to ShouldProcessMessage to return true only for the given channels.
//
// By default, posts from all channels are allowed to be processed.
func FilterChannelIDs(filterChannelIDs []string) ShouldProcessMessageOption {
return func(options *shouldProcessMessageOptions) {
options.FilterChannelIDs = filterChannelIDs
}
}
// FilterUserIDs configures a call to ShouldProcessMessage to return true only for the given users.
//
// By default, posts from all non-bot users are allowed.
func FilterUserIDs(filterUserIDs []string) ShouldProcessMessageOption {
return func(options *shouldProcessMessageOptions) {
options.FilterUserIDs = filterUserIDs
}
}
// OnlyBotDMs configures a call to ShouldProcessMessage to return true only for direct messages sent to the bot created by EnsureBot.
//
// By default, posts from all channels are allowed.
func OnlyBotDMs() ShouldProcessMessageOption {
return func(options *shouldProcessMessageOptions) {
options.OnlyBotDMs = true
}
}
// If provided, BotID configures ShouldProcessMessage to skip its retrieval from the store.
//
// By default, posts from all non-bot users are allowed.
func BotID(botID string) ShouldProcessMessageOption {
return func(options *shouldProcessMessageOptions) {
options.BotID = botID
}
}
// ShouldProcessMessage returns if the message should be processed by a message hook.
//
// Use this method to avoid processing unnecessary messages in a MessageHasBeenPosted
// or MessageWillBePosted hook, and indeed in some cases avoid an infinite loop between
// two automated bots or plugins.
//
// The behavior is customizable using the given options, since plugin needs may vary.
// By default, system messages and messages from bots will be skipped.
//
// Minimum server version: 5.2
func (p *PostService) ShouldProcessMessage(post *model.Post, options ...ShouldProcessMessageOption) (bool, error) {
messageProcessOptions := &shouldProcessMessageOptions{}
for _, option := range options {
option(messageProcessOptions)
}
var botIDBytes []byte
var kvGetErr *model.AppError
if messageProcessOptions.BotID != "" {
botIDBytes = []byte(messageProcessOptions.BotID)
} else {
botIDBytes, kvGetErr = p.api.KVGet(botUserKey)
if kvGetErr != nil {
return false, errors.Wrap(kvGetErr, "failed to get bot")
}
}
if botIDBytes != nil {
if post.UserId == string(botIDBytes) {
return false, nil
}
}
if post.IsSystemMessage() && !messageProcessOptions.AllowSystemMessages {
return false, nil
}
if !messageProcessOptions.AllowWebhook && post.GetProp("from_webhook") == "true" {
return false, nil
}
if !messageProcessOptions.AllowBots {
user, appErr := p.api.GetUser(post.UserId)
if appErr != nil {
return false, errors.Wrap(appErr, "unable to get user")
}
if user.IsBot {
return false, nil
}
}
if len(messageProcessOptions.FilterChannelIDs) != 0 && !stringInSlice(post.ChannelId, messageProcessOptions.FilterChannelIDs) {
return false, nil
}
if len(messageProcessOptions.FilterUserIDs) != 0 && !stringInSlice(post.UserId, messageProcessOptions.FilterUserIDs) {
return false, nil
}
if botIDBytes != nil && messageProcessOptions.OnlyBotDMs {
channel, appErr := p.api.GetChannel(post.ChannelId)
if appErr != nil {
return false, errors.Wrap(appErr, "unable to get channel")
}
if !model.IsBotDMChannel(channel, string(botIDBytes)) {
return false, nil
}
}
return true, nil
}