mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-06-07 20:28:38 +00:00
[commands] Fix nested hybrid groups inserting manual app commands
This commit is contained in:
parent
c7f6e95f1c
commit
69e9bc9454
@ -305,6 +305,7 @@ class Cog(metaclass=CogMeta):
|
||||
|
||||
# Register the application commands
|
||||
children: List[Union[app_commands.Group, app_commands.Command[Self, ..., Any]]] = []
|
||||
app_command_refs: Dict[str, Union[app_commands.Group, app_commands.Command[Self, ..., Any]]] = {}
|
||||
|
||||
if cls.__cog_is_app_commands_group__:
|
||||
group = app_commands.Group(
|
||||
@ -331,6 +332,16 @@ class Cog(metaclass=CogMeta):
|
||||
# Get the latest parent reference
|
||||
parent = lookup[parent.qualified_name] # type: ignore
|
||||
|
||||
# Hybrid commands already deal with updating the reference
|
||||
# Due to the copy below, so we need to handle them specially
|
||||
if hasattr(parent, '__commands_is_hybrid__') and hasattr(command, '__commands_is_hybrid__'):
|
||||
app_command: Optional[Union[app_commands.Group, app_commands.Command[Self, ..., Any]]] = getattr(
|
||||
command, 'app_command', None
|
||||
)
|
||||
updated = app_command_refs.get(command.qualified_name)
|
||||
if app_command and updated:
|
||||
command.app_command = updated # type: ignore # Safe attribute access
|
||||
|
||||
# Update our parent's reference to our self
|
||||
parent.remove_command(command.name) # type: ignore
|
||||
parent.add_command(command) # type: ignore
|
||||
@ -345,6 +356,11 @@ class Cog(metaclass=CogMeta):
|
||||
# The type checker does not see the app_command attribute even though it exists
|
||||
command.app_command = app_command # type: ignore
|
||||
|
||||
# Update all the references to point to the new copy
|
||||
if isinstance(app_command, app_commands.Group):
|
||||
for child in app_command.walk_commands():
|
||||
app_command_refs[child.qualified_name] = child
|
||||
|
||||
if self.__cog_app_commands_group__:
|
||||
children.append(app_command) # type: ignore # Somehow it thinks it can be None here
|
||||
|
||||
|
@ -397,3 +397,85 @@ def test_cog_group_with_custom_state_issue9383():
|
||||
assert cog.inner.my_command.parent is cog.inner
|
||||
assert cog.my_inner_command.parent is cog.inner
|
||||
assert cog.my_inner_command.binding is cog
|
||||
|
||||
|
||||
def test_cog_hybrid_group_manual_command():
|
||||
class MyCog(commands.Cog):
|
||||
@commands.hybrid_group()
|
||||
async def first(self, ctx: commands.Context) -> None:
|
||||
...
|
||||
|
||||
@first.command(name='both')
|
||||
async def second_both(self, ctx: commands.Context) -> None:
|
||||
...
|
||||
|
||||
@first.app_command.command(name='second')
|
||||
async def second_app(self, interaction: discord.Interaction) -> None:
|
||||
...
|
||||
|
||||
client = discord.Client(intents=discord.Intents.default())
|
||||
tree = app_commands.CommandTree(client)
|
||||
|
||||
cog = MyCog()
|
||||
tree.add_command(cog.first.app_command)
|
||||
|
||||
assert cog.first is not MyCog.first
|
||||
assert cog.second_both is not MyCog.second_both
|
||||
assert cog.second_app is not MyCog.second_app
|
||||
assert cog.first.parent is None
|
||||
assert cog.second_both.parent is cog.first
|
||||
assert cog.second_app.parent is cog.first.app_command
|
||||
assert cog.second_app.binding is cog
|
||||
assert tree.get_command('first') is cog.first.app_command
|
||||
|
||||
first = tree.get_command('first')
|
||||
assert isinstance(first, app_commands.Group)
|
||||
both = first.get_command('both')
|
||||
assert isinstance(both, app_commands.Command)
|
||||
assert both.parent is first
|
||||
assert both.binding is cog
|
||||
|
||||
second = first.get_command('second')
|
||||
assert isinstance(second, app_commands.Command)
|
||||
assert second.parent is first
|
||||
assert second.binding is cog
|
||||
|
||||
|
||||
def test_cog_hybrid_group_manual_nested_command():
|
||||
class MyCog(commands.Cog):
|
||||
@commands.hybrid_group()
|
||||
async def first(self, ctx: commands.Context) -> None:
|
||||
pass
|
||||
|
||||
@first.group()
|
||||
async def second(self, ctx: commands.Context) -> None:
|
||||
pass
|
||||
|
||||
@second.app_command.command()
|
||||
async def third(self, interaction: discord.Interaction) -> None:
|
||||
pass
|
||||
|
||||
client = discord.Client(intents=discord.Intents.default())
|
||||
tree = app_commands.CommandTree(client)
|
||||
|
||||
cog = MyCog()
|
||||
tree.add_command(cog.first.app_command)
|
||||
|
||||
assert cog.first is not MyCog.first
|
||||
assert cog.second is not MyCog.second
|
||||
assert cog.third is not MyCog.third
|
||||
assert cog.first.parent is None
|
||||
assert cog.second.parent is cog.first
|
||||
assert cog.third.parent is cog.second.app_command
|
||||
assert cog.third.binding is cog
|
||||
|
||||
first = tree.get_command('first')
|
||||
assert isinstance(first, app_commands.Group)
|
||||
|
||||
second = first.get_command('second')
|
||||
assert isinstance(second, app_commands.Group)
|
||||
|
||||
third = second.get_command('third')
|
||||
assert isinstance(third, app_commands.Command)
|
||||
assert third.parent is second
|
||||
assert third.binding is cog
|
||||
|
Loading…
x
Reference in New Issue
Block a user