What I'm trying to implement in my discord bot is a system that stops a running command coroutine as soon as another command is invoked by the same user, in an attempt to sort of keep a unique active session for each user.
So essentially I need to be able to access that coroutine object and stop it from within another coroutine.
What I've tried so far looks logic to me but I'm sure there is some misconception about how discord API handles coroutines. Here's a basic example:
active_sessions = {}
@bot.command()
async def first_command(ctx):
# Saving the coroutine in the dictionary with the user ID as key:
active_sessions[ctx.author.id] = ctx.command.callback
# do stuff
@bot.command()
async def second_command(ctx):
# Accessing the coroutine object and trying to stop it.
try:
coro = active_sessions[ctx.author.id]
coro.close()
except KeyError:
pass
which throws an AttributeError stating that function object has no attribute close.
But, as per discord.py docs, command.callback refers to a coroutine object that should have the close method. Also tried coro.cancel() with the same result.
I'm conceptually doing something wrong here but I'm not sure what exactly, and also I have no clue how to implement my idea correctly, so any help is very appreciated.
EDIT
So, since my goal might still be unclear, here is what I'm trying to accomplish.
I'm doing a discord bot that is sort of a game. Users can run several commands, many of which would wait for a certain amount of time for a reaction or message from the command author.
But this user might run another command without 'completing' the first one, and if they come back to the first, their reactions would still be accepted.
I'm trying to avoid this behaviour and keep the user focused on a 'single session'; whatever command they run, the execution of the previous one needs to be automatically stopped.
So how I'm implementing this, which comes from a wrong misconception of coroutines, is having a dictionary that associates each user with the loop of the command thy're currently running. If another loop starts with the other one still running, the 'old loop' would be stopped and the respective entry in the dictionary would be updated with the new loop:
active_sessions = {}
@bot.command()
async def first_command(ctx):
# In this first command I want to assign the current loop to a variable and
# add it to the active_sessions dictionary along with the ID of the command author.
# Then there's a loop that waits for user's reaction.
# Ignore the details such as the check function.
while True:
try:
reaction, user = await bot.wait_for("reaction_add",timeout=60,check=check)
# some if conditions here make the bot behave differently according
# to the specific reaction added
except asyncio.TimeoutError:
return
@bot.command()
async def second_command(ctx):
# As soon as this second command is invoked, I need to access the 'loop object'
# previously stored in the dictionary (if any) and stop it from here.