Skip to content

Commit 8948a52

Browse files
Properly implement qualified_name and command.id temporarily
1 parent 8d8f389 commit 8948a52

File tree

2 files changed

+55
-16
lines changed

2 files changed

+55
-16
lines changed

discord/bot.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ async def register_commands(self) -> None:
192192
guild_ids=None,
193193
type=i["type"],
194194
)
195-
self.application_commands[i["id"]] = cmd
195+
cmd.id = i["id"]
196+
self.application_commands[cmd.id] = cmd
196197

197198
# Permissions (Roles will be converted to IDs just before Upsert for Global Commands)
198199
global_permissions.append({"id": i["id"], "permissions": cmd.permissions})
@@ -226,7 +227,8 @@ async def register_commands(self) -> None:
226227
else:
227228
for i in cmds:
228229
cmd = find(lambda cmd: cmd.name == i["name"] and cmd.type == i["type"] and int(i["guild_id"]) in cmd.guild_ids, self.pending_application_commands)
229-
self.application_commands[i["id"]] = cmd
230+
cmd.id = i["id"]
231+
self.application_commands[cmd.id] = cmd
230232

231233
# Permissions
232234
permissions = [

discord/commands/commands.py

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,36 @@ async def call_after_hooks(self, ctx: ApplicationContext) -> None:
287287
if hook is not None:
288288
await hook(ctx)
289289

290+
@property
291+
def full_parent_name(self) -> str:
292+
""":class:`str`: Retrieves the fully qualified parent command name.
293+
294+
This the base command name required to execute it. For example,
295+
in ``/one two three`` the parent name would be ``one two``.
296+
"""
297+
entries = []
298+
command = self
299+
while command.parent is not None and hasattr(command.parent, "name"):
300+
command = command.parent
301+
entries.append(command.name)
302+
303+
return ' '.join(reversed(entries))
304+
305+
def qualified_name(self) -> str:
306+
""":class:`str`: Retrieves the fully qualified command name.
307+
308+
This is the full parent name with the command name as well.
309+
For example, in ``/one two three`` the qualified name would be
310+
``one two three``.
311+
"""
312+
313+
parent = self.full_parent_name
314+
315+
if parent:
316+
return parent + ' ' + self.name
317+
else:
318+
return self.name
319+
290320
class SlashCommand(ApplicationCommand):
291321
r"""A class that implements the protocol for a slash command.
292322
@@ -305,6 +335,9 @@ class SlashCommand(ApplicationCommand):
305335
The ids of the guilds where this command will be registered.
306336
options: List[:class:`Option`]
307337
The parameters for this command.
338+
parent: Optional[:class:`SlashCommandGroup`]
339+
The parent group that this command belongs to. ``None`` if there
340+
isn't one.
308341
default_permission: :class:`bool`
309342
Whether the command is enabled by default when it is added to a guild.
310343
permissions: List[:class:`Permission`]
@@ -342,6 +375,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None:
342375
name = kwargs.get("name") or func.__name__
343376
validate_chat_input_name(name)
344377
self.name: str = name
378+
self.id = None
345379

346380
description = kwargs.get("description") or (
347381
inspect.cleandoc(func.__doc__).splitlines()[0]
@@ -350,7 +384,9 @@ def __init__(self, func: Callable, *args, **kwargs) -> None:
350384
)
351385
validate_chat_input_description(description)
352386
self.description: str = description
353-
self.is_subcommand: bool = False
387+
self.parent = kwargs.get('parent')
388+
self.is_subcommand: bool = self.parent is not None
389+
354390
self.cog = None
355391

356392
params = self._get_signature_parameters()
@@ -509,8 +545,6 @@ async def invoke_autocomplete_callback(self, interaction: Interaction):
509545
]
510546
return await interaction.response.send_autocomplete_result(choices=choices)
511547

512-
def qualified_name(self):
513-
return self.name
514548

515549
def copy(self):
516550
"""Creates a copy of this command.
@@ -593,7 +627,7 @@ def __init__(
593627
minmax_types = (int, float)
594628
else:
595629
minmax_types = (type(None),)
596-
minmax_typehint = Optional[Union[minmax_types]]
630+
minmax_typehint = Optional[Union[minmax_types]] # type: ignore
597631

598632
self.min_value: minmax_typehint = kwargs.pop("min_value", None)
599633
self.max_value: minmax_typehint = kwargs.pop("max_value", None)
@@ -664,8 +698,9 @@ class SlashCommandGroup(ApplicationCommand, Option):
664698
The description for the command.
665699
guild_ids: Optional[List[:class:`int`]]
666700
The ids of the guilds where this command will be registered.
667-
parent_group: Optional[:class:`SlashCommandGroup`]
668-
The parent group of this group.
701+
parent: Optional[:class:`SlashCommandGroup`]
702+
The parent group that this group belongs to. ``None`` if there
703+
isn't one.
669704
subcommands: List[Union[:class:`SlashCommand`, :class:`SlashCommandGroup`]]
670705
The list of all subcommands under this group.
671706
cog: Optional[:class:`Cog`]
@@ -691,7 +726,7 @@ def __init__(
691726
name: str,
692727
description: str,
693728
guild_ids: Optional[List[int]] = None,
694-
parent_group: Optional[SlashCommandGroup] = None,
729+
parent: Optional[SlashCommandGroup] = None,
695730
**kwargs
696731
) -> None:
697732
validate_chat_input_name(name)
@@ -703,7 +738,7 @@ def __init__(
703738
)
704739
self.subcommands: List[Union[SlashCommand, SlashCommandGroup]] = []
705740
self.guild_ids = guild_ids
706-
self.parent_group = parent_group
741+
self.parent = parent
707742
self.checks = []
708743

709744
self._before_invoke = None
@@ -723,26 +758,25 @@ def to_dict(self) -> Dict:
723758
"options": [c.to_dict() for c in self.subcommands],
724759
}
725760

726-
if self.parent_group is not None:
761+
if self.parent is not None:
727762
as_dict["type"] = self.input_type.value
728763

729764
return as_dict
730765

731766
def command(self, **kwargs) -> SlashCommand:
732767
def wrap(func) -> SlashCommand:
733-
command = SlashCommand(func, **kwargs)
734-
command.is_subcommand = True
768+
command = SlashCommand(func, parent=self, **kwargs)
735769
self.subcommands.append(command)
736770
return command
737771

738772
return wrap
739773

740774
def command_group(self, name, description) -> SlashCommandGroup:
741-
if self.parent_group is not None:
775+
if self.parent is not None:
742776
# TODO: Improve this error message
743777
raise Exception("Subcommands can only be nested once")
744778

745-
sub_command_group = SlashCommandGroup(name, description, parent_group=self)
779+
sub_command_group = SlashCommandGroup(name, description, parent=self)
746780
self.subcommands.append(sub_command_group)
747781
return sub_command_group
748782

@@ -817,9 +851,12 @@ def __init__(self, func: Callable, *args, **kwargs) -> None:
817851

818852
self.validate_parameters()
819853

820-
# Context Commands don't have permissions
854+
# Context Menu commands don't have permissions
821855
self.permissions = []
822856

857+
# Context Menu commands can't have parents
858+
self.parent = None
859+
823860
def validate_parameters(self):
824861
params = self._get_signature_parameters()
825862
if list(params.items())[0][0] == "self":

0 commit comments

Comments
 (0)