Rapptz / discord.py

An API wrapper for Discord written in Python.
http://discordpy.rtfd.org/en/latest
MIT License
14.72k stars 3.74k forks source link

the "is_owner" check used on cog commands is conflicting with "on_command" #1789

Open tesence opened 5 years ago

tesence commented 5 years ago

If you use the decorator @commands.is_owner() (and maybe other decorators aswell), on a command defined in a cog and you print the value of ctx.command.name in on_command as follow

async def on_command(self, ctx):
    print(f"Invoked command: {ctx.command.name}")

and invoke the default help command, on_command will pint the name of the command using that check that has been loaded the first.

Minimal test case (tested on rewrite, not async)

class Bot(commands.Bot):

async def on_command(self, ctx):
    print(f"Invoked command: {ctx.command.name}")

bot = Bot(command_prefix="!") bot.load_extension("cog") bot.load_extension("cog2") bot.run("")


* in `cog.py`

from discord.ext import commands

class HelloWorldCog:

def __init__(self, bot):
    self.bot = bot

@commands.command()
@commands.is_owner()
async def hello_world(self, ctx):
    await ctx.send("Hello world")

def setup(bot): bot.add_cog(HelloWorldCog(bot))


* in `cog2.py`

from discord.ext import commands

class HelloWorldCog2:

def __init__(self, bot):
    self.bot = bot

@commands.command()
@commands.is_owner()
async def hello_world2(self, ctx):
    await ctx.send("Hello world")

def setup(bot): bot.add_cog(HelloWorldCog2(bot))


If you run that code and invoke the default `help` command, `on command` will print:
`Invoked command: hello_world`

If you switch these 2 lines from:

bot.load_extension("cog") bot.load_extension("cog2")

 to

bot.load_extension("cog2") bot.load_extension("cog")


 then run the bot again and invoke the default `help` command, `on_command` will print:
`Invoked command: hello_world2`
NCPlayz commented 5 years ago

Can reproduce... sort of. Since this is an old error, had to convert to the new Cog style, just subclassing commands.Cog worked fine.

Version Information

  • Python v3.7.3-final
  • discord.py v1.2.0-alpha -- 007b7eb
    • discord.py pkg_resources: v1.0.0a1718+g42a7c4f
  • aiohttp v3.5.4
  • websockets v6.0
  • system info: Windows 10 10.0.18362

Results

cog.py loaded first, then cog2.py.

Invoked command: hello_world2

cog2.py loaded first, then cog.py.

Invoked command: hello_world

scrazzz commented 3 years ago

CR. When loading cog.py first, then cog2.py, invoking the default help command prints "Invoked command: hello_world".

When loading cog2.py first, then cog.py, invoking the default help command prints "Invoked command: hello_world2".

ooliver1 commented 2 years ago

my findings have shown that:

this stashing of the current instance causes issues https://github.com/Rapptz/discord.py/blob/master/discord/ext/commands/core.py#L1232-L1233 as the command is never reset at https://github.com/Rapptz/discord.py/blob/master/discord/ext/commands/core.py#L1252 then a race condition can occur when the help command invokes can_run on each command