@@ -43,7 +43,7 @@ def add_slash_command(self,
4343 auto_convert : dict = None ,
4444 guild_id : int = None ,
4545 options : list = None ,
46- subcommand : dict = None ):
46+ has_subcommands : bool = False ):
4747 """
4848 Registers slash command to SlashCommand.
4949
@@ -53,7 +53,7 @@ def add_slash_command(self,
5353 :param auto_convert: Dictionary of how to convert option values. Default ``None``.
5454 :param guild_id: Guild ID of where the command will be used. Default ``None``, which will be global command.
5555 :param options: Options of the slash command. This will affect ``auto_convert`` and command data at Discord API. Default ``None``.
56- :param subcommand: Subcommand if any .
56+ :param has_subcommands: Whether it has subcommand. Default ``False`` .
5757 :return: ``None``
5858 """
5959 _cmd = {
@@ -62,11 +62,14 @@ def add_slash_command(self,
6262 "auto_convert" : auto_convert ,
6363 "guild_id" : guild_id ,
6464 "api_options" : options ,
65- "subcommands " : subcommand
65+ "has_subcommands " : has_subcommands
6666 }
6767 self .commands [cmd .__name__ if not name else name ] = _cmd
6868 self .logger .debug (f"Added command `{ cmd .__name__ if not name else name } `" )
6969
70+ def add_subcommand (self ,):
71+ pass
72+
7073 def slash (self ,
7174 * ,
7275 name : str = None ,
@@ -128,6 +131,41 @@ def wrapper(cmd):
128131 return cmd
129132 return wrapper
130133
134+ def subcommand (self ,
135+ * ,
136+ base ,
137+ subcommand_group = None ,
138+ name = None ,
139+ description : str = None ,
140+ auto_convert : dict = None ,
141+ guild_id : int = None ):
142+ """
143+ Decorator that registers subcommand.
144+ Unlike discord.py, you don't need base command.
145+
146+ Example:
147+
148+ .. code-block:: python
149+ @slash.subcommand(base="group", name="say")
150+ async def _group_say(ctx, _str):
151+ await ctx.send(content=_str)
152+
153+ .. note::
154+ Unlike normal slash command, this doesn't support ``options`` arg, since it will be very complicated.\n
155+ Also, subcommands won't be automatically registered to Discord API even if you set ``auto_register`` to ``True``.
156+
157+ :param base: Name of the base command.
158+ :param subcommand_group: Name of the subcommand group, if any. Default ``None`` which represents there is no sub group.
159+ :param name: Name of the subcommand. Default name of the coroutine.
160+ :param description: Description of the subcommand. Default ``None``.
161+ :param auto_convert: Dictionary of how to convert option values. Default ``None``.
162+ :param guild_id: Guild ID of where the command will be used. Default ``None``, which will be global command.
163+ :return:
164+ """
165+ def wrapper (cmd ):
166+ return cmd
167+ return wrapper
168+
131169 def process_options (self , guild : discord .Guild , options : list , auto_convert : dict ) -> list :
132170 """
133171 Processes Role, User, and Channel option types to discord.py's models.
@@ -182,13 +220,25 @@ async def on_socket_response(self, msg):
182220 if msg ["t" ] != "INTERACTION_CREATE" :
183221 return
184222 to_use = msg ["d" ]
223+ print (to_use )
185224 if to_use ["data" ]["name" ] in self .commands .keys ():
186225 selected_cmd = self .commands [to_use ["data" ]["name" ]]
187226 ctx = model .SlashContext (self .req , to_use , self ._discord )
188227 if selected_cmd ["guild_id" ]:
189228 if selected_cmd ["guild_id" ] != ctx .guild .id :
190229 return
230+ if selected_cmd ["has_subcommands" ]:
231+ return await self .handle_subcommand (to_use )
191232 args = self .process_options (ctx .guild , to_use ["data" ]["options" ], selected_cmd ["auto_convert" ]) \
192233 if "options" in to_use ["data" ] else []
193234 self .logger .debug (f"Command { to_use ['data' ]['name' ]} invoked." )
194235 await selected_cmd ["func" ](ctx , * args )
236+
237+ async def handle_subcommand (self , data : dict ):
238+ """
239+ Coroutine for handling subcommand.
240+
241+ :param data:
242+ :return:
243+ """
244+ pass
0 commit comments