This gist shows how to make the bot wait for a message or reaction after doing a command. This should not be copypasted.
Check the discord.py docs for a detailed explanation of how it all works internally and which kwargs it takes.
See here two commands, one waiting for any message in a channel and the other waiting for a reaction with a specific emoji.
Both examples have a check that checks if the author and channel matches with the context.
Need to wait for X in dms? Replace the channel check with a check for the guild like so, <message>.guild is None
.
import asyncio
import discord
@bot.command(name="messagecheck")
async def message_check(ctx): # waiting for message here
await ctx.send(f"**{ctx.author}**, send anything in 60 seconds!")
def check(m: discord.Message): # m = discord.Message.
return m.author.id == ctx.author.id and m.channel.id == ctx.channel.id
# checking author and channel, you could add a line to check the content.
# and m.content == "xxx"
# the check won't become True until it detects (in the example case): xxx
# but that's not what we want here.
# Waiting for a number?
# str has a method called "isdigit" that returns True -
# - if the string is a number
# so.. we can add something like following in the check:
# m.content.isdigit()
# and now the won't become True
# until the content is all numbers, no letters.
try:
# event = on_message without on_
msg = await bot.wait_for('message', check = check, timeout = 60.0)
# msg = discord.Message
except asyncio.TimeoutError:
# at this point, the check didn't become True, let's handle it.
await ctx.send(f"**{ctx.author}**, you didn't send any message that meets the check in this channel for 60 seconds..")
return
else:
# at this point, the check has become True and the wait_for has done its work, now we can do ours.
# we could also do things based on the message content here, like so
# if msg.content == "this is cool":
# return await ctx.send("wait_for is indeed a cool method")
await ctx.send(f"**{ctx.author}**, you responded with {msg.content}!")
return
# invoke: [p]messagecheck
import asyncio
import discord
from typing import Union
@bot.command(name="reactiontest")
async def reaction_test(ctx): # waiting for reactions (✅, ❌) here
await ctx.send(f"**{ctx.author}**, please react with :white_check_mark: or :x: on this message in 60 seconds")
def check(r: discord.Reaction, u: Union[discord.Member, discord.User]): # r = discord.Reaction, u = discord.Member or discord.User.
return u.id == ctx.author.id and r.message.channel.id == ctx.channel.id and \
str(r.emoji) in ["\U00002705", "\U0000274c"]
# checking author, channel and only having the check become True when detecting a ✅ or ❌
# else, it will timeout.
try:
# event = on_reaction_add without on_
reaction, user = await bot.wait_for('reaction_add', check = check, timeout = 60.0)
# reaction = discord.Reaction, user = discord.Member or discord.User.
except asyncio.TimeoutError:
# at this point, the check didn't become True.
await ctx.send(f"**{ctx.author}**, you didnt react with a ✅ or ❌ in 60 seconds.")
return
else:
# at this point, the check has become True and the wait_for has done its work, now we can do ours.
# here we are sending some text based on the reaction we detected.
# unicode for ✅ :
# https://emojipedia.org/emoji/✅/#:~:text=Codepoints
if str(reaction.emoji) == "\U00002705":
return await ctx.send(f"{ctx.author} reacted with a ✅")
# or we could also add a role here, like so
# role = await ctx.guild.get_role(ROLE_ID)
# await ctx.author.add_roles(role)
# unicode for ❌ :
# https://emojipedia.org/emoji/❌/#:~:text=Codepoints
if str(reaction.emoji) == "\U0000274c":
return await ctx.send(f"{ctx.author} reacted with a ❌")
Hi, i would like to know if it possible to combine bot code on single command?
For example: i would like to make a bot where it return a list of link but i made it in multiple pages. Then the user can choose the number on the list by sending message.
It basically just both the code above combined but i don't know how to do that, searching on google didn't help.
Thanks