@@ -26,6 +26,7 @@ class SlashCommand:
2626 :ivar auto_register: Whether to register commands automatically.
2727 :ivar has_listener: Whether discord client has listener add function.
2828 """
29+
2930 def __init__ (self ,
3031 client : typing .Union [discord .Client , commands .Bot ],
3132 auto_register : bool = False ,
@@ -38,7 +39,8 @@ def __init__(self,
3839 self .auto_register = auto_register
3940 if self .auto_register :
4041 self ._discord .loop .create_task (self .register_all_commands ())
41- if not isinstance (client , commands .Bot ) and not isinstance (client , commands .AutoShardedBot ) and not override_type :
42+ if not isinstance (client , commands .Bot ) and not isinstance (client ,
43+ commands .AutoShardedBot ) and not override_type :
4244 self .logger .info ("Detected discord.Client! Overriding on_socket_response." )
4345 self ._discord .on_socket_response = self .on_socket_response
4446 self .has_listener = False
@@ -58,12 +60,33 @@ def remove(self):
5860 return
5961 self ._discord .remove_listener (self .on_socket_response )
6062
63+ def get_cog_commands (self , cog : commands .Cog ):
64+ func_list = [getattr (cog , x ) for x in dir (cog )]
65+ res = [x for x in func_list if
66+ isinstance (x , model .CogCommandObject ) or isinstance (x , model .CogSubcommandObject )]
67+ for x in res :
68+ if isinstance (x , model .CogCommandObject ):
69+ self .commands [x .name ] = x
70+ else :
71+ if x .base in self .commands .keys ():
72+ self .commands [x .base ].allowed_guild_ids += x .allowed_guild_ids
73+ self .commands [x .base ].has_subcommands = True
74+ if x .base not in self .subcommands .keys ():
75+ self .subcommands [x .base ] = {}
76+ if x .subcommand_group :
77+ if x .subcommand_group not in self .subcommands :
78+ self .subcommands [x .base ][x .subcommand_group ] = {}
79+ else :
80+ self .subcommands [x .base ][x .subcommand_group ][x .name ] = x
81+ else :
82+ self .subcommands [x .base ][x .name ] = x
83+
6184 async def register_all_commands (self ):
6285 """
6386 Registers all slash commands except subcommands to Discord API.\n
6487 If ``auto_register`` is ``True``, then this will be automatically called.
6588 """
66- await self ._discord .wait_until_ready () # In case commands are still not registered to SlashCommand.
89+ await self ._discord .wait_until_ready () # In case commands are still not registered to SlashCommand.
6790 self .logger .info ("Registering commands..." )
6891 for x in self .commands .keys ():
6992 selected = self .commands [x ]
@@ -129,7 +152,7 @@ def add_slash_command(self,
129152 "api_options" : options if options else [],
130153 "has_subcommands" : has_subcommands
131154 }
132- self .commands [name ] = _cmd
155+ self .commands [name ] = model . CommandObject ( name , _cmd )
133156 self .logger .debug (f"Added command `{ name } `" )
134157
135158 def add_subcommand (self ,
@@ -163,7 +186,11 @@ def add_subcommand(self,
163186 name = cmd .__name__ if not name else name
164187 name = name .lower ()
165188 _cmd = {
189+ "func" : None ,
190+ "description" : description if description else "No description." ,
191+ "auto_convert" : {},
166192 "guild_ids" : guild_ids ,
193+ "api_options" : [],
167194 "has_subcommands" : True
168195 }
169196 _sub = {
@@ -174,18 +201,20 @@ def add_subcommand(self,
174201 "guild_ids" : guild_ids ,
175202 }
176203 if base not in self .commands .keys ():
177- self .commands [base ] = _cmd
204+ self .commands [base ] = model . CommandObject ( base , _cmd )
178205 else :
179- self .subcommands [base ]["has_subcommands" ] = True
206+ self .subcommands [base ].has_subcommands = True
207+ self .subcommands [base ].guild_ids += guild_ids
180208 if base not in self .subcommands .keys ():
181209 self .subcommands [base ] = {}
182210 if subcommand_group :
183211 if subcommand_group not in self .subcommands [base ].keys ():
184212 self .subcommands [base ][subcommand_group ] = {}
185- self .subcommands [base ][subcommand_group ][name ] = _sub
213+ self .subcommands [base ][subcommand_group ][name ] = model . SubcommandObject ( _sub , base , name , subcommand_group )
186214 else :
187- self .subcommands [base ][name ] = _sub
188- self .logger .debug (f"Added subcommand `{ base } { subcommand_group if subcommand_group else '' } { cmd .__name__ if not name else name } `" )
215+ self .subcommands [base ][name ] = model .SubcommandObject (_sub , base , name )
216+ self .logger .debug (
217+ f"Added subcommand `{ base } { subcommand_group if subcommand_group else '' } { cmd .__name__ if not name else name } `" )
189218
190219 def slash (self ,
191220 * ,
@@ -259,6 +288,7 @@ async def _pick(ctx, choice1, choice2): # Command with 1 or more args.
259288 def wrapper (cmd ):
260289 self .add_slash_command (cmd , name , description , auto_convert , guild_ids , options )
261290 return cmd
291+
262292 return wrapper
263293
264294 def subcommand (self ,
@@ -311,6 +341,7 @@ async def _group_kick_user(ctx, user):
311341 def wrapper (cmd ):
312342 self .add_subcommand (cmd , base , subcommand_group , name , description , auto_convert , guild_ids )
313343 return cmd
344+
314345 return wrapper
315346
316347 async def process_options (self , guild : discord .Guild , options : list , auto_convert : dict ) -> list :
@@ -388,18 +419,21 @@ async def on_socket_response(self, msg):
388419 return
389420 to_use = msg ["d" ]
390421 if to_use ["data" ]["name" ] in self .commands .keys ():
391- selected_cmd = self .commands [to_use ["data" ]["name" ]]
392422 ctx = model .SlashContext (self .req , to_use , self ._discord , self .logger )
393- if selected_cmd ["guild_ids" ]:
394- if ctx .guild .id not in selected_cmd ["guild_ids" ]:
423+ cmd_name = to_use ["data" ]["name" ]
424+ if cmd_name not in self .commands .keys () and cmd_name in self .subcommands .keys ():
425+ return await self .handle_subcommand (ctx , to_use )
426+ selected_cmd = self .commands [to_use ["data" ]["name" ]]
427+ if selected_cmd .allowed_guild_ids :
428+ if ctx .guild .id not in selected_cmd .allowed_guild_ids :
395429 return
396- if selected_cmd [ " has_subcommands" ] :
430+ if selected_cmd . has_subcommands :
397431 return await self .handle_subcommand (ctx , to_use )
398- args = await self .process_options (ctx .guild , to_use ["data" ]["options" ], selected_cmd [ " auto_convert" ] ) \
432+ args = await self .process_options (ctx .guild , to_use ["data" ]["options" ], selected_cmd . auto_convert ) \
399433 if "options" in to_use ["data" ] else []
400434 self ._discord .dispatch ("slash_command" , ctx )
401435 try :
402- await selected_cmd [ "func" ] (ctx , * args )
436+ await selected_cmd . invoke (ctx , * args )
403437 except Exception as ex :
404438 await self .on_slash_command_error (ctx , ex )
405439
@@ -429,20 +463,20 @@ async def handle_subcommand(self, ctx: model.SlashContext, data: dict):
429463 return
430464 ctx .subcommand_group = sub_group
431465 selected = base [sub_name ][sub_group ]
432- args = await self .process_options (ctx .guild , x ["options" ], selected [ " auto_convert" ] ) \
466+ args = await self .process_options (ctx .guild , x ["options" ], selected . auto_convert ) \
433467 if "options" in x .keys () else []
434468 self ._discord .dispatch ("slash_command" , ctx )
435469 try :
436- await selected [ "func" ] (ctx , * args )
470+ await selected . invoke (ctx , * args )
437471 except Exception as ex :
438472 await self .on_slash_command_error (ctx , ex )
439473 return
440474 selected = base [sub_name ]
441- args = await self .process_options (ctx .guild , sub_opts , selected [ " auto_convert" ] ) \
475+ args = await self .process_options (ctx .guild , sub_opts , selected . auto_convert ) \
442476 if "options" in sub .keys () else []
443477 self ._discord .dispatch ("slash_command" , ctx )
444478 try :
445- await selected [ "func" ] (ctx , * args )
479+ await selected . invoke (ctx , * args )
446480 except Exception as ex :
447481 await self .on_slash_command_error (ctx , ex )
448482
0 commit comments