Reputation: 67
My bot is supposed to send a message, and then check if somebody reacted on that message with :tada:, and if someone did, it is supposed to give that user a particular role, that part works fine, but I also want it to check if the user removed their reaction, if yes, then remove the role.
I put the role remover and role adder into their own async
coroutine functions,
# Listening for reactions
await participation_message.add_reaction("🎉")
reaction_check = lambda reaction, user: str(reaction.emoji) == "🎉" and reaction.message.id == participation_message.id # In case you might be wondering, participation_message is a discord.Message that I send before this code block
async def remove_participants_loop():
while True:
try:
reaction, user = await self.client.wait_for('reaction_remove', timeout=60, check=reaction_check)
try:
await user.remove_roles(participant_role)
except Exception as e:
console_log("Error in removing participant role from user: {}".format(e), "white", "on_red")
except TimeoutError:
break
async def add_participants_loop(timeout=delete_after*60):
while True:
try:
reaction, user = await self.client.wait_for('reaction_add', timeout=60, check=reaction_check)
try:
await user.add_roles(participant_role)
except Exception as e:
console_log("Error in adding participant role to user: {}".format(e), "white", "on_red")
except TimeoutError:
break
and I put them into their own coroutines, because I need both of them to run asynchronously, and for that I now do
asyncio.create_task(add_participants_loop())
asyncio.create_task(remove_participants_loop())
This works for the add_participants_loop()
but doesn't work for the remove_participants_loop()
, I have tried to debug it using breakpoints, and found that the remove_participants_loop
does run properly, but when it waits for "reaction_remove"
, it doesn't detect it when I remove my reaction, and keeps waiting and eventually raises the asyncio.TimoutError
.
wait_for()
's documentation states that, "event (str) – The event name, similar to the event reference, but without the on_ prefix, to wait for.", and the event reference shows that the proper term would indeed be "reaction_remove" and not anything elseUpvotes: 2
Views: 704
Reputation: 67
In an issue on the discord.py Github Repository, it's stated that:
this requires the message cache and for the message to be there. It also requires member cache since discord does not provide this event with member data.
and it also states that
If you want to get event without this limitation then use the
on_raw_reaction_remove
event.
Therefore the reaction_remove
event doesn't work because of absent cache. Hence raw_reaction_remove
should be used here instead, because it isn't bound to this limitation, and it returns a payload discord.RawReactionActionEvent object, instead of the standard User and Reaction, which can then be used to get the User and the Reaction.
Hence the lambda check for that would now be something like:
lambda payload: str(payload.emoji) == "🎉" and payload.message_id == participation_message.id
putting that in the wait_for coroutine,
payload = await self.client.wait_for('raw_reaction_remove', timeout=timeout, check=lambda payload: str(payload.emoji) == "🎉" and payload.message_id == participation_message.id)
# And then the User/Member who removed the Reaction can
# Be obtained by the user_id in the returned payload
user = self.client.get_guild(payload.guild_id).get_member(payload.user_id)
Upvotes: 1
Reputation: 468
I think wait_for
can only handle "message" and "reaction_add", not "reaction_remove".
Upvotes: 0