@@ -26,6 +26,7 @@ class SlashCommand:
26
26
:ivar auto_register: Whether to register commands automatically.
27
27
:ivar has_listener: Whether discord client has listener add function.
28
28
"""
29
+
29
30
def __init__ (self ,
30
31
client : typing .Union [discord .Client , commands .Bot ],
31
32
auto_register : bool = False ,
@@ -38,7 +39,8 @@ def __init__(self,
38
39
self .auto_register = auto_register
39
40
if self .auto_register :
40
41
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 :
42
44
self .logger .info ("Detected discord.Client! Overriding on_socket_response." )
43
45
self ._discord .on_socket_response = self .on_socket_response
44
46
self .has_listener = False
@@ -58,12 +60,33 @@ def remove(self):
58
60
return
59
61
self ._discord .remove_listener (self .on_socket_response )
60
62
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
+
61
84
async def register_all_commands (self ):
62
85
"""
63
86
Registers all slash commands except subcommands to Discord API.\n
64
87
If ``auto_register`` is ``True``, then this will be automatically called.
65
88
"""
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.
67
90
self .logger .info ("Registering commands..." )
68
91
for x in self .commands .keys ():
69
92
selected = self .commands [x ]
@@ -129,7 +152,7 @@ def add_slash_command(self,
129
152
"api_options" : options if options else [],
130
153
"has_subcommands" : has_subcommands
131
154
}
132
- self .commands [name ] = _cmd
155
+ self .commands [name ] = model . CommandObject ( name , _cmd )
133
156
self .logger .debug (f"Added command `{ name } `" )
134
157
135
158
def add_subcommand (self ,
@@ -163,7 +186,11 @@ def add_subcommand(self,
163
186
name = cmd .__name__ if not name else name
164
187
name = name .lower ()
165
188
_cmd = {
189
+ "func" : None ,
190
+ "description" : description if description else "No description." ,
191
+ "auto_convert" : {},
166
192
"guild_ids" : guild_ids ,
193
+ "api_options" : [],
167
194
"has_subcommands" : True
168
195
}
169
196
_sub = {
@@ -174,18 +201,20 @@ def add_subcommand(self,
174
201
"guild_ids" : guild_ids ,
175
202
}
176
203
if base not in self .commands .keys ():
177
- self .commands [base ] = _cmd
204
+ self .commands [base ] = model . CommandObject ( base , _cmd )
178
205
else :
179
- self .subcommands [base ]["has_subcommands" ] = True
206
+ self .subcommands [base ].has_subcommands = True
207
+ self .subcommands [base ].guild_ids += guild_ids
180
208
if base not in self .subcommands .keys ():
181
209
self .subcommands [base ] = {}
182
210
if subcommand_group :
183
211
if subcommand_group not in self .subcommands [base ].keys ():
184
212
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 )
186
214
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 } `" )
189
218
190
219
def slash (self ,
191
220
* ,
@@ -259,6 +288,7 @@ async def _pick(ctx, choice1, choice2): # Command with 1 or more args.
259
288
def wrapper (cmd ):
260
289
self .add_slash_command (cmd , name , description , auto_convert , guild_ids , options )
261
290
return cmd
291
+
262
292
return wrapper
263
293
264
294
def subcommand (self ,
@@ -311,6 +341,7 @@ async def _group_kick_user(ctx, user):
311
341
def wrapper (cmd ):
312
342
self .add_subcommand (cmd , base , subcommand_group , name , description , auto_convert , guild_ids )
313
343
return cmd
344
+
314
345
return wrapper
315
346
316
347
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):
388
419
return
389
420
to_use = msg ["d" ]
390
421
if to_use ["data" ]["name" ] in self .commands .keys ():
391
- selected_cmd = self .commands [to_use ["data" ]["name" ]]
392
422
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 :
395
429
return
396
- if selected_cmd [ " has_subcommands" ] :
430
+ if selected_cmd . has_subcommands :
397
431
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 ) \
399
433
if "options" in to_use ["data" ] else []
400
434
self ._discord .dispatch ("slash_command" , ctx )
401
435
try :
402
- await selected_cmd [ "func" ] (ctx , * args )
436
+ await selected_cmd . invoke (ctx , * args )
403
437
except Exception as ex :
404
438
await self .on_slash_command_error (ctx , ex )
405
439
@@ -429,20 +463,20 @@ async def handle_subcommand(self, ctx: model.SlashContext, data: dict):
429
463
return
430
464
ctx .subcommand_group = sub_group
431
465
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 ) \
433
467
if "options" in x .keys () else []
434
468
self ._discord .dispatch ("slash_command" , ctx )
435
469
try :
436
- await selected [ "func" ] (ctx , * args )
470
+ await selected . invoke (ctx , * args )
437
471
except Exception as ex :
438
472
await self .on_slash_command_error (ctx , ex )
439
473
return
440
474
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 ) \
442
476
if "options" in sub .keys () else []
443
477
self ._discord .dispatch ("slash_command" , ctx )
444
478
try :
445
- await selected [ "func" ] (ctx , * args )
479
+ await selected . invoke (ctx , * args )
446
480
except Exception as ex :
447
481
await self .on_slash_command_error (ctx , ex )
448
482
0 commit comments