Example #1
0
    async def format_cog_help(self, ctx: Context, obj: commands.Cog, help_settings: HelpSettings):
        coms = await self.get_cog_help_mapping(ctx, obj, help_settings=help_settings)
        if not (coms or help_settings.verify_exists):
            return

        description = obj.format_help_for_context(ctx)
        tagline = (help_settings.tagline) or self.get_default_tagline(ctx)

        if await ctx.embed_requested():
            emb = {
                "embed": {"title": "", "description": ""},
                "footer": {"text": ""},
                "fields": [],
            }

            emb["footer"]["text"] = tagline
            if description:
                splitted = description.split("\n\n")
                name = splitted[0]
                value = "\n\n".join(splitted[1:])
                if not value:
                    value = EMPTY_STRING
                field = EmbedField(f"{name[:252]}", value[:1024], False)
                emb["fields"].append(field)

            if coms:

                def shorten_line(a_line: str) -> str:
                    if len(a_line) < 70:  # embed max width needs to be lower
                        return a_line
                    return a_line[:67] + "..."

                spacing = len(max(coms.keys(), key=len))
                command_text = "\n".join(
                    shorten_line(f"`{name:<{spacing}}:`{command.format_shortdoc_for_context(ctx)}")
                    for name, command in sorted(coms.items())
                )
                for i, page in enumerate(pagify(command_text, page_length=500, shorten_by=0)):
                    if i == 0:
                        title = _("**__Commands:__**")
                    else:
                        title = _("**__Commands:__** (continued)")
                    field = EmbedField(title, page, False)
                    emb["fields"].append(field)

            pages = await self.make_embeds(ctx, emb, help_settings=help_settings)
            await self.send_pages(ctx, pages, embed=True, help_settings=help_settings)
        else:
            await ctx.send("Enable embeds pls")
Example #2
0
    async def format_bot_help(self,
                              ctx: Context,
                              help_settings: HelpSettings,
                              get_pages: bool = False):
        if await ctx.embed_requested():
            emb = await self.embed_template(help_settings, ctx,
                                            ctx.bot.description)
            filtered_categories = await self.filter_categories(
                ctx, GLOBAL_CATEGORIES)
            for i in pagify(
                    "\n".join(
                        f"{str(cat.reaction) if cat.reaction else ''} `{ctx.clean_prefix}help {cat.name:<10}:`**{cat.desc}**\n"
                        for cat in filtered_categories if cat.cogs),
                    page_length=1018,
            ):
                emb["fields"].append(EmbedField("Categories:", i, False))

            pages = await self.make_embeds(ctx,
                                           emb,
                                           help_settings=help_settings)
            if get_pages:
                return pages
            else:
                await self.send_pages(
                    ctx,
                    pages,
                    embed=True,
                    help_settings=help_settings,
                    add_emojis=((await self.config.settings())["react"])
                    and True,
                    emoji_mapping=filtered_categories,
                )
        else:
            await ctx.send(_("You need to enable embeds to use the help menu"))
Example #3
0
    async def format_command_help(self, ctx: Context, obj: commands.Command,
                                  help_settings: HelpSettings):

        send = help_settings.verify_exists
        if not send:
            async for __ in self.help_filter_func(ctx, (obj, ),
                                                  bypass_hidden=True,
                                                  help_settings=help_settings):
                send = True

        if not send:
            return

        command = obj

        description = command.description or ""

        signature = _(
            "`Syntax: {ctx.clean_prefix}{command.qualified_name} {command.signature}`"
        ).format(ctx=ctx, command=command)
        subcommands = None

        if hasattr(command, "all_commands"):
            grp = cast(commands.Group, command)
            subcommands = await self.get_group_help_mapping(
                ctx, grp, help_settings=help_settings)

        if await ctx.embed_requested():
            emb = await self.embed_template(help_settings, ctx)

            if description:
                emb["embed"]["title"] = f"{description[:250]}"

            emb["embed"]["description"] = signature

            command_help = command.format_help_for_context(ctx)
            if command_help:
                splitted = command_help.split("\n\n")
                name = splitted[0]
                value = "\n\n".join(splitted[1:])
                if not value:
                    value = EMPTY_STRING
                field = EmbedField("Description",
                                   name[:250] + "\n" + value[:1024], False)
                emb["fields"].append(field)

                if alias := get_aliases(command, ctx.invoked_with):
                    emb["fields"].append(
                        EmbedField("Aliases", ",".join(alias), False))

                if final_perms := get_perms(command):
                    emb["fields"].append(
                        EmbedField("Permissions", final_perms, False))

                if cooldowns := get_cooldowns(command):
                    emb["fields"].append(
                        EmbedField("Cooldowns", "\n".join(cooldowns), False))
