1
votes

I have a discord.py bot that I want to code to do the following things:

  1. When a user types the command, the bot should send the user a DM
  2. Then, it should add reactions to this message (A thumbs up and thumbs down)
  3. Finally, it should wait for the user to react with one of those reactions.

Now based on the docs and previous projects, I came up with this function for adding reactions:

async def get_reacts(user, client, message, emojis, timeout=None):
    for emoji in emojis:
        await message.add_reaction(emoji)
    try:
        def check(reaction, reactor):
            return reactor.id == user.id and reaction.emoji in emojis
        reaction, user = await client.wait_for("reaction_add", check=check, timeout=timeout)
        return reaction.emoji
    except:
        pass

This code works perfectly when in a server, but when the message is in a DM, it does something peculiar. First, it doesn't detect the user reactions at all. When I put a print statement within the check function, it told me that it parsed one reaction, and that reaction was the bot itself reacting with the thumbs down. When I reacted to the message, the check function was never called.

I saw some other solutions used a Cog listener to go through all added reactions, and use a global list of messages. However, this won't work for my bot as everything it does is in one command. Additionally, it takes up a lot of memory. This is why I went with the client.wait_for approach instead.

Is there a problem with using client.wait_for in DMs? Should I use Cog listeners instead? Or is it a problem with my code? Any help is appreciated. Thanks in advance!

EDIT: Intents enabled: None (Do I need an intent to check DM reactions?)

EDIT 2: Added default intents, still the same issue

EDIT 3: How I am using the get_reacts function:

msg = await context.author.send("Message")
reaction = await get_reacts(context.author, self.client, msg, ["????", "????"])
3
What intents have you enabled? Could you also add that to the question pleaseŁukasz Kwieciński
@ŁukaszKwieciński I edited the questionKrishnan Shankar

3 Answers

2
votes

Solution

In order to receive reactions event in DM from users you need to enable the members intent.

So the only thing you need to do is create your default intent and then set the members value to True :

intents = discord.Intents.default()
intents.members = True

Explanation

Op was asking for clarification so here it is.

If you take a look at the discord.Intents.default() code :

@classmethod
def default(cls):
    self = cls.all()
    self.presences = False
    self.members = False
    return self

You can see it does two things :

  • Generate intents for everything (using its own discord.Intents.all())
  • From those intents, remove the one corresponding to presence and members

So the assumptions of op :

This makes me think that maybe dm_reactions and reactions are not included in default intents

is not true. Because only presence and members are removed, all the other ones are in it.

Now, turns out even with dm_reactions, reactions, and dm_messages on, you still need to have the members on. So that is what is happenning in the solution.

And as OP pointed out, it does work with discord.Intents.all() because, in this case, the member intent is enabled.

0
votes

Yes, you need intents. dm_reactions and reactions (It shouldn't work without them). Easiest for you would be to simply enable default intents

intents = discord.Intents.default()
client = commands.Bot(..., intents=intents)
0
votes

Adding on to Łukasz's answer, I tried some experimentation, and found that using discord.Intents.all() worked, but not discord.Intents.default(). This makes me think that maybe dm_reactions and reactions are not included in default intents, but are included in all intents? Any clarification on this is still appreciated, as I just started learning discord.py a few months ago.