-
Notifications
You must be signed in to change notification settings - Fork 1
/
reaction_handlers.go
107 lines (95 loc) · 2.74 KB
/
reaction_handlers.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
package bcr
import (
"github.com/diamondburned/arikawa/v3/discord"
"github.com/diamondburned/arikawa/v3/gateway"
)
type reactionInfo struct {
userID discord.UserID
ctx *Context
fn func(*Context)
deleteOnTrigger bool
deleteReaction bool
respondToRemove bool
}
type reactionKey struct {
messageID discord.MessageID
emoji discord.APIEmoji
}
// ReactionAdd runs when a reaction is added to a message
func (r *Router) ReactionAdd(e *gateway.MessageReactionAddEvent) {
r.reactionMu.Lock()
defer r.reactionMu.Unlock()
if v, ok := r.reactions[reactionKey{
messageID: e.MessageID,
emoji: e.Emoji.APIString(),
}]; ok {
// check if the reacting user is the same as the required user
if v.userID != e.UserID {
return
}
// handle deleting the reaction
// only delete if:
// - the user isn't the user the reaction's for
// - or the reaction is supposed to be deleted
// - and the user is not the bot user
if v.deleteReaction && e.GuildID.IsValid() && e.UserID != r.Bot.ID {
state, _ := r.StateFromGuildID(e.GuildID)
if p, err := state.Permissions(e.ChannelID, r.Bot.ID); err == nil {
if p.Has(discord.PermissionManageMessages) {
state.DeleteUserReaction(e.ChannelID, e.MessageID, e.UserID, e.Emoji.APIString())
}
}
}
// run the handler
// fork this off to a goroutine to unlock the reaction mutex immediately
go v.fn(v.ctx)
// if the handler should be deleted after running, do that
if v.deleteOnTrigger {
delete(r.reactions, reactionKey{
messageID: e.MessageID,
emoji: e.Emoji.APIString(),
})
}
}
}
// ReactionRemove runs when a reaction is removed from a message
func (r *Router) ReactionRemove(ev *gateway.MessageReactionRemoveEvent) {
r.reactionMu.Lock()
defer r.reactionMu.Unlock()
if v, ok := r.reactions[reactionKey{
messageID: ev.MessageID,
emoji: ev.Emoji.APIString(),
}]; ok {
if !v.respondToRemove {
return
}
// check if the reacting user is the same as the required user
if v.userID != ev.UserID {
return
}
// run the handler
// fork this off to a goroutine to unlock the reaction mutex immediately
go v.fn(v.ctx)
// if the handler should be deleted after running, do that
if v.deleteOnTrigger {
delete(r.reactions, reactionKey{
messageID: ev.MessageID,
emoji: ev.Emoji.APIString(),
})
}
}
}
// ReactionMessageDelete cleans up old handlers on deleted messages
func (r *Router) ReactionMessageDelete(m *gateway.MessageDeleteEvent) {
r.DeleteReactions(m.ID)
}
// DeleteReactions deletes all reactions for a message
func (r *Router) DeleteReactions(m discord.MessageID) {
r.reactionMu.Lock()
for k := range r.reactions {
if k.messageID == m {
delete(r.reactions, k)
}
}
r.reactionMu.Unlock()
}