Example #4
0
    async def format_cog_help(self, ctx: Context, obj: commands.Cog,
                              help_settings: HelpSettings):
        coms = await self.get_cog_help_mapping(ctx,
                                               obj,
                                               help_settings=help_settings)
        if not (coms or help_settings.verify_exists):
            return

        if await ctx.embed_requested():
            emb = await self.embed_template(help_settings, ctx,
                                            obj.format_help_for_context(ctx))

            if coms:
                spacing = len(max(coms.keys(), key=len))
                command_text = "\n".join(
                    shorten_line(
                        f"`{name:<{spacing}}:`{command.format_shortdoc_for_context(ctx)}"
                    ) for name, command in sorted(coms.items()))
                for i, page in enumerate(
                        pagify(command_text, page_length=500, shorten_by=0)):
                    if i == 0:
                        title = _("**__Commands:__**")
                    else:
                        title = _("**__Commands:__** (continued)")
                    field = EmbedField(title, page, False)
                    emb["fields"].append(field)

            pages = await self.make_embeds(ctx,
                                           emb,
                                           help_settings=help_settings)
            await self.send_pages(ctx,
                                  pages,
                                  embed=True,
                                  help_settings=help_settings)
        else:
            await ctx.send(_("You need to enable embeds to use the help menu"))
Example #5
0
    async def send_pages(
        self,
        ctx: Context,
        pages: List[Union[str, discord.Embed]],
        embed: bool = True,
        help_settings: HelpSettings = None,
        add_emojis: bool = False,
    ):
        """
        Sends pages based on settings.
        """

        # save on config calls
        channel_permissions = ctx.channel.permissions_for(ctx.me)

        if not (channel_permissions.add_reactions and help_settings.use_menus):

            max_pages_in_guild = help_settings.max_pages_in_guild
            use_DMs = len(pages) > max_pages_in_guild
            destination = ctx.author if use_DMs else ctx.channel
            delete_delay = help_settings.delete_delay
            messages: List[discord.Message] = []
            for page in pages:
                try:
                    if embed:
                        msg = await destination.send(embed=page)
                    else:
                        msg = await destination.send(page)
                except discord.Forbidden:
                    return await ctx.send(
                        _(
                            "I couldn't send the help message to you in DM. "
                            "Either you blocked me or you disabled DMs in this server."
                        )
                    )
                else:
                    messages.append(msg)
            if use_DMs and help_settings.use_tick:
                await ctx.tick()
            # The if statement takes into account that 'destination' will be
            # the context channel in non-DM context, reusing 'channel_permissions' to avoid
            # computing the permissions twice.
            if (
                not use_DMs  # we're not in DMs
                and delete_delay > 0  # delete delay is enabled
                and channel_permissions.manage_messages  # we can manage messages here
            ):

                # We need to wrap this in a task to not block after-sending-help interactions.
                # The channel has to be TextChannel as we can't bulk-delete from DMs
                async def _delete_delay_help(
                    channel: discord.TextChannel,
                    messages: List[discord.Message],
                    delay: int,
                ):
                    await asyncio.sleep(delay)
                    await mass_purge(messages, channel)

                asyncio.create_task(_delete_delay_help(destination, messages, delete_delay))
        else:
            # Specifically ensuring the menu's message is sent prior to returning
            # m = await (ctx.send(embed=pages[0]) if embed else ctx.send(pages[0]))
            trans = {
                "left": prev_page,
                "cross": close_menu,
                "right": next_page,
            }
            final_menu = get_menu()(ListPages(pages))
            for thing in trans:
                final_menu.add_button(trans[thing](ARROWS[thing]))
            # TODO important!
            if add_emojis:
                # Adding additional category emojis , regex from dpy server
                for cat in GLOBAL_CATEGORIES:
                    if cat.reaction:
                        if await self.blacklist(ctx, cat.name):
                            final_menu.add_button(
                                await react_page(ctx, cat.reaction, help_settings)
                            )
                final_menu.add_button(await home_page(ctx, ARROWS["home"], help_settings))
            await final_menu.start(ctx)
Example #6
0
    async def make_embeds(
        self,
        ctx,
        embed_dict: dict,
        help_settings: HelpSettings,
    ):
        """Returns Embed pages (Really copy paste from core)"""
        pages = []
        thumbnail_url = await self.config.settings.thumbnail()
        page_char_limit = help_settings.page_char_limit
        page_char_limit = min(page_char_limit, 5500)
        author_info = {
            "name": _("{ctx.me.display_name} Help Menu").format(ctx=ctx),
            "icon_url": ctx.me.avatar_url,
        }
        offset = len(author_info["name"]) + 20
        foot_text = embed_dict["footer"]["text"]
        if foot_text:
            offset += len(foot_text)
        offset += len(embed_dict["embed"]["description"])
        offset += len(embed_dict["embed"]["title"])
        if page_char_limit + offset > 5500:
            page_char_limit = 5500 - offset
        elif page_char_limit < 250:
            page_char_limit = 250

        field_groups = self.group_embed_fields(embed_dict["fields"], page_char_limit)

        color = await ctx.embed_color()
        page_count = len(field_groups)

        if not field_groups:  # This can happen on single command without a docstring
            embed = discord.Embed(color=color, **embed_dict["embed"])
            embed.set_author(**author_info)
            embed.set_footer(**embed_dict["footer"])
            if thumbnail_url:
                embed.set_thumbnail(url=thumbnail_url)
            pages.append(embed)

        for i, group in enumerate(field_groups, 1):
            embed = discord.Embed(color=color, **embed_dict["embed"])

            if page_count > 1:
                description = _("*Page {page_num} of {page_count}*\n{content_description}").format(
                    content_description=embed.description,
                    page_num=i,
                    page_count=page_count,
                )
                embed.description = description

            embed.set_author(**author_info)

            for field in group:
                embed.add_field(**field._asdict())

            embed.set_footer(**embed_dict["footer"])
            if thumbnail_url:
                embed.set_thumbnail(url=thumbnail_url)
            pages.append(embed)

        return pages
Example #7
0
    async def format_command_help(
        self, ctx: Context, obj: commands.Command, help_settings: HelpSettings
    ):

        send = help_settings.verify_exists
        if not send:
            async for __ in self.help_filter_func(
                ctx, (obj,), bypass_hidden=True, help_settings=help_settings
            ):
                send = True

        if not send:
            return

        command = obj

        description = command.description or ""

        tagline = (help_settings.tagline) or self.get_default_tagline(ctx)
        signature = _(
            "`Syntax: {ctx.clean_prefix}{command.qualified_name} {command.signature}`"
        ).format(ctx=ctx, command=command)
        subcommands = None

        if hasattr(command, "all_commands"):
            grp = cast(commands.Group, command)
            subcommands = await self.get_group_help_mapping(ctx, grp, help_settings=help_settings)

        if await ctx.embed_requested():
            emb = {
                "embed": {"title": "", "description": ""},
                "footer": {"text": ""},
                "fields": [],
            }

            if description:
                emb["embed"]["title"] = f"*{description[:250]}*"

            emb["footer"]["text"] = tagline
            emb["embed"]["description"] = signature

            command_help = command.format_help_for_context(ctx)
            if command_help:
                splitted = command_help.split("\n\n")
                name = splitted[0]
                value = "\n\n".join(splitted[1:])
                if not value:
                    value = EMPTY_STRING
                field = EmbedField("Description", name[:250] + "\n" + value[:1024], False)
                emb["fields"].append(field)

                # Add aliases
                if alias := command.aliases:
                    if ctx.invoked_with in alias:
                        alias.remove(ctx.invoked_with)
                        alias.append(command.name)
                    emb["fields"].append(EmbedField("Aliases", ",".join(alias), False))

                # Add permissions
                get_list = ["user_perms", "bot_perms"]
                final_perms = []
                neat_format = lambda x: " ".join(
                    i.capitalize() for i in x.replace("_", " ").split()
                )
                for thing in get_list:
                    if perms := getattr(command.requires, thing):
                        perms_list = [
                            neat_format(i) for i, j in perms if j
                        ]  # TODO pls learn more to fix this
                        if perms_list:
                            final_perms += perms_list
                if perms := command.requires.privilege_level:
                    if perms.name != "NONE":
                        final_perms.append(neat_format(perms.name))
Example #8
0
            if subcommands:

                def shorten_line(a_line: str) -> str:
                    if len(a_line) < 70:  # embed max width needs to be lower
                        return a_line
                    return a_line[:67] + ".."

                spacing = len(max(subcommands.keys(), key=len))
                subtext = "\n" + "\n".join(
                    shorten_line(f"`{name:<{spacing}}:`{command.format_shortdoc_for_context(ctx)}")
                    for name, command in sorted(subcommands.items())
                )
                for i, page in enumerate(pagify(subtext, page_length=500, shorten_by=0)):
                    if i == 0:
                        title = _("**__Subcommands:__**")
                    else:
                        title = EMPTY_STRING
                    field = EmbedField(title, page, False)
                    emb["fields"].append(field)
            pages = await self.make_embeds(ctx, emb, help_settings=help_settings)
            await self.send_pages(ctx, pages, embed=True, help_settings=help_settings)
        else:
            await ctx.send("Enable embeds pls")

    async def format_bot_help(
        self, ctx: Context, help_settings: HelpSettings, get_pages: bool = False
    ):
        description = ctx.bot.description or ""
        tagline = (help_settings.tagline) or self.get_default_tagline(ctx)
        if not await ctx.embed_requested():  # Maybe redirect to non-embed minimal format
Example #9
0
                field = EmbedField(title, page, False)
                emb["fields"].append(field)
                title = EMPTY_STRING

            pages = await self.make_embeds(ctx,
                                           emb,
                                           help_settings=help_settings)
            if get_pages:
                return pages
            else:
                await self.send_pages(ctx,
                                      pages,
                                      embed=True,
                                      help_settings=help_settings)
        else:
            await ctx.send(_("You need to enable embeds to use the help menu"))

    async def format_cog_help(self, ctx: Context, obj: commands.Cog,
                              help_settings: HelpSettings):
        coms = await self.get_cog_help_mapping(ctx,
                                               obj,
                                               help_settings=help_settings)
        if not (coms or help_settings.verify_exists):
            return

        if await ctx.embed_requested():
            emb = await self.embed_template(help_settings, ctx,
                                            obj.format_help_for_context(ctx))

            if coms:
                spacing = len(max(coms.keys(), key=len))