Search code examples
discorddiscord.py

Discord Bot asyncio.sleep Not Working as Intended


I am trying to create a reminder bot. Below is the section of code for the command. When I test it with the set time being within an hour, it seems to work fine. But, when I test it with the set time being a couple hours in the future, it sends the 1 hour reminder message perfect, but the 5 minute and happening now messages are sent wayyyy late, sometimes hours late. Any ideas why?

@bot.command()
async def cfgr(ctx, ac: str, date: str, time: str):
    for k, v in list(acdict.items()):
        if k == ac:
            del acdict[k]
    ac_date = date + " " + time
    acdict[ac] = ac_date
    date = date + " " + time
    date = datetime.strptime(date, "%Y-%m-%d %H:%M")
    date = date.replace(tzinfo=timezone.utc)
    to_wait = date.timestamp() - datetime.now().timestamp()
    to_wait2 = to_wait - 300
    to_wait3 = to_wait - 3600
    embed = discord.Embed(title="Configured")
    embed.add_field(name=ac + " is set for:", value=date.strftime("%Y-%m-%d %H:%M"))
    await ctx.send(embed=embed)
    await asyncio.sleep(to_wait3)
    embed = discord.Embed(title="NOTIFICATION")
    embed.add_field(name=ac + " is in 1 hour.", value="")
    await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)
    await asyncio.sleep(to_wait2)
    embed = discord.Embed(title="NOTIFICATION")
    embed.add_field(name=ac + " is in 5 minutes.", value="")
    await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)
    await asyncio.sleep(to_wait)
    embed = discord.Embed(title="NOTIFICATION")
    embed.add_field(name=ac + " is happening now!", value="")
    await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)

Solution

  • Pay attention to the code you've developed. The intervals are being calculated based on the time of creation of the alert and the end time of the notification. When you sleep successively using these intervals, their time will be added together. That's why your first alert (1 hour) is at the correct time. But the following ones are sleeping much longer than necessary. Make this change to your code and it should work correctly:

    @bot.command()
    async def cfgr(ctx, ac: str, date: str, time: str):
        for k, v in list(acdict.items()):
            if k == ac:
                del acdict[k]
        ac_date = date + " " + time
        acdict[ac] = ac_date
        date = date + " " + time
        date = datetime.strptime(date, "%Y-%m-%d %H:%M")
        date = date.replace(tzinfo=timezone.utc)
        to_wait = date.timestamp() - datetime.utcnow().timestamp() - 3600
        embed = discord.Embed(title="Configured")
        embed.add_field(name=ac + " is set for:", value=date.strftime("%Y-%m-%d %H:%M"))
        await ctx.send(embed=embed)
        await asyncio.sleep(to_wait)
        embed = discord.Embed(title="NOTIFICATION")
        embed.add_field(name=ac + " is in 1 hour.", value="")
        await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)
        await asyncio.sleep(3600-300)
        embed = discord.Embed(title="NOTIFICATION")
        embed.add_field(name=ac + " is in 5 minutes.", value="")
        await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)
        await asyncio.sleep(300)
        embed = discord.Embed(title="NOTIFICATION")
        embed.add_field(name=ac + " is happening now!", value="")
        await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)