I'm quite new to both Python and Discord.py, and I'm trying to find how to make the bot wait for either a message or reaction from user at the same time.
I tried separating each but just resulted in the bot needing a message response before a reaction.
Here's a similar code I'm trying to do:
@bot.event
async def on_message(ctx):
if ctx.author == bot.user:
return
if ctx.content == "$respond":
message = await ctx.send("Waiting for response...")
while True:
try:
response = #Will wait for a message(Yes or No) or reaction(Check or Cross) from ctx.author for 30 secs
except asyncio.TimeoutError:
await message.edit(content=f"{ctx.author} did not respond anymore!")
break
if response.content == "yes":
await message.edit(content=f"{ctx.author} said yes!")
continue
elif response.content == "no":
await message.edit(content=f"{ctx.author} said nyo!")
continue
#These are reactions
elif str(response.emoji) == "✅":
await message.edit(content=f"ctx.author reacted ✅!")
continue
elif str(response.emoji) == "❌":
await messave.edit(content=f"Stopped listening to responses.")
break
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 :

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"))
which would get you the same result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With