@@ -214,51 +214,101 @@ async def sync_commands(self) -> None:
214
214
215
215
async def register_commands (self ) -> None :
216
216
"""|coro|
217
-
218
217
Registers all commands that have been added through :meth:`.add_application_command`.
219
218
This method cleans up all commands over the API and should sync them with the internal cache of commands.
220
-
219
+ This will only be rolled out to Discord if :meth:`.http.get_global_commands` has certain keys that differ from :data:`.pending_application_commands`
221
220
By default, this coroutine is called inside the :func:`.on_connect`
222
221
event. If you choose to override the :func:`.on_connect` event, then
223
222
you should invoke this coroutine as well.
224
-
225
223
.. versionadded:: 2.0
226
224
"""
227
- commands = []
225
+ commands_to_bulk = []
226
+
227
+ needs_bulk = False
228
228
229
229
# Global Command Permissions
230
230
global_permissions : List = []
231
231
232
232
registered_commands = await self .http .get_global_commands (self .user .id )
233
+ # 'Your app cannot have two global commands with the same name. Your app cannot have two guild commands within the same name on the same guild.'
234
+ # We can therefore safely use the name of the command in our global slash commands as a unique identifier
235
+ registered_commands_dict = {cmd ["name" ]:cmd for cmd in registered_commands }
236
+ global_pending_application_commands_dict = {}
237
+
233
238
for command in [
234
239
cmd for cmd in self .pending_application_commands if cmd .guild_ids is None
235
240
]:
236
241
as_dict = command .to_dict ()
237
- if len (registered_commands ) > 0 :
238
- matches = [
239
- x
240
- for x in registered_commands
241
- if x ["name" ] == command .name and x ["type" ] == command .type
242
- ]
243
- # TODO: rewrite this, it seems inefficient
244
- if matches :
245
- as_dict ["id" ] = matches [0 ]["id" ]
246
- commands .append (as_dict )
247
-
248
- cmds = await self .http .bulk_upsert_global_commands (self .user .id , commands )
249
-
250
- for i in cmds :
242
+
243
+ global_pending_application_commands_dict [command .name ] = as_dict
244
+ if command .name in registered_commands_dict :
245
+ match = registered_commands_dict [command .name ]
246
+ else :
247
+ match = None
248
+ # TODO: There is probably a far more efficient way of doing this
249
+ # We want to check if the registered global command on Discord servers matches the given global commands
250
+ if match :
251
+ as_dict ["id" ] = match ["id" ]
252
+
253
+ keys_to_check = {"default_permission" : True , "name" : True , "description" : True , "options" : ["type" , "name" , "description" , "autocomplete" , "choices" ]}
254
+ for key , more_keys in {
255
+ key :more_keys
256
+ for key , more_keys in keys_to_check .items ()
257
+ if key in as_dict .keys ()
258
+ if key in match .keys ()
259
+ }.items ():
260
+ if key == "options" :
261
+ for i , option_dict in enumerate (as_dict [key ]):
262
+ if command .name == "recent" :
263
+ print (option_dict , "|||||" , match [key ][i ])
264
+ for key2 in more_keys :
265
+ pendingVal = None
266
+ if key2 in option_dict .keys ():
267
+ pendingVal = option_dict [key2 ]
268
+ if pendingVal == False or pendingVal == []: # Registered commands are not available if choices is an empty array or if autocomplete is false
269
+ pendingVal = None
270
+ matchVal = None
271
+ if key2 in match [key ][i ].keys ():
272
+ matchVal = match [key ][i ][key2 ]
273
+ if matchVal == False or matchVal == []: # Registered commands are not available if choices is an empty array or if autocomplete is false
274
+ matchVal = None
275
+
276
+ if pendingVal != matchVal :
277
+ # When a property in the options of a pending global command is changed
278
+ needs_bulk = True
279
+ else :
280
+ if as_dict [key ] != match [key ]:
281
+ # When a property in a pending global command is changed
282
+ needs_bulk = True
283
+ else :
284
+ # When a name of a pending global command is not registered in Discord
285
+ needs_bulk = True
286
+
287
+ commands_to_bulk .append (as_dict )
288
+
289
+ for name , command in registered_commands_dict .items ():
290
+ if not name in global_pending_application_commands_dict .keys ():
291
+ # When a registered global command is not available in the pending global commands
292
+ needs_bulk = True
293
+
294
+ if needs_bulk :
295
+ commands = await self .http .bulk_upsert_global_commands (self .user .id , commands_to_bulk )
296
+ else :
297
+ commands = registered_commands
298
+
299
+ for i in commands :
251
300
cmd = get (
252
301
self .pending_application_commands ,
253
302
name = i ["name" ],
254
303
guild_ids = None ,
255
304
type = i ["type" ],
256
305
)
257
- cmd .id = i ["id" ]
258
- self ._application_commands [cmd .id ] = cmd
306
+ if cmd :
307
+ cmd .id = i ["id" ]
308
+ self ._application_commands [cmd .id ] = cmd
259
309
260
- # Permissions (Roles will be converted to IDs just before Upsert for Global Commands)
261
- global_permissions .append ({"id" : i ["id" ], "permissions" : cmd .permissions })
310
+ # Permissions (Roles will be converted to IDs just before Upsert for Global Commands)
311
+ global_permissions .append ({"id" : i ["id" ], "permissions" : cmd .permissions })
262
312
263
313
update_guild_commands = {}
264
314
async for guild in self .fetch_guilds (limit = None ):
@@ -275,7 +325,7 @@ async def register_commands(self) -> None:
275
325
276
326
for guild_id , guild_data in update_guild_commands .items ():
277
327
try :
278
- cmds = await self .http .bulk_upsert_guild_commands (
328
+ commands = await self .http .bulk_upsert_guild_commands (
279
329
self .user .id , guild_id , update_guild_commands [guild_id ]
280
330
)
281
331
@@ -287,7 +337,7 @@ async def register_commands(self) -> None:
287
337
print (f"Failed to add command to guild { guild_id } " , file = sys .stderr )
288
338
raise
289
339
else :
290
- for i in cmds :
340
+ for i in commands :
291
341
cmd = find (lambda cmd : cmd .name == i ["name" ] and cmd .type == i ["type" ] and int (i ["guild_id" ]) in cmd .guild_ids , self .pending_application_commands )
292
342
cmd .id = i ["id" ]
293
343
self ._application_commands [cmd .id ] = cmd
0 commit comments