[Python] How to inject arguments from a custom decorator to a command in discord.py?

Discussão em 'Python' iniciado por Stack, Fevereiro 9, 2025.

  1. Stack

    Stack Membro Participativo

    I'm working on a bot which keeps track of various text-based games in different channels. Commands used outside the channel in which the relevant game is running should do nothing of course, and neither should they activate is the game is not running (for example, when a new game is starting soon). Therefore, almost all my commands start with the same few lines of code

    @commands.command()
    async def example_command(self, ctx):
    game = self.game_manager.get_game(ctx.channel.id)
    if not game or game.state == GameState.FINISHED:
    return


    I'd prefer to just decorate all these methods instead. Discord.py handily provides a system of "check" decorators to automate these kinds of checks, but this does not allow me to pass on the game object to the command. As every command needs a reference to this object, I'd have to retrieve it every time again anyway, and ideally I'd like to just pass it along to the command.

    My naive attempt at a decorator looks as follows

    def is_game_running(func):
    async def wrapper(self, ctx):
    # Retrieve `game` object here and do some checks
    game = ...

    return await func(self, ctx, game)

    wrapper.__name__ = func.__name__

    return wrapper

    # Somewhere in the class
    @commands.command()
    @is_game_running
    async def example_command(self, ctx, game):
    pass


    However this gives me the quite cryptic error "discord.ext.commands.errors.MissingRequiredArgument: ctx is a required argument that is missing."

    I've tried a few variants of this, using *args etc... but nothing seems to work.

    Continue reading...

Compartilhe esta Página