@@ -100,7 +100,9 @@ def add_application_command(self, command: ApplicationCommand) -> None:
100
100
command .guild_ids = self .debug_guilds
101
101
self ._pending_application_commands .append (command )
102
102
103
- def remove_application_command (self , command : ApplicationCommand ) -> Optional [ApplicationCommand ]:
103
+ def remove_application_command (
104
+ self , command : ApplicationCommand
105
+ ) -> Optional [ApplicationCommand ]:
104
106
"""Remove a :class:`.ApplicationCommand` from the internal list
105
107
of commands.
106
108
@@ -155,7 +157,9 @@ async def register_commands(self) -> None:
155
157
global_permissions : List = []
156
158
157
159
registered_commands = await self .http .get_global_commands (self .user .id )
158
- for command in [cmd for cmd in self .pending_application_commands if cmd .guild_ids is None ]:
160
+ for command in [
161
+ cmd for cmd in self .pending_application_commands if cmd .guild_ids is None
162
+ ]:
159
163
as_dict = command .to_dict ()
160
164
if len (registered_commands ) > 0 :
161
165
matches = [
@@ -185,16 +189,21 @@ async def register_commands(self) -> None:
185
189
update_guild_commands = {}
186
190
async for guild in self .fetch_guilds (limit = None ):
187
191
update_guild_commands [guild .id ] = []
188
- for command in [cmd for cmd in self .pending_application_commands if cmd .guild_ids is not None ]:
192
+ for command in [
193
+ cmd
194
+ for cmd in self .pending_application_commands
195
+ if cmd .guild_ids is not None
196
+ ]:
189
197
as_dict = command .to_dict ()
190
198
for guild_id in command .guild_ids :
191
199
to_update = update_guild_commands [guild_id ]
192
200
update_guild_commands [guild_id ] = to_update + [as_dict ]
193
201
194
202
for guild_id in update_guild_commands :
195
203
try :
196
- cmds = await self .http .bulk_upsert_guild_commands (self .user .id , guild_id ,
197
- update_guild_commands [guild_id ])
204
+ cmds = await self .http .bulk_upsert_guild_commands (
205
+ self .user .id , guild_id , update_guild_commands [guild_id ]
206
+ )
198
207
199
208
# Permissions for this Guild
200
209
guild_permissions : List = []
@@ -206,20 +215,39 @@ async def register_commands(self) -> None:
206
215
raise
207
216
else :
208
217
for i in cmds :
209
- cmd = get (self .pending_application_commands , name = i ["name" ], description = i ["description" ],
210
- type = i ['type' ])
218
+ cmd = get (
219
+ self .pending_application_commands ,
220
+ name = i ["name" ],
221
+ description = i ["description" ],
222
+ type = i ["type" ],
223
+ )
211
224
self .application_commands [i ["id" ]] = cmd
212
225
213
226
# Permissions
214
- permissions = [perm .to_dict () for perm in cmd .permissions if perm .guild_id is None or (
215
- perm .guild_id == guild_id and perm .guild_id in cmd .guild_ids )]
216
- guild_permissions .append ({"id" : i ["id" ], "permissions" : permissions })
227
+ permissions = [
228
+ perm .to_dict ()
229
+ for perm in cmd .permissions
230
+ if perm .guild_id is None
231
+ or (
232
+ perm .guild_id == guild_id and perm .guild_id in cmd .guild_ids
233
+ )
234
+ ]
235
+ guild_permissions .append (
236
+ {"id" : i ["id" ], "permissions" : permissions }
237
+ )
217
238
218
239
for global_command in global_permissions :
219
- permissions = [perm .to_dict () for perm in global_command ['permissions' ] if
220
- perm .guild_id is None or (
221
- perm .guild_id == guild_id and perm .guild_id in cmd .guild_ids )]
222
- guild_permissions .append ({"id" : global_command ["id" ], "permissions" : permissions })
240
+ permissions = [
241
+ perm .to_dict ()
242
+ for perm in global_command ["permissions" ]
243
+ if perm .guild_id is None
244
+ or (
245
+ perm .guild_id == guild_id and perm .guild_id in cmd .guild_ids
246
+ )
247
+ ]
248
+ guild_permissions .append (
249
+ {"id" : global_command ["id" ], "permissions" : permissions }
250
+ )
223
251
224
252
# Collect & Upsert Permissions for Each Guild
225
253
# Command Permissions for this Guild
@@ -231,47 +259,80 @@ async def register_commands(self) -> None:
231
259
232
260
# Replace Role / Owner Names with IDs
233
261
for permission in item ["permissions" ]:
234
- if isinstance (permission ['id' ], str ):
262
+ if isinstance (permission ["id" ], str ):
235
263
# Replace Role Names
236
- if permission ['type' ] == 1 and isinstance (permission ['id' ], str ):
237
- role = get (self .get_guild (guild_id ).roles , name = permission ['id' ])
264
+ if permission ["type" ] == 1 and isinstance (
265
+ permission ["id" ], str
266
+ ):
267
+ role = get (
268
+ self .get_guild (guild_id ).roles ,
269
+ name = permission ["id" ],
270
+ )
238
271
239
272
# If not missing
240
273
if not role is None :
241
274
new_cmd_perm ["permissions" ].append (
242
- {"id" : role .id , "type" : 1 , "permission" : permission ['permission' ]})
275
+ {
276
+ "id" : role .id ,
277
+ "type" : 1 ,
278
+ "permission" : permission ["permission" ],
279
+ }
280
+ )
243
281
else :
244
- print ("No Role ID found in Guild ({guild_id}) for Role ({role})" .format (
245
- guild_id = guild_id , role = permission ['id' ]))
282
+ print (
283
+ "No Role ID found in Guild ({guild_id}) for Role ({role})" .format (
284
+ guild_id = guild_id , role = permission ["id" ]
285
+ )
286
+ )
246
287
# Add Owner IDs
247
- elif permission ['type' ] == 2 and permission ['id' ] == "owner" :
288
+ elif (
289
+ permission ["type" ] == 2 and permission ["id" ] == "owner"
290
+ ):
248
291
app = await self .application_info () # type: ignore
249
292
if app .team :
250
293
for m in app .team .members :
251
294
new_cmd_perm ["permissions" ].append (
252
- {"id" : m .id , "type" : 2 , "permission" : permission ['permission' ]})
295
+ {
296
+ "id" : m .id ,
297
+ "type" : 2 ,
298
+ "permission" : permission ["permission" ],
299
+ }
300
+ )
253
301
else :
254
302
new_cmd_perm ["permissions" ].append (
255
- {"id" : app .owner .id , "type" : 2 , "permission" : permission ['permission' ]})
303
+ {
304
+ "id" : app .owner .id ,
305
+ "type" : 2 ,
306
+ "permission" : permission ["permission" ],
307
+ }
308
+ )
256
309
# Add the Rest
257
310
else :
258
311
new_cmd_perm ["permissions" ].append (permission )
259
312
260
313
# Make sure we don't have over 10 overwrites
261
- if len (new_cmd_perm [' permissions' ]) > 10 :
314
+ if len (new_cmd_perm [" permissions" ]) > 10 :
262
315
print (
263
316
"Command '{name}' has more than 10 permission overrides in guild ({guild_id}).\n will only use the first 10 permission overrides." .format (
264
- name = self .application_commands [new_cmd_perm ['id' ]].name , guild_id = guild_id ))
265
- new_cmd_perm ['permissions' ] = new_cmd_perm ['permissions' ][:10 ]
317
+ name = self .application_commands [new_cmd_perm ["id" ]].name ,
318
+ guild_id = guild_id ,
319
+ )
320
+ )
321
+ new_cmd_perm ["permissions" ] = new_cmd_perm ["permissions" ][:10 ]
266
322
267
323
# Append to guild_cmd_perms
268
324
guild_cmd_perms .append (new_cmd_perm )
269
325
270
326
# Upsert
271
327
try :
272
- await self .http .bulk_upsert_command_permissions (self .user .id , guild_id , guild_cmd_perms )
328
+ await self .http .bulk_upsert_command_permissions (
329
+ self .user .id , guild_id , guild_cmd_perms
330
+ )
273
331
except Forbidden :
274
- print (f"Failed to add command permissions to guild { guild_id } " , file = sys .stderr )
332
+ print (
333
+ f"Failed to add command permissions to guild { guild_id } " ,
334
+ file = sys .stderr ,
335
+ )
275
336
raise
276
337
277
338
async def process_application_commands (self , interaction : Interaction ) -> None :
@@ -306,16 +367,16 @@ async def process_application_commands(self, interaction: Interaction) -> None:
306
367
else :
307
368
ctx = await self .get_application_context (interaction )
308
369
ctx .command = command
309
- self .dispatch (' application_command' , ctx )
370
+ self .dispatch (" application_command" , ctx )
310
371
try :
311
372
if await self .can_run (ctx , call_once = True ):
312
373
await ctx .command .invoke (ctx )
313
374
else :
314
- raise CheckFailure (' The global check once functions failed.' )
375
+ raise CheckFailure (" The global check once functions failed." )
315
376
except DiscordException as exc :
316
377
await ctx .command .dispatch_error (ctx , exc )
317
378
else :
318
- self .dispatch (' application_command_completion' , ctx )
379
+ self .dispatch (" application_command_completion" , ctx )
319
380
320
381
def slash_command (self , ** kwargs ):
321
382
"""A shortcut decorator that invokes :func:`.ApplicationCommandMixin.command` and adds it to
@@ -400,7 +461,9 @@ def command(self, **kwargs):
400
461
"""
401
462
return self .application_command (** kwargs )
402
463
403
- def command_group (self , name : str , description : str , guild_ids = None ) -> SlashCommandGroup :
464
+ def command_group (
465
+ self , name : str , description : str , guild_ids = None
466
+ ) -> SlashCommandGroup :
404
467
# TODO: Write documentation for this. I'm not familiar enough with what this function does to do it myself.
405
468
group = SlashCommandGroup (name , description , guild_ids )
406
469
self .add_application_command (group )
@@ -451,24 +514,30 @@ def __init__(self, description=None, *args, **options):
451
514
self ._check_once = []
452
515
self ._before_invoke = None
453
516
self ._after_invoke = None
454
- self .description = inspect .cleandoc (description ) if description else ''
455
- self .owner_id = options .get (' owner_id' )
456
- self .owner_ids = options .get (' owner_ids' , set ())
517
+ self .description = inspect .cleandoc (description ) if description else ""
518
+ self .owner_id = options .get (" owner_id" )
519
+ self .owner_ids = options .get (" owner_ids" , set ())
457
520
458
- self .debug_guild = options .pop ("debug_guild" , None ) # TODO: remove or reimplement
521
+ self .debug_guild = options .pop (
522
+ "debug_guild" , None
523
+ ) # TODO: remove or reimplement
459
524
self .debug_guilds = options .pop ("debug_guilds" , None )
460
525
461
526
if self .owner_id and self .owner_ids :
462
- raise TypeError (' Both owner_id and owner_ids are set.' )
527
+ raise TypeError (" Both owner_id and owner_ids are set." )
463
528
464
- if self .owner_ids and not isinstance (self .owner_ids , collections .abc .Collection ):
465
- raise TypeError (f'owner_ids must be a collection not { self .owner_ids .__class__ !r} ' )
529
+ if self .owner_ids and not isinstance (
530
+ self .owner_ids , collections .abc .Collection
531
+ ):
532
+ raise TypeError (
533
+ f"owner_ids must be a collection not { self .owner_ids .__class__ !r} "
534
+ )
466
535
467
536
if self .debug_guild :
468
537
if self .debug_guilds is None :
469
538
self .debug_guilds = [self .debug_guild ]
470
539
else :
471
- raise TypeError (' Both debug_guild and debug_guilds are set.' )
540
+ raise TypeError (" Both debug_guild and debug_guilds are set." )
472
541
473
542
self ._checks = []
474
543
self ._check_once = []
@@ -481,7 +550,9 @@ async def on_connect(self):
481
550
async def on_interaction (self , interaction ):
482
551
await self .process_application_commands (interaction )
483
552
484
- async def on_application_command_error (self , context : ApplicationContext , exception : DiscordException ) -> None :
553
+ async def on_application_command_error (
554
+ self , context : ApplicationContext , exception : DiscordException
555
+ ) -> None :
485
556
"""|coro|
486
557
487
558
The default command error handler provided by the bot.
@@ -504,8 +575,10 @@ async def on_application_command_error(self, context: ApplicationContext, except
504
575
# if cog and cog.has_error_handler():
505
576
# return
506
577
507
- print (f'Ignoring exception in command { context .command } :' , file = sys .stderr )
508
- traceback .print_exception (type (exception ), exception , exception .__traceback__ , file = sys .stderr )
578
+ print (f"Ignoring exception in command { context .command } :" , file = sys .stderr )
579
+ traceback .print_exception (
580
+ type (exception ), exception , exception .__traceback__ , file = sys .stderr
581
+ )
509
582
510
583
# global check registration
511
584
# TODO: Remove these from commands.Bot
@@ -611,7 +684,9 @@ def whitelist(ctx):
611
684
self .add_check (func , call_once = True )
612
685
return func
613
686
614
- async def can_run (self , ctx : ApplicationContext , * , call_once : bool = False ) -> bool :
687
+ async def can_run (
688
+ self , ctx : ApplicationContext , * , call_once : bool = False
689
+ ) -> bool :
615
690
data = self ._check_once if call_once else self ._checks
616
691
617
692
if len (data ) == 0 :
@@ -620,7 +695,6 @@ async def can_run(self, ctx: ApplicationContext, *, call_once: bool = False) ->
620
695
# type-checker doesn't distinguish between functions and methods
621
696
return await async_all (f (ctx ) for f in data ) # type: ignore
622
697
623
-
624
698
def before_invoke (self , coro ):
625
699
"""A decorator that registers a coroutine as a pre-invoke hook.
626
700
A pre-invoke hook is called directly before the command is
@@ -646,7 +720,7 @@ def before_invoke(self, coro):
646
720
The coroutine passed is not actually a coroutine.
647
721
"""
648
722
if not asyncio .iscoroutinefunction (coro ):
649
- raise TypeError (' The pre-invoke hook must be a coroutine.' )
723
+ raise TypeError (" The pre-invoke hook must be a coroutine." )
650
724
651
725
self ._before_invoke = coro
652
726
return coro
@@ -678,11 +752,12 @@ def after_invoke(self, coro):
678
752
679
753
"""
680
754
if not asyncio .iscoroutinefunction (coro ):
681
- raise TypeError (' The post-invoke hook must be a coroutine.' )
755
+ raise TypeError (" The post-invoke hook must be a coroutine." )
682
756
683
757
self ._after_invoke = coro
684
758
return coro
685
759
760
+
686
761
class Bot (BotBase , Client ):
687
762
"""Represents a discord bot.
688
763
0 commit comments