Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
816 views
in Technique[技术] by (71.8m points)

python - Discord.py Bot Reactions in DMs

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, ["??", "??"])
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...