@@ -29,6 +29,8 @@ class SlashCommand:
29
29
:type client: Union[discord.Client, discord.ext.commands.Bot]
30
30
:param sync_commands: Whether to sync commands automatically. Default `False`.
31
31
:type sync_commands: bool
32
+ :param debug_guild: Guild ID of guild to use for testing commands. Prevents setting global commands in favor of guild commands, which update instantly
33
+ :type debug_guild: int
32
34
:param delete_from_unused_guilds: If the bot should make a request to set no commands for guilds that haven't got any commands registered in :class:``SlashCommand``. Default `False`.
33
35
:type delete_from_unused_guilds: bool
34
36
:param sync_on_cog_reload: Whether to sync commands on cog reload. Default `False`.
@@ -56,6 +58,7 @@ def __init__(
56
58
self ,
57
59
client : typing .Union [discord .Client , commands .Bot ],
58
60
sync_commands : bool = False ,
61
+ debug_guild : typing .Optional [int ] = None ,
59
62
delete_from_unused_guilds : bool = False ,
60
63
sync_on_cog_reload : bool = False ,
61
64
override_type : bool = False ,
@@ -68,6 +71,7 @@ def __init__(
68
71
self .logger = logging .getLogger ("discord_slash" )
69
72
self .req = http .SlashCommandRequest (self .logger , self ._discord , application_id )
70
73
self .sync_commands = sync_commands
74
+ self .debug_guild = debug_guild
71
75
self .sync_on_cog_reload = sync_on_cog_reload
72
76
73
77
if self .sync_commands :
@@ -424,7 +428,8 @@ async def sync_all_commands(
424
428
permissions_map = {}
425
429
cmds = await self .to_dict ()
426
430
self .logger .info ("Syncing commands..." )
427
- cmds_formatted = {None : cmds ["global" ]}
431
+ # if debug_guild is set, global commands get re-routed to the guild to update quickly
432
+ cmds_formatted = {self .debug_guild : cmds ["global" ]}
428
433
for guild in cmds ["guild" ]:
429
434
cmds_formatted [guild ] = cmds ["guild" ][guild ]
430
435
@@ -1389,15 +1394,24 @@ async def on_socket_response(self, msg):
1389
1394
1390
1395
to_use = msg ["d" ]
1391
1396
interaction_type = to_use ["type" ]
1392
- if interaction_type in (1 , 2 , 3 ) or msg ["s" ] == 5 :
1397
+
1398
+ # dis_snek variance seq
1399
+
1400
+ if interaction_type in (1 , 2 ):
1393
1401
await self ._on_slash (to_use )
1394
1402
await self ._on_context_menu (to_use )
1403
+ elif interaction_type == 3 :
1395
1404
try :
1396
1405
await self ._on_component (to_use ) # noqa
1397
1406
except KeyError :
1398
1407
pass # for some reason it complains about custom_id being an optional arg when it's fine?
1408
+ finally :
1409
+ await self ._on_context_menu (to_use )
1410
+ else :
1411
+ raise NotImplementedError (
1412
+ f"Unknown Interaction Received: { interaction_type } "
1413
+ ) # check if discord does a sneaky event change on us
1399
1414
return
1400
- # raise NotImplementedError
1401
1415
1402
1416
async def _on_component (self , to_use ):
1403
1417
ctx = context .ComponentContext (self .req , to_use , self ._discord , self .logger )
@@ -1410,7 +1424,7 @@ async def _on_component(self, to_use):
1410
1424
self ._discord .dispatch ("component_callback" , ctx , callback )
1411
1425
await self .invoke_component_callback (callback , ctx )
1412
1426
1413
- async def _on_slash (self , to_use ):
1427
+ async def _on_slash (self , to_use ): # slash commands only.
1414
1428
if to_use ["data" ]["name" ] in self .commands :
1415
1429
1416
1430
ctx = context .SlashContext (self .req , to_use , self ._discord , self .logger )
@@ -1421,6 +1435,9 @@ async def _on_slash(self, to_use):
1421
1435
1422
1436
selected_cmd = self .commands [to_use ["data" ]["name" ]]
1423
1437
1438
+ if selected_cmd ._type != 1 :
1439
+ return # If its a menu, ignore.
1440
+
1424
1441
if (
1425
1442
selected_cmd .allowed_guild_ids
1426
1443
and ctx .guild_id not in selected_cmd .allowed_guild_ids
@@ -1457,6 +1474,12 @@ async def _on_slash(self, to_use):
1457
1474
await self .invoke_command (selected_cmd , ctx , args )
1458
1475
1459
1476
async def _on_context_menu (self , to_use ):
1477
+ # Slash Command Logic
1478
+
1479
+ # to prevent any potential keyerrors:
1480
+ if "name" not in to_use ["data" ].keys ():
1481
+ return
1482
+
1460
1483
if to_use ["data" ]["name" ] in self .commands ["context" ]:
1461
1484
ctx = context .MenuContext (self .req , to_use , self ._discord , self .logger )
1462
1485
cmd_name = to_use ["data" ]["name" ]
@@ -1484,6 +1507,39 @@ async def _on_context_menu(self, to_use):
1484
1507
1485
1508
await self .invoke_command (selected_cmd , ctx , args = {})
1486
1509
1510
+ # Cog Logic
1511
+
1512
+ elif to_use ["data" ]["name" ] in self .commands :
1513
+ ctx = context .MenuContext (self .req , to_use , self ._discord , self .logger )
1514
+ cmd_name = to_use ["data" ]["name" ]
1515
+
1516
+ if cmd_name not in self .commands and cmd_name in self .subcommands :
1517
+ return # menus don't have subcommands you smooth brain
1518
+
1519
+ selected_cmd = self .commands [cmd_name ]
1520
+ if type (selected_cmd ) == dict :
1521
+ return # Get rid of any selection thats a dict somehow
1522
+ if selected_cmd ._type == 1 : # noqa
1523
+ return # Slash command obj.
1524
+
1525
+ if (
1526
+ selected_cmd .allowed_guild_ids
1527
+ and ctx .guild_id not in selected_cmd .allowed_guild_ids
1528
+ ):
1529
+ return
1530
+
1531
+ if selected_cmd .has_subcommands and not selected_cmd .func :
1532
+ return await self .handle_subcommand (ctx , to_use )
1533
+
1534
+ if "options" in to_use ["data" ]:
1535
+ for x in to_use ["data" ]["options" ]:
1536
+ if "value" not in x :
1537
+ return await self .handle_subcommand (ctx , to_use )
1538
+
1539
+ self ._discord .dispatch ("context_menu" , ctx )
1540
+
1541
+ await self .invoke_command (selected_cmd , ctx , args = {})
1542
+
1487
1543
async def handle_subcommand (self , ctx : context .SlashContext , data : dict ):
1488
1544
"""
1489
1545
Coroutine for handling subcommand.
0 commit comments