How can I run a command from another command?

Viewed 188

I'm trying to write a Discord bot, where if I run a certain command, a part of the program will run, but the other part won't.

For example: In my case, when they type in "?m", they will get a message saying "xy", but then for 90 seconds, they won't be able to call that command again. If they do call it in this 90 second period, another command called "?x" will run.

Can someone help me out?

2 Answers

You can do it using bot.invoke() method:

@bot.command()
async def x(ctx):
    pass  # whatever here


@bot.command()
async def m(ctx):
    if something:
        ctx.command = bot.get_command("x")
        await bot.invoke(ctx)  # invoke a command called x

With Python's time module, you can check how long it's been since the command was last successfully called. time.time() returns the current time (expressed as a number of seconds since January 1st, 1970).

Calling one command from within another can be as simple as calling it with await, like any other coroutine, and passing the same context to it.

import time
from discord.ext.commands import Bot
from tokens import TOKEN

bot = Bot(command_prefix='?')
# Set the initial time as 0 (effectly 1970) so it was definitely long
# ago for the command to now be called.
last_called = 0

@bot.command()
async def hi(ctx):
    # Compare the current time to when the command was last successfully
    # called.
    global last_called
    now = time.time()
    if now - last_called <= 90:
        await not_now(ctx)
    else:
        last_called = now
        await ctx.send('Hello')

@bot.command()
async def not_now(ctx):
    await ctx.send('Please wait a minute.')

bot.run(TOKEN)

Using global variables is not generally the best idea, but unfortunately subclassing Bot for tidier encapsulation of data into a single object is quite clunky.

Related