Skip to content

Instantly share code, notes, and snippets.

@http-nova
Forked from AbstractUmbra/00-deprecation.md
Created February 19, 2024 18:08
Show Gist options
  • Save http-nova/0048382e705783dff46fc6c28d6e1b4f to your computer and use it in GitHub Desktop.
Save http-nova/0048382e705783dff46fc6c28d6e1b4f to your computer and use it in GitHub Desktop.

Revisions

  1. @AbstractUmbra AbstractUmbra revised this gist Dec 14, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion 00-deprecation.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,3 @@
    # This gist has now been 'deprecated' and has moved...

    ... to [my blog style space](https://about.abstractumbra.dev/dpy) for easier contribution by third parties and to provide what I believe to be an easier reading experience. Please field all enquiries and issues to [the source repository](https://github.com/AbstractUmbra/abstractumbra.github.io)
    ... to [my blog style space](https://about.abstractumbra.dev/dpy) for easier contribution by third parties and to provide what I believe to be an easier reading experience. Please field all enquiries and issues to [the source repository](https://github.com/AbstractUmbra/abstractumbra.github.io).
  2. @AbstractUmbra AbstractUmbra revised this gist Dec 14, 2023. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions 00-deprecation.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    # This gist has now been 'deprecated' and has moved...

    ... to [my blog style space](https://about.abstractumbra.dev/dpy) for easier contribution by third parties and to provide what I believe to be an easier reading experience. Please field all enquiries and issues to [the source repository](https://github.com/AbstractUmbra/abstractumbra.github.io)
  3. @AbstractUmbra AbstractUmbra revised this gist Mar 31, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion 03-syncing_gotchas_and_tricks.md
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ There is a ratelimit on syncing global commands which add commands.
    Updating commands (currently) has no ratelimit.

    It is still recommended to sync your commands to a test guild before syncing them globally. Discord.py has added a helper method to do just that:
    [`CommandTree.copy_global_to`](https://discordpy.readthedocs.io/en/master/interactions/api.html#discord.app_commands.CommandTree.copy_global_to)
    [`CommandTree.copy_global_to`](https://discordpy.readthedocs.io/en/latest/interactions/api.html#discord.app_commands.CommandTree.copy_global_to)

    This util is used as follows:

  4. @AbstractUmbra AbstractUmbra revised this gist Dec 30, 2022. 9 changed files with 0 additions and 0 deletions.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
  5. @AbstractUmbra AbstractUmbra revised this gist Nov 21, 2022. No changes.
  6. @AbstractUmbra AbstractUmbra revised this gist Nov 21, 2022. 1 changed file with 47 additions and 1 deletion.
    48 changes: 47 additions & 1 deletion 3-syncing_gotchas_and_tricks.md
    Original file line number Diff line number Diff line change
    @@ -23,4 +23,50 @@ Bot.tree.copy_global_to(guild=guild)
    ```
    All this method does is copy your defined global commands (so ones without a `guild` or `guilds` kwarg, or without the `@app_commands.guilds()` decorator)
    to the specified guild within the CommandTree.
    When you use this method you **must** sync afterward still, you can refer to `when_to_sync.md` for details there.
    When you use this method you **must** sync afterward still, you can refer to `when_to_sync.md` for details there.

    ## Sync command example
    <details>
    <br>

    ```python
    from typing import Literal, Optional
    from discord.ext import commands
    from discord.ext.commands import Greedy, Context # or a subclass of yours

    @bot.command()
    @commands.guild_only()
    @commands.is_owner()
    async def sync(
    ctx: Context, guilds: Greedy[discord.Object], spec: Optional[Literal["~", "*", "^"]] = None) -> None:
    if not guilds:
    if spec == "~":
    synced = await ctx.bot.tree.sync(guild=ctx.guild)
    elif spec == "*":
    ctx.bot.tree.copy_global_to(guild=ctx.guild)
    synced = await ctx.bot.tree.sync(guild=ctx.guild)
    elif spec == "^":
    ctx.bot.tree.clear_commands(guild=ctx.guild)
    await ctx.bot.tree.sync(guild=ctx.guild)
    synced = []
    else:
    synced = await ctx.bot.tree.sync()

    await ctx.send(
    f"Synced {len(synced)} commands {'globally' if spec is None else 'to the current guild.'}"
    )
    return

    ret = 0
    for guild in guilds:
    try:
    await ctx.bot.tree.sync(guild=guild)
    except discord.HTTPException:
    pass
    else:
    ret += 1

    await ctx.send(f"Synced the tree to {ret}/{len(guilds)}.")
    ```

    </details>
  7. @AbstractUmbra AbstractUmbra revised this gist Nov 21, 2022. 9 changed files with 19 additions and 0 deletions.
    File renamed without changes.
    19 changes: 19 additions & 0 deletions 2-in_depth_syncing.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    # Syncing the command tree in discord.py

    This seems to be a common "gotcha" with users new to the library. As such I have been asked to cover it a bit more here.

    [CommandTree.sync](https://discordpy.readthedocs.io/en/stable/interactions/api.html#discord.app_commands.CommandTree.sync) is how we make Discord aware of our command definitions. This means that we use an API request to send them a copy of what our commands look like and act like, so they can display it to your users in the client.
    If you do not sync your tree, the commands will not show up, or update them if you make changes locally.

    I cover some more items relating to this in the next file below. But for now let's cover the basics and what you can do here.

    ## Common caveats

    In my time as Helper, I see people syncing their CommandTree in the `on_ready_event` or in the new `setup_hook` entrypoint method.
    I do not advise this personally, it can lead to footguns if you aren't prepared.
    For examples, if you sync your tree before you load your extensions (which have your application commands), then you're effectively syncing an empty tree to Discord, which will wipe your commands.
    If you sync your tree and then make changes, you rely on the autosync and forget to sync changes, resulting in errors and failing commands.

    This is why it is strongly recommended to sync on demand with a command (ideally with a message command) and know when to do such things. I cover that later too.

    I'll add more things when I can think of them.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
  8. @AbstractUmbra AbstractUmbra revised this gist Oct 6, 2022. 1 changed file with 9 additions and 7 deletions.
    16 changes: 9 additions & 7 deletions 9-subclassing_group.py
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,10 @@
    # this a app command group
    # you can nest these up 1:
    # `/group group` = VALID
    # /group group group` = INVALID
    # etc... all invalid.
    # This an App command group.
    # You can nest these down a few levels, like so:-

    # /group subcommand (up to 25)
    # /group subcommand group
    # /group subcommand group subcommand (up to 25).


    # this example shows one way to do this, subclassing
    # the other is constructing an instance of app_commands.Group()
    @@ -11,8 +13,8 @@
    import discord
    from discord import app_commands

    # the @app_commands.guilds and others (including checks) can be used above the class
    # these will apply to ALL subcommand, subcommands cannot have invidual perms!
    # the @app_commands.guilds and @app_commands.default_permissions decorators (also including checks) can be used above the class.
    # these will apply to ALL subcommands, subcommands cannot have invidual perms!
    @app_commands.guild_only()
    class Group(app_commands.Group):

  9. @AbstractUmbra AbstractUmbra revised this gist Sep 8, 2022. 2 changed files with 1 addition and 11 deletions.
    12 changes: 1 addition & 11 deletions 1-primer.md
    Original file line number Diff line number Diff line change
    @@ -2,17 +2,7 @@

    This short example will cover how to make slash commands within an ``ext.commands.Bot``'s extension and Cog ecosystem.

    There will be 3 examples:
    - A Cog Group, which will house all sub-commmands and the Cog is the parent.
    - This means the Cog class is regarded as the parent command, and all commands defined are "sub" commands.
    e.g. `/cog sub_cmd`

    - A free Cog, where all commands will be top-level.
    - This means like:
    i.e `/my_cmd`
    - A hybrid of the two, for when you want to group them accordingly.
    - So this will allow:
    i.e `/parent sub_1`, `/parent sub_2` and `/hello`
    This will cover most slash situations within discord.py

    I added how this command would be invoked in the doc strings.

    File renamed without changes.
  10. @AbstractUmbra AbstractUmbra revised this gist Sep 8, 2022. 8 changed files with 0 additions and 0 deletions.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
    File renamed without changes.
  11. @AbstractUmbra AbstractUmbra revised this gist Aug 27, 2022. 1 changed file with 33 additions and 0 deletions.
    33 changes: 33 additions & 0 deletions subclassing_group.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,33 @@
    # this a app command group
    # you can nest these up 1:
    # `/group group` = VALID
    # /group group group` = INVALID
    # etc... all invalid.

    # this example shows one way to do this, subclassing
    # the other is constructing an instance of app_commands.Group()
    # that one is shown in "free_function_commands-py"

    import discord
    from discord import app_commands

    # the @app_commands.guilds and others (including checks) can be used above the class
    # these will apply to ALL subcommand, subcommands cannot have invidual perms!
    @app_commands.guild_only()
    class Group(app_commands.Group):

    # subcommand of Group
    @app_commands.command()
    async def my_subcommand(self, interaction: discord.Interaction) -> None:
    await interaction.response.send_message("hello from the subcommand!")

    # nested group command
    group2 = app_commands.Group(name="group2", description="This a nested group!")

    # subcommand of group2
    @group2.command()
    async def my_second_group_command(self, interaction: discord.Interaction) -> None:
    await interaction.response.send_message("hello from the second subcommand!")

    # unlike commands.GroupCog, you need to add this class to your tree yourself.
    tree.add_command(Group())
  12. @AbstractUmbra AbstractUmbra revised this gist May 5, 2022. 2 changed files with 47 additions and 0 deletions.
    File renamed without changes.
    47 changes: 47 additions & 0 deletions hybrid_commands.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    # discord.py recently added full hybrid commands. They work as follows:
    ## Note: as I don't see a reason not to, I will present an example using a commands.Cog.

    ## IMPORTANT: hybrid commands only work if the signature is compatible with app commands.
    # this means that all parameters must have a type annotation, even if it is just `str`.
    # this also means that you must use `Transformers` not `Coverters` in these cases.


    import discord
    from discord.ext import commands

    class MyCog(commands.Cog):
    def __init__(self, bot: commands.Bot) -> None:
    self.bot: commands.Bot = bot

    @commands.hybrid_command(name="ping")
    async def ping_command(self, ctx: commands.Context) -> None:
    """
    This command is actually used as an app command AND a message command.
    This means it is invoked with `?ping` and `/ping` (once synced, of course).
    """

    await ctx.send("Hello!")
    # we use ctx.send and this will handle both the message command and app command of sending.
    # added note: you can check if this command is invoked as an app command by checking the `ctx.interaction` attribute.


    @commands.hybrid_group(name="parent")
    async def parent_command(self, ctx: commands.Context) -> None:
    """
    We even have the use of parents. This will work as usual for ext.commands but will be un-invokable for app commands.
    This is a discord limitation as groups are un-invokable.
    """
    ... # nothing we want to do in here, I guess!

    @parent_command.command(name="sub")
    async def sub_command(self, ctx: commands.Context, argument: str) -> None:
    """
    This subcommand can now be invoked with `?parent sub <arg>` or `/parent sub <arg>` (once synced).
    """

    await ctx.send(f"Hello, you sent {argument}!")

    async def setup(bot: commands.Bot) -> None:
    await bot.add_cog(MyCog(bot))


  13. @AbstractUmbra AbstractUmbra revised this gist May 5, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion extension_with_group.py
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    from discord import app_commands
    from discord.ext import commands

    class MyCog(commands.Cog, app_commands.Group, name="parent"):
    class MyCog(commands.GroupCog, name="parent"):
    def __init__(self, bot: commands.Bot) -> None:
    self.bot = bot
    super().__init__() # this is now required in this context.
  14. @AbstractUmbra AbstractUmbra revised this gist Apr 12, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions when_to_sync.md
    Original file line number Diff line number Diff line change
    @@ -7,6 +7,7 @@ Let's try and write up some bullet points:-
    ## When to sync

    - When you add a new command.
    - When you remove a command.
    - When a command's name or description changes.
    - When the callback's parameters change.
    - This includes parameter names, types or descriptions.
  15. @AbstractUmbra AbstractUmbra revised this gist Apr 12, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion syncing_gotchas_and_tricks.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    # Sync examples and details

    What I've been recommending to people, is to maintain a sync command as a Message Command (`@bot.command()`) or some sort of message invoke.
    Bots without the message content intent can still receive full dms or message content with a their mention in them.
    Bots without the message content intent will still receive content of messages that mention them or are in DMs.

    ~~It's not like you can use a slash command to sync... when that command isn't synced.~~

  16. @AbstractUmbra AbstractUmbra revised this gist Apr 12, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion syncing_gotchas_and_tricks.md
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ There is a ratelimit on syncing global commands which add commands.
    Updating commands (currently) has no ratelimit.

    It is still recommended to sync your commands to a test guild before syncing them globally. Discord.py has added a helper method to do just that:
    [`CommandTree.copy_global_to`](https://discordpy.readthedocs.io/en/master/interactions/api.html#discord.app_commands.CommandTree.copy_global_to3)
    [`CommandTree.copy_global_to`](https://discordpy.readthedocs.io/en/master/interactions/api.html#discord.app_commands.CommandTree.copy_global_to)

    This util is used as follows:

  17. @AbstractUmbra AbstractUmbra revised this gist Apr 12, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions when_to_sync.md
    Original file line number Diff line number Diff line change
    @@ -12,5 +12,6 @@ Let's try and write up some bullet points:-
    - This includes parameter names, types or descriptions.
    - Also when you add or remove a parameter.
    - If you change a global to a guild command, or vice versa.
    - NOTE: If you do this, you will need to sync both global and to that guild to reflect the change.

    These are currently the only times you should re-sync.
  18. @AbstractUmbra AbstractUmbra revised this gist Apr 12, 2022. No changes.
  19. @AbstractUmbra AbstractUmbra revised this gist Apr 12, 2022. 4 changed files with 72 additions and 0 deletions.
    30 changes: 30 additions & 0 deletions free_function_commands.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    import asyncio

    from discord.ext import commands
    from discord import app_commands

    # define Bot with **needed** parameters
    bot = commands.Bot(command_prefix="some_prefix", intents=some_intents_definition)

    # You can now use `@bot.tree.command()` as a decorator:
    @bot.tree.command()
    async def my_command(interaction: discord.Interaction) -> None:
    await interaction.response.send_message("Hello from my command!")
    ### NOTE: the above is a global command, see the `main()` func below:

    # we can even use Groups
    group = app_commands.Group(name="some-parent", description="description")

    @group.command()
    async def my_subcommand(interaction: discord.Interaction) -> None:
    await interaction.response.send_message("hello from the subcommand!")

    bot.tree.add_command(group, guild=discord.Object(id=...))

    async def main():
    async with bot:
    # do you setup stuff if you need it here, then:
    bot.tree.copy_global_to(guild=discord.Object(id=...)) # we copy the global commands we have to a guild, this is optional
    await bot.start(MY_TOKEN)

    # We still need to sync this tree somehow, but you can make a command as discussed already.
    File renamed without changes.
    26 changes: 26 additions & 0 deletions syncing_gotchas_and_tricks.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    # Sync examples and details

    What I've been recommending to people, is to maintain a sync command as a Message Command (`@bot.command()`) or some sort of message invoke.
    Bots without the message content intent can still receive full dms or message content with a their mention in them.

    ~~It's not like you can use a slash command to sync... when that command isn't synced.~~

    ## Syncing gotchas

    There is a ratelimit on syncing global commands which add commands.
    Updating commands (currently) has no ratelimit.

    It is still recommended to sync your commands to a test guild before syncing them globally. Discord.py has added a helper method to do just that:
    [`CommandTree.copy_global_to`](https://discordpy.readthedocs.io/en/master/interactions/api.html#discord.app_commands.CommandTree.copy_global_to3)

    This util is used as follows:

    ```python
    # you have a defined Bot, with a tree and have commands added to it that are global.

    guild = ctx.guild or discord.Object(id=...) # you can use a full discord.Guild as the method accepts a Snowflake
    Bot.tree.copy_global_to(guild=guild)
    ```
    All this method does is copy your defined global commands (so ones without a `guild` or `guilds` kwarg, or without the `@app_commands.guilds()` decorator)
    to the specified guild within the CommandTree.
    When you use this method you **must** sync afterward still, you can refer to `when_to_sync.md` for details there.
    16 changes: 16 additions & 0 deletions when_to_sync.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    # Syncing your commands

    At the time of writing this, it's still mostly unclear to most users when they should be syncing their commands to Discord.

    Let's try and write up some bullet points:-

    ## When to sync

    - When you add a new command.
    - When a command's name or description changes.
    - When the callback's parameters change.
    - This includes parameter names, types or descriptions.
    - Also when you add or remove a parameter.
    - If you change a global to a guild command, or vice versa.

    These are currently the only times you should re-sync.
  20. @AbstractUmbra AbstractUmbra revised this gist Mar 20, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion extension_with_group.py
    Original file line number Diff line number Diff line change
    @@ -10,7 +10,7 @@ def __init__(self, bot: commands.Bot) -> None:
    super().__init__() # this is now required in this context.

    @app_commands.command(name="sub-1")
    async def my_sub_command_1(self, intereaction: discord.Interaction) -> None:
    async def my_sub_command_1(self, interaction: discord.Interaction) -> None:
    """ /parent sub-1 """
    await interaction.response.send_message("Hello from sub command 1", ephemeral=True)

  21. @AbstractUmbra AbstractUmbra revised this gist Mar 17, 2022. 3 changed files with 3 additions and 0 deletions.
    1 change: 1 addition & 0 deletions extension_hybrid.py
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    import discord
    from discord import app_commands
    from discord.ext import commands

    1 change: 1 addition & 0 deletions extension_no_group.py
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    import discord
    from discord import app_commands
    from discord.ext import commands

    1 change: 1 addition & 0 deletions extension_with_group.py
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,6 @@
    # for simplicity, these commands are all global. You can add `guild=` or `guilds=` to `Bot.add_cog` in `setup` to add them to a guild.

    import discord
    from discord import app_commands
    from discord.ext import commands

  22. @AbstractUmbra AbstractUmbra revised this gist Mar 17, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions extension_with_group.py
    Original file line number Diff line number Diff line change
    @@ -9,12 +9,12 @@ def __init__(self, bot: commands.Bot) -> None:
    super().__init__() # this is now required in this context.

    @app_commands.command(name="sub-1")
    async def my_sub_command_1(self, discord.Interaction) -> None:
    async def my_sub_command_1(self, intereaction: discord.Interaction) -> None:
    """ /parent sub-1 """
    await interaction.response.send_message("Hello from sub command 1", ephemeral=True)

    @app_commands.command(name="sub-2")
    async def my_sub_command_2(self, discord.Interaction) -> None:
    async def my_sub_command_2(self, interaction: discord.Interaction) -> None:
    """ /parent sub-2 """
    await interaction.response.send_message("Hello from sub command 2", ephemeral=True)

  23. @AbstractUmbra AbstractUmbra revised this gist Mar 16, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions extension_hybrid.py
    Original file line number Diff line number Diff line change
    @@ -13,12 +13,12 @@ def __init__(self, bot: commands.Bot) -> None:
    @app_commands.command(name="top-command")
    async def my_top_command(self, interaction: discord.Interaction) -> None:
    """ /top-command """
    await interaction.send("Hello from top level command!", ephemeral=True)
    await interaction.response.send_message("Hello from top level command!", ephemeral=True)

    @group.command(name="sub-command") # we use the declared group to make a command.
    async def my_sub_command(self, interaction: discord.Interaction) -> None:
    """ /parent sub-command """
    await interaction.send("Hello from the sub command!", ephemeral=True)
    await interaction.response.send_message("Hello from the sub command!", ephemeral=True)

    async def setup(bot: commands.Bot) -> None:
    await bot.add_cog(MyCog(bot))
  24. @AbstractUmbra AbstractUmbra revised this gist Mar 15, 2022. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion extension_hybrid.py
    Original file line number Diff line number Diff line change
    @@ -6,13 +6,16 @@ def __init__(self, bot: commands.Bot) -> None:
    self.bot = bot

    group = app_commands.Group(name="parent", description="...")
    # Above, we declare a command Group, in discord terms this is a parent command
    # We define it within the class scope (not an instance scope) so we can use it as a decorator.
    # This does have namespace caveats but i don't believe they're worth outlining in our needs.

    @app_commands.command(name="top-command")
    async def my_top_command(self, interaction: discord.Interaction) -> None:
    """ /top-command """
    await interaction.send("Hello from top level command!", ephemeral=True)

    @group.command(name="sub-command")
    @group.command(name="sub-command") # we use the declared group to make a command.
    async def my_sub_command(self, interaction: discord.Interaction) -> None:
    """ /parent sub-command """
    await interaction.send("Hello from the sub command!", ephemeral=True)
  25. @AbstractUmbra AbstractUmbra revised this gist Mar 15, 2022. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -16,4 +16,6 @@ There will be 3 examples:

    I added how this command would be invoked in the doc strings.

    This does not account for the fact you still need to sync `Bot.tree` somewhere, please remember to do this.
    This does not account for the fact you still need to sync `Bot.tree` somewhere, please remember to do this.

    N.B: Ping Umbra#0009 in the d.py server if you want to suggest edits/improvements.
  26. @AbstractUmbra AbstractUmbra revised this gist Mar 15, 2022. 4 changed files with 30 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -12,4 +12,8 @@ There will be 3 examples:
    i.e `/my_cmd`
    - A hybrid of the two, for when you want to group them accordingly.
    - So this will allow:
    i.e `/parent sub_1`, `/parent sub_2` and `/hello`
    i.e `/parent sub_1`, `/parent sub_2` and `/hello`

    I added how this command would be invoked in the doc strings.

    This does not account for the fact you still need to sync `Bot.tree` somewhere, please remember to do this.
    21 changes: 21 additions & 0 deletions extension_hybrid.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    from discord import app_commands
    from discord.ext import commands

    class MyCog(commands.Cog):
    def __init__(self, bot: commands.Bot) -> None:
    self.bot = bot

    group = app_commands.Group(name="parent", description="...")

    @app_commands.command(name="top-command")
    async def my_top_command(self, interaction: discord.Interaction) -> None:
    """ /top-command """
    await interaction.send("Hello from top level command!", ephemeral=True)

    @group.command(name="sub-command")
    async def my_sub_command(self, interaction: discord.Interaction) -> None:
    """ /parent sub-command """
    await interaction.send("Hello from the sub command!", ephemeral=True)

    async def setup(bot: commands.Bot) -> None:
    await bot.add_cog(MyCog(bot))
    2 changes: 2 additions & 0 deletions extension_no_group.py
    Original file line number Diff line number Diff line change
    @@ -7,11 +7,13 @@ def __init__(self, bot: commands.Bot) -> None:

    @app_commands.command(name="command-1")
    async def my_command(self, interaction: discord.Interaction) -> None:
    """ /command-1 """
    await interaction.response.send_message("Hello from command 1!", ephemeral=True)

    @app_commands.command(name="command-2")
    @app_commands.guilds(discord.Object(id=...), ...)
    async def my_private_command(self, interaction: discord.Interaction) -> None:
    """ /command-2 """
    await interaction.response.send_message("Hello from private command!", ephemeral=True)

    async def setup(bot: commands.Bot) -> None:
    2 changes: 2 additions & 0 deletions extension_with_group.py
    Original file line number Diff line number Diff line change
    @@ -10,10 +10,12 @@ def __init__(self, bot: commands.Bot) -> None:

    @app_commands.command(name="sub-1")
    async def my_sub_command_1(self, discord.Interaction) -> None:
    """ /parent sub-1 """
    await interaction.response.send_message("Hello from sub command 1", ephemeral=True)

    @app_commands.command(name="sub-2")
    async def my_sub_command_2(self, discord.Interaction) -> None:
    """ /parent sub-2 """
    await interaction.response.send_message("Hello from sub command 2", ephemeral=True)

    async def setup(bot: commands.Bot) -> None:
  27. @AbstractUmbra AbstractUmbra revised this gist Mar 15, 2022. 1 changed file with 18 additions and 0 deletions.
    18 changes: 18 additions & 0 deletions extension_no_group.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,18 @@
    from discord import app_commands
    from discord.ext import commands

    class MyCog(commands.Cog):
    def __init__(self, bot: commands.Bot) -> None:
    self.bot = bot

    @app_commands.command(name="command-1")
    async def my_command(self, interaction: discord.Interaction) -> None:
    await interaction.response.send_message("Hello from command 1!", ephemeral=True)

    @app_commands.command(name="command-2")
    @app_commands.guilds(discord.Object(id=...), ...)
    async def my_private_command(self, interaction: discord.Interaction) -> None:
    await interaction.response.send_message("Hello from private command!", ephemeral=True)

    async def setup(bot: commands.Bot) -> None:
    await bot.add_cog(MyCog(bot))
  28. @AbstractUmbra AbstractUmbra revised this gist Mar 15, 2022. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion extension_with_group.py
    Original file line number Diff line number Diff line change
    @@ -17,4 +17,6 @@ async def my_sub_command_2(self, discord.Interaction) -> None:
    await interaction.response.send_message("Hello from sub command 2", ephemeral=True)

    async def setup(bot: commands.Bot) -> None:
    await bot.add_cog(MyCog)
    await bot.add_cog(MyCog(bot))
    # or if you want guild/guilds only...
    await bot.add_cog(MyCog(bot), guilds=[discord.Object(id=...)])
  29. @AbstractUmbra AbstractUmbra revised this gist Mar 15, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion extension_with_group.py
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # for simplicity, these commands are all global. You can add
    # for simplicity, these commands are all global. You can add `guild=` or `guilds=` to `Bot.add_cog` in `setup` to add them to a guild.

    from discord import app_commands
    from discord.ext import commands
  30. @AbstractUmbra AbstractUmbra created this gist Mar 15, 2022.
    15 changes: 15 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    # Slash Commands and you

    This short example will cover how to make slash commands within an ``ext.commands.Bot``'s extension and Cog ecosystem.

    There will be 3 examples:
    - A Cog Group, which will house all sub-commmands and the Cog is the parent.
    - This means the Cog class is regarded as the parent command, and all commands defined are "sub" commands.
    e.g. `/cog sub_cmd`

    - A free Cog, where all commands will be top-level.
    - This means like:
    i.e `/my_cmd`
    - A hybrid of the two, for when you want to group them accordingly.
    - So this will allow:
    i.e `/parent sub_1`, `/parent sub_2` and `/hello`
    20 changes: 20 additions & 0 deletions extension_with_group.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    # for simplicity, these commands are all global. You can add

    from discord import app_commands
    from discord.ext import commands

    class MyCog(commands.Cog, app_commands.Group, name="parent"):
    def __init__(self, bot: commands.Bot) -> None:
    self.bot = bot
    super().__init__() # this is now required in this context.

    @app_commands.command(name="sub-1")
    async def my_sub_command_1(self, discord.Interaction) -> None:
    await interaction.response.send_message("Hello from sub command 1", ephemeral=True)

    @app_commands.command(name="sub-2")
    async def my_sub_command_2(self, discord.Interaction) -> None:
    await interaction.response.send_message("Hello from sub command 2", ephemeral=True)

    async def setup(bot: commands.Bot) -> None:
    await bot.add_cog(MyCog)