Search code examples
pythondiscordpycord

How to remove a specific reaction from message


I'm developing a simple game in discord.py/pycord and would like my bot to be able to delete a specific reaction when clicked. Is this possible?

I'm trying to reproduce the scenario shown below:

Expected result

Here's the code I'm using (I'm using pycord):

import discord
from discord.ext import commands

intents = discord.Intents().all()

bot = commands.Bot(intents=intents)

@bot.event
async def on_message(message):
    if message.author == bot.user:
        return
    if message.content == 'test':
        me = await message.reply('Is this cool?')
        await me.add_reaction("SomeEmoji")
        await me.add_reaction("SomeEmoji")
        try:
            reaction, user = await bot.wait_for("reaction_add", check=lambda reaction, user: 
    user == message.author and reaction.emoji in ["SomeEmoji", "SomeEmoji"], timeout=30.0)

        except asyncio.TimeoutError:
            await message.reply("Timeout bro.")
        else:
            if reaction.emoji == "":
                await message.reply('Like it.')
                await reaction.delete()

            else:
                await message.reply("NO like")
                await reaction.delete()

I want to know how to remove the specific reaction on each click. Currently, this code is not working as expected.


Solution

  • You first get the reaction object, then you remove it. Docs

    Code:

    @bot.slash_command(name='removereaction', description="I'm helping someone with their Stack post")
    async def removereaction(ctx, message: discord.Option(discord.Message)):
        print(message)
        for i in message.reactions:
            async for user in i.users():
                await i.remove(user)
        await ctx.respond(message.reactions)
    

    How this works is it gets the message from the parameter message that has type discord.Option. The discord.Option is set so that you can use a message from a link or ID. Then, it uses this to cycle through all of the message's reactions. Then it cycles through each user that reacted with said reaction. It must be async, because i.users() is async (See here).

    The full code that may help you:

    import discord
    from discord.ext import commands
    
    intents = discord.Intents().all()
    
    bot = commands.Bot(intents=intents)
    
    @bot.event
    
    async def on_message(message):
        if message.author == bot.user:
            return
        if message.content == 'test':
            me = await message.reply('Is this cool?')
            await me.add_reaction("👎")
            await me.add_reaction("👍")
            try:
                reaction, user = await bot.wait_for("reaction_add", check=lambda reaction, user: 
    user == message.author and reaction.emoji in ["👎", "👍"], timeout=30.0)
    
    
            except asyncio.TimeoutError:
                await message.reply("Tmieout bro")
            else:
                if reaction.emoji == "👍":
                    await message.reply('Like it.')
                    async for user in reaction.users():
                        await reaction.remove(user)
    
                else:
                    await message.reply("NO like")
                    async for user in reaction.users():
                        await reaction.remove(user)
                    
    

    If you want to remove JUST the bot's reactions change the following line:

    async for user in reaction.users():
                            await reaction.remove(user)
    

    To:

        await reaction.remove(bot.user)