I’m working on a Discord bot that has a timer feature, but I’m running into an issue where users can start multiple timers at the same time. I need to limit it so only one timer can run at a time.
Here’s my current implementation:
import discord
import asyncio
async def start_timer(parameters, msg, bot, command):
await bot.send_message(msg.channel, "Timer: 10 minutes remaining")
await asyncio.sleep(120)
await bot.send_message(msg.channel, "Timer: 8 minutes remaining")
await asyncio.sleep(120)
await bot.send_message(msg.channel, "Timer: 6 minutes remaining")
await asyncio.sleep(120)
await bot.send_message(msg.channel, "Timer: 4 minutes remaining")
await asyncio.sleep(60)
await bot.send_message(msg.channel, "Timer: 3 minutes remaining")
await asyncio.sleep(60)
await bot.send_message(msg.channel, "Timer: 2 minutes remaining")
await asyncio.sleep(45)
await bot.send_message(msg.channel, "Timer: 1 minute remaining")
await asyncio.sleep(30)
await bot.send_message(msg.channel, "Timer: 30 seconds left")
# Error message for when timer is active
# await bot.send_message(msg.channel, embed=discord.Embed(color=discord.Color.orange(), description="Timer is currently active! Please wait until it finishes."))
Right now multiple users can trigger this timer function simultaneously, which creates chaos in the channel. How can I implement a check to ensure only one timer runs at a time?
you could also use asyncio.Event or asyncio.Lock for better thread safety. create timer_lock = asyncio.Lock() at the top, then wrap your timer code with async with timer_lock:. if someone tries starting another timer while one’s running, it’ll wait automatically. or use try_acquire() to reject it immediately. works better than boolean flags for preventing race conditions.
Just use a boolean flag to track if your timer’s running. Set up a global variable like timer_active = False and check it before starting. Flip it to True when the timer starts, back to False when it’s done:
timer_active = False
async def start_timer(parameters, msg, bot, command):
global timer_active
if timer_active:
await bot.send_message(msg.channel, embed=discord.Embed(color=discord.Color.orange(), description="Timer is currently active! Please wait until it finishes."))
return
timer_active = True
try:
# your existing timer code here
await bot.send_message(msg.channel, "Timer: 10 minutes remaining")
# ... rest of your timer logic
finally:
timer_active = False
The try/finally block makes sure the flag gets reset even if something breaks. Simple solution that’ll fix your simultaneous timer issue without making things complicated.
You can also store the timer task itself and check if it’s running. Use asyncio.create_task() to get a reference to your timer coroutine, then check its status before starting a new one:
current_timer = None
async def start_timer(parameters, msg, bot, command):
global current_timer
if current_timer and not current_timer.done():
await bot.send_message(msg.channel, embed=discord.Embed(color=discord.Color.orange(), description="Timer is currently active! Please wait until it finishes."))
return
current_timer = asyncio.create_task(run_timer(msg, bot))
await current_timer
This gives you more control over the timer lifecycle. You can cancel the existing timer with current_timer.cancel() for admin commands, which beats just tracking state with flags.
This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.