PyDrocsid/cogs

View on GitHub
information/help/cog.py

Summary

Maintainability
A
0 mins
Test Coverage
from typing import List, Optional, Union

from discord import Embed, Message
from discord.ext import commands
from discord.ext.commands import Command, CommandError, Context, Group

from PyDrocsid.cog import Cog, get_documentation
from PyDrocsid.command import can_run_command, docs, get_optional_permissions
from PyDrocsid.config import Contributor
from PyDrocsid.embeds import send_long_embed
from PyDrocsid.permission import BasePermission, BasePermissionLevel
from PyDrocsid.translations import t

from .colors import Colors


tg = t.g
t = t.help


async def send_help(ctx: Context, command_name: Optional[Union[str, Command]]) -> List[Message]:
    def format_command(cmd: Command) -> str:
        doc = " - " + cmd.short_doc if cmd.short_doc else ""
        return f"`{cmd.name}`{doc}"

    async def add_commands(cog_name: str, cmds: List[Command]):
        desc: List[str] = []
        for cmd in sorted(cmds, key=lambda c: c.name):
            if not cmd.hidden and await can_run_command(cmd, ctx):
                emoji = getattr(cmd._callback, "emoji", ":small_orange_diamond:")
                desc.append(emoji + " " + format_command(cmd))
        if desc:
            embed.add_field(name=cog_name, value="\n".join(desc), inline=False)

    embed = Embed(title=t.help, color=Colors.help)
    if command_name is None:
        for cog in sorted(ctx.bot.cogs.values(), key=lambda c: c.qualified_name):
            await add_commands(cog.qualified_name, cog.get_commands())
        await add_commands(t.no_category, [command for command in ctx.bot.commands if command.cog is None])

        embed.add_field(name="** **", value=t.help_usage(ctx.prefix), inline=False)

        return await send_long_embed(ctx, embed, paginate=True, max_fields=8)

    if isinstance(command_name, str):
        cog: Optional[Cog] = ctx.bot.get_cog(command_name)
        if cog is not None:
            await add_commands(cog.qualified_name, cog.get_commands())
            if doc_url := get_documentation(cog):
                embed.add_field(name=t.documentation, value=doc_url, inline=False)
            return await send_long_embed(ctx, embed)

        command: Optional[Union[Command, Group]] = ctx.bot.get_command(command_name)
        if command is None:
            raise CommandError(t.cog_or_command_not_found)
    else:
        command: Command = command_name

    if not await can_run_command(command, ctx):
        raise CommandError(tg.not_allowed)

    description = ctx.prefix
    if command.full_parent_name:
        description += command.full_parent_name + " "
    if command.aliases:
        description += "[" + "|".join([command.name] + command.aliases) + "] "
    else:
        description += command.name + " "
    description += command.signature

    embed.description = f"```css\n{description.strip()}\n```"
    embed.add_field(name=t.description, value=command.help, inline=False)

    if isinstance(command, Group):
        await add_commands(t.subcommands, command.commands)

    permissions: list[str] = []
    permission_levels: list[BasePermissionLevel] = []

    cmds = []
    cmd = command
    while cmd:
        cmds.append(cmd)
        cmd = cmd.parent

    for cmd in reversed(cmds):
        for check in cmd.checks:
            permission: Union[BasePermission, BasePermissionLevel, None] = getattr(check, "level", None)
            if isinstance(permission, BasePermission):
                permissions.append(permission.fullname)
            elif isinstance(permission, BasePermissionLevel):
                permission_levels.append(permission)

    if permissions:
        embed.add_field(
            name=t.required_permissions,
            value="\n".join(f":small_orange_diamond: `{p}`" for p in permissions),
            inline=False,
        )
    if permission_levels:
        permission_level: BasePermissionLevel = max(permission_levels, key=lambda pl: pl.level)
        if permission_level.level > 0:
            embed.add_field(
                name=t.required_permission_level,
                value=f":small_orange_diamond: **{permission_level.description}**",
                inline=False,
            )

    optional_permissions: list[str] = [permission.fullname for permission in get_optional_permissions(command)]
    if optional_permissions:
        embed.add_field(
            name=t.optional_permissions,
            value="\n".join(f":small_blue_diamond: `{p}`" for p in optional_permissions),
            inline=False,
        )

    if (doc_url := get_documentation(cmd.cog)) and not getattr(cmd.callback, "no_documentation", False):
        embed.add_field(name=t.documentation, value=doc_url, inline=False)

    return await send_long_embed(ctx, embed)


class HelpCog(Cog, name="Help"):
    CONTRIBUTORS = [Contributor.Defelo, Contributor.ce_phox]

    @commands.command()
    @docs(t.commands.help)
    async def help(self, ctx: Context, *, cog_or_command: Optional[str]):
        await send_help(ctx, cog_or_command)