0

I have a timer command in my bot, it uses asyncio.sleep. I want to make a command to cancel the timer if the user wishes to do so.

@bot.command()
async def timer(ctx, time: int):
   await ctx.send('Timer set for ' + str(time) + ' seconds')
   await asyncio.sleep(time)
   await ctx.send('Time over!')

Is there a way to do so, ( ill prefer a method without making a new file, do it in the same file)

Ashhar Amir
  • 38
  • 3
  • 9

1 Answers1

0

Referencing Interrupt all asyncio.sleep currently executing

Credits to https://stackoverflow.com/users/2846140/vincent for the asyncio code.

You can add this function (by vincent):

def make_sleep():
    async def sleep(delay, result=None, *, loop=None):
        coro = asyncio.sleep(delay, result=result, loop=loop)
        task = asyncio.ensure_future(coro)
        sleep.tasks.add(task)
        try:
            return await task
        except asyncio.CancelledError:
            return result
        finally:
            sleep.tasks.remove(task)

    sleep.tasks = set()
    sleep.cancel_all = lambda: sum(task.cancel() for task in sleep.tasks)
    return sleep

And the usage in this case would be:

@bot.command()
async def timer(ctx, time: int):
   await ctx.send('Timer set for ' + str(time) + ' seconds')
   await sleep(time)
   await ctx.send('Time over!')

@bot.command()
async def canceltimers(ctx):
    sleep.cancel_all()
    await asyncio.wait(sleep.tasks)
    await ctx.send('Timers cancelled')

Where you will have your bot.run(token) just before it put sleep = make_sleep() or it will not work.

Now, the problem we face now is that with this code; we cancel all of the timers; which is of course not what we want as there would be obvious conflicts. How you could go about doing this is purely up to you; but you could try to add an identifier in the sleep function which is stored by userID. It's really up to you, but this is the theory and basic code behind it.

damaredayo
  • 1,048
  • 6
  • 19