1

If I send out a request to a user for them to reply to a yes or no question, how can I make it such that after a certain amount of time, the question expires and is no longer accepting replies?

Background

I'm currently working on a discord.py bot, and I'm getting to the part where I start scanning the messages for user input. How it works is that somebody can challenge someone to a game of tic tac toe, and then the challenged person has 10 seconds to reply with yes or no. How can I make it such that after 10 seconds, the challenge expires?

Examples

One example I thought of is the bot Dank Memer. If you challenge someone to a tic tac toe game on there, then the challenged person has to respond to you within a time limit, or else the challenge expires. It also works with commands like pls trivia, where after 10 seconds it stops accepting answers to the question.

I'm pretty sure that people have already asked this question, but I have looked over and over on Google and I can't find a solution. It's probably because of my wording, I think.

It's also hard for me to do a minimal-reproducible example, as that would require you guys to have to create a discord account and token for the bot, which is not at all efficient.

PythonPikachu8
  • 359
  • 2
  • 11
  • Regarding your minimum reproducible example, just include it, it doesn't matter if it requires us to create a bot or an app. your question is regarding code, its better to include the code. – Ceres Apr 03 '21 at 04:43
  • `Bot.wait_for(...)` has an argument `timeout` which can be used to accomplish this. `Bot.wait_for(timeout=time_in_seconds, ...)` – NikoX Apr 03 '21 at 11:02

3 Answers3

2

You can use a await client.wait_for(check=check). Check is a function you must define that needs to return either true or false. Within check, you can add various conditions and actions if you need to. I made a command that does a math equation with it, if you'd like to see an example.

WBMJunior
  • 46
  • 4
1

You can try using bot.wait_for() with a check and time out.

import asyncio

@bot.command()
async def tic_tac_toe(ctx):
    def check(m):
        # returns whether the author of the (input) message is the author of the
        # command and whether the channel of the message is the channel of the command
        return m.author == ctx.author and m.channel == ctx.channel

    # asking the question
    await ctx.send("Do you want to play a game of tic tac toe? Respond with yes or no within 10 seconds.")
    
    try:
        # storing the response in a variable, adding the check
        # and setting timeout to 10 seconds (float)
        response = await bot.wait_for('message', check=check, timeout=10.0)

        if response.content == 'yes':
            # whatever action
        else:
            # whatever action

    # now comes the real part
    except asyncio.TimeOutError:
        await ctx.send("Aw man! You did not respond within ten seconds... try again!")
Supreme1707
  • 158
  • 1
  • 8
0

I havent tried making it myself (good thing I used discord.js before), but for this, I would first prompt the yes/no question, then use sleep() from python's time module, after sleep() has yielded, if there was no response, say that no more responses will be accepted

the general idea is this

channels with a prompted question = {}

def prompt question(...):
   display the question
   channels[this channel id] = some function to handle responses for the question

   sleep for N seconds
   
   if this channel id in channels:
      announce in channel that prompt has timed out
      channels.pop(this channel id)

def handle message in a channel(...):
   if channel id in channels:
      channels[channel id](...) # run the prompt's function

prompt question() is called when prompting the question in a discord channel handle message in a channel() is called when a message is received in a channel and the function you'd insert into the channels dictionary would check if a message is valid for the prompt, handle the response, and pop it from the channels dictionary when it's complete

(sorry, I'm on mobile, so my formate sucks)

Steve
  • 88
  • 8