From 950246ff586d58fb491db70e3a1fd8ac9c87c7d9 Mon Sep 17 00:00:00 2001 From: DLCHAMP <36091350+dlchamp@users.noreply.github.com> Date: Sun, 3 Sep 2023 20:06:49 -0500 Subject: [PATCH] Deployed a4419b8 with MkDocs version: 1.5.2 --- reference/helply/utils/embeds/index.html | 2 +- search/search_index.json | 2 +- sitemap.xml | 24 +++++++++++------------ sitemap.xml.gz | Bin 312 -> 313 bytes 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/reference/helply/utils/embeds/index.html b/reference/helply/utils/embeds/index.html index 1e6ff93..7597a89 100755 --- a/reference/helply/utils/embeds/index.html +++ b/reference/helply/utils/embeds/index.html @@ -1335,7 +1335,7 @@

if command.checks.roles: if guild: - roles = AppCommandHelp.roles_from_checks(command.checks, guild) + roles = Helply.roles_from_checks(command.checks, guild) role_checks = ", ".join(r.mention for r in roles) else: role_checks = ", ".join(str(check) for check in command.checks.roles) diff --git a/search/search_index.json b/search/search_index.json index ca72669..337e894 100755 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Helply","text":"

A user-friendly Python library designed to streamline the creation of \"help\" commands for Discord bots using application commands within the disnake library. This library will automatically parse your commands and provide details for each command, such as name, description, role and permission checks, etc.

Disclaimer

Please note that this library is not officially associated with the disnake project or any of its maintainers. It is an independent creation by a user of the Disnake library who wanted to streamline the process of creating /help commands without needing to rewrite the implementation each time.

"},{"location":"#key-features","title":"Key Features","text":""},{"location":"#installation","title":"Installation","text":"

To install the helply package, you will need git. If you don't have git installed on your system, you can download it from here.

Once you have git installed, run the following command inside your Python environment to install the package:

pip install git+https://github.com/dlchamp/Helply\n
"},{"location":"#usage","title":"Usage","text":"

After installing the package, you can use it in your project by importing it as follows:

from helply import Helply\n

AppCommands will be created and cached upon first use of helply to retrieve commands. This allows all commands to become registered with Discord before helply steps in to create it's own objects with the consolidated attributes provided by InvokableApplicationCommand and APIApplicationCommand

"},{"location":"#description-parsing","title":"Description parsing","text":"

Disnake will automatically parse your command descriptions from the docstring in your callback function, or by populating the description keyword argument. Helply uses that description, however, it also parses descriptions found in the extras key-word argument when it finds the \"help\" key. This proves exceptionally useful for menu commands that do not normally have a description that is displayed by the user's client.

Example - User Command:

# Since this is a user command that does not inherently have a description. We are using\n# extras to set the description for the help command.\n@bot.user_command(name=\"View Avatar\", extras={\"help\": \"Display the target user's avatar\"})\nasync def view_avatar(...):\n    ...\n

While designed to allow command descriptions for your menu commands, you may also use this feature to create longer descriptions for your slash commands as it would appear in your help response. For slash commands, this is really only useful if you wish to provide more information that would normally exceed the 100 character limit set by Discord.

Important

Setting extras will override your command.description when displayed in the help response.

In this example, the user will see \"Kick a member from the server\" when attempting to use the command while \"Removes the target member from the guild\" will appear as the command description in the help response.

@bot.slash_command(\n    name=\"kick\",\n    description=\"Kick the target member\",\n    extras={\"help\": \"Removes the target member from the guild\"}\n)\nasync def kick_member(...):\n\"\"\"Kick a member from the server\"\"\"\n
"},{"location":"#support-for-commands-checks","title":"Support for @commands Checks","text":"

The helply library also supports parsing of @commands style checks. For instance, if you are using @commands.has_permissions() to restrict command usage, the extension will recognize and display these permission requirements in the help response.

Example:

@bot.slash_command(name=\"kick\")\n@commands.has_permissions(kick_members=True)\nasync def kick_member(inter: disnake.GuildCommandInteraction, member: disnake.Member):\n\"\"\"Kick a member from the server\n\n    Parameters\n    ----------\n    member: Select a member to kick\n    \"\"\"\n

"},{"location":"#cogs-categories-and-disnake-ext-plugin-support","title":"Cogs, Categories, and disnake-ext-plugin support","text":"

Helply is able to parse the cog or category a command belongs to. This is useful if you wish to display an overview of command available within a category. If you are using cogs, you do not have to do anything extra. The cog associated with a command will be parsed automatically. However, if you're using disnake-ext-plugins, a command's cog will always be None. So, to set a commands category, we go back to the extras keyword to set the command's category:

@some_plugin.slash_command(name='command', extras={\"category\": \"General\"})\nasync def some_command(inter: disnake.ApplicationCommandInteractions):\n    ...\n
"},{"location":"#filtering-commands","title":"Filtering Commands","text":"

When retrieving commands from Helply, you may choose to pass in a member's guild_permissions. This will ensure that only commands the user has permissions to use will be retrieved.

Here, if the command is used within a guild, we want to show all commands available within the guild, including global commands, and only commands that the inter.author is able to use.

Important Permissions are compared against default_member_permissions. Setting this by default hides commands from members unable to use them, Passing permissions also allows helply to ensure these commands stay hidden, even in help responses.

# construct AppCommandHelp with the provided bot and a sequence of commands to ignore\n# ignore commands will not appear in any help responses.\nhelply = Helply(bot, commands_to_ignore=('help',))\n\n@bot.slash_command(name='help')\nasync def help_command(inter: disnake.ApplicationCommandInteraction):\n\n    if inter.guild:\n        guild_id = inter.guild_id\n        permissions = inter.author.guild_permissions\n        dm_only = False\n    else:\n        # command likely used in direct message\n        guild_id = None\n        permissions = None\n        dm_only = True\n\n    commands = helply.get_all_commands(guild_id, permissions=permissions, dm_only=dm_only)\n

"},{"location":"#support","title":"Support","text":"

Join the discord to get support or just chat.

"},{"location":"license/","title":"MIT License","text":"

Copyright (c) 2023 DLCHAMP

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

"},{"location":"examples/advanced/","title":"Advanced","text":"

This is a full example that implements all features of this project. Using the below example automatically handles commands being used within the context of a guild or via direct message to the bot.

from typing import Optional, Tuple\n\nimport disnake\nfrom disnake.ext import commands\n\nfrom helply import Helpy, utils\n\nbot = commands.InteractionBot()\n\n# construct the Helpy instance with the passed in `bot`\nhelpy = Helply(bot)\n\n\n@bot.slash_command(name=\"ping\")\nasync def ping(inter: disnake.ApplicationCommandInteraction):\n\"\"\"Ping the bot to see its latency\"\"\"\n    await inter.response.send_message(\n        f\"Pong! Responded in {(bot.latency * 1000):.2f} ms.\",\n    )\n\n\n@bot.slash_command(name=\"help\")\nasync def help_command(\n    inter: disnake.GuildCommandInteraction,\n    name: Optional[str] = None,\n    category: Optional[str] = None,\n):\n\"\"\"Display help info about this bot's commands.\n\n    Parameters\n    ----------\n    name: Select an available command to view its details\n    category: Select an available category to view its commands.\n    \"\"\"\n\n    if name and category:\n        await inter.response.send_message(\n            \"Please only select a command or a category.\", ephemeral=True\n        )\n        return\n\n    # Since autocomplete for name is a dict[name, str(id)], name in this case\n    # will be the str(id), convert it to int and try to find the command.\n    if name:\n        command = helply.get_command(int(name))\n        if command is None:\n            await inter.response.send_message(\n                \"It appears this command is not available.\", ephemeral=True\n            )\n            return\n\n        # use the included helper embeds module to create the detailed\n        # view of the command.\n        embed = utils.command_detail_embed(command, guild=inter.guild)\n        view = disnake.utils.MISSING\n\n    elif category:\n        guild_id, dm_only, nsfw, permissions = get_helper_query_attrs(inter)\n\n        commands = helply.get_commands_by_category(\n            category, guild_id=guild_id, permissions=permissions, dm_only=dm_only\n        )\n\n        if not commands:\n            await inter.response.send_message(\n                \"No commands available in the selected category.\", ephemeral=True\n            )\n            return\n\n        category_embeds = utils.commands_overview_embeds(\n            commands, max_fields=3, max_field_chars=100, color=disnake.Color.random()\n        )\n\n        if len(category_embeds) > 1:\n            view = utils.Paginator(embeds=category_embeds)\n        else:\n            view = disnake.utils.MISSING\n\n        embed = category_embeds[0]\n\n    else:\n        guild_id, dm_only, nsfw, permissions = get_helper_query_attrs(inter)\n\n        commands = helply.get_all_commands(\n            guild_id, dm_only=dm_only, include_nsfw=nsfw, permissions=permissions\n        )\n        if not commands:\n            await inter.response.send_message(\n                \"Could not find any available commands.\", ephemeral=True\n            )\n            return\n\n        command_embeds = utils.commands_overview_embeds(\n            commands, max_fields=3, max_field_chars=100, color=disnake.Color.random()\n        )\n\n        if len(command_embeds) > 1:\n            view = utils.Paginator(embeds=command_embeds)\n        else:\n            view = disnake.utils.MISSING\n\n        embed = command_embeds[0]\n\n    await inter.response.send_message(embed=embed, view=view)\n\n\n@help_command.autocomplete(\"name\")\nasync def autocomplete_command_names(\n    inter: disnake.ApplicationCommandInteraction,\n    string: str,\n):\n    string = string.casefold()\n\n    guild_id, dm_only, nsfw, permissions = get_helper_query_attrs(inter)\n\n    commands = helply.get_all_commands(\n        guild_id, dm_only=dm_only, include_nsfw=nsfw, permissions=permissions\n    )\n\n    return {c.name: str(c.id) for c in commands}\n\n\n@help_command.autocomplete(\"category\")\nasync def autocomplete_command_categories(\n    inter: disnake.ApplicationCommandInteraction, string: str\n):\n    string = string.casefold()\n\n    guild_id, dm_only, nsfw, permissions = get_helper_query_attrs(inter)\n\n    categories = helply.get_categories(\n        guild_id, dm_only=dm_only, include_nsfw=nsfw, permissions=permissions\n    )\n\n    return [cat for cat in categories if string in cat.casefold()]\n\n\ndef get_helper_query_attrs(\n    inter: disnake.ApplicationCommandInteraction,\n) -> Tuple[Optional[int], bool, bool, Optional[disnake.Permissions]]:\n    # command does not originate from within a guild\n    if not inter.guild or isinstance(inter.author, disnake.User):\n        guild_id = None\n        dm_only = True\n        nsfw = False\n        permissions = None\n\n    else:\n        guild_id = inter.guild_id\n        dm_only = False\n        nsfw = getattr(inter.channel, \"nsfw\", False)\n        permissions = inter.author.guild_permissions\n\n    return guild_id, dm_only, nsfw, permissions\n\n\nif __name__ == \"__main__\":\n    import os\n    bot.run(os.getenv(\"TOKEN\"))\n
"},{"location":"examples/autocomplete/","title":"Autocomplete","text":"

Here are some examples using autocompletion with your created /help command

All examples on this page assume you have the helper class and a help command defined like so:

from helply import Helply\n\n\nhelper = Helply(bot)\n\n...\n...\n\n@bot.slash_command(name='help')\nasync def help_command(inter: disnake.GuildCommandInteraction, name: Optional[str] = None)\n

"},{"location":"examples/autocomplete/#autocomplete-example-using-command-names","title":"Autocomplete example using command names","text":"

This will construct a list of command names available to the user based on their guild_permissions. We then return that list if the name matches what's been inputted into name argument, and we slice the return to return no more than 25 items.

@help_command.autocomplete('name')\nasync def helper_command_name(\n    inter: disnake.GuildCommandInteraction, name: str\n) -> List[str]:\n\n\n    name = name.casefold()\n\n    commands = helply.get_all_commands(\n        inter.guild.id, permissions=inter.author.guild_permissions\n    )\n\n    return [c.name for c in commands if name in c.name.casefold()][:25]\n
"},{"location":"examples/autocomplete/#autocomplete-example-using-command-names-and-ids","title":"Autocomplete example using command names and IDs","text":"

Defining an autocomplete in this fashion will display the command name to the user, however the bot will receive the command's ID as a string. So it will need to be cast to an int before being passed to the `help.get_command(ID) method.

@help_command.autocomplete('name')\nasync def helper_command_name(\n    inter: disnake.GuildCommandInteraction, name: str\n) -> Dict[str, str]:\n\n    name = name.casefold()\n\n    commands = helply.get_all_commands(\n        inter.guild.id, permissions=inter.author.guild_permissions\n    )\n\n    return {c.name: str(c.id) for c in commands if name in c.name.casefold()}\n
"},{"location":"examples/autocomplete/#autocomplete-for-categories","title":"Autocomplete for categories","text":"

You may also want to display all commands available within a specific category or cog. Heres an example of what that might look like.

@help_command.autocomplete('category')\nasync def helper_command_name(\n    inter: disnake.GuildCommandInteraction, category: str)\n -> List[str]:\n    category = category.casefold()\n\n    categories = helper.get_categories(\n        inter.guild.id, permissions=inter.author.guild_permissions\n    )\n\n    return [cat for cat in categories if category in cat.casefold()][:25]\n
"},{"location":"examples/extras/","title":"Extras","text":"

This project also allows you to create some help descriptions for your menu commands @bot.user_command, and @bot.message_command. Since these commands do not inherently have a description that is parsed, we can simply add their descriptions as extras

"},{"location":"examples/extras/#setting-help-description","title":"Setting help description","text":""},{"location":"examples/extras/#user-command","title":"User Command","text":"
@bot.user_command(name=\"User Avatar\", extras={\"help\": \"Display a user's avatar\"})\nasync def user_avatar_menu(\n    inter: disnake.UserCommandInteraction, user: Union[disnake.User, disnake.Member]\n):\n    avatar = user.avatar or user.default_avatar\n    embed = disnake.Embed().set_image(url=avatar.url)\n\n    await inter.response.send_message(embed=embed)\n
"},{"location":"examples/extras/#message-command","title":"Message Command","text":"
@bot.slash_command(\n    name=\"example\",\n    extras={\n        \"help\": (\n            \"This is a much longer description for the command that would normally \"\n            \"exceed the 100 character limit set by Discord\"\n        )\n    },\n)\nasync def example(inter: disnake.ApplicationCommandInteraction):\n\"\"\"A shorter description that does not exceed the 100 character limit\"\"\"\n    ...\n
"},{"location":"examples/extras/#setting-category-with-plugins","title":"Setting category with Plugins","text":"

If using disnake-ext-plugins setting command categories is as easy as:

@plugin.slash_command(name=\"command\", extras={\"category\": \"General\"})\nasync def some_command(inter: disnake.ApplicationCommandInteraction):\n
"},{"location":"examples/simple/","title":"Simple","text":"

A very simple implementation using only a single command. This example should work as is and provides some basic insight into how to use this project.

import os\nfrom typing import Optional\n\nimport disnake\nfrom disnake.ext import commands\n\nfrom helply import Helply, utils\n\nbot = commands.InteractionBot()\n\n# construct the helper class with the bot and sequence of commands to ignore\nhelply = Helply(bot, commands_to_ignore=(\"help\",))\n\n\n@bot.slash_command_name(name=\"kick\")\n@commands.has_permissions(kick_members=True)\n@commands.default_member_permissions(kick_members=True)\nasync def kick_member(\n    inter: disnake.GuildCommandInteraction,\n    member: disnake.Member,\n    reason: Optional[str] = None,\n) -> None:\n\"\"\"Kick a member from the server\n\n    Parameters\n    ----------\n    member: Select a member to kick\n    \"\"\"\n    try:\n        await member.kick(reason=reason)\n\n    except disnake.Forbidden as e:\n        await inter.response.send_message(f\"Unable to kick {member.mention} - {e}\", ephemeral=True)\n        return\n\n    await inter.response.send_message(\n        f\"{member} was kicked by {inter.author}. Reason: {reason}\", ephemeral=True\n    )\n\n\n@bot.slash_command(name=\"help\")\nasync def help_command(inter: disnake.GuildCommandInteraction, name: Optional[str] = None) -> None:\n\"\"\"Display command information\n\n    Parameters\n    ----------\n    name: Choose a command to view its details.\n    \"\"\"\n\n    if name is None:\n        # get all commands available to the command author\n        # by passing in the inter.guild_id, we ensure only global commands and any commands\n        # available only for this guild are retrieved.\n        commands = helply.get_all_commands(\n            inter.guild_id, permissions=inter.author.guild_permissions\n        )\n\n        # since this takes into consideration the default_member_permissions required to use commands\n        # and we passed in the command author's permissions, retrieved commands may be an empty list\n        # if they cannot use any commands the bot provides.\n        if not commands:\n            await inter.response.send_message(\"There are no commands available.\", ephemeral=True)\n            return\n\n        # now we use the include embed builder utility to create the embeds.\n        # in this instance, since there is only one command, embeds will be a single embed\n        embeds = utils.commands_overview_embeds(commands)\n\n        embed = embeds[0]\n\n    else:\n        # Since autocomplete does not force a user to make a selection, we will try to get\n        # the command by the provided name, however, it could result in `None`, so we handle it.\n        command = helply.get_command_named(name)\n        if not command:\n            await inter.response.send_message(\"Unable to find that command.\", ephemeral=True)\n            return\n\n        # Now we again use the embed builder utility for the specific command to view its\n        # full details, description, parameters, if any, and required permissions\n        embed = utils.command_detail_embed(command)\n\n    await inter.response.send_message(embed=embed)\n\n\nif __name__ == \"__main__\":\n    bot.run(os.getenv(\"TOKEN\"))\n
"},{"location":"reference/SUMMARY/","title":"SUMMARY","text":""},{"location":"reference/helply/help/","title":"help","text":""},{"location":"reference/helply/help/#helply.help.Helply","title":"Helply","text":"

Represents an application command helper.

Parameters:

Source code in src\\helply\\help.py
class Helply:\n\"\"\"Represents an application command helper.\n\n    Parameters\n    ----------\n    bot : Union[commands.Bot, commands.InteractionBot]\n        The bot for which this help class will be associated with.\n    commands_to_ignore: Iterable[str]\n        Provide a list of command names to ignore when walking all app commands.\n    \"\"\"\n\n    def __init__(self, bot: Bot, commands_to_ignore: Optional[Sequence[str]] = None) -> None:\n        self.bot = bot\n\n        if commands_to_ignore is not None:\n            self.commands_to_ignore = set(commands_to_ignore)\n        else:\n            self.commands_to_ignore = None\n\n        self._app_commands: Dict[int, AppCommand] = {}\n\n    def _get_command_args(\n        self, command: Union[disnake.APISlashCommand, disnake.Option]\n    ) -> List[Argument]:\n\"\"\"Parse and return the `SlashCommand` or `SubCommand` arguments.\n\n        Parameters\n        ----------\n        command : Union[disnake.APISlashCommand, disnake.Option]\n            The slash command or a slash command's sub_command.\n\n        Returns\n        -------\n        List[Argument]\n            A sequence of the command or sub_command's arguments.\n        \"\"\"\n        args: List[Argument] = []\n        for option in command.options:\n            if option.type in (\n                disnake.OptionType.sub_command,\n                disnake.OptionType.sub_command_group,\n            ):\n                continue\n\n            args.append(\n                Argument(name=option.name, required=option.required, description=option.description)\n            )\n\n        return args\n\n    def _get_command_desc(self, name: str) -> str:\n\"\"\"Get the description for a command.\n\n        Parameters\n        ----------\n        name : str\n            The name of the command.\n\n        Returns\n        -------\n        str\n            The description of the command.\n        \"\"\"\n        desc = \"-\"\n        command = self.bot.get_slash_command(name)\n\n        if command and isinstance(command, (commands.InvokableSlashCommand, commands.SubCommand)):\n            desc = command.extras.get(\"help\", \"\") or command.description\n\n        return desc\n\n    def _get_sub_commands(\n        self,\n        command: Union[disnake.APISlashCommand, disnake.Option],\n        checks: CommandChecks,\n        category: str,\n        parent_command: Optional[disnake.APISlashCommand] = None,\n    ) -> List[SlashCommand]:\n\"\"\"Get and return the `APISlashCommand`'s registered `SubCommands` if any.\n\n        Parameters\n        ----------\n        command : Union[disnake.APISlashCommand, disnake.Option]\n            The registered slash command or the command's SubCommand.\n        checks : CommandChecks\n            The permission and role checks assigned to the parent command.\n        parent_name : Optional[str]\n            Parent command's name. Only used if sub_group is used and this function is called\n            recursively.\n\n        Returns\n        -------\n        List[SlashCommand]\n            A list of sub-commands, if any.\n        \"\"\"\n        sub_commands: List[SlashCommand] = []\n\n        for option in command.options:\n            name = (\n                f\"{parent_command.name} {command.name} {option.name}\"\n                if parent_command\n                else f\"{command.name} {option.name}\"\n            )\n            if option.type == disnake.OptionType.sub_command:\n                args = self._get_command_args(option)\n\n                if parent_command:\n                    command_id = parent_command.id\n                    dm_permissions = parent_command.dm_permission\n                    nsfw = parent_command.nsfw\n\n                elif isinstance(command, disnake.APISlashCommand):\n                    command_id = command.id\n                    dm_permissions = command.dm_permission\n                    nsfw = command.nsfw\n\n                else:\n                    # should realistically never be reached\n                    raise TypeError(\n                        \"Command must be an instance of `disnake.APISlashCommand` \"\n                        \"if parent_command is `None`\"\n                    ) from None\n\n                desc = self._get_command_desc(name)\n                sub_commands.append(\n                    SlashCommand(\n                        id=command_id,\n                        name=name,\n                        description=desc,\n                        args=args,\n                        checks=checks,\n                        type=AppCommandType.slash,\n                        dm_permission=dm_permissions,\n                        nsfw=nsfw,\n                        category=category,\n                    )\n                )\n            elif option.type == disnake.OptionType.sub_command_group:\n                sub_commands.extend(\n                    self._get_sub_commands(option, checks, category, parent_command)\n                )\n\n        return sub_commands\n\n    def _parse_checks(\n        self,\n        command: commands.InvokableApplicationCommand,\n    ) -> CommandChecks:\n\"\"\"Parse the checks associated with a command and extract registered permissions and roles.\n\n        Parameters\n        ----------\n        command : commands.InvokableApplicationCommand\n            The command object to parse checks from.\n\n        Returns\n        -------\n        CommandChecks\n            A NamedTuple containing a list of permissions and/or role names or IDs\n            required to invoke the command.\n        \"\"\"\n\n        permissions: List[str] = []\n        roles: List[Union[str, int]] = []\n\n        # command.checks provides a list of check predicates\n        # associated with the command\n        checks = command.checks\n\n        # iterate those checks and analyze them to access\n        # check names (ie. \"has_any_role\")\n        for check in checks:\n            name = check.__qualname__.split(\".\")[0]\n            if \"bot\" in name or not check.__closure__:\n                continue\n\n            # for each check that does not include \"bot\" (ie. \"bot_has_permissions\")\n            # the arguments will be parsed and used to populate `CommandChecks`\n            closure = check.__closure__[0]\n\n            args = (\n                closure.cell_contents\n                if len(closure.cell_contents) > 1\n                else (closure.cell_contents,)\n            )\n\n            # checks pertaining to roles will populate CommandChecks.roles\n            if \"role\" in name:\n                roles.extend(args)\n\n            # remaining checks should be permissions based and are formatted\n            # then added to CommandChecks.permissions\n            else:\n                permissions.extend(\n                    [p.replace(\"_\", \" \").title() for p, v in closure.cell_contents.items() if v]\n                )\n\n        return CommandChecks(permissions, roles)\n\n    def _handle_slash_command(self, command: disnake.APISlashCommand) -> List[SlashCommand]:\n\"\"\"Handle creation of `SlashCommand` from `disnake.APISlashCommand`.\n\n        Parameters\n        ----------\n        command : disnake.APISlashCommand\n            The APISlashCommand provided by Discord's API.\n\n        Return\n        ------\n        List[SlashCommand]\n            The constructed `SlashCommand`.\n        \"\"\"\n        invokable = self.bot.get_slash_command(command.name)\n        if invokable is None:\n            return []\n\n        checks = self._parse_checks(invokable)\n        desc = self._get_command_desc(invokable.qualified_name)\n        category = self._get_command_category(invokable)\n        args = self._get_command_args(command)\n        sub_commands = self._get_sub_commands(command, checks, category)\n\n        if sub_commands:\n            return sub_commands\n\n        return [\n            SlashCommand(\n                id=command.id,\n                name=command.name,\n                description=desc,\n                args=args,\n                checks=checks,\n                type=AppCommandType.slash,\n                dm_permission=command.dm_permission,\n                nsfw=command.nsfw,\n                guild_id=command.guild_id,\n                default_member_permissions=invokable.default_member_permissions,\n                category=category,\n            )\n        ]\n\n    def _handle_message_command(\n        self, command: disnake.APIMessageCommand\n    ) -> Optional[MessageCommand]:\n\"\"\"Handle creation of `MessageCommand` from `disnake.APIMessageCommand`.\n\n        Parameters\n        ----------\n        command : disnake.APIUserCommand\n            The APIMessageCommand provided by Discord's API.\n\n        Return\n        ------\n        Optional[MessageCommand]\n            The constructed `MessageCommand`.\n        \"\"\"\n        invokable = self.bot.get_message_command(command.name)\n        if invokable is None:\n            return\n\n        checks = self._parse_checks(invokable)\n        desc = invokable.extras.get(\"help\", \"-\")\n        category = self._get_command_category(invokable)\n\n        return MessageCommand(\n            id=command.id,\n            name=command.name,\n            checks=checks,\n            type=AppCommandType.message,\n            description=desc,\n            dm_permission=command.dm_permission,\n            nsfw=command.nsfw,\n            guild_id=command.guild_id,\n            default_member_permissions=command.default_member_permissions,\n            category=category,\n        )\n\n    def _handle_user_command(self, command: disnake.APIUserCommand) -> Optional[UserCommand]:\n\"\"\"Handle creation of `UserCommand` from `disnake.APIUserCommand`.\n\n        Parameters\n        ----------\n        command : disnake.APIUserCommand\n            The APIUserCommand provided by Discord's API.\n\n        Return\n        ------\n        Optional[UserCommand]\n            The constructed `UserCommand`.\n        \"\"\"\n        invokable = self.bot.get_user_command(command.name)\n\n        if invokable is None:\n            return\n\n        checks = self._parse_checks(invokable)\n        desc = invokable.extras.get(\"help\", \"-\")\n        category = self._get_command_category(invokable)\n\n        return UserCommand(\n            id=command.id,\n            name=command.name,\n            type=AppCommandType.user,\n            checks=checks,\n            description=desc,\n            dm_permission=command.dm_permission,\n            nsfw=command.nsfw,\n            guild_id=command.guild_id,\n            default_member_permissions=command.default_member_permissions,\n            category=category,\n        )\n\n    def _get_command_category(self, invokable: commands.InvokableApplicationCommand) -> str:\n\"\"\"Get the command's cog or category name, if available\n\n        `cog_name` would be derived from `disnake.ext.commands.Cog`, whereas\n        `category` would come from using [disnake-ext-plugins](https://github.com/DisnakeCommunity/disnake-ext-plugins)\n\n        Parameters\n        ----------\n        invokable: commands.InvokableApplicationCommand\n\n        Returns\n        -------\n        str\n            `Cog's` name or str value set in `.extras['category']` or 'None'\n\n        \"\"\"\n        name = invokable.cog_name or invokable.extras.get(\"category\")\n        if not name:\n            name = \"None\"\n\n        return name\n\n    def _walk_app_commands(self) -> None:\n\"\"\"Retrieve all global and guild-specific application commands.\"\"\"\n        all_commands = self.bot.global_application_commands\n        for guild in self.bot.guilds:\n            all_commands.extend(self.bot.get_guild_application_commands(guild.id))\n\n        for command in all_commands:\n            if self.commands_to_ignore and command.name in self.commands_to_ignore:\n                continue\n\n            if isinstance(command, disnake.APISlashCommand):\n                self._app_commands.update({c.id: c for c in self._handle_slash_command(command)})\n\n            elif isinstance(command, disnake.MessageCommand):\n                msg_command = self._handle_message_command(command)\n\n                if msg_command:\n                    self._app_commands[msg_command.id] = msg_command\n\n            else:\n                user_command = self._handle_user_command(command)\n\n                if user_command:\n                    self._app_commands[user_command.id] = user_command\n\n    def get_all_commands(\n        self,\n        guild_id: Optional[int] = None,\n        *,\n        permissions: Optional[disnake.Permissions] = None,\n        include_nsfw: bool = True,\n        dm_only: bool = False,\n    ) -> List[AppCommand]:\n\"\"\"Retrieve a filtered list of AppCommand based on specified criteria.\n\n        By default, this method should return all registered commands. Specify filters\n        to narrow down the output results.\n\n        Parameters\n        ----------\n        guild_id : Optional[int]\n            Filter commands registered to the specified guild_id.  If not specified,\n            all commands may be returned.\n        permissions: Optional[disnake.Permissions]\n            Filter commands that do not exceed permissions. If not specified,\n            commands will not be filtered by permissions.\n            !!! Note\n                Should not be used with `dm_only`\n        include_nsfw : bool\n            Whether or not to include categories NSFW commands.\n        dm_only: bool\n            Whether or not to include only commands with direct message enabled.\n            !!! Note\n                Should not specify `guild_id` or `permissions` if setting this to True\n\n        Returns\n        -------\n        List[AppCommand]\n            Resulting list of AppCommands after filters have been applied.\n        \"\"\"\n\n        if not self._app_commands:\n            self._walk_app_commands()\n\n        commands: List[AppCommand] = []\n\n        for command in self._app_commands.values():\n            if guild_id and command.guild_id and command.guild_id != guild_id:\n                continue\n\n            if dm_only and not command.dm_permission:\n                continue\n\n            if not permissions and command.default_member_permissions:\n                continue\n\n            if (\n                permissions\n                and command.default_member_permissions\n                and not permissions >= command.default_member_permissions\n            ):\n                continue\n\n            if not include_nsfw and command.nsfw:\n                continue\n\n            commands.append(command)\n\n        return commands\n\n    def get_command_named(\n        self, name: str, cmd_type: Optional[AppCommandType] = None\n    ) -> Optional[AppCommand]:\n\"\"\"Get a command by its name.\n\n        Parameters\n        ----------\n        name : str\n            Name of the ApplicationCommand.\n        cmd_type: Optional[AppCommandType]\n            Specify the type of command to be returned. If not specified, the first matching\n            command will be returned regardless of its type.\n\n\n        Returns\n        -------\n        Optional[AppCommand]\n            The command that matches the provided name, if found.\n        \"\"\"\n        for command in self._app_commands.values():\n            if command.name == name and (cmd_type is None or command.type is cmd_type):\n                return command\n\n    def get_command(self, id: int) -> Optional[AppCommand]:\n\"\"\"Get a command by its ID\n\n        Parameters\n        ----------\n        id: int\n            ID of the AppCommand\n\n        Returns\n        --------\n        Optional[AppCommand]\n            The retrieved AppCommand or None of not found.\n        \"\"\"\n        return self._app_commands.get(id)\n\n    def get_commands_by_category(\n        self,\n        category: str,\n        *,\n        guild_id: Optional[int] = None,\n        permissions: Optional[disnake.Permissions] = None,\n        include_nsfw: bool = True,\n        dm_only: bool = False,\n    ) -> List[AppCommand]:\n\"\"\"Retrieve a filtered list of AppCommand based on specified criteria within a category.\n\n        By default, this method should return all registered commands within a category.\n        Specify filters to narrow down the output results.\n\n        Parameters\n        ----------\n        category: str\n            Category for which commands are in.\n        guild_id : Optional[int]\n            Filter commands registered to the specified guild_id.  If not specified,\n            all commands may be returned.\n        permissions: Optional[disnake.Permissions]\n            Filter commands that do not exceed permissions. If not specified,\n            commands will not be filtered by permissions.\n            !!! Note\n                Should not be used with `dm_only`\n        include_nsfw : bool\n            Whether or not to include categories NSFW commands.\n        dm_only: bool\n            Whether or not to include only commands with direct message enabled.\n            !!! Note\n                Should not specify `guild_id` or `permissions` if setting this to True\n\n        Returns\n        --------\n        List[AppCommand]\n            A list of commands within the specified group name.\n\n        \"\"\"\n        commands = self.get_all_commands(\n            guild_id,\n            permissions=permissions,\n            include_nsfw=include_nsfw,\n            dm_only=dm_only,\n        )\n        return [command for command in commands if command.category == category]\n\n    def get_categories(\n        self,\n        guild_id: Optional[int] = None,\n        *,\n        permissions: Optional[disnake.Permissions] = None,\n        include_nsfw: bool = True,\n        dm_only: bool = False,\n    ) -> List[str]:\n\"\"\"Return a unique list of command group names.\n\n        Useful if you wish to have an autocomplete for users to select from available\n        command groups\n\n        Parameters\n        ----------\n        guild_id : Optional[int]\n            Filter categories with commands registered to the specified guild_id. If not\n            specified, all categories may be returned.\n        permissions: Optional[disnake.Permissions]\n            Filter commands that do not exceed permissions. If not specified,\n            commands will not be filtered by permissions.\n            !!! Note\n                Should not be used with `dm_only`\n        include_nsfw : bool\n            Whether or not to include categories NSFW commands.\n        dm_only: bool\n            Whether or not to include only commands with direct message enabled.\n            !!! Note\n                Should not specify `guild_id` or `permissions` if setting this to True\n\n        Example:\n        ```py\n        @some_command.autocomplete('category')\n        async def some_command_group_autocomplete(\n            inter: disnake.ApplicationCommandInteraction, string: str\n        ) -> List[str]:\n            string = string.casefold()\n            commands = helper.get_command_categories(inter.guild.id)\n            return [g for g in commands if string in g.casefold()]\n        ```\n\n        Returns\n        -------\n        List[str]\n            A list of unique command categories.\n        \"\"\"\n        categories: List[str] = []\n\n        for command in self.get_all_commands(\n            guild_id,\n            permissions=permissions,\n            include_nsfw=include_nsfw,\n            dm_only=dm_only,\n        ):\n            if command.category not in categories:\n                categories.append(command.category)\n\n        return categories\n\n    def get_dm_only_commands(self, *, include_nsfw: bool = False) -> List[AppCommand]:\n\"\"\"A shortcut method for returning only commands with direct message enabled.\n\n        Parameters\n        ----------\n        include_nsfw: bool\n            Whether or not to include NSFW commands.\n\n        Returns\n        -------\n        List[AppCommand]\n            A list of commands with `.dm_permissions` set to True\n        \"\"\"\n        return self.get_all_commands(dm_only=True, include_nsfw=include_nsfw)\n\n    def get_guild_only_commands(\n        self,\n        guild_id: int,\n        *,\n        include_nsfw: bool = False,\n        permissions: Optional[disnake.Permissions] = None,\n    ):\n\"\"\"This method returns global and guild-specific commands available within a guild context.\n\n        !!! Note\n            Including `permissions` will restrict the command list further to commands that\n            do not require more, or higher, permissions than the permissions specified.\n\n        Parameters\n        guild_id: int\n            ID for the guild for which guild-specific command are registered.\n        include_nsfw: bool\n            Whether or not to include NSFW commands.\n        permissions: Optional[disnake.Permissions]\n            Set the permission limit of the resulting commands.  Any commands that exceed specified\n            permissions will be omitted\n        \"\"\"\n        return self.get_all_commands(guild_id, include_nsfw=include_nsfw, permissions=permissions)\n\n    @staticmethod\n    def roles_from_checks(checks: CommandChecks, guild: disnake.Guild) -> List[disnake.Role]:\n\"\"\"Parse the command's role checks and return a list of `disnake.Role`.\n\n        Parameters\n        ----------\n        checks : CommandChecks\n            A command's checks\n\n        Returns\n        -------\n        List[disnake.Role]\n            `Roles` that have been successfully converted from name or ID.\n        \"\"\"\n        role_checks = checks.roles\n        roles: List[disnake.Role] = []\n\n        for name_or_id in role_checks:\n            if isinstance(name_or_id, int) or name_or_id.isdigit():\n                role = guild.get_role(int(name_or_id))\n            else:\n                role = disnake.utils.get(guild.roles, name=name_or_id)\n\n            if role:\n                roles.append(role)\n\n        return roles\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_all_commands","title":"get_all_commands(guild_id=None, *, permissions=None, include_nsfw=True, dm_only=False)","text":"

Retrieve a filtered list of AppCommand based on specified criteria.

By default, this method should return all registered commands. Specify filters to narrow down the output results.

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_all_commands(\n    self,\n    guild_id: Optional[int] = None,\n    *,\n    permissions: Optional[disnake.Permissions] = None,\n    include_nsfw: bool = True,\n    dm_only: bool = False,\n) -> List[AppCommand]:\n\"\"\"Retrieve a filtered list of AppCommand based on specified criteria.\n\n    By default, this method should return all registered commands. Specify filters\n    to narrow down the output results.\n\n    Parameters\n    ----------\n    guild_id : Optional[int]\n        Filter commands registered to the specified guild_id.  If not specified,\n        all commands may be returned.\n    permissions: Optional[disnake.Permissions]\n        Filter commands that do not exceed permissions. If not specified,\n        commands will not be filtered by permissions.\n        !!! Note\n            Should not be used with `dm_only`\n    include_nsfw : bool\n        Whether or not to include categories NSFW commands.\n    dm_only: bool\n        Whether or not to include only commands with direct message enabled.\n        !!! Note\n            Should not specify `guild_id` or `permissions` if setting this to True\n\n    Returns\n    -------\n    List[AppCommand]\n        Resulting list of AppCommands after filters have been applied.\n    \"\"\"\n\n    if not self._app_commands:\n        self._walk_app_commands()\n\n    commands: List[AppCommand] = []\n\n    for command in self._app_commands.values():\n        if guild_id and command.guild_id and command.guild_id != guild_id:\n            continue\n\n        if dm_only and not command.dm_permission:\n            continue\n\n        if not permissions and command.default_member_permissions:\n            continue\n\n        if (\n            permissions\n            and command.default_member_permissions\n            and not permissions >= command.default_member_permissions\n        ):\n            continue\n\n        if not include_nsfw and command.nsfw:\n            continue\n\n        commands.append(command)\n\n    return commands\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_categories","title":"get_categories(guild_id=None, *, permissions=None, include_nsfw=True, dm_only=False)","text":"

Return a unique list of command group names.

Useful if you wish to have an autocomplete for users to select from available command groups

Parameters:

Example:

@some_command.autocomplete('category')\nasync def some_command_group_autocomplete(\n    inter: disnake.ApplicationCommandInteraction, string: str\n) -> List[str]:\n    string = string.casefold()\n    commands = helper.get_command_categories(inter.guild.id)\n    return [g for g in commands if string in g.casefold()]\n

Returns:

Source code in src\\helply\\help.py
def get_categories(\n    self,\n    guild_id: Optional[int] = None,\n    *,\n    permissions: Optional[disnake.Permissions] = None,\n    include_nsfw: bool = True,\n    dm_only: bool = False,\n) -> List[str]:\n\"\"\"Return a unique list of command group names.\n\n    Useful if you wish to have an autocomplete for users to select from available\n    command groups\n\n    Parameters\n    ----------\n    guild_id : Optional[int]\n        Filter categories with commands registered to the specified guild_id. If not\n        specified, all categories may be returned.\n    permissions: Optional[disnake.Permissions]\n        Filter commands that do not exceed permissions. If not specified,\n        commands will not be filtered by permissions.\n        !!! Note\n            Should not be used with `dm_only`\n    include_nsfw : bool\n        Whether or not to include categories NSFW commands.\n    dm_only: bool\n        Whether or not to include only commands with direct message enabled.\n        !!! Note\n            Should not specify `guild_id` or `permissions` if setting this to True\n\n    Example:\n    ```py\n    @some_command.autocomplete('category')\n    async def some_command_group_autocomplete(\n        inter: disnake.ApplicationCommandInteraction, string: str\n    ) -> List[str]:\n        string = string.casefold()\n        commands = helper.get_command_categories(inter.guild.id)\n        return [g for g in commands if string in g.casefold()]\n    ```\n\n    Returns\n    -------\n    List[str]\n        A list of unique command categories.\n    \"\"\"\n    categories: List[str] = []\n\n    for command in self.get_all_commands(\n        guild_id,\n        permissions=permissions,\n        include_nsfw=include_nsfw,\n        dm_only=dm_only,\n    ):\n        if command.category not in categories:\n            categories.append(command.category)\n\n    return categories\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_command","title":"get_command(id)","text":"

Get a command by its ID

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_command(self, id: int) -> Optional[AppCommand]:\n\"\"\"Get a command by its ID\n\n    Parameters\n    ----------\n    id: int\n        ID of the AppCommand\n\n    Returns\n    --------\n    Optional[AppCommand]\n        The retrieved AppCommand or None of not found.\n    \"\"\"\n    return self._app_commands.get(id)\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_command_named","title":"get_command_named(name, cmd_type=None)","text":"

Get a command by its name.

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_command_named(\n    self, name: str, cmd_type: Optional[AppCommandType] = None\n) -> Optional[AppCommand]:\n\"\"\"Get a command by its name.\n\n    Parameters\n    ----------\n    name : str\n        Name of the ApplicationCommand.\n    cmd_type: Optional[AppCommandType]\n        Specify the type of command to be returned. If not specified, the first matching\n        command will be returned regardless of its type.\n\n\n    Returns\n    -------\n    Optional[AppCommand]\n        The command that matches the provided name, if found.\n    \"\"\"\n    for command in self._app_commands.values():\n        if command.name == name and (cmd_type is None or command.type is cmd_type):\n            return command\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_commands_by_category","title":"get_commands_by_category(category, *, guild_id=None, permissions=None, include_nsfw=True, dm_only=False)","text":"

Retrieve a filtered list of AppCommand based on specified criteria within a category.

By default, this method should return all registered commands within a category. Specify filters to narrow down the output results.

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_commands_by_category(\n    self,\n    category: str,\n    *,\n    guild_id: Optional[int] = None,\n    permissions: Optional[disnake.Permissions] = None,\n    include_nsfw: bool = True,\n    dm_only: bool = False,\n) -> List[AppCommand]:\n\"\"\"Retrieve a filtered list of AppCommand based on specified criteria within a category.\n\n    By default, this method should return all registered commands within a category.\n    Specify filters to narrow down the output results.\n\n    Parameters\n    ----------\n    category: str\n        Category for which commands are in.\n    guild_id : Optional[int]\n        Filter commands registered to the specified guild_id.  If not specified,\n        all commands may be returned.\n    permissions: Optional[disnake.Permissions]\n        Filter commands that do not exceed permissions. If not specified,\n        commands will not be filtered by permissions.\n        !!! Note\n            Should not be used with `dm_only`\n    include_nsfw : bool\n        Whether or not to include categories NSFW commands.\n    dm_only: bool\n        Whether or not to include only commands with direct message enabled.\n        !!! Note\n            Should not specify `guild_id` or `permissions` if setting this to True\n\n    Returns\n    --------\n    List[AppCommand]\n        A list of commands within the specified group name.\n\n    \"\"\"\n    commands = self.get_all_commands(\n        guild_id,\n        permissions=permissions,\n        include_nsfw=include_nsfw,\n        dm_only=dm_only,\n    )\n    return [command for command in commands if command.category == category]\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_dm_only_commands","title":"get_dm_only_commands(*, include_nsfw=False)","text":"

A shortcut method for returning only commands with direct message enabled.

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_dm_only_commands(self, *, include_nsfw: bool = False) -> List[AppCommand]:\n\"\"\"A shortcut method for returning only commands with direct message enabled.\n\n    Parameters\n    ----------\n    include_nsfw: bool\n        Whether or not to include NSFW commands.\n\n    Returns\n    -------\n    List[AppCommand]\n        A list of commands with `.dm_permissions` set to True\n    \"\"\"\n    return self.get_all_commands(dm_only=True, include_nsfw=include_nsfw)\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_guild_only_commands","title":"get_guild_only_commands(guild_id, *, include_nsfw=False, permissions=None)","text":"

This method returns global and guild-specific commands available within a guild context.

Note

Including permissions will restrict the command list further to commands that do not require more, or higher, permissions than the permissions specified.

Parameters guild_id: int ID for the guild for which guild-specific command are registered. include_nsfw: bool Whether or not to include NSFW commands. permissions: Optional[disnake.Permissions] Set the permission limit of the resulting commands. Any commands that exceed specified permissions will be omitted

Source code in src\\helply\\help.py
def get_guild_only_commands(\n    self,\n    guild_id: int,\n    *,\n    include_nsfw: bool = False,\n    permissions: Optional[disnake.Permissions] = None,\n):\n\"\"\"This method returns global and guild-specific commands available within a guild context.\n\n    !!! Note\n        Including `permissions` will restrict the command list further to commands that\n        do not require more, or higher, permissions than the permissions specified.\n\n    Parameters\n    guild_id: int\n        ID for the guild for which guild-specific command are registered.\n    include_nsfw: bool\n        Whether or not to include NSFW commands.\n    permissions: Optional[disnake.Permissions]\n        Set the permission limit of the resulting commands.  Any commands that exceed specified\n        permissions will be omitted\n    \"\"\"\n    return self.get_all_commands(guild_id, include_nsfw=include_nsfw, permissions=permissions)\n
"},{"location":"reference/helply/help/#helply.help.Helply.roles_from_checks","title":"roles_from_checks(checks, guild) staticmethod","text":"

Parse the command's role checks and return a list of disnake.Role.

Parameters:

Returns:

Source code in src\\helply\\help.py
@staticmethod\ndef roles_from_checks(checks: CommandChecks, guild: disnake.Guild) -> List[disnake.Role]:\n\"\"\"Parse the command's role checks and return a list of `disnake.Role`.\n\n    Parameters\n    ----------\n    checks : CommandChecks\n        A command's checks\n\n    Returns\n    -------\n    List[disnake.Role]\n        `Roles` that have been successfully converted from name or ID.\n    \"\"\"\n    role_checks = checks.roles\n    roles: List[disnake.Role] = []\n\n    for name_or_id in role_checks:\n        if isinstance(name_or_id, int) or name_or_id.isdigit():\n            role = guild.get_role(int(name_or_id))\n        else:\n            role = disnake.utils.get(guild.roles, name=name_or_id)\n\n        if role:\n            roles.append(role)\n\n    return roles\n
"},{"location":"reference/helply/types/checks/","title":"checks","text":""},{"location":"reference/helply/types/checks/#helply.types.checks.CommandChecks","title":"CommandChecks","text":"

Bases: NamedTuple

Wrap the command's permission or role requirements.

Attributes:

Source code in src\\helply\\types\\checks.py
class CommandChecks(typing.NamedTuple):\n\"\"\"Wrap the command's permission or role requirements.\n\n    Attributes\n    ----------\n    permissions : List[str]\n        A list of permission names required to use this command.\n    roles : List[Union[str, int]]\n        A list of role names or role IDs required to use this command.\n    \"\"\"\n\n    permissions: typing.List[str]\n    roles: typing.List[typing.Union[str, int]]\n
"},{"location":"reference/helply/types/commands/","title":"commands","text":""},{"location":"reference/helply/types/commands/#helply.types.commands.AppCommand","title":"AppCommand dataclass","text":"

Represents an AppCommand.

AppCommands are dataclasses that include various attributes from both .ApplicationCommand and .InvokableApplicationCommand

Attributes:

"},{"location":"reference/helply/types/commands/#helply.types.commands.AppCommand--properties","title":"Properties","text":"

mention : str Return the command as a mentionable if slash command, else returns bolded name.

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass AppCommand:\n\"\"\"Represents an AppCommand.\n\n    AppCommands are dataclasses that include various attributes from both\n    `.ApplicationCommand` and `.InvokableApplicationCommand`\n\n    Attributes\n    ----------\n    id : int\n        The command's unique identifier.\n    name : str\n        The name of the command.\n    checks : CommandChecks\n        The command's permission and role requirements.\n    type: AppCommandType\n        Type of command\n    category: str\n        Name of cog command belongs to. Also parses `.extras['category']` for implementations using\n        [disnake-ext-plugins](https://github.com/DisnakeCommunity/disnake-ext-plugins)\n    description : str\n        A brief description of the command.\n    dm_permission : bool\n        Whether the command is available in DMs or not.\n    nsfw : bool\n        Whether the command is NSFW (Not Safe For Work).\n    guild_id : int, optional\n        The ID of the guild where the command is available.\n    default_member_permissions : Permissions, optional\n        Default member permissions required to use this command.\n\n    Properties\n    ----------\n    mention : str\n        Return the command as a mentionable if slash command, else returns bolded name.\n    \"\"\"\n\n    id: int\n    name: str\n    checks: CommandChecks\n    type: \"AppCommandType\"\n    category: str = \"None\"\n    dm_permission: bool = True\n    nsfw: bool = False\n    description: str = \"-\"\n    guild_id: Optional[int] = None\n    default_member_permissions: Optional[Permissions] = None\n\n    @property\n    def mention(self) -> str:\n        if isinstance(self, SlashCommand):\n            return f\"</{self.name}:{self.id}>\"\n        return f\"**{self.name}**\"\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.Argument","title":"Argument dataclass","text":"

Represents a SlashCommand argument.

Attributes:

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass Argument:\n\"\"\"Represents a SlashCommand argument.\n\n    Attributes\n    ----------\n    name : str\n        Name of the argument.\n    required : bool\n        Indicate if the argument is required.\n    description : str\n        A brief description of the argument.\n    \"\"\"\n\n    name: str\n    required: bool\n    description: str\n\n    def __str__(self) -> str:\n\"\"\"Return the argument as a string.\n\n        Required arguments will have `[]` wrapped around their name,\n        while optional arguments will be wrapped with `()`.\n        \"\"\"\n        if self.required:\n            return f\"[{self.name}]\"\n        return f\"({self.name})\"\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.Argument.__str__","title":"__str__()","text":"

Return the argument as a string.

Required arguments will have [] wrapped around their name, while optional arguments will be wrapped with ().

Source code in src\\helply\\types\\commands.py
def __str__(self) -> str:\n\"\"\"Return the argument as a string.\n\n    Required arguments will have `[]` wrapped around their name,\n    while optional arguments will be wrapped with `()`.\n    \"\"\"\n    if self.required:\n        return f\"[{self.name}]\"\n    return f\"({self.name})\"\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.MessageCommand","title":"MessageCommand dataclass","text":"

Bases: AppCommand

Represents a MessageCommand type of AppCommand.

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass MessageCommand(AppCommand):\n\"\"\"Represents a MessageCommand type of AppCommand.\"\"\"\n\n    ...\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.SlashCommand","title":"SlashCommand dataclass","text":"

Bases: AppCommand

Represents a SlashCommand type AppCommand.

Attributes:

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass SlashCommand(AppCommand):\n\"\"\"Represents a SlashCommand type AppCommand.\n\n    Attributes\n    ----------\n    args : List[Argument]\n        A list of the command's Arguments, if any.\n    \"\"\"\n\n    args: List[Argument] = dataclasses.field(default_factory=list)\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.UserCommand","title":"UserCommand dataclass","text":"

Bases: AppCommand

Represents a UserCommand type of AppCommand.

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass UserCommand(AppCommand):\n\"\"\"Represents a UserCommand type of AppCommand.\"\"\"\n\n    ...\n
"},{"location":"reference/helply/types/enums/","title":"enums","text":""},{"location":"reference/helply/types/enums/#helply.types.enums.AppCommandType","title":"AppCommandType","text":"

Bases: Enum

Enum for AppCommandType

Attributes:

Source code in src\\helply\\types\\enums.py
class AppCommandType(enum.Enum):\n\"\"\"Enum for AppCommandType\n\n    Attributes\n    ----------\n    slash: SlashCommand\n    message: MessageCommand\n    user UserCommand\n    \"\"\"\n\n    slash = SlashCommand\n    message = MessageCommand\n    user = UserCommand\n
"},{"location":"reference/helply/utils/embeds/","title":"embeds","text":"

Embeds module adds some pre-configured embeds to streamline the creation of your help command

"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.MAX_CHARS_PER_FIELD","title":"MAX_CHARS_PER_FIELD = 1024 module-attribute","text":"

Set the max and default character limit per embed field.

This is a Discord limitation, so we use this for chunking command description lines for the overview embed(s) which allow us to split into multiple fields within a single embed.

"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.MAX_CHARS_PER_FIELD--notes","title":"Notes","text":"

I do not recommend exceeding 400 characters as this can create very tall embeds.

"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.MAX_FIELDS_PER_EMBED","title":"MAX_FIELDS_PER_EMBED = 25 module-attribute","text":"

Set the max and default field per embed.

Discord limits this to 25, so that's what has been set as the max here as well.

"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.command_detail_embed","title":"command_detail_embed(command, *, thumbnail=None, guild=None, color=None)","text":"

Create and return an embed showing command details.

Parameters:

Examples:

from disnake.ext.app_command_help import AppCommandHelp, utils\n\n...\napp_command_help = AppCommandHelp(bot)\n\n...\ncommand = app_command_help.get_command_named(name)\nembed = utils.command_detail_embed(command, guild=inter.guild)\nawait inter.response.send_message(embed=embed)\n

Returns:

Source code in src\\helply\\utils\\embeds.py
def command_detail_embed(\n    command: AppCommand,\n    *,\n    thumbnail: Optional[disnake.File] = None,\n    guild: Optional[disnake.Guild] = None,\n    color: Optional[disnake.Color] = None,\n) -> disnake.Embed:\n\"\"\"Create and return an embed showing command details.\n\n    Parameters\n    ----------\n    command: AppCommand\n        The `AppCommand` retrieved from `AppCommandHelp.get_command_named`\n    thumbnail: disnake.File, optional\n        A `disnake.File` converted image to be set as the embed thumbnail.\n    guild: disnake.Guild, optional\n        Guild where this embed will be displayed. Used to convert\n        any role checks into role objects\n    color: disnake.Color, optional\n        Set the color the embed. Default is None\n\n    Examples\n    --------\n    ```py\n    from disnake.ext.app_command_help import AppCommandHelp, utils\n\n    ...\n    app_command_help = AppCommandHelp(bot)\n\n    ...\n    command = app_command_help.get_command_named(name)\n    embed = utils.command_detail_embed(command, guild=inter.guild)\n    await inter.response.send_message(embed=embed)\n    ```\n\n    Returns\n    -------\n    disnake.Embed\n        The created embed containing the command details.\n    \"\"\"\n    type_ = (\n        \"Slash Command Details\"\n        if isinstance(command, SlashCommand)\n        else \"User Command Details\"\n        if isinstance(command, UserCommand)\n        else \"Message Command Details\"\n    )\n\n    embed = disnake.Embed(description=f\"{command.mention}\\n{command.description}\", color=color)\n    embed.set_author(name=f'{type_} {\"(NSFW)\" if command.nsfw else \"\"}')\n    if thumbnail:\n        embed.set_thumbnail(file=thumbnail)\n\n    if command.checks.permissions:\n        permissions = \", \".join(command.checks.permissions)\n        embed.add_field(name=\"Required Permissions\", value=permissions, inline=True)\n\n    if command.checks.roles:\n        if guild:\n            roles = AppCommandHelp.roles_from_checks(command.checks, guild)\n            role_checks = \", \".join(r.mention for r in roles)\n        else:\n            role_checks = \", \".join(str(check) for check in command.checks.roles)\n\n        roles_as_string = f\"**Required Roles**:\\n{role_checks}\"\n        embed.add_field(name=\"Required Role(s)\", value=roles_as_string, inline=True)\n\n    if isinstance(command, SlashCommand):\n        embed.set_footer(text=\"[ required ] | ( optional )\")\n        if command.args:\n            args = \"\\n\".join(f\"**{arg}**: *{arg.description}*\" for arg in command.args)\n            embed.add_field(name=\"Parameters\", value=args, inline=False)\n        else:\n            embed.add_field(name=\"Parameters\", value=\"None\", inline=True)\n\n    return embed\n
"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.commands_overview_embeds","title":"commands_overview_embeds(commands, *, thumbnail=None, max_field_chars=MAX_CHARS_PER_FIELD, max_fields=MAX_FIELDS_PER_EMBED, color=None)","text":"

Create and return one or more embeds containing all commands and descriptions.

Parameters:

Examples:

from disnake.ext.app_command_help import AppCommandHelp, utils\n\n...\napp_command_help = AppCommandHelp(bot)\n\n...\ncommands = app_command_help.get_all_commands(inter.guild)\nembeds = utils.commands_overview_embeds()\nawait inter.response.send_message(embeds=embeds)\n

Returns:

Source code in src\\helply\\utils\\embeds.py
def commands_overview_embeds(\n    commands: List[AppCommand],\n    *,\n    thumbnail: Optional[disnake.File] = None,\n    max_field_chars: int = MAX_CHARS_PER_FIELD,\n    max_fields: int = MAX_FIELDS_PER_EMBED,\n    color: Optional[disnake.Color] = None,\n) -> List[disnake.Embed]:\n\"\"\"Create and return one or more embeds containing all commands and descriptions.\n\n    Parameters\n    ----------\n    commands: List[AppCommand]\n        List of `AppCommand` received from `AppCommandHelp.get_all_commands`\n    thumbnail: disnake.File, optional\n        A `disnake.File` converted image to be set as the embed thumbnail.\n    max_field_chars: int\n        Max number of characters per embed field description, default is MAX_CHARS_PER_FIELD (1024)\n    max_fields: int\n        Max number of fields per embed. default is MAX_FIELDS_PER_EMBED (10)\n    color: disnake.Color, optional\n        Set the color the embed(s). Default is None\n    Examples\n    --------\n    ```py\n    from disnake.ext.app_command_help import AppCommandHelp, utils\n\n    ...\n    app_command_help = AppCommandHelp(bot)\n\n    ...\n    commands = app_command_help.get_all_commands(inter.guild)\n    embeds = utils.commands_overview_embeds()\n    await inter.response.send_message(embeds=embeds)\n    ```\n\n    Returns\n    ------\n    List[disnake.Embed]\n        A list of disnake.Embed containing an overview of the commands.\n    \"\"\"\n\n    if max_field_chars > MAX_CHARS_PER_FIELD:\n        max_field_chars = MAX_CHARS_PER_FIELD\n\n    if max_fields > MAX_FIELDS_PER_EMBED:\n        max_fields = MAX_FIELDS_PER_EMBED\n\n    embeds: List[disnake.Embed] = []\n    current_embed: Optional[disnake.Embed] = None\n    current_field: str = \"\"\n    current_field_chars: int = 0\n\n    for command in commands:\n        command_type = (\n            \"Slash Command\"\n            if isinstance(command, SlashCommand)\n            else \"User Command\"\n            if isinstance(command, UserCommand)\n            else \"Message Command\"\n        )\n\n        nsfw = \"*(NSFW)*\" if command.nsfw else \"\"\n\n        command_lines = (\n            f\"{command.mention} *({command_type})* {nsfw}\\n\" f\"{command.description}\\n\\n\"\n        )\n\n        if current_embed is None:\n            title = \"Commands Overview\" if not embeds else \"Commands Overview (continued)\"\n            current_embed = _create_base_embed(title, color, thumbnail)\n            current_field_chars = 0\n\n        if current_field_chars + len(command_lines) <= max_field_chars:\n            current_field += command_lines\n            current_field_chars += len(command_lines)\n        else:\n            current_embed.add_field(name=\"\\u200b\", value=current_field, inline=False)\n            current_field = command_lines\n            current_field_chars = len(command_lines)\n\n        if len(current_embed.fields) >= max_fields:\n            embeds.append(current_embed)\n            current_embed = None\n\n    if current_embed is not None:\n        current_embed.add_field(name=\"\\u200b\", value=current_field, inline=False)\n        embeds.append(current_embed)\n\n    return embeds\n
"},{"location":"reference/helply/utils/paginator/","title":"paginator","text":"

Provides a basic Paginator View to provide a clean interface for users to navigator your multiple command embeds.

Note

This can be used for pretty much any embeds, but is designed specifically to work with the list of embeds returned from embeds.all_commands_overview()

"},{"location":"reference/helply/utils/paginator/#helply.utils.paginator.Paginator","title":"Paginator","text":"

Bases: View

Provides a basic paginator that allows users to navigate over multiple embeds.

Inspired by the paginator.py example provided by disnake

Parameters:

Source code in src\\helply\\utils\\paginator.py
class Paginator(disnake.ui.View):\n\n\"\"\"Provides a basic paginator that allows users to navigate over multiple embeds.\n\n    Inspired by the paginator.py example provided by\n    [disnake](https://github.com/DisnakeDev/disnake/blob/stable/examples/views/button/paginator.py)\n\n    Parameters\n    ----------\n    embeds: List[disnake.Embed]\n        List of embeds that will be cycled through\n    user: disnake.User, optional\n        Include a user to prevent others from using buttons.\n    timeout: int, optional\n        Set the timeout for the `View` in seconds, default is 180.\n    \"\"\"\n\n    def __init__(\n        self,\n        *,\n        embeds: List[disnake.Embed],\n        user: Optional[disnake.Member] = None,\n        timeout: int = 180,\n    ) -> None:\n        super().__init__(timeout=timeout)\n        self.user = user\n        self.embeds = embeds\n        self.index = 0\n\n        self._update_state()\n\n    async def interaction_check(self, interaction: disnake.MessageInteraction) -> bool:\n\"\"\"A check that is performed when any button in this view is interacted with\n\n\n        Parameters\n        ----------\n        interaction: disnake.MessageInteraction\n            The interaction invoked by a button\n\n        Returns\n        -------\n        bool\n            True if the interaction check passes and the button callback should be invoked,\n            else False and the callback will not be invoked.\n        \"\"\"\n        if self.user and self.user.id != interaction.author.id:\n            await interaction.response.send_message(\n                \"You do not have permission to interact with this button.\", ephemeral=True\n            )\n            return False\n\n        return True\n\n    def _update_state(self) -> None:\n\"\"\"\n        Update the \"state\" of the view.\n\n        Enable/disable navigation buttons and update the disable counter component\n        \"\"\"\n        self._page_counter.label = f\"{self.index + 1} / {len(self.embeds)}\"\n        self._first_page.disabled = self._prev_page.disabled = self.index == 0\n        self._last_page.disabled = self._next_page.disabled = self.index == len(self.embeds) - 1\n\n    @disnake.ui.button(label=\"First Page\", style=disnake.ButtonStyle.primary)\n    async def _first_page(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Jump to the first embed\"\"\"\n        self.index = 0\n        self._update_state()\n\n        await inter.response.edit_message(embed=self.embeds[self.index], view=self)\n\n    @disnake.ui.button(label=\"Prev Page\", style=disnake.ButtonStyle.primary)\n    async def _prev_page(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Go back one page\"\"\"\n        self.index -= 1\n        self._update_state()\n\n        await inter.response.edit_message(embed=self.embeds[self.index], view=self)\n\n    @disnake.ui.button(label=\"\", style=disnake.ButtonStyle.primary, disabled=True)\n    async def _page_counter(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Just a page counter and cannot be interacted with\"\"\"\n\n    @disnake.ui.button(label=\"Next Page\", style=disnake.ButtonStyle.primary)\n    async def _next_page(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Go to next page\"\"\"\n        self.index += 1\n        self._update_state()\n\n        await inter.response.edit_message(embed=self.embeds[self.index], view=self)\n\n    @disnake.ui.button(label=\"Last Page\", style=disnake.ButtonStyle.primary)\n    async def _last_page(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Go to last page\"\"\"\n        self.index = len(self.embeds) - 1\n        self._update_state()\n\n        await inter.response.edit_message(embed=self.embeds[self.index], view=self)\n
"},{"location":"reference/helply/utils/paginator/#helply.utils.paginator.Paginator.interaction_check","title":"interaction_check(interaction) async","text":"

A check that is performed when any button in this view is interacted with

Parameters:

Returns:

Source code in src\\helply\\utils\\paginator.py
async def interaction_check(self, interaction: disnake.MessageInteraction) -> bool:\n\"\"\"A check that is performed when any button in this view is interacted with\n\n\n    Parameters\n    ----------\n    interaction: disnake.MessageInteraction\n        The interaction invoked by a button\n\n    Returns\n    -------\n    bool\n        True if the interaction check passes and the button callback should be invoked,\n        else False and the callback will not be invoked.\n    \"\"\"\n    if self.user and self.user.id != interaction.author.id:\n        await interaction.response.send_message(\n            \"You do not have permission to interact with this button.\", ephemeral=True\n        )\n        return False\n\n    return True\n
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Helply","text":"

A user-friendly Python library designed to streamline the creation of \"help\" commands for Discord bots using application commands within the disnake library. This library will automatically parse your commands and provide details for each command, such as name, description, role and permission checks, etc.

Disclaimer

Please note that this library is not officially associated with the disnake project or any of its maintainers. It is an independent creation by a user of the Disnake library who wanted to streamline the process of creating /help commands without needing to rewrite the implementation each time.

"},{"location":"#key-features","title":"Key Features","text":""},{"location":"#installation","title":"Installation","text":"

To install the helply package, you will need git. If you don't have git installed on your system, you can download it from here.

Once you have git installed, run the following command inside your Python environment to install the package:

pip install git+https://github.com/dlchamp/Helply\n
"},{"location":"#usage","title":"Usage","text":"

After installing the package, you can use it in your project by importing it as follows:

from helply import Helply\n

AppCommands will be created and cached upon first use of helply to retrieve commands. This allows all commands to become registered with Discord before helply steps in to create it's own objects with the consolidated attributes provided by InvokableApplicationCommand and APIApplicationCommand

"},{"location":"#description-parsing","title":"Description parsing","text":"

Disnake will automatically parse your command descriptions from the docstring in your callback function, or by populating the description keyword argument. Helply uses that description, however, it also parses descriptions found in the extras key-word argument when it finds the \"help\" key. This proves exceptionally useful for menu commands that do not normally have a description that is displayed by the user's client.

Example - User Command:

# Since this is a user command that does not inherently have a description. We are using\n# extras to set the description for the help command.\n@bot.user_command(name=\"View Avatar\", extras={\"help\": \"Display the target user's avatar\"})\nasync def view_avatar(...):\n    ...\n

While designed to allow command descriptions for your menu commands, you may also use this feature to create longer descriptions for your slash commands as it would appear in your help response. For slash commands, this is really only useful if you wish to provide more information that would normally exceed the 100 character limit set by Discord.

Important

Setting extras will override your command.description when displayed in the help response.

In this example, the user will see \"Kick a member from the server\" when attempting to use the command while \"Removes the target member from the guild\" will appear as the command description in the help response.

@bot.slash_command(\n    name=\"kick\",\n    description=\"Kick the target member\",\n    extras={\"help\": \"Removes the target member from the guild\"}\n)\nasync def kick_member(...):\n\"\"\"Kick a member from the server\"\"\"\n
"},{"location":"#support-for-commands-checks","title":"Support for @commands Checks","text":"

The helply library also supports parsing of @commands style checks. For instance, if you are using @commands.has_permissions() to restrict command usage, the extension will recognize and display these permission requirements in the help response.

Example:

@bot.slash_command(name=\"kick\")\n@commands.has_permissions(kick_members=True)\nasync def kick_member(inter: disnake.GuildCommandInteraction, member: disnake.Member):\n\"\"\"Kick a member from the server\n\n    Parameters\n    ----------\n    member: Select a member to kick\n    \"\"\"\n

"},{"location":"#cogs-categories-and-disnake-ext-plugin-support","title":"Cogs, Categories, and disnake-ext-plugin support","text":"

Helply is able to parse the cog or category a command belongs to. This is useful if you wish to display an overview of command available within a category. If you are using cogs, you do not have to do anything extra. The cog associated with a command will be parsed automatically. However, if you're using disnake-ext-plugins, a command's cog will always be None. So, to set a commands category, we go back to the extras keyword to set the command's category:

@some_plugin.slash_command(name='command', extras={\"category\": \"General\"})\nasync def some_command(inter: disnake.ApplicationCommandInteractions):\n    ...\n
"},{"location":"#filtering-commands","title":"Filtering Commands","text":"

When retrieving commands from Helply, you may choose to pass in a member's guild_permissions. This will ensure that only commands the user has permissions to use will be retrieved.

Here, if the command is used within a guild, we want to show all commands available within the guild, including global commands, and only commands that the inter.author is able to use.

Important Permissions are compared against default_member_permissions. Setting this by default hides commands from members unable to use them, Passing permissions also allows helply to ensure these commands stay hidden, even in help responses.

# construct AppCommandHelp with the provided bot and a sequence of commands to ignore\n# ignore commands will not appear in any help responses.\nhelply = Helply(bot, commands_to_ignore=('help',))\n\n@bot.slash_command(name='help')\nasync def help_command(inter: disnake.ApplicationCommandInteraction):\n\n    if inter.guild:\n        guild_id = inter.guild_id\n        permissions = inter.author.guild_permissions\n        dm_only = False\n    else:\n        # command likely used in direct message\n        guild_id = None\n        permissions = None\n        dm_only = True\n\n    commands = helply.get_all_commands(guild_id, permissions=permissions, dm_only=dm_only)\n

"},{"location":"#support","title":"Support","text":"

Join the discord to get support or just chat.

"},{"location":"license/","title":"MIT License","text":"

Copyright (c) 2023 DLCHAMP

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

"},{"location":"examples/advanced/","title":"Advanced","text":"

This is a full example that implements all features of this project. Using the below example automatically handles commands being used within the context of a guild or via direct message to the bot.

from typing import Optional, Tuple\n\nimport disnake\nfrom disnake.ext import commands\n\nfrom helply import Helpy, utils\n\nbot = commands.InteractionBot()\n\n# construct the Helpy instance with the passed in `bot`\nhelpy = Helply(bot)\n\n\n@bot.slash_command(name=\"ping\")\nasync def ping(inter: disnake.ApplicationCommandInteraction):\n\"\"\"Ping the bot to see its latency\"\"\"\n    await inter.response.send_message(\n        f\"Pong! Responded in {(bot.latency * 1000):.2f} ms.\",\n    )\n\n\n@bot.slash_command(name=\"help\")\nasync def help_command(\n    inter: disnake.GuildCommandInteraction,\n    name: Optional[str] = None,\n    category: Optional[str] = None,\n):\n\"\"\"Display help info about this bot's commands.\n\n    Parameters\n    ----------\n    name: Select an available command to view its details\n    category: Select an available category to view its commands.\n    \"\"\"\n\n    if name and category:\n        await inter.response.send_message(\n            \"Please only select a command or a category.\", ephemeral=True\n        )\n        return\n\n    # Since autocomplete for name is a dict[name, str(id)], name in this case\n    # will be the str(id), convert it to int and try to find the command.\n    if name:\n        command = helply.get_command(int(name))\n        if command is None:\n            await inter.response.send_message(\n                \"It appears this command is not available.\", ephemeral=True\n            )\n            return\n\n        # use the included helper embeds module to create the detailed\n        # view of the command.\n        embed = utils.command_detail_embed(command, guild=inter.guild)\n        view = disnake.utils.MISSING\n\n    elif category:\n        guild_id, dm_only, nsfw, permissions = get_helper_query_attrs(inter)\n\n        commands = helply.get_commands_by_category(\n            category, guild_id=guild_id, permissions=permissions, dm_only=dm_only\n        )\n\n        if not commands:\n            await inter.response.send_message(\n                \"No commands available in the selected category.\", ephemeral=True\n            )\n            return\n\n        category_embeds = utils.commands_overview_embeds(\n            commands, max_fields=3, max_field_chars=100, color=disnake.Color.random()\n        )\n\n        if len(category_embeds) > 1:\n            view = utils.Paginator(embeds=category_embeds)\n        else:\n            view = disnake.utils.MISSING\n\n        embed = category_embeds[0]\n\n    else:\n        guild_id, dm_only, nsfw, permissions = get_helper_query_attrs(inter)\n\n        commands = helply.get_all_commands(\n            guild_id, dm_only=dm_only, include_nsfw=nsfw, permissions=permissions\n        )\n        if not commands:\n            await inter.response.send_message(\n                \"Could not find any available commands.\", ephemeral=True\n            )\n            return\n\n        command_embeds = utils.commands_overview_embeds(\n            commands, max_fields=3, max_field_chars=100, color=disnake.Color.random()\n        )\n\n        if len(command_embeds) > 1:\n            view = utils.Paginator(embeds=command_embeds)\n        else:\n            view = disnake.utils.MISSING\n\n        embed = command_embeds[0]\n\n    await inter.response.send_message(embed=embed, view=view)\n\n\n@help_command.autocomplete(\"name\")\nasync def autocomplete_command_names(\n    inter: disnake.ApplicationCommandInteraction,\n    string: str,\n):\n    string = string.casefold()\n\n    guild_id, dm_only, nsfw, permissions = get_helper_query_attrs(inter)\n\n    commands = helply.get_all_commands(\n        guild_id, dm_only=dm_only, include_nsfw=nsfw, permissions=permissions\n    )\n\n    return {c.name: str(c.id) for c in commands}\n\n\n@help_command.autocomplete(\"category\")\nasync def autocomplete_command_categories(\n    inter: disnake.ApplicationCommandInteraction, string: str\n):\n    string = string.casefold()\n\n    guild_id, dm_only, nsfw, permissions = get_helper_query_attrs(inter)\n\n    categories = helply.get_categories(\n        guild_id, dm_only=dm_only, include_nsfw=nsfw, permissions=permissions\n    )\n\n    return [cat for cat in categories if string in cat.casefold()]\n\n\ndef get_helper_query_attrs(\n    inter: disnake.ApplicationCommandInteraction,\n) -> Tuple[Optional[int], bool, bool, Optional[disnake.Permissions]]:\n    # command does not originate from within a guild\n    if not inter.guild or isinstance(inter.author, disnake.User):\n        guild_id = None\n        dm_only = True\n        nsfw = False\n        permissions = None\n\n    else:\n        guild_id = inter.guild_id\n        dm_only = False\n        nsfw = getattr(inter.channel, \"nsfw\", False)\n        permissions = inter.author.guild_permissions\n\n    return guild_id, dm_only, nsfw, permissions\n\n\nif __name__ == \"__main__\":\n    import os\n    bot.run(os.getenv(\"TOKEN\"))\n
"},{"location":"examples/autocomplete/","title":"Autocomplete","text":"

Here are some examples using autocompletion with your created /help command

All examples on this page assume you have the helper class and a help command defined like so:

from helply import Helply\n\n\nhelper = Helply(bot)\n\n...\n...\n\n@bot.slash_command(name='help')\nasync def help_command(inter: disnake.GuildCommandInteraction, name: Optional[str] = None)\n

"},{"location":"examples/autocomplete/#autocomplete-example-using-command-names","title":"Autocomplete example using command names","text":"

This will construct a list of command names available to the user based on their guild_permissions. We then return that list if the name matches what's been inputted into name argument, and we slice the return to return no more than 25 items.

@help_command.autocomplete('name')\nasync def helper_command_name(\n    inter: disnake.GuildCommandInteraction, name: str\n) -> List[str]:\n\n\n    name = name.casefold()\n\n    commands = helply.get_all_commands(\n        inter.guild.id, permissions=inter.author.guild_permissions\n    )\n\n    return [c.name for c in commands if name in c.name.casefold()][:25]\n
"},{"location":"examples/autocomplete/#autocomplete-example-using-command-names-and-ids","title":"Autocomplete example using command names and IDs","text":"

Defining an autocomplete in this fashion will display the command name to the user, however the bot will receive the command's ID as a string. So it will need to be cast to an int before being passed to the `help.get_command(ID) method.

@help_command.autocomplete('name')\nasync def helper_command_name(\n    inter: disnake.GuildCommandInteraction, name: str\n) -> Dict[str, str]:\n\n    name = name.casefold()\n\n    commands = helply.get_all_commands(\n        inter.guild.id, permissions=inter.author.guild_permissions\n    )\n\n    return {c.name: str(c.id) for c in commands if name in c.name.casefold()}\n
"},{"location":"examples/autocomplete/#autocomplete-for-categories","title":"Autocomplete for categories","text":"

You may also want to display all commands available within a specific category or cog. Heres an example of what that might look like.

@help_command.autocomplete('category')\nasync def helper_command_name(\n    inter: disnake.GuildCommandInteraction, category: str)\n -> List[str]:\n    category = category.casefold()\n\n    categories = helper.get_categories(\n        inter.guild.id, permissions=inter.author.guild_permissions\n    )\n\n    return [cat for cat in categories if category in cat.casefold()][:25]\n
"},{"location":"examples/extras/","title":"Extras","text":"

This project also allows you to create some help descriptions for your menu commands @bot.user_command, and @bot.message_command. Since these commands do not inherently have a description that is parsed, we can simply add their descriptions as extras

"},{"location":"examples/extras/#setting-help-description","title":"Setting help description","text":""},{"location":"examples/extras/#user-command","title":"User Command","text":"
@bot.user_command(name=\"User Avatar\", extras={\"help\": \"Display a user's avatar\"})\nasync def user_avatar_menu(\n    inter: disnake.UserCommandInteraction, user: Union[disnake.User, disnake.Member]\n):\n    avatar = user.avatar or user.default_avatar\n    embed = disnake.Embed().set_image(url=avatar.url)\n\n    await inter.response.send_message(embed=embed)\n
"},{"location":"examples/extras/#message-command","title":"Message Command","text":"
@bot.slash_command(\n    name=\"example\",\n    extras={\n        \"help\": (\n            \"This is a much longer description for the command that would normally \"\n            \"exceed the 100 character limit set by Discord\"\n        )\n    },\n)\nasync def example(inter: disnake.ApplicationCommandInteraction):\n\"\"\"A shorter description that does not exceed the 100 character limit\"\"\"\n    ...\n
"},{"location":"examples/extras/#setting-category-with-plugins","title":"Setting category with Plugins","text":"

If using disnake-ext-plugins setting command categories is as easy as:

@plugin.slash_command(name=\"command\", extras={\"category\": \"General\"})\nasync def some_command(inter: disnake.ApplicationCommandInteraction):\n
"},{"location":"examples/simple/","title":"Simple","text":"

A very simple implementation using only a single command. This example should work as is and provides some basic insight into how to use this project.

import os\nfrom typing import Optional\n\nimport disnake\nfrom disnake.ext import commands\n\nfrom helply import Helply, utils\n\nbot = commands.InteractionBot()\n\n# construct the helper class with the bot and sequence of commands to ignore\nhelply = Helply(bot, commands_to_ignore=(\"help\",))\n\n\n@bot.slash_command_name(name=\"kick\")\n@commands.has_permissions(kick_members=True)\n@commands.default_member_permissions(kick_members=True)\nasync def kick_member(\n    inter: disnake.GuildCommandInteraction,\n    member: disnake.Member,\n    reason: Optional[str] = None,\n) -> None:\n\"\"\"Kick a member from the server\n\n    Parameters\n    ----------\n    member: Select a member to kick\n    \"\"\"\n    try:\n        await member.kick(reason=reason)\n\n    except disnake.Forbidden as e:\n        await inter.response.send_message(f\"Unable to kick {member.mention} - {e}\", ephemeral=True)\n        return\n\n    await inter.response.send_message(\n        f\"{member} was kicked by {inter.author}. Reason: {reason}\", ephemeral=True\n    )\n\n\n@bot.slash_command(name=\"help\")\nasync def help_command(inter: disnake.GuildCommandInteraction, name: Optional[str] = None) -> None:\n\"\"\"Display command information\n\n    Parameters\n    ----------\n    name: Choose a command to view its details.\n    \"\"\"\n\n    if name is None:\n        # get all commands available to the command author\n        # by passing in the inter.guild_id, we ensure only global commands and any commands\n        # available only for this guild are retrieved.\n        commands = helply.get_all_commands(\n            inter.guild_id, permissions=inter.author.guild_permissions\n        )\n\n        # since this takes into consideration the default_member_permissions required to use commands\n        # and we passed in the command author's permissions, retrieved commands may be an empty list\n        # if they cannot use any commands the bot provides.\n        if not commands:\n            await inter.response.send_message(\"There are no commands available.\", ephemeral=True)\n            return\n\n        # now we use the include embed builder utility to create the embeds.\n        # in this instance, since there is only one command, embeds will be a single embed\n        embeds = utils.commands_overview_embeds(commands)\n\n        embed = embeds[0]\n\n    else:\n        # Since autocomplete does not force a user to make a selection, we will try to get\n        # the command by the provided name, however, it could result in `None`, so we handle it.\n        command = helply.get_command_named(name)\n        if not command:\n            await inter.response.send_message(\"Unable to find that command.\", ephemeral=True)\n            return\n\n        # Now we again use the embed builder utility for the specific command to view its\n        # full details, description, parameters, if any, and required permissions\n        embed = utils.command_detail_embed(command)\n\n    await inter.response.send_message(embed=embed)\n\n\nif __name__ == \"__main__\":\n    bot.run(os.getenv(\"TOKEN\"))\n
"},{"location":"reference/SUMMARY/","title":"SUMMARY","text":""},{"location":"reference/helply/help/","title":"help","text":""},{"location":"reference/helply/help/#helply.help.Helply","title":"Helply","text":"

Represents an application command helper.

Parameters:

Source code in src\\helply\\help.py
class Helply:\n\"\"\"Represents an application command helper.\n\n    Parameters\n    ----------\n    bot : Union[commands.Bot, commands.InteractionBot]\n        The bot for which this help class will be associated with.\n    commands_to_ignore: Iterable[str]\n        Provide a list of command names to ignore when walking all app commands.\n    \"\"\"\n\n    def __init__(self, bot: Bot, commands_to_ignore: Optional[Sequence[str]] = None) -> None:\n        self.bot = bot\n\n        if commands_to_ignore is not None:\n            self.commands_to_ignore = set(commands_to_ignore)\n        else:\n            self.commands_to_ignore = None\n\n        self._app_commands: Dict[int, AppCommand] = {}\n\n    def _get_command_args(\n        self, command: Union[disnake.APISlashCommand, disnake.Option]\n    ) -> List[Argument]:\n\"\"\"Parse and return the `SlashCommand` or `SubCommand` arguments.\n\n        Parameters\n        ----------\n        command : Union[disnake.APISlashCommand, disnake.Option]\n            The slash command or a slash command's sub_command.\n\n        Returns\n        -------\n        List[Argument]\n            A sequence of the command or sub_command's arguments.\n        \"\"\"\n        args: List[Argument] = []\n        for option in command.options:\n            if option.type in (\n                disnake.OptionType.sub_command,\n                disnake.OptionType.sub_command_group,\n            ):\n                continue\n\n            args.append(\n                Argument(name=option.name, required=option.required, description=option.description)\n            )\n\n        return args\n\n    def _get_command_desc(self, name: str) -> str:\n\"\"\"Get the description for a command.\n\n        Parameters\n        ----------\n        name : str\n            The name of the command.\n\n        Returns\n        -------\n        str\n            The description of the command.\n        \"\"\"\n        desc = \"-\"\n        command = self.bot.get_slash_command(name)\n\n        if command and isinstance(command, (commands.InvokableSlashCommand, commands.SubCommand)):\n            desc = command.extras.get(\"help\", \"\") or command.description\n\n        return desc\n\n    def _get_sub_commands(\n        self,\n        command: Union[disnake.APISlashCommand, disnake.Option],\n        checks: CommandChecks,\n        category: str,\n        parent_command: Optional[disnake.APISlashCommand] = None,\n    ) -> List[SlashCommand]:\n\"\"\"Get and return the `APISlashCommand`'s registered `SubCommands` if any.\n\n        Parameters\n        ----------\n        command : Union[disnake.APISlashCommand, disnake.Option]\n            The registered slash command or the command's SubCommand.\n        checks : CommandChecks\n            The permission and role checks assigned to the parent command.\n        parent_name : Optional[str]\n            Parent command's name. Only used if sub_group is used and this function is called\n            recursively.\n\n        Returns\n        -------\n        List[SlashCommand]\n            A list of sub-commands, if any.\n        \"\"\"\n        sub_commands: List[SlashCommand] = []\n\n        for option in command.options:\n            name = (\n                f\"{parent_command.name} {command.name} {option.name}\"\n                if parent_command\n                else f\"{command.name} {option.name}\"\n            )\n            if option.type == disnake.OptionType.sub_command:\n                args = self._get_command_args(option)\n\n                if parent_command:\n                    command_id = parent_command.id\n                    dm_permissions = parent_command.dm_permission\n                    nsfw = parent_command.nsfw\n\n                elif isinstance(command, disnake.APISlashCommand):\n                    command_id = command.id\n                    dm_permissions = command.dm_permission\n                    nsfw = command.nsfw\n\n                else:\n                    # should realistically never be reached\n                    raise TypeError(\n                        \"Command must be an instance of `disnake.APISlashCommand` \"\n                        \"if parent_command is `None`\"\n                    ) from None\n\n                desc = self._get_command_desc(name)\n                sub_commands.append(\n                    SlashCommand(\n                        id=command_id,\n                        name=name,\n                        description=desc,\n                        args=args,\n                        checks=checks,\n                        type=AppCommandType.slash,\n                        dm_permission=dm_permissions,\n                        nsfw=nsfw,\n                        category=category,\n                    )\n                )\n            elif option.type == disnake.OptionType.sub_command_group:\n                sub_commands.extend(\n                    self._get_sub_commands(option, checks, category, parent_command)\n                )\n\n        return sub_commands\n\n    def _parse_checks(\n        self,\n        command: commands.InvokableApplicationCommand,\n    ) -> CommandChecks:\n\"\"\"Parse the checks associated with a command and extract registered permissions and roles.\n\n        Parameters\n        ----------\n        command : commands.InvokableApplicationCommand\n            The command object to parse checks from.\n\n        Returns\n        -------\n        CommandChecks\n            A NamedTuple containing a list of permissions and/or role names or IDs\n            required to invoke the command.\n        \"\"\"\n\n        permissions: List[str] = []\n        roles: List[Union[str, int]] = []\n\n        # command.checks provides a list of check predicates\n        # associated with the command\n        checks = command.checks\n\n        # iterate those checks and analyze them to access\n        # check names (ie. \"has_any_role\")\n        for check in checks:\n            name = check.__qualname__.split(\".\")[0]\n            if \"bot\" in name or not check.__closure__:\n                continue\n\n            # for each check that does not include \"bot\" (ie. \"bot_has_permissions\")\n            # the arguments will be parsed and used to populate `CommandChecks`\n            closure = check.__closure__[0]\n\n            args = (\n                closure.cell_contents\n                if len(closure.cell_contents) > 1\n                else (closure.cell_contents,)\n            )\n\n            # checks pertaining to roles will populate CommandChecks.roles\n            if \"role\" in name:\n                roles.extend(args)\n\n            # remaining checks should be permissions based and are formatted\n            # then added to CommandChecks.permissions\n            else:\n                permissions.extend(\n                    [p.replace(\"_\", \" \").title() for p, v in closure.cell_contents.items() if v]\n                )\n\n        return CommandChecks(permissions, roles)\n\n    def _handle_slash_command(self, command: disnake.APISlashCommand) -> List[SlashCommand]:\n\"\"\"Handle creation of `SlashCommand` from `disnake.APISlashCommand`.\n\n        Parameters\n        ----------\n        command : disnake.APISlashCommand\n            The APISlashCommand provided by Discord's API.\n\n        Return\n        ------\n        List[SlashCommand]\n            The constructed `SlashCommand`.\n        \"\"\"\n        invokable = self.bot.get_slash_command(command.name)\n        if invokable is None:\n            return []\n\n        checks = self._parse_checks(invokable)\n        desc = self._get_command_desc(invokable.qualified_name)\n        category = self._get_command_category(invokable)\n        args = self._get_command_args(command)\n        sub_commands = self._get_sub_commands(command, checks, category)\n\n        if sub_commands:\n            return sub_commands\n\n        return [\n            SlashCommand(\n                id=command.id,\n                name=command.name,\n                description=desc,\n                args=args,\n                checks=checks,\n                type=AppCommandType.slash,\n                dm_permission=command.dm_permission,\n                nsfw=command.nsfw,\n                guild_id=command.guild_id,\n                default_member_permissions=invokable.default_member_permissions,\n                category=category,\n            )\n        ]\n\n    def _handle_message_command(\n        self, command: disnake.APIMessageCommand\n    ) -> Optional[MessageCommand]:\n\"\"\"Handle creation of `MessageCommand` from `disnake.APIMessageCommand`.\n\n        Parameters\n        ----------\n        command : disnake.APIUserCommand\n            The APIMessageCommand provided by Discord's API.\n\n        Return\n        ------\n        Optional[MessageCommand]\n            The constructed `MessageCommand`.\n        \"\"\"\n        invokable = self.bot.get_message_command(command.name)\n        if invokable is None:\n            return\n\n        checks = self._parse_checks(invokable)\n        desc = invokable.extras.get(\"help\", \"-\")\n        category = self._get_command_category(invokable)\n\n        return MessageCommand(\n            id=command.id,\n            name=command.name,\n            checks=checks,\n            type=AppCommandType.message,\n            description=desc,\n            dm_permission=command.dm_permission,\n            nsfw=command.nsfw,\n            guild_id=command.guild_id,\n            default_member_permissions=command.default_member_permissions,\n            category=category,\n        )\n\n    def _handle_user_command(self, command: disnake.APIUserCommand) -> Optional[UserCommand]:\n\"\"\"Handle creation of `UserCommand` from `disnake.APIUserCommand`.\n\n        Parameters\n        ----------\n        command : disnake.APIUserCommand\n            The APIUserCommand provided by Discord's API.\n\n        Return\n        ------\n        Optional[UserCommand]\n            The constructed `UserCommand`.\n        \"\"\"\n        invokable = self.bot.get_user_command(command.name)\n\n        if invokable is None:\n            return\n\n        checks = self._parse_checks(invokable)\n        desc = invokable.extras.get(\"help\", \"-\")\n        category = self._get_command_category(invokable)\n\n        return UserCommand(\n            id=command.id,\n            name=command.name,\n            type=AppCommandType.user,\n            checks=checks,\n            description=desc,\n            dm_permission=command.dm_permission,\n            nsfw=command.nsfw,\n            guild_id=command.guild_id,\n            default_member_permissions=command.default_member_permissions,\n            category=category,\n        )\n\n    def _get_command_category(self, invokable: commands.InvokableApplicationCommand) -> str:\n\"\"\"Get the command's cog or category name, if available\n\n        `cog_name` would be derived from `disnake.ext.commands.Cog`, whereas\n        `category` would come from using [disnake-ext-plugins](https://github.com/DisnakeCommunity/disnake-ext-plugins)\n\n        Parameters\n        ----------\n        invokable: commands.InvokableApplicationCommand\n\n        Returns\n        -------\n        str\n            `Cog's` name or str value set in `.extras['category']` or 'None'\n\n        \"\"\"\n        name = invokable.cog_name or invokable.extras.get(\"category\")\n        if not name:\n            name = \"None\"\n\n        return name\n\n    def _walk_app_commands(self) -> None:\n\"\"\"Retrieve all global and guild-specific application commands.\"\"\"\n        all_commands = self.bot.global_application_commands\n        for guild in self.bot.guilds:\n            all_commands.extend(self.bot.get_guild_application_commands(guild.id))\n\n        for command in all_commands:\n            if self.commands_to_ignore and command.name in self.commands_to_ignore:\n                continue\n\n            if isinstance(command, disnake.APISlashCommand):\n                self._app_commands.update({c.id: c for c in self._handle_slash_command(command)})\n\n            elif isinstance(command, disnake.MessageCommand):\n                msg_command = self._handle_message_command(command)\n\n                if msg_command:\n                    self._app_commands[msg_command.id] = msg_command\n\n            else:\n                user_command = self._handle_user_command(command)\n\n                if user_command:\n                    self._app_commands[user_command.id] = user_command\n\n    def get_all_commands(\n        self,\n        guild_id: Optional[int] = None,\n        *,\n        permissions: Optional[disnake.Permissions] = None,\n        include_nsfw: bool = True,\n        dm_only: bool = False,\n    ) -> List[AppCommand]:\n\"\"\"Retrieve a filtered list of AppCommand based on specified criteria.\n\n        By default, this method should return all registered commands. Specify filters\n        to narrow down the output results.\n\n        Parameters\n        ----------\n        guild_id : Optional[int]\n            Filter commands registered to the specified guild_id.  If not specified,\n            all commands may be returned.\n        permissions: Optional[disnake.Permissions]\n            Filter commands that do not exceed permissions. If not specified,\n            commands will not be filtered by permissions.\n            !!! Note\n                Should not be used with `dm_only`\n        include_nsfw : bool\n            Whether or not to include categories NSFW commands.\n        dm_only: bool\n            Whether or not to include only commands with direct message enabled.\n            !!! Note\n                Should not specify `guild_id` or `permissions` if setting this to True\n\n        Returns\n        -------\n        List[AppCommand]\n            Resulting list of AppCommands after filters have been applied.\n        \"\"\"\n\n        if not self._app_commands:\n            self._walk_app_commands()\n\n        commands: List[AppCommand] = []\n\n        for command in self._app_commands.values():\n            if guild_id and command.guild_id and command.guild_id != guild_id:\n                continue\n\n            if dm_only and not command.dm_permission:\n                continue\n\n            if not permissions and command.default_member_permissions:\n                continue\n\n            if (\n                permissions\n                and command.default_member_permissions\n                and not permissions >= command.default_member_permissions\n            ):\n                continue\n\n            if not include_nsfw and command.nsfw:\n                continue\n\n            commands.append(command)\n\n        return commands\n\n    def get_command_named(\n        self, name: str, cmd_type: Optional[AppCommandType] = None\n    ) -> Optional[AppCommand]:\n\"\"\"Get a command by its name.\n\n        Parameters\n        ----------\n        name : str\n            Name of the ApplicationCommand.\n        cmd_type: Optional[AppCommandType]\n            Specify the type of command to be returned. If not specified, the first matching\n            command will be returned regardless of its type.\n\n\n        Returns\n        -------\n        Optional[AppCommand]\n            The command that matches the provided name, if found.\n        \"\"\"\n        for command in self._app_commands.values():\n            if command.name == name and (cmd_type is None or command.type is cmd_type):\n                return command\n\n    def get_command(self, id: int) -> Optional[AppCommand]:\n\"\"\"Get a command by its ID\n\n        Parameters\n        ----------\n        id: int\n            ID of the AppCommand\n\n        Returns\n        --------\n        Optional[AppCommand]\n            The retrieved AppCommand or None of not found.\n        \"\"\"\n        return self._app_commands.get(id)\n\n    def get_commands_by_category(\n        self,\n        category: str,\n        *,\n        guild_id: Optional[int] = None,\n        permissions: Optional[disnake.Permissions] = None,\n        include_nsfw: bool = True,\n        dm_only: bool = False,\n    ) -> List[AppCommand]:\n\"\"\"Retrieve a filtered list of AppCommand based on specified criteria within a category.\n\n        By default, this method should return all registered commands within a category.\n        Specify filters to narrow down the output results.\n\n        Parameters\n        ----------\n        category: str\n            Category for which commands are in.\n        guild_id : Optional[int]\n            Filter commands registered to the specified guild_id.  If not specified,\n            all commands may be returned.\n        permissions: Optional[disnake.Permissions]\n            Filter commands that do not exceed permissions. If not specified,\n            commands will not be filtered by permissions.\n            !!! Note\n                Should not be used with `dm_only`\n        include_nsfw : bool\n            Whether or not to include categories NSFW commands.\n        dm_only: bool\n            Whether or not to include only commands with direct message enabled.\n            !!! Note\n                Should not specify `guild_id` or `permissions` if setting this to True\n\n        Returns\n        --------\n        List[AppCommand]\n            A list of commands within the specified group name.\n\n        \"\"\"\n        commands = self.get_all_commands(\n            guild_id,\n            permissions=permissions,\n            include_nsfw=include_nsfw,\n            dm_only=dm_only,\n        )\n        return [command for command in commands if command.category == category]\n\n    def get_categories(\n        self,\n        guild_id: Optional[int] = None,\n        *,\n        permissions: Optional[disnake.Permissions] = None,\n        include_nsfw: bool = True,\n        dm_only: bool = False,\n    ) -> List[str]:\n\"\"\"Return a unique list of command group names.\n\n        Useful if you wish to have an autocomplete for users to select from available\n        command groups\n\n        Parameters\n        ----------\n        guild_id : Optional[int]\n            Filter categories with commands registered to the specified guild_id. If not\n            specified, all categories may be returned.\n        permissions: Optional[disnake.Permissions]\n            Filter commands that do not exceed permissions. If not specified,\n            commands will not be filtered by permissions.\n            !!! Note\n                Should not be used with `dm_only`\n        include_nsfw : bool\n            Whether or not to include categories NSFW commands.\n        dm_only: bool\n            Whether or not to include only commands with direct message enabled.\n            !!! Note\n                Should not specify `guild_id` or `permissions` if setting this to True\n\n        Example:\n        ```py\n        @some_command.autocomplete('category')\n        async def some_command_group_autocomplete(\n            inter: disnake.ApplicationCommandInteraction, string: str\n        ) -> List[str]:\n            string = string.casefold()\n            commands = helper.get_command_categories(inter.guild.id)\n            return [g for g in commands if string in g.casefold()]\n        ```\n\n        Returns\n        -------\n        List[str]\n            A list of unique command categories.\n        \"\"\"\n        categories: List[str] = []\n\n        for command in self.get_all_commands(\n            guild_id,\n            permissions=permissions,\n            include_nsfw=include_nsfw,\n            dm_only=dm_only,\n        ):\n            if command.category not in categories:\n                categories.append(command.category)\n\n        return categories\n\n    def get_dm_only_commands(self, *, include_nsfw: bool = False) -> List[AppCommand]:\n\"\"\"A shortcut method for returning only commands with direct message enabled.\n\n        Parameters\n        ----------\n        include_nsfw: bool\n            Whether or not to include NSFW commands.\n\n        Returns\n        -------\n        List[AppCommand]\n            A list of commands with `.dm_permissions` set to True\n        \"\"\"\n        return self.get_all_commands(dm_only=True, include_nsfw=include_nsfw)\n\n    def get_guild_only_commands(\n        self,\n        guild_id: int,\n        *,\n        include_nsfw: bool = False,\n        permissions: Optional[disnake.Permissions] = None,\n    ):\n\"\"\"This method returns global and guild-specific commands available within a guild context.\n\n        !!! Note\n            Including `permissions` will restrict the command list further to commands that\n            do not require more, or higher, permissions than the permissions specified.\n\n        Parameters\n        guild_id: int\n            ID for the guild for which guild-specific command are registered.\n        include_nsfw: bool\n            Whether or not to include NSFW commands.\n        permissions: Optional[disnake.Permissions]\n            Set the permission limit of the resulting commands.  Any commands that exceed specified\n            permissions will be omitted\n        \"\"\"\n        return self.get_all_commands(guild_id, include_nsfw=include_nsfw, permissions=permissions)\n\n    @staticmethod\n    def roles_from_checks(checks: CommandChecks, guild: disnake.Guild) -> List[disnake.Role]:\n\"\"\"Parse the command's role checks and return a list of `disnake.Role`.\n\n        Parameters\n        ----------\n        checks : CommandChecks\n            A command's checks\n\n        Returns\n        -------\n        List[disnake.Role]\n            `Roles` that have been successfully converted from name or ID.\n        \"\"\"\n        role_checks = checks.roles\n        roles: List[disnake.Role] = []\n\n        for name_or_id in role_checks:\n            if isinstance(name_or_id, int) or name_or_id.isdigit():\n                role = guild.get_role(int(name_or_id))\n            else:\n                role = disnake.utils.get(guild.roles, name=name_or_id)\n\n            if role:\n                roles.append(role)\n\n        return roles\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_all_commands","title":"get_all_commands(guild_id=None, *, permissions=None, include_nsfw=True, dm_only=False)","text":"

Retrieve a filtered list of AppCommand based on specified criteria.

By default, this method should return all registered commands. Specify filters to narrow down the output results.

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_all_commands(\n    self,\n    guild_id: Optional[int] = None,\n    *,\n    permissions: Optional[disnake.Permissions] = None,\n    include_nsfw: bool = True,\n    dm_only: bool = False,\n) -> List[AppCommand]:\n\"\"\"Retrieve a filtered list of AppCommand based on specified criteria.\n\n    By default, this method should return all registered commands. Specify filters\n    to narrow down the output results.\n\n    Parameters\n    ----------\n    guild_id : Optional[int]\n        Filter commands registered to the specified guild_id.  If not specified,\n        all commands may be returned.\n    permissions: Optional[disnake.Permissions]\n        Filter commands that do not exceed permissions. If not specified,\n        commands will not be filtered by permissions.\n        !!! Note\n            Should not be used with `dm_only`\n    include_nsfw : bool\n        Whether or not to include categories NSFW commands.\n    dm_only: bool\n        Whether or not to include only commands with direct message enabled.\n        !!! Note\n            Should not specify `guild_id` or `permissions` if setting this to True\n\n    Returns\n    -------\n    List[AppCommand]\n        Resulting list of AppCommands after filters have been applied.\n    \"\"\"\n\n    if not self._app_commands:\n        self._walk_app_commands()\n\n    commands: List[AppCommand] = []\n\n    for command in self._app_commands.values():\n        if guild_id and command.guild_id and command.guild_id != guild_id:\n            continue\n\n        if dm_only and not command.dm_permission:\n            continue\n\n        if not permissions and command.default_member_permissions:\n            continue\n\n        if (\n            permissions\n            and command.default_member_permissions\n            and not permissions >= command.default_member_permissions\n        ):\n            continue\n\n        if not include_nsfw and command.nsfw:\n            continue\n\n        commands.append(command)\n\n    return commands\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_categories","title":"get_categories(guild_id=None, *, permissions=None, include_nsfw=True, dm_only=False)","text":"

Return a unique list of command group names.

Useful if you wish to have an autocomplete for users to select from available command groups

Parameters:

Example:

@some_command.autocomplete('category')\nasync def some_command_group_autocomplete(\n    inter: disnake.ApplicationCommandInteraction, string: str\n) -> List[str]:\n    string = string.casefold()\n    commands = helper.get_command_categories(inter.guild.id)\n    return [g for g in commands if string in g.casefold()]\n

Returns:

Source code in src\\helply\\help.py
def get_categories(\n    self,\n    guild_id: Optional[int] = None,\n    *,\n    permissions: Optional[disnake.Permissions] = None,\n    include_nsfw: bool = True,\n    dm_only: bool = False,\n) -> List[str]:\n\"\"\"Return a unique list of command group names.\n\n    Useful if you wish to have an autocomplete for users to select from available\n    command groups\n\n    Parameters\n    ----------\n    guild_id : Optional[int]\n        Filter categories with commands registered to the specified guild_id. If not\n        specified, all categories may be returned.\n    permissions: Optional[disnake.Permissions]\n        Filter commands that do not exceed permissions. If not specified,\n        commands will not be filtered by permissions.\n        !!! Note\n            Should not be used with `dm_only`\n    include_nsfw : bool\n        Whether or not to include categories NSFW commands.\n    dm_only: bool\n        Whether or not to include only commands with direct message enabled.\n        !!! Note\n            Should not specify `guild_id` or `permissions` if setting this to True\n\n    Example:\n    ```py\n    @some_command.autocomplete('category')\n    async def some_command_group_autocomplete(\n        inter: disnake.ApplicationCommandInteraction, string: str\n    ) -> List[str]:\n        string = string.casefold()\n        commands = helper.get_command_categories(inter.guild.id)\n        return [g for g in commands if string in g.casefold()]\n    ```\n\n    Returns\n    -------\n    List[str]\n        A list of unique command categories.\n    \"\"\"\n    categories: List[str] = []\n\n    for command in self.get_all_commands(\n        guild_id,\n        permissions=permissions,\n        include_nsfw=include_nsfw,\n        dm_only=dm_only,\n    ):\n        if command.category not in categories:\n            categories.append(command.category)\n\n    return categories\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_command","title":"get_command(id)","text":"

Get a command by its ID

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_command(self, id: int) -> Optional[AppCommand]:\n\"\"\"Get a command by its ID\n\n    Parameters\n    ----------\n    id: int\n        ID of the AppCommand\n\n    Returns\n    --------\n    Optional[AppCommand]\n        The retrieved AppCommand or None of not found.\n    \"\"\"\n    return self._app_commands.get(id)\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_command_named","title":"get_command_named(name, cmd_type=None)","text":"

Get a command by its name.

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_command_named(\n    self, name: str, cmd_type: Optional[AppCommandType] = None\n) -> Optional[AppCommand]:\n\"\"\"Get a command by its name.\n\n    Parameters\n    ----------\n    name : str\n        Name of the ApplicationCommand.\n    cmd_type: Optional[AppCommandType]\n        Specify the type of command to be returned. If not specified, the first matching\n        command will be returned regardless of its type.\n\n\n    Returns\n    -------\n    Optional[AppCommand]\n        The command that matches the provided name, if found.\n    \"\"\"\n    for command in self._app_commands.values():\n        if command.name == name and (cmd_type is None or command.type is cmd_type):\n            return command\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_commands_by_category","title":"get_commands_by_category(category, *, guild_id=None, permissions=None, include_nsfw=True, dm_only=False)","text":"

Retrieve a filtered list of AppCommand based on specified criteria within a category.

By default, this method should return all registered commands within a category. Specify filters to narrow down the output results.

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_commands_by_category(\n    self,\n    category: str,\n    *,\n    guild_id: Optional[int] = None,\n    permissions: Optional[disnake.Permissions] = None,\n    include_nsfw: bool = True,\n    dm_only: bool = False,\n) -> List[AppCommand]:\n\"\"\"Retrieve a filtered list of AppCommand based on specified criteria within a category.\n\n    By default, this method should return all registered commands within a category.\n    Specify filters to narrow down the output results.\n\n    Parameters\n    ----------\n    category: str\n        Category for which commands are in.\n    guild_id : Optional[int]\n        Filter commands registered to the specified guild_id.  If not specified,\n        all commands may be returned.\n    permissions: Optional[disnake.Permissions]\n        Filter commands that do not exceed permissions. If not specified,\n        commands will not be filtered by permissions.\n        !!! Note\n            Should not be used with `dm_only`\n    include_nsfw : bool\n        Whether or not to include categories NSFW commands.\n    dm_only: bool\n        Whether or not to include only commands with direct message enabled.\n        !!! Note\n            Should not specify `guild_id` or `permissions` if setting this to True\n\n    Returns\n    --------\n    List[AppCommand]\n        A list of commands within the specified group name.\n\n    \"\"\"\n    commands = self.get_all_commands(\n        guild_id,\n        permissions=permissions,\n        include_nsfw=include_nsfw,\n        dm_only=dm_only,\n    )\n    return [command for command in commands if command.category == category]\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_dm_only_commands","title":"get_dm_only_commands(*, include_nsfw=False)","text":"

A shortcut method for returning only commands with direct message enabled.

Parameters:

Returns:

Source code in src\\helply\\help.py
def get_dm_only_commands(self, *, include_nsfw: bool = False) -> List[AppCommand]:\n\"\"\"A shortcut method for returning only commands with direct message enabled.\n\n    Parameters\n    ----------\n    include_nsfw: bool\n        Whether or not to include NSFW commands.\n\n    Returns\n    -------\n    List[AppCommand]\n        A list of commands with `.dm_permissions` set to True\n    \"\"\"\n    return self.get_all_commands(dm_only=True, include_nsfw=include_nsfw)\n
"},{"location":"reference/helply/help/#helply.help.Helply.get_guild_only_commands","title":"get_guild_only_commands(guild_id, *, include_nsfw=False, permissions=None)","text":"

This method returns global and guild-specific commands available within a guild context.

Note

Including permissions will restrict the command list further to commands that do not require more, or higher, permissions than the permissions specified.

Parameters guild_id: int ID for the guild for which guild-specific command are registered. include_nsfw: bool Whether or not to include NSFW commands. permissions: Optional[disnake.Permissions] Set the permission limit of the resulting commands. Any commands that exceed specified permissions will be omitted

Source code in src\\helply\\help.py
def get_guild_only_commands(\n    self,\n    guild_id: int,\n    *,\n    include_nsfw: bool = False,\n    permissions: Optional[disnake.Permissions] = None,\n):\n\"\"\"This method returns global and guild-specific commands available within a guild context.\n\n    !!! Note\n        Including `permissions` will restrict the command list further to commands that\n        do not require more, or higher, permissions than the permissions specified.\n\n    Parameters\n    guild_id: int\n        ID for the guild for which guild-specific command are registered.\n    include_nsfw: bool\n        Whether or not to include NSFW commands.\n    permissions: Optional[disnake.Permissions]\n        Set the permission limit of the resulting commands.  Any commands that exceed specified\n        permissions will be omitted\n    \"\"\"\n    return self.get_all_commands(guild_id, include_nsfw=include_nsfw, permissions=permissions)\n
"},{"location":"reference/helply/help/#helply.help.Helply.roles_from_checks","title":"roles_from_checks(checks, guild) staticmethod","text":"

Parse the command's role checks and return a list of disnake.Role.

Parameters:

Returns:

Source code in src\\helply\\help.py
@staticmethod\ndef roles_from_checks(checks: CommandChecks, guild: disnake.Guild) -> List[disnake.Role]:\n\"\"\"Parse the command's role checks and return a list of `disnake.Role`.\n\n    Parameters\n    ----------\n    checks : CommandChecks\n        A command's checks\n\n    Returns\n    -------\n    List[disnake.Role]\n        `Roles` that have been successfully converted from name or ID.\n    \"\"\"\n    role_checks = checks.roles\n    roles: List[disnake.Role] = []\n\n    for name_or_id in role_checks:\n        if isinstance(name_or_id, int) or name_or_id.isdigit():\n            role = guild.get_role(int(name_or_id))\n        else:\n            role = disnake.utils.get(guild.roles, name=name_or_id)\n\n        if role:\n            roles.append(role)\n\n    return roles\n
"},{"location":"reference/helply/types/checks/","title":"checks","text":""},{"location":"reference/helply/types/checks/#helply.types.checks.CommandChecks","title":"CommandChecks","text":"

Bases: NamedTuple

Wrap the command's permission or role requirements.

Attributes:

Source code in src\\helply\\types\\checks.py
class CommandChecks(typing.NamedTuple):\n\"\"\"Wrap the command's permission or role requirements.\n\n    Attributes\n    ----------\n    permissions : List[str]\n        A list of permission names required to use this command.\n    roles : List[Union[str, int]]\n        A list of role names or role IDs required to use this command.\n    \"\"\"\n\n    permissions: typing.List[str]\n    roles: typing.List[typing.Union[str, int]]\n
"},{"location":"reference/helply/types/commands/","title":"commands","text":""},{"location":"reference/helply/types/commands/#helply.types.commands.AppCommand","title":"AppCommand dataclass","text":"

Represents an AppCommand.

AppCommands are dataclasses that include various attributes from both .ApplicationCommand and .InvokableApplicationCommand

Attributes:

"},{"location":"reference/helply/types/commands/#helply.types.commands.AppCommand--properties","title":"Properties","text":"

mention : str Return the command as a mentionable if slash command, else returns bolded name.

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass AppCommand:\n\"\"\"Represents an AppCommand.\n\n    AppCommands are dataclasses that include various attributes from both\n    `.ApplicationCommand` and `.InvokableApplicationCommand`\n\n    Attributes\n    ----------\n    id : int\n        The command's unique identifier.\n    name : str\n        The name of the command.\n    checks : CommandChecks\n        The command's permission and role requirements.\n    type: AppCommandType\n        Type of command\n    category: str\n        Name of cog command belongs to. Also parses `.extras['category']` for implementations using\n        [disnake-ext-plugins](https://github.com/DisnakeCommunity/disnake-ext-plugins)\n    description : str\n        A brief description of the command.\n    dm_permission : bool\n        Whether the command is available in DMs or not.\n    nsfw : bool\n        Whether the command is NSFW (Not Safe For Work).\n    guild_id : int, optional\n        The ID of the guild where the command is available.\n    default_member_permissions : Permissions, optional\n        Default member permissions required to use this command.\n\n    Properties\n    ----------\n    mention : str\n        Return the command as a mentionable if slash command, else returns bolded name.\n    \"\"\"\n\n    id: int\n    name: str\n    checks: CommandChecks\n    type: \"AppCommandType\"\n    category: str = \"None\"\n    dm_permission: bool = True\n    nsfw: bool = False\n    description: str = \"-\"\n    guild_id: Optional[int] = None\n    default_member_permissions: Optional[Permissions] = None\n\n    @property\n    def mention(self) -> str:\n        if isinstance(self, SlashCommand):\n            return f\"</{self.name}:{self.id}>\"\n        return f\"**{self.name}**\"\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.Argument","title":"Argument dataclass","text":"

Represents a SlashCommand argument.

Attributes:

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass Argument:\n\"\"\"Represents a SlashCommand argument.\n\n    Attributes\n    ----------\n    name : str\n        Name of the argument.\n    required : bool\n        Indicate if the argument is required.\n    description : str\n        A brief description of the argument.\n    \"\"\"\n\n    name: str\n    required: bool\n    description: str\n\n    def __str__(self) -> str:\n\"\"\"Return the argument as a string.\n\n        Required arguments will have `[]` wrapped around their name,\n        while optional arguments will be wrapped with `()`.\n        \"\"\"\n        if self.required:\n            return f\"[{self.name}]\"\n        return f\"({self.name})\"\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.Argument.__str__","title":"__str__()","text":"

Return the argument as a string.

Required arguments will have [] wrapped around their name, while optional arguments will be wrapped with ().

Source code in src\\helply\\types\\commands.py
def __str__(self) -> str:\n\"\"\"Return the argument as a string.\n\n    Required arguments will have `[]` wrapped around their name,\n    while optional arguments will be wrapped with `()`.\n    \"\"\"\n    if self.required:\n        return f\"[{self.name}]\"\n    return f\"({self.name})\"\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.MessageCommand","title":"MessageCommand dataclass","text":"

Bases: AppCommand

Represents a MessageCommand type of AppCommand.

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass MessageCommand(AppCommand):\n\"\"\"Represents a MessageCommand type of AppCommand.\"\"\"\n\n    ...\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.SlashCommand","title":"SlashCommand dataclass","text":"

Bases: AppCommand

Represents a SlashCommand type AppCommand.

Attributes:

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass SlashCommand(AppCommand):\n\"\"\"Represents a SlashCommand type AppCommand.\n\n    Attributes\n    ----------\n    args : List[Argument]\n        A list of the command's Arguments, if any.\n    \"\"\"\n\n    args: List[Argument] = dataclasses.field(default_factory=list)\n
"},{"location":"reference/helply/types/commands/#helply.types.commands.UserCommand","title":"UserCommand dataclass","text":"

Bases: AppCommand

Represents a UserCommand type of AppCommand.

Source code in src\\helply\\types\\commands.py
@dataclasses.dataclass\nclass UserCommand(AppCommand):\n\"\"\"Represents a UserCommand type of AppCommand.\"\"\"\n\n    ...\n
"},{"location":"reference/helply/types/enums/","title":"enums","text":""},{"location":"reference/helply/types/enums/#helply.types.enums.AppCommandType","title":"AppCommandType","text":"

Bases: Enum

Enum for AppCommandType

Attributes:

Source code in src\\helply\\types\\enums.py
class AppCommandType(enum.Enum):\n\"\"\"Enum for AppCommandType\n\n    Attributes\n    ----------\n    slash: SlashCommand\n    message: MessageCommand\n    user UserCommand\n    \"\"\"\n\n    slash = SlashCommand\n    message = MessageCommand\n    user = UserCommand\n
"},{"location":"reference/helply/utils/embeds/","title":"embeds","text":"

Embeds module adds some pre-configured embeds to streamline the creation of your help command

"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.MAX_CHARS_PER_FIELD","title":"MAX_CHARS_PER_FIELD = 1024 module-attribute","text":"

Set the max and default character limit per embed field.

This is a Discord limitation, so we use this for chunking command description lines for the overview embed(s) which allow us to split into multiple fields within a single embed.

"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.MAX_CHARS_PER_FIELD--notes","title":"Notes","text":"

I do not recommend exceeding 400 characters as this can create very tall embeds.

"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.MAX_FIELDS_PER_EMBED","title":"MAX_FIELDS_PER_EMBED = 25 module-attribute","text":"

Set the max and default field per embed.

Discord limits this to 25, so that's what has been set as the max here as well.

"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.command_detail_embed","title":"command_detail_embed(command, *, thumbnail=None, guild=None, color=None)","text":"

Create and return an embed showing command details.

Parameters:

Examples:

from disnake.ext.app_command_help import AppCommandHelp, utils\n\n...\napp_command_help = AppCommandHelp(bot)\n\n...\ncommand = app_command_help.get_command_named(name)\nembed = utils.command_detail_embed(command, guild=inter.guild)\nawait inter.response.send_message(embed=embed)\n

Returns:

Source code in src\\helply\\utils\\embeds.py
def command_detail_embed(\n    command: AppCommand,\n    *,\n    thumbnail: Optional[disnake.File] = None,\n    guild: Optional[disnake.Guild] = None,\n    color: Optional[disnake.Color] = None,\n) -> disnake.Embed:\n\"\"\"Create and return an embed showing command details.\n\n    Parameters\n    ----------\n    command: AppCommand\n        The `AppCommand` retrieved from `AppCommandHelp.get_command_named`\n    thumbnail: disnake.File, optional\n        A `disnake.File` converted image to be set as the embed thumbnail.\n    guild: disnake.Guild, optional\n        Guild where this embed will be displayed. Used to convert\n        any role checks into role objects\n    color: disnake.Color, optional\n        Set the color the embed. Default is None\n\n    Examples\n    --------\n    ```py\n    from disnake.ext.app_command_help import AppCommandHelp, utils\n\n    ...\n    app_command_help = AppCommandHelp(bot)\n\n    ...\n    command = app_command_help.get_command_named(name)\n    embed = utils.command_detail_embed(command, guild=inter.guild)\n    await inter.response.send_message(embed=embed)\n    ```\n\n    Returns\n    -------\n    disnake.Embed\n        The created embed containing the command details.\n    \"\"\"\n    type_ = (\n        \"Slash Command Details\"\n        if isinstance(command, SlashCommand)\n        else \"User Command Details\"\n        if isinstance(command, UserCommand)\n        else \"Message Command Details\"\n    )\n\n    embed = disnake.Embed(description=f\"{command.mention}\\n{command.description}\", color=color)\n    embed.set_author(name=f'{type_} {\"(NSFW)\" if command.nsfw else \"\"}')\n    if thumbnail:\n        embed.set_thumbnail(file=thumbnail)\n\n    if command.checks.permissions:\n        permissions = \", \".join(command.checks.permissions)\n        embed.add_field(name=\"Required Permissions\", value=permissions, inline=True)\n\n    if command.checks.roles:\n        if guild:\n            roles = Helply.roles_from_checks(command.checks, guild)\n            role_checks = \", \".join(r.mention for r in roles)\n        else:\n            role_checks = \", \".join(str(check) for check in command.checks.roles)\n\n        roles_as_string = f\"**Required Roles**:\\n{role_checks}\"\n        embed.add_field(name=\"Required Role(s)\", value=roles_as_string, inline=True)\n\n    if isinstance(command, SlashCommand):\n        embed.set_footer(text=\"[ required ] | ( optional )\")\n        if command.args:\n            args = \"\\n\".join(f\"**{arg}**: *{arg.description}*\" for arg in command.args)\n            embed.add_field(name=\"Parameters\", value=args, inline=False)\n        else:\n            embed.add_field(name=\"Parameters\", value=\"None\", inline=True)\n\n    return embed\n
"},{"location":"reference/helply/utils/embeds/#helply.utils.embeds.commands_overview_embeds","title":"commands_overview_embeds(commands, *, thumbnail=None, max_field_chars=MAX_CHARS_PER_FIELD, max_fields=MAX_FIELDS_PER_EMBED, color=None)","text":"

Create and return one or more embeds containing all commands and descriptions.

Parameters:

Examples:

from disnake.ext.app_command_help import AppCommandHelp, utils\n\n...\napp_command_help = AppCommandHelp(bot)\n\n...\ncommands = app_command_help.get_all_commands(inter.guild)\nembeds = utils.commands_overview_embeds()\nawait inter.response.send_message(embeds=embeds)\n

Returns:

Source code in src\\helply\\utils\\embeds.py
def commands_overview_embeds(\n    commands: List[AppCommand],\n    *,\n    thumbnail: Optional[disnake.File] = None,\n    max_field_chars: int = MAX_CHARS_PER_FIELD,\n    max_fields: int = MAX_FIELDS_PER_EMBED,\n    color: Optional[disnake.Color] = None,\n) -> List[disnake.Embed]:\n\"\"\"Create and return one or more embeds containing all commands and descriptions.\n\n    Parameters\n    ----------\n    commands: List[AppCommand]\n        List of `AppCommand` received from `AppCommandHelp.get_all_commands`\n    thumbnail: disnake.File, optional\n        A `disnake.File` converted image to be set as the embed thumbnail.\n    max_field_chars: int\n        Max number of characters per embed field description, default is MAX_CHARS_PER_FIELD (1024)\n    max_fields: int\n        Max number of fields per embed. default is MAX_FIELDS_PER_EMBED (10)\n    color: disnake.Color, optional\n        Set the color the embed(s). Default is None\n    Examples\n    --------\n    ```py\n    from disnake.ext.app_command_help import AppCommandHelp, utils\n\n    ...\n    app_command_help = AppCommandHelp(bot)\n\n    ...\n    commands = app_command_help.get_all_commands(inter.guild)\n    embeds = utils.commands_overview_embeds()\n    await inter.response.send_message(embeds=embeds)\n    ```\n\n    Returns\n    ------\n    List[disnake.Embed]\n        A list of disnake.Embed containing an overview of the commands.\n    \"\"\"\n\n    if max_field_chars > MAX_CHARS_PER_FIELD:\n        max_field_chars = MAX_CHARS_PER_FIELD\n\n    if max_fields > MAX_FIELDS_PER_EMBED:\n        max_fields = MAX_FIELDS_PER_EMBED\n\n    embeds: List[disnake.Embed] = []\n    current_embed: Optional[disnake.Embed] = None\n    current_field: str = \"\"\n    current_field_chars: int = 0\n\n    for command in commands:\n        command_type = (\n            \"Slash Command\"\n            if isinstance(command, SlashCommand)\n            else \"User Command\"\n            if isinstance(command, UserCommand)\n            else \"Message Command\"\n        )\n\n        nsfw = \"*(NSFW)*\" if command.nsfw else \"\"\n\n        command_lines = (\n            f\"{command.mention} *({command_type})* {nsfw}\\n\" f\"{command.description}\\n\\n\"\n        )\n\n        if current_embed is None:\n            title = \"Commands Overview\" if not embeds else \"Commands Overview (continued)\"\n            current_embed = _create_base_embed(title, color, thumbnail)\n            current_field_chars = 0\n\n        if current_field_chars + len(command_lines) <= max_field_chars:\n            current_field += command_lines\n            current_field_chars += len(command_lines)\n        else:\n            current_embed.add_field(name=\"\\u200b\", value=current_field, inline=False)\n            current_field = command_lines\n            current_field_chars = len(command_lines)\n\n        if len(current_embed.fields) >= max_fields:\n            embeds.append(current_embed)\n            current_embed = None\n\n    if current_embed is not None:\n        current_embed.add_field(name=\"\\u200b\", value=current_field, inline=False)\n        embeds.append(current_embed)\n\n    return embeds\n
"},{"location":"reference/helply/utils/paginator/","title":"paginator","text":"

Provides a basic Paginator View to provide a clean interface for users to navigator your multiple command embeds.

Note

This can be used for pretty much any embeds, but is designed specifically to work with the list of embeds returned from embeds.all_commands_overview()

"},{"location":"reference/helply/utils/paginator/#helply.utils.paginator.Paginator","title":"Paginator","text":"

Bases: View

Provides a basic paginator that allows users to navigate over multiple embeds.

Inspired by the paginator.py example provided by disnake

Parameters:

Source code in src\\helply\\utils\\paginator.py
class Paginator(disnake.ui.View):\n\n\"\"\"Provides a basic paginator that allows users to navigate over multiple embeds.\n\n    Inspired by the paginator.py example provided by\n    [disnake](https://github.com/DisnakeDev/disnake/blob/stable/examples/views/button/paginator.py)\n\n    Parameters\n    ----------\n    embeds: List[disnake.Embed]\n        List of embeds that will be cycled through\n    user: disnake.User, optional\n        Include a user to prevent others from using buttons.\n    timeout: int, optional\n        Set the timeout for the `View` in seconds, default is 180.\n    \"\"\"\n\n    def __init__(\n        self,\n        *,\n        embeds: List[disnake.Embed],\n        user: Optional[disnake.Member] = None,\n        timeout: int = 180,\n    ) -> None:\n        super().__init__(timeout=timeout)\n        self.user = user\n        self.embeds = embeds\n        self.index = 0\n\n        self._update_state()\n\n    async def interaction_check(self, interaction: disnake.MessageInteraction) -> bool:\n\"\"\"A check that is performed when any button in this view is interacted with\n\n\n        Parameters\n        ----------\n        interaction: disnake.MessageInteraction\n            The interaction invoked by a button\n\n        Returns\n        -------\n        bool\n            True if the interaction check passes and the button callback should be invoked,\n            else False and the callback will not be invoked.\n        \"\"\"\n        if self.user and self.user.id != interaction.author.id:\n            await interaction.response.send_message(\n                \"You do not have permission to interact with this button.\", ephemeral=True\n            )\n            return False\n\n        return True\n\n    def _update_state(self) -> None:\n\"\"\"\n        Update the \"state\" of the view.\n\n        Enable/disable navigation buttons and update the disable counter component\n        \"\"\"\n        self._page_counter.label = f\"{self.index + 1} / {len(self.embeds)}\"\n        self._first_page.disabled = self._prev_page.disabled = self.index == 0\n        self._last_page.disabled = self._next_page.disabled = self.index == len(self.embeds) - 1\n\n    @disnake.ui.button(label=\"First Page\", style=disnake.ButtonStyle.primary)\n    async def _first_page(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Jump to the first embed\"\"\"\n        self.index = 0\n        self._update_state()\n\n        await inter.response.edit_message(embed=self.embeds[self.index], view=self)\n\n    @disnake.ui.button(label=\"Prev Page\", style=disnake.ButtonStyle.primary)\n    async def _prev_page(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Go back one page\"\"\"\n        self.index -= 1\n        self._update_state()\n\n        await inter.response.edit_message(embed=self.embeds[self.index], view=self)\n\n    @disnake.ui.button(label=\"\", style=disnake.ButtonStyle.primary, disabled=True)\n    async def _page_counter(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Just a page counter and cannot be interacted with\"\"\"\n\n    @disnake.ui.button(label=\"Next Page\", style=disnake.ButtonStyle.primary)\n    async def _next_page(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Go to next page\"\"\"\n        self.index += 1\n        self._update_state()\n\n        await inter.response.edit_message(embed=self.embeds[self.index], view=self)\n\n    @disnake.ui.button(label=\"Last Page\", style=disnake.ButtonStyle.primary)\n    async def _last_page(self, _, inter: disnake.MessageInteraction) -> None:\n\"\"\"Go to last page\"\"\"\n        self.index = len(self.embeds) - 1\n        self._update_state()\n\n        await inter.response.edit_message(embed=self.embeds[self.index], view=self)\n
"},{"location":"reference/helply/utils/paginator/#helply.utils.paginator.Paginator.interaction_check","title":"interaction_check(interaction) async","text":"

A check that is performed when any button in this view is interacted with

Parameters:

Returns:

Source code in src\\helply\\utils\\paginator.py
async def interaction_check(self, interaction: disnake.MessageInteraction) -> bool:\n\"\"\"A check that is performed when any button in this view is interacted with\n\n\n    Parameters\n    ----------\n    interaction: disnake.MessageInteraction\n        The interaction invoked by a button\n\n    Returns\n    -------\n    bool\n        True if the interaction check passes and the button callback should be invoked,\n        else False and the callback will not be invoked.\n    \"\"\"\n    if self.user and self.user.id != interaction.author.id:\n        await interaction.response.send_message(\n            \"You do not have permission to interact with this button.\", ephemeral=True\n        )\n        return False\n\n    return True\n
"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 19c700a..5d5e326 100755 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,62 +2,62 @@ https://dlchamp.github.io/helply/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/license/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/examples/advanced/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/examples/autocomplete/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/examples/extras/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/examples/simple/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/reference/helply/help/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/reference/helply/types/checks/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/reference/helply/types/commands/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/reference/helply/types/enums/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/reference/helply/utils/embeds/ - 2023-09-03 + 2023-09-04 daily https://dlchamp.github.io/helply/reference/helply/utils/paginator/ - 2023-09-03 + 2023-09-04 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 7199a6158da8396c799cae307743829b7dd99af2..145695410ad61be0cd34583a930e4de985579c64 100755 GIT binary patch literal 313 zcmV-90ml9xiwFp*E%jsq|8r?{Wo=<_E_iKh0M(YyZo?o9#_xTKh+e9ziVL9rTKt4q{2sCIQh zve8!c(ha;bsUMHr1kr;X>>_Hhw%y;7m|W29uG&47)xNBrspY2KwUM3g;1uDj)za9d z7I(@ONBr{qiOd=W9^rurVJ6uE3aQW1E6`c6jwz_H)+vkG!ki*K_Y6qUtoeaSBb*@8 z=7Aq!O*!$VWuQ6J0#u)vA$M?2dYvIT_|avBJtkub+Z{n?$UVr;c$q@{fAmYDUq|~5 LywE=Ar3e53Qf8V+ literal 312 zcmV-80muFyiwFoM1@&YC|8r?{Wo=<_E_iKh0M(YyZo?o9#_xTKDEC0xUe+m1Z+n96 z0Vuc$8hx%_sBeCkt6Lr`ej~3IVlu$8yW+vH&N&(ylv}AMbC~ zOL=NH%@_dv%M(c-bZw zBpYR9FYLfN9sBXjwC6pT!7RMtscn5rV6O)oUspX-q+Q`mza0&3$DxuBN z@Rf4M;lDh8A~RZoLwI6Bm`OH(T&SyX5>ytfWAxIeI%Y9jm}8*lo&hQ9l%JS1zy$(r z9{3Sb%855F1I?Khp!~!PxxKZ*sSL@%jW#RnF=|8D_6#aR?m=|giRi=squ&z!I@)h5 K2FsbH2mk