Discord.py wait for message or reaction

bot.wait_for is what you're looking for here.

I would recommend using bot.command() for command handling purposes but this is fine as well.

This is how you wait for specific events (provided as the first argument) with specific conditions (as provided in the check param)

@bot.event
async def on_message(msg):
    if msg.author == bot.user:
        # if the author is the bot itself we just return to prevent recursive behaviour
        return
    if msg.content == "$response":

        sent_message = await msg.channel.send("Waiting for response...")
        res = await bot.wait_for(
            "message",
            check=lambda x: x.channel.id == msg.channel.id
            and msg.author.id == x.author.id
            and x.content.lower() == "yes"
            or x.content.lower() == "no",
            timeout=None,
        )

        if res.content.lower() == "yes":
            await sent_message.edit(content=f"{msg.author} said yes!")
        else:
            await sent_message.edit(content=f"{msg.author} said no!")

This would result in : result

Listening for multiple events is a rather a bit interesting, Replace the existing wait_for with this snippet :

done, pending = await asyncio.wait([
                    bot.loop.create_task(bot.wait_for('message')),
                    bot.loop.create_task(bot.wait_for('reaction_add'))
                ], return_when=asyncio.FIRST_COMPLETED)

and you can listen for two events simultaneously

Here's how you can handle this using @bot.command()

import discord
import os
from discord.ext import commands

bot = commands.Bot(command_prefix="$", case_insensitive=True)


@bot.event
async def on_ready():
    print(f"Logged in as {bot.user}")


@bot.command()
async def response(ctx):
    sent_message = await ctx.channel.send("Waiting for response...")
    res = await bot.wait_for(
        "message",
        check=lambda x: x.channel.id == ctx.channel.id
        and ctx.author.id == x.author.id
        and x.content.lower() == "yes"
        or x.content.lower() == "no",
        timeout=None,
    )

    if res.content.lower() == "yes":
        await sent_message.edit(content=f"{ctx.author} said yes!")
    else:
        await sent_message.edit(content=f"{ctx.author} said no!")


bot.run(os.getenv("DISCORD_TOKEN"))

new_result which would get you the same result.