Send a message based on a user reaction discord.py

Viewed 3121

I would like my discord bot to respond with a certain message back within a server based on the reaction given by the user: either or .

I am not too familiar with discord.py and the docs I have read are slightly confusing, I followed a youtube tutorial and made edits. I get to see the reaction printed in the console, however I get the error message:

Instance of 'Bot' has no 'channel' member

Here is my code:

import os
import datetime
import discord
from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

client = commands.Bot(command_prefix = '!')

@client.event
async def on_ready():
    print('Bot is logged in.')

@client.command(name='feedback', help='Ask person for feedback')
async def roll(ctx):
    await ctx.send('Are you enjoying this bot? \n :thumbsup: :-1: ')

@client.event
async def on_raw_reaction_add(reaction, user):
    print(reaction.emoji)
    channel = reaction.message.channel
    await client.channel.send_message(channel, reaction.emoji)
    if reaction.emoji == ':thumbsup:':
        await client.channel.send_message(channel, 'Thank you for your feedback')
    elif reaction.emoji == ':-1:':
        await client.channel.send_message(channel, 'Sorry you feel that way')

client.run(TOKEN)

All help greatly appreciated

1 Answers

Instead of using the on_raw_reaction_add event, it's better in this case to use a wait_for command event. This would mean the event can only be triggered once and only when the command was invoked. However with your current event, this allows anyone to react to a message with that emoji and the bot would respond.

By using client.wait_for("reaction_add"), this would allow you to control when a user can react to the emoji. You can also add checks, this means only the user would be able to use the reactions on the message the bot sends. Other parameters can be passed, but it's up to you how you want to style it.

In the example below shows, the user can invoke the command, then is asked to react with a thumbs up or thumbs down. The bot already adds these reactions, so the user would only need to react. The wait_for attribute would wait for the user to either react with the specified emojis and your command would send a message.

Here is the example applied in your code.

@client.command(name='feedback', help='Ask person for feedback')
async def roll(ctx):
    message = await ctx.send('Are you enjoying this bot? \n :thumbsup: :-1: ')

    thumb_up = ''
    thumb_down = ''

    await message.add_reaction(thumb_up)
    await message.add_reaction(thumb_down)

    def check(reaction, user):
        return user == ctx.author and str(
            reaction.emoji) in [thumb_up, thumb_down]

    member = ctx.author

    while True:
        try:
            reaction, user = await client.wait_for("reaction_add", timeout=10.0, check=check)

            if str(reaction.emoji) == thumb_up:
                await ctx.send('Thank you for your feedback')


            if str(reaction.emoji) == thumb_down:
                await ctx.send('Sorry you feel that way')

You are also getting the error, Instance of 'Bot' has no 'channel' member because you are using an event which limits attributes from the "Bot". However using this within a command allows you to use ctx.send

Related