Tutez
Tutez

Reputation: 39

Discord.py count reactions on a message

I'm doing a bot discord and I'd like my bot to count the number of reactions to a message before deleting him

@client.event
async def on_raw_reaction_add(payload):
    if payload.channel_id == 614467771866021944:
        if payload.emoji.name == "🔁":
            # if number of reactions > 4:
            # delete the message

Upvotes: 1

Views: 14799

Answers (2)

Patrick Haugh
Patrick Haugh

Reputation: 61014

You need to use the ids in the payload to get the Message object of the message and then check the count attribute of the appropriate Reaction from Message.reactions:

from discord.utils import get

@client.event
async def on_raw_reaction_add(payload):
    if payload.channel_id == 614467771866021944:
        if payload.emoji.name == "🔁":
            channel = client.get_channel(payload.channel_id)
            message = await channel.fetch_message(payload.message_id)
            reaction = get(message.reactions, emoji=payload.emoji.name)
            if reaction and reaction.count > 4:
                await message.delete()

Upvotes: 5

iyrin
iyrin

Reputation: 642

How Do I Get a Custom Emoji Count in Discord.py?

Patrick Haugh's answer works for native emojis, but I wanted to add an additional answer to explain getting the count attribute for custom emojis since Discord.py defines these attributes differently. The solution itself is easily applies and you can skip to the solution example below if you don't want to read the explanation.

The emoji attribute for custom emoji reactions contains a nested set of attributes instead of the single value that native emojis have. Say there is a reaction using a custom emoji named kirby. If you were to print message.reactions, it would output something like this (assuming you have already appropriately defined message):

[<Reaction emoji='🔁' me=True count=1>, <Reaction emoji=<Emoji id=900000000123456789 name='kirby' animated=False managed=False> me=False count=1>]

The first reaction has the emoji itself as the attribute emoji.
So when you call get(message.reactions, emoji=payload.emoji.name) it is just passing the values like so: get(message.reactions, emoji='🔁')

Now look at the emoji attribute for the custom emoji called kirby. Instead of using the emoji as the value here, you will see four attributes nested as the value for the emoji attribute. The attributes are id, name, animated, managed. Your custom emoji only exists on your server. That means you can't simply paste the emoji into your bot's code the way you can do with native emojis.

You also can't pass the name value alone as payload.emoji.name will do. Passing emoji='kirby in the get() utility will cause it to return None because it will not be able to match kirby in the emoji attribute.

If nothing is found that matches the attributes passed, then None is returned.1

Solution

The simplest way I've found is to drop the .name attribute and just pass payload.emoji as your value. Discord.py seems to prefer working with this name:id format for custom emojis. In this example, get() will match the emoji attribute to a string of nested values <kirby:900000000123456789>

Now the get() utility will be able to match and return the reaction which includes the count attribute you are looking to work with. This example assumes you have already defined message:

  if payload.emoji.name == 'kirby':
      # payload.emoji will be defined as <kirby:900000000123456789>
      reaction = discord.utils.get(message.reactions, emoji=payload.emoji)
      # Now you can get reaction.count for the custom emoji!
      print(f'The reaction count for this custom emoji is: {reaction.count}.')

Upvotes: 3

Related Questions