Running two loops at the same time on my discord bot

Viewed 573

So my discord bot in python has the task to send an embed as soon as the user sends the message "$start". After this the code is starting a while loop and checking if a user has reacted. Simultaneously I want to edit the message of the bot every second so I can display some kind of timer to show the users how much time they have left to react but I dont know how to implement a timer running at the same time. Would it be useful to use multiprocessing for this one? Here is my very specific code if anyone needs it to answer my question :)

@client.command()
async def start(ctx):
    timer = 120
    remTime = timer
    seedCapital = 10000
    sessionEmpty = True

players[ctx.author] = seedCapital

em = discord.Embed(title = "New Poker Session", description = "Waiting for players to join ...\nreact with  to join or ▶️ to start (only host)", color = discord.Color.green())
#em.add_field(name = "2 minutes remaining from now on!", value = "")
botMsg = await ctx.send(embed = em)
await botMsg.add_reaction("")
await botMsg.add_reaction("▶️")

while True:
    mom0 = time.perf_counter()
    try:
        reaction, user = await client.wait_for('reaction_add', timeout = remTime, check = lambda reaction, user: reaction.emoji in ["", "▶️"])
        #msg = await client.wait_for('message', timeout = remTime, check = lambda m: m.channel == ctx.channel)
        #print(f"receiving message: {msg.content}")
    except asyncio.TimeoutError:
        break

    if reaction.emoji == "":
        sessionEmpty = False
        await ctx.send(f"{user.mention} joined the session!")
        players[user] = seedCapital
    elif user == ctx.author and reaction.emoji == "▶️":
        break

    mom1 = time.perf_counter()
    neededTime = mom1 - mom0
    remTime -= neededTime
    print(remTime)

if not sessionEmpty:
    await ctx.send("starting session ...")
    #start session
else:
    await ctx.send("Noone joined your session :(")
1 Answers

We can use asyncio.gather to run coroutines concurrently.

#after command
from datetime import datetime, timedelta

end_time = datetime.now() + timedelta(seconds=30) #30 seconds to react

async def coro():
   for i in range(30, 0, 5):
       await botMsg.edit(f'time remaining: {i}') #send another message if you don't want old content to be erased
       await asyncio.sleep(5)

async def coro2():
   while datetime.now() <= endtime:
      #do stuff

await asyncio.gather(coro(), coro2())

Note: There might be a small delay between the completion of the two coroutines.

References:

Edit: Here is the small delay I mentioned Open In Colab

Related