@@ -104,9 +104,9 @@ def get_cog_commands(self, cog: commands.Cog):
104104 self .commands [x .name ] = x
105105 else :
106106 if x .base in self .commands :
107- for i in self . commands [ x . base ] .allowed_guild_ids :
108- if i not in x .allowed_guild_ids :
109- x .allowed_guild_ids .append (i )
107+ for i in x .allowed_guild_ids :
108+ if i not in self . commands [ x . base ] .allowed_guild_ids :
109+ self . commands [ x . base ] .allowed_guild_ids .append (i )
110110 self .commands [x .base ].has_subcommands = True
111111 else :
112112 _cmd = {
@@ -188,65 +188,89 @@ async def to_dict(self):
188188 Commands are in the format specified by discord `here <https://discord.com/developers/docs/interactions/slash-commands#applicationcommand>`_
189189 """
190190 await self ._discord .wait_until_ready () # In case commands are still not registered to SlashCommand.
191+ all_guild_ids = []
192+ for x in self .commands :
193+ for i in self .commands [x ].allowed_guild_ids :
194+ if i not in all_guild_ids :
195+ all_guild_ids .append (i )
191196 cmds = {
192197 "global" : [],
193- "guild" : {}
198+ "guild" : {x : [] for x in all_guild_ids }
194199 }
200+ wait = {} # Before merging to return dict, let's first put commands to temporary dict.
195201 for x in self .commands :
196202 selected = self .commands [x ]
197- if selected .has_subcommands and selected .func :
198- # Registering both subcommand and command with same base name / name
199- # will result in only subcommand being registered,
200- # so we will warn this at registering subcommands.
201- self .logger .warning (f"Detected command name with same subcommand base name! "
202- f"This command will only have subcommand: { x } " )
203-
204- options = []
205- if selected .has_subcommands :
206- tgt = self .subcommands [x ]
207- for y in tgt :
208- sub = tgt [y ]
209- if isinstance (sub , model .SubcommandObject ):
210- _dict = {
211- "name" : sub .name ,
212- "description" : sub .description or "No Description." ,
213- "type" : model .SlashCommandOptionType .SUB_COMMAND ,
214- "options" : sub .options or []
215- }
216- options .append (_dict )
217- else :
218- base_dict = {
219- "name" : y ,
220- "description" : "No Description." ,
221- "type" : model .SlashCommandOptionType .SUB_COMMAND_GROUP ,
222- "options" : []
223- }
224- for z in sub :
225- sub_sub = sub [z ]
226- _dict = {
227- "name" : sub_sub .name ,
228- "description" : sub_sub .description or "No Description." ,
229- "type" : model .SlashCommandOptionType .SUB_COMMAND ,
230- "options" : sub_sub .options or []
231- }
232- base_dict ["options" ].append (_dict )
233- if sub_sub .subcommand_group_description :
234- base_dict ["description" ] = sub_sub .subcommand_group_description
235- options .append (base_dict )
236-
237203 command_dict = {
238204 "name" : x ,
239205 "description" : selected .description or "No Description." ,
240- "options" : selected .options if not options else options
206+ "options" : selected .options or []
241207 }
242208 if selected .allowed_guild_ids :
243209 for y in selected .allowed_guild_ids :
244- try :
245- cmds ["guild" ][y ].append (command_dict )
246- except KeyError :
247- cmds ["guild" ][y ] = [command_dict ]
210+ if y not in wait :
211+ wait [y ] = {}
212+ wait [y ][x ] = command_dict
248213 else :
249- cmds ["global" ].append (command_dict )
214+ if "global" not in wait :
215+ wait ["global" ] = {}
216+ wait ["global" ][x ] = command_dict
217+
218+ # Separated normal command add and subcommand add not to
219+ # merge subcommands to one. More info at Issue #88
220+ # https://github.com/eunwoo1104/discord-py-slash-command/issues/88
221+
222+ for x in self .commands :
223+ if not self .commands [x ].has_subcommands :
224+ continue
225+ tgt = self .subcommands [x ]
226+ for y in tgt :
227+ sub = tgt [y ]
228+ if isinstance (sub , model .SubcommandObject ):
229+ _dict = {
230+ "name" : sub .name ,
231+ "description" : sub .description or "No Description." ,
232+ "type" : model .SlashCommandOptionType .SUB_COMMAND ,
233+ "options" : sub .options or []
234+ }
235+ if sub .allowed_guild_ids :
236+ for z in sub .allowed_guild_ids :
237+ wait [z ][x ]["options" ].append (_dict )
238+ else :
239+ wait ["global" ][x ]["options" ].append (_dict )
240+ else :
241+ queue = {}
242+ base_dict = {
243+ "name" : y ,
244+ "description" : "No Description." ,
245+ "type" : model .SlashCommandOptionType .SUB_COMMAND_GROUP ,
246+ "options" : []
247+ }
248+ for z in sub :
249+ sub_sub = sub [z ]
250+ _dict = {
251+ "name" : sub_sub .name ,
252+ "description" : sub_sub .description or "No Description." ,
253+ "type" : model .SlashCommandOptionType .SUB_COMMAND ,
254+ "options" : sub_sub .options or []
255+ }
256+ if sub_sub .allowed_guild_ids :
257+ for i in sub_sub .allowed_guild_ids :
258+ if i not in queue :
259+ queue [i ] = base_dict
260+ queue [i ]["options" ].append (_dict )
261+ else :
262+ if "global" not in queue :
263+ queue ["global" ] = base_dict
264+ queue ["global" ]["options" ].append (_dict )
265+ print (__import__ ("json" ).dumps (queue , indent = 2 ))
266+ for i in queue :
267+ wait [i ][x ]["options" ].append (queue [i ])
268+
269+ for x in wait :
270+ if x == "global" :
271+ [cmds ["global" ].append (n ) for n in wait ["global" ].values ()]
272+ else :
273+ [cmds ["guild" ][x ].append (n ) for n in wait [x ].values ()]
250274
251275 return cmds
252276
@@ -326,8 +350,10 @@ def add_slash_command(self,
326350 "connector" : connector or {},
327351 "has_subcommands" : has_subcommands
328352 }
329- self .commands [name ] = model .CommandObject (name , _cmd )
353+ obj = model .CommandObject (name , _cmd )
354+ self .commands [name ] = obj
330355 self .logger .debug (f"Added command `{ name } `" )
356+ return obj
331357
332358 def add_subcommand (self ,
333359 cmd ,
@@ -371,10 +397,9 @@ def add_subcommand(self,
371397 description = description or getdoc (cmd )
372398
373399 if base in self .commands :
374- tgt = self .commands [base ]
375- for x in tgt .allowed_guild_ids :
376- if x not in guild_ids :
377- guild_ids .append (x )
400+ for x in guild_ids :
401+ if x not in self .commands [base ].allowed_guild_ids :
402+ self .commands [base ].allowed_guild_ids .append (x )
378403
379404 if options is None :
380405 options = manage_commands .generate_options (cmd , description )
@@ -401,7 +426,6 @@ def add_subcommand(self,
401426 self .commands [base ] = model .CommandObject (base , _cmd )
402427 else :
403428 self .commands [base ].has_subcommands = True
404- self .commands [base ].allowed_guild_ids = guild_ids
405429 if self .commands [base ].description :
406430 _cmd ["description" ] = self .commands [base ].description
407431 if base not in self .subcommands :
@@ -411,12 +435,15 @@ def add_subcommand(self,
411435 self .subcommands [base ][subcommand_group ] = {}
412436 if name in self .subcommands [base ][subcommand_group ]:
413437 raise error .DuplicateCommand (f"{ base } { subcommand_group } { name } " )
414- self .subcommands [base ][subcommand_group ][name ] = model .SubcommandObject (_sub , base , name , subcommand_group )
438+ obj = model .SubcommandObject (_sub , base , name , subcommand_group )
439+ self .subcommands [base ][subcommand_group ][name ] = obj
415440 else :
416441 if name in self .subcommands [base ]:
417442 raise error .DuplicateCommand (f"{ base } { name } " )
418- self .subcommands [base ][name ] = model .SubcommandObject (_sub , base , name )
443+ obj = model .SubcommandObject (_sub , base , name )
444+ self .subcommands [base ][name ] = obj
419445 self .logger .debug (f"Added subcommand `{ base } { subcommand_group or '' } { name or cmd .__name__ } `" )
446+ return obj
420447
421448 def slash (self ,
422449 * ,
@@ -485,8 +512,8 @@ async def _pick(ctx, choice1, choice2): # Command with 1 or more args.
485512 guild_ids = [guild_id ]
486513
487514 def wrapper (cmd ):
488- self .add_slash_command (cmd , name , description , guild_ids , options , connector )
489- return cmd
515+ obj = self .add_slash_command (cmd , name , description , guild_ids , options , connector )
516+ return obj
490517
491518 return wrapper
492519
@@ -557,8 +584,8 @@ async def _group_kick_user(ctx, user):
557584 subcommand_group_description = subcommand_group_description or sub_group_desc
558585
559586 def wrapper (cmd ):
560- self .add_subcommand (cmd , base , subcommand_group , name , description , base_description , subcommand_group_description , guild_ids , options , connector )
561- return cmd
587+ obj = self .add_subcommand (cmd , base , subcommand_group , name , description , base_description , subcommand_group_description , guild_ids , options , connector )
588+ return obj
562589
563590 return wrapper
564591
0 commit comments