github.com/starshine-sys/bcr@v0.21.0/reaction_handlers.go (about) 1 package bcr 2 3 import ( 4 "github.com/diamondburned/arikawa/v3/discord" 5 "github.com/diamondburned/arikawa/v3/gateway" 6 ) 7 8 type reactionInfo struct { 9 userID discord.UserID 10 ctx *Context 11 fn func(*Context) 12 deleteOnTrigger bool 13 deleteReaction bool 14 respondToRemove bool 15 } 16 17 type reactionKey struct { 18 messageID discord.MessageID 19 emoji discord.APIEmoji 20 } 21 22 // ReactionAdd runs when a reaction is added to a message 23 func (r *Router) ReactionAdd(e *gateway.MessageReactionAddEvent) { 24 r.reactionMu.Lock() 25 defer r.reactionMu.Unlock() 26 if v, ok := r.reactions[reactionKey{ 27 messageID: e.MessageID, 28 emoji: e.Emoji.APIString(), 29 }]; ok { 30 // check if the reacting user is the same as the required user 31 if v.userID != e.UserID { 32 return 33 } 34 // handle deleting the reaction 35 // only delete if: 36 // - the user isn't the user the reaction's for 37 // - or the reaction is supposed to be deleted 38 // - and the user is not the bot user 39 if v.deleteReaction && e.GuildID.IsValid() && e.UserID != r.Bot.ID { 40 state, _ := r.StateFromGuildID(e.GuildID) 41 42 if p, err := state.Permissions(e.ChannelID, r.Bot.ID); err == nil { 43 if p.Has(discord.PermissionManageMessages) { 44 state.DeleteUserReaction(e.ChannelID, e.MessageID, e.UserID, e.Emoji.APIString()) 45 } 46 } 47 } 48 // run the handler 49 // fork this off to a goroutine to unlock the reaction mutex immediately 50 go v.fn(v.ctx) 51 52 // if the handler should be deleted after running, do that 53 if v.deleteOnTrigger { 54 delete(r.reactions, reactionKey{ 55 messageID: e.MessageID, 56 emoji: e.Emoji.APIString(), 57 }) 58 } 59 } 60 } 61 62 // ReactionRemove runs when a reaction is removed from a message 63 func (r *Router) ReactionRemove(ev *gateway.MessageReactionRemoveEvent) { 64 r.reactionMu.Lock() 65 defer r.reactionMu.Unlock() 66 if v, ok := r.reactions[reactionKey{ 67 messageID: ev.MessageID, 68 emoji: ev.Emoji.APIString(), 69 }]; ok { 70 if !v.respondToRemove { 71 return 72 } 73 74 // check if the reacting user is the same as the required user 75 if v.userID != ev.UserID { 76 return 77 } 78 79 // run the handler 80 // fork this off to a goroutine to unlock the reaction mutex immediately 81 go v.fn(v.ctx) 82 83 // if the handler should be deleted after running, do that 84 if v.deleteOnTrigger { 85 delete(r.reactions, reactionKey{ 86 messageID: ev.MessageID, 87 emoji: ev.Emoji.APIString(), 88 }) 89 } 90 } 91 } 92 93 // ReactionMessageDelete cleans up old handlers on deleted messages 94 func (r *Router) ReactionMessageDelete(m *gateway.MessageDeleteEvent) { 95 r.DeleteReactions(m.ID) 96 } 97 98 // DeleteReactions deletes all reactions for a message 99 func (r *Router) DeleteReactions(m discord.MessageID) { 100 r.reactionMu.Lock() 101 for k := range r.reactions { 102 if k.messageID == m { 103 delete(r.reactions, k) 104 } 105 } 106 r.reactionMu.Unlock() 107 }