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  }