Advertisement
sadasdasdsadasd

Untitled

Jul 8th, 2023
39
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.98 KB | None | 0 0
  1. """A pycord extension that allows splitting command groups into multiple cogs."""
  2.  
  3. from typing import Callable, Dict, List, Optional
  4.  
  5. import discord
  6. from discord.utils import copy_doc
  7.  
  8. __all__ = ("add_to_group", "apply_multicog", "Bot")
  9.  
  10.  
  11. group_mapping: Dict[str, List[discord.SlashCommand]] = {}
  12.  
  13.  
  14. def add_to_group(name: str) -> Callable[[discord.SlashCommand], discord.SlashCommand]:
  15. """A decorator to add a slash command to a slash command group.
  16. This will take effect and change the `parent` and `guild_ids` attributes
  17. of the command when `apply_multicog` is ran.
  18. """
  19.  
  20. def decorator(command: discord.SlashCommand) -> discord.SlashCommand:
  21. if command.parent:
  22. raise TypeError(f"command {command.name} is already in a group.")
  23.  
  24. try:
  25. group_mapping[name].append(command)
  26. except:
  27. group_mapping[name] = [command]
  28.  
  29. return command
  30.  
  31. return decorator
  32.  
  33.  
  34. def find_group(bot: discord.Bot, name: str) -> Optional[discord.SlashCommandGroup]:
  35. """A helper function to find and return a (sub)group with the provided name."""
  36.  
  37. for command in bot._pending_application_commands:
  38. if isinstance(command, discord.SlashCommandGroup):
  39. if command.name == name:
  40. return command
  41.  
  42. for subcommand in command.subcommands:
  43. if (
  44. isinstance(subcommand, discord.SlashCommandGroup)
  45. and subcommand.name == name
  46. ):
  47. return subcommand
  48.  
  49.  
  50. def apply_multicog(bot: discord.Bot) -> None:
  51. """A function to update the attributes of the pending commands which were
  52. used with `add_to_group`.
  53. """
  54.  
  55. for group_name, pending_commands in group_mapping.items():
  56. if (group := find_group(bot, group_name)) is None:
  57. raise RuntimeError(f"no slash command group named {group_name} found.")
  58.  
  59. for command in pending_commands:
  60. command.guild_ids = group.guild_ids
  61. bot._pending_application_commands.remove(command)
  62. command.parent = group
  63. for cog in bot.cogs.values():
  64. if (
  65. attr := getattr(cog, command.callback.__name__, None)
  66. ) and attr.callback == command.callback:
  67. command.cog = cog
  68. break
  69. else:
  70. command.cog = group.cog
  71. # fallback, will use the cog of the target group
  72. group.subcommands.append(command)
  73.  
  74.  
  75. class Bot(discord.Bot):
  76. """A subclass of `discord.Bot` that calls `apply_multicog` when `sync_commands`
  77. is ran with no arguments."""
  78.  
  79. @copy_doc(discord.Bot.sync_commands)
  80. async def sync_commands(
  81. self,
  82. commands: Optional[List[discord.ApplicationCommand]] = None,
  83. **kwargs,
  84. ) -> None:
  85. if not commands:
  86. apply_multicog(self)
  87. await super().sync_commands(commands, **kwargs)
  88.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement