Skip to content

Instantly share code, notes, and snippets.

@Soheab
Last active July 11, 2023 16:56
Show Gist options
  • Save Soheab/e73ab6f66881ee4102be37815da3a24e to your computer and use it in GitHub Desktop.
Save Soheab/e73ab6f66881ee4102be37815da3a24e to your computer and use it in GitHub Desktop.
Examples for a wait_for in ext.commands.

This gist shows how to make the bot wait for a message or reaction after doing a command. This should not be copypasted.

Docs

Check the discord.py docs for a detailed explanation of how it all works internally and which kwargs it takes.

Commands

See here two commands, one waiting for any message in a channel and the other waiting for a reaction with a specific emoji.

Check

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.

Message:

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

Reaction:

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 ❌")
@enzo405
Copy link

enzo405 commented Mar 13, 2022

is this possible to make the 2nd part in DM ??? because it's been 2d i don't get it !! please help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment