@@ -287,6 +287,36 @@ async def call_after_hooks(self, ctx: ApplicationContext) -> None:
287
287
if hook is not None :
288
288
await hook (ctx )
289
289
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
+
290
320
class SlashCommand (ApplicationCommand ):
291
321
r"""A class that implements the protocol for a slash command.
292
322
@@ -305,6 +335,9 @@ class SlashCommand(ApplicationCommand):
305
335
The ids of the guilds where this command will be registered.
306
336
options: List[:class:`Option`]
307
337
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.
308
341
default_permission: :class:`bool`
309
342
Whether the command is enabled by default when it is added to a guild.
310
343
permissions: List[:class:`Permission`]
@@ -342,6 +375,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None:
342
375
name = kwargs .get ("name" ) or func .__name__
343
376
validate_chat_input_name (name )
344
377
self .name : str = name
378
+ self .id = None
345
379
346
380
description = kwargs .get ("description" ) or (
347
381
inspect .cleandoc (func .__doc__ ).splitlines ()[0 ]
@@ -350,7 +384,9 @@ def __init__(self, func: Callable, *args, **kwargs) -> None:
350
384
)
351
385
validate_chat_input_description (description )
352
386
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
+
354
390
self .cog = None
355
391
356
392
params = self ._get_signature_parameters ()
@@ -509,8 +545,6 @@ async def invoke_autocomplete_callback(self, interaction: Interaction):
509
545
]
510
546
return await interaction .response .send_autocomplete_result (choices = choices )
511
547
512
- def qualified_name (self ):
513
- return self .name
514
548
515
549
def copy (self ):
516
550
"""Creates a copy of this command.
@@ -593,7 +627,7 @@ def __init__(
593
627
minmax_types = (int , float )
594
628
else :
595
629
minmax_types = (type (None ),)
596
- minmax_typehint = Optional [Union [minmax_types ]]
630
+ minmax_typehint = Optional [Union [minmax_types ]] # type: ignore
597
631
598
632
self .min_value : minmax_typehint = kwargs .pop ("min_value" , None )
599
633
self .max_value : minmax_typehint = kwargs .pop ("max_value" , None )
@@ -664,8 +698,9 @@ class SlashCommandGroup(ApplicationCommand, Option):
664
698
The description for the command.
665
699
guild_ids: Optional[List[:class:`int`]]
666
700
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.
669
704
subcommands: List[Union[:class:`SlashCommand`, :class:`SlashCommandGroup`]]
670
705
The list of all subcommands under this group.
671
706
cog: Optional[:class:`Cog`]
@@ -691,7 +726,7 @@ def __init__(
691
726
name : str ,
692
727
description : str ,
693
728
guild_ids : Optional [List [int ]] = None ,
694
- parent_group : Optional [SlashCommandGroup ] = None ,
729
+ parent : Optional [SlashCommandGroup ] = None ,
695
730
** kwargs
696
731
) -> None :
697
732
validate_chat_input_name (name )
@@ -703,7 +738,7 @@ def __init__(
703
738
)
704
739
self .subcommands : List [Union [SlashCommand , SlashCommandGroup ]] = []
705
740
self .guild_ids = guild_ids
706
- self .parent_group = parent_group
741
+ self .parent = parent
707
742
self .checks = []
708
743
709
744
self ._before_invoke = None
@@ -723,26 +758,25 @@ def to_dict(self) -> Dict:
723
758
"options" : [c .to_dict () for c in self .subcommands ],
724
759
}
725
760
726
- if self .parent_group is not None :
761
+ if self .parent is not None :
727
762
as_dict ["type" ] = self .input_type .value
728
763
729
764
return as_dict
730
765
731
766
def command (self , ** kwargs ) -> SlashCommand :
732
767
def wrap (func ) -> SlashCommand :
733
- command = SlashCommand (func , ** kwargs )
734
- command .is_subcommand = True
768
+ command = SlashCommand (func , parent = self , ** kwargs )
735
769
self .subcommands .append (command )
736
770
return command
737
771
738
772
return wrap
739
773
740
774
def command_group (self , name , description ) -> SlashCommandGroup :
741
- if self .parent_group is not None :
775
+ if self .parent is not None :
742
776
# TODO: Improve this error message
743
777
raise Exception ("Subcommands can only be nested once" )
744
778
745
- sub_command_group = SlashCommandGroup (name , description , parent_group = self )
779
+ sub_command_group = SlashCommandGroup (name , description , parent = self )
746
780
self .subcommands .append (sub_command_group )
747
781
return sub_command_group
748
782
@@ -817,9 +851,12 @@ def __init__(self, func: Callable, *args, **kwargs) -> None:
817
851
818
852
self .validate_parameters ()
819
853
820
- # Context Commands don't have permissions
854
+ # Context Menu commands don't have permissions
821
855
self .permissions = []
822
856
857
+ # Context Menu commands can't have parents
858
+ self .parent = None
859
+
823
860
def validate_parameters (self ):
824
861
params = self ._get_signature_parameters ()
825
862
if list (params .items ())[0 ][0 ] == "self" :
0 commit comments