Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d9dbba3
feat: embedded help command
H4ckerxx44 Jul 9, 2022
63609fa
remove: unused imports
H4ckerxx44 Jul 9, 2022
62616a5
style: auto fixes from pre-commit hooks
pre-commit-ci[bot] Jul 9, 2022
832433c
docs: add EmbeddedHelpCommand
H4ckerxx44 Jul 9, 2022
44ba503
Merge branch 'embedded_help_command' of https://github.com/H4ckerxx44…
H4ckerxx44 Jul 9, 2022
9029359
refactor: wording
H4ckerxx44 Jul 9, 2022
1ca3fc3
remove: TYPE_CHECKING import with associated if statement
H4ckerxx44 Jul 10, 2022
9d2219a
fix: make EmbeddedHelpCommand directly importable
H4ckerxx44 Jul 13, 2022
4562fc4
fix: only add "bare" commands field if there are any
H4ckerxx44 Jul 13, 2022
5562733
fix: use command.help instead
H4ckerxx44 Jul 13, 2022
98024d3
feat: Overhauled version of EmbeddedHelpCommand
H4ckerxx44 Jul 14, 2022
2e14504
refactor: use proper naming
H4ckerxx44 Jul 14, 2022
5c69c1a
feat: have an additional fallback to .brief if .help is not found
H4ckerxx44 Jul 14, 2022
7a3b1fa
feat: show all commands on help <cog>, it's helpful after all
H4ckerxx44 Jul 14, 2022
4d2f944
docs: Add docstring for EmbeddedHelpCommand
H4ckerxx44 Jul 17, 2022
a05d40c
refactor: switch from **options to explicit definitions
H4ckerxx44 Jul 17, 2022
fb932f1
remove: self.options no longer exist
H4ckerxx44 Jul 17, 2022
0b0cc15
fix: grammar and missing linebreak, thanks ethan
H4ckerxx44 Jul 17, 2022
1265fda
fix: correct linebreaks
H4ckerxx44 Jul 17, 2022
2b861d7
fix: Implement suggested changes
H4ckerxx44 Jul 22, 2022
814bb20
style: auto fixes from pre-commit hooks
pre-commit-ci[bot] Jul 22, 2022
966b4e9
style: put each item in __all__ on separate line
H4ckerxx44 Jul 22, 2022
d5455b6
docs: adjust docstring
H4ckerxx44 Jul 22, 2022
a7ceb9b
refactor: Sub-Commans -> subcommands
H4ckerxx44 Jul 24, 2022
c7da551
refactor: Cog-Commands --> commands
H4ckerxx44 Jul 24, 2022
6f3cb26
fix: do not put "optional" and "required" in backticks
H4ckerxx44 Jul 27, 2022
37a5024
Merge remote-tracking branch 'origin/embedded_help_command' into embe…
H4ckerxx44 Jul 27, 2022
cc637c4
fix: escape docstring linebreak, add period to first sentence
H4ckerxx44 Jul 30, 2022
0ce7a86
refactor: include more readable suggestion from tea
H4ckerxx44 Aug 8, 2022
977f22d
fix: only docs need 4 backslashes
H4ckerxx44 Aug 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/ext/help_commands/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ PaginatedHelpCommand
.. autoclass:: PaginatedHelpCommand
:members:

EmbeddedHelpCommand
~~~~~~~~~~~~~~~~~~~~

.. autoclass:: EmbeddedHelpCommand
:members:

Exceptions
----------
Expand Down
2 changes: 2 additions & 0 deletions nextcord/ext/help_commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .embedded import EmbeddedHelpCommand
from .errors import MissingDependencyError
from .paginated import PaginatedHelpCommand

Expand All @@ -7,4 +8,5 @@
__all__ = (
"MissingDependencyError",
"PaginatedHelpCommand",
"EmbeddedHelpCommand",
)
190 changes: 190 additions & 0 deletions nextcord/ext/help_commands/embedded.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
from typing import Mapping, Optional, Union

from nextcord import Embed, Message
from nextcord.ext import commands


class EmbeddedHelpCommand(commands.HelpCommand):
"""A help command implementation using embeds.
This inherits from :class:`HelpCommand`.
It extends it with the following attributes.

Attributes
------------
dm_help: :class:`bool`
A bool that indicates if the output should only be sent via DM instead of the channel.
Defaults to False.
default_color: :class:`int`
The default color of all embeds.
Defaults to 0xFFFFFF (White).
main_embed_title: :class:`str`
The title for the embed which gets sent by invoking `help`.
Defaults to "Overview about Cogs, Groups and Commands".
main_embed_description: Optional[:class:`str`]
The description for the embed which gets sent by invoking `help`.
main_embed_color: Optional[:class:`int`]
The color for the embed which gets sent by invoking `help`.
Defaults to default_color.
command_embed_title: :class:`str`
The title for the embed which gets sent by `help <command>`.
Defaults to "Command help".
command_embed_description: :class:`str`
The description for the embed which gets sent by invoking `help <command>`.
Defaults to "If a parameter is surrounded by `<>`, it is a required parameter\\\\nIf a parameter is surrounded by `[]`, it is an optional parameter."
command_embed_color: Optional[:class:`int`]
The color for the embed which gets sent by invoking `help <command>`.
Defaults to default_color.
group_embed_title: :class:`str`
The title for the embed which gets sent by invoking `help <group>`.
Defaults to "Group help".
group_embed_description: Optional[:class:`str`]
The description for the embed which gets sent by invoking `help <group>`.
group_embed_color: Optional[:class:`int`]
The color for the embed which gets sent by invoking `help <group>`.
Defaults to default_color.
cog_embed_title: :class:`str`
The title for the embed which gets sent by invoking `help <cog>`.
Defaults to "Cog help".
cog_embed_description: Optional[:class:`str`]
The description for the embed which gets sent by invoking `help <cog>`.
cog_embed_color: Optional[:class:`int`]
The color for the embed which gets sent by invoking `help <cog>`.
Defaults to default_color.
"""

def __init__(
self,
*,
dm_help: bool = False,
default_color: int = 0xFFFFFF,
main_embed_title: str = "Overview about Cogs, Groups and Commands",
main_embed_description: Optional[str] = None,
main_embed_color: Optional[int] = None,
command_embed_title: str = "Command help",
command_embed_description: str = "If a parameter is surrounded by `<>`, it is a required parameter. \nIf a parameter is surrounded by `[]`, it is an optional parameter.",
command_embed_color: Optional[int] = None,
group_embed_title: str = "Group help",
group_embed_description: Optional[str] = None,
group_embed_color: Optional[int] = None,
cog_embed_title: str = "Cog help",
cog_embed_description: Optional[str] = None,
cog_embed_color: Optional[int] = None,
):

self.dm_help = dm_help
self.default_color = default_color

self.main_embed_title = main_embed_title
self.main_embed_description = main_embed_description
self.main_embed_color = main_embed_color or self.default_color

self.command_embed_title = command_embed_title
self.command_embed_description = command_embed_description
self.command_embed_color = command_embed_color or self.default_color

self.group_embed_title = group_embed_title
self.group_embed_description = group_embed_description
self.group_embed_color = group_embed_color or self.default_color

self.cog_embed_title = cog_embed_title
self.cog_embed_description = cog_embed_description
self.cog_embed_color = cog_embed_color or self.default_color

super().__init__()

@staticmethod
def determine_group_or_command(obj: Union[commands.Command, commands.Group]):
return f"`{obj.name}[group]`" if isinstance(obj, commands.Group) else f"`{obj.name}`"

async def send_embed(self, emb: Embed):
if self.dm_help:
return await self.context.author.send(embed=emb)
return await self.context.send(embed=emb)

# help
async def send_bot_help(self, mapping: Mapping) -> Message:
total_command_count = len(self.context.bot.commands)
main_embed = Embed(
title=self.main_embed_title,
description=self.main_embed_description,
color=self.main_embed_color,
)

bare_cmd_list = " ".join(
self.determine_group_or_command(bare_cmd)
for bare_cmd in self.context.bot.commands
if not bare_cmd.cog
)
if bare_cmd_list:
bare_cmd_count = len(
[bare_cmd.name for bare_cmd in self.context.bot.commands if not bare_cmd.cog]
)
main_embed.add_field(name=f"Bare [{bare_cmd_count}]", value=bare_cmd_list, inline=False)

for cog in self.context.bot.cogs:
cog = self.context.bot.get_cog(cog)
cog_cmds = cog.get_commands()
cog_cmd_list = " ".join(self.determine_group_or_command(cmd) for cmd in cog_cmds)
if cog_cmd_list:
main_embed.add_field(
name=f"**{cog.qualified_name} Commands [{len(cog_cmds)}]:**",
value=cog_cmd_list,
inline=False,
)
main_embed.set_footer(text=f"{total_command_count} Commands")
return await self.send_embed(main_embed)

# help <command>
async def send_command_help(self, command: commands.Command) -> Message:
syntax = f"{self.context.clean_prefix}{command.qualified_name} {command.signature}"
command_embed = Embed(
title=self.command_embed_title,
description=self.command_embed_description,
color=self.command_embed_color,
)
command_embed.add_field(
name=syntax,
value=f"`{command.help or command.brief or 'No description provided.'}`",
inline=False,
)

return await self.send_embed(command_embed)

# help <group>
async def send_group_help(self, group: commands.Group) -> Message:
group_embed = Embed(
title=self.group_embed_title,
description=self.group_embed_description,
color=self.group_embed_color,
)

for sub_command in group.walk_commands():
syntax = f"{self.context.clean_prefix}{group.qualified_name} {sub_command.name} {sub_command.signature}"
group_embed.add_field(
name=syntax,
value=f"`{sub_command.help or sub_command.brief or 'No description provided.'}`",
inline=False,
)
group_embed.set_footer(text=f"{len(group.commands)} subcommands")
return await self.send_embed(group_embed)

# help <cog>
async def send_cog_help(self, cog: commands.Cog) -> Message:
cog_embed = Embed(
title=self.cog_embed_title,
description=self.cog_embed_description,
color=self.cog_embed_color,
)

cog_cmds = cog.get_commands()
for command in cog.walk_commands():
if not command.parent:
syntax = f"{self.context.clean_prefix}{command.qualified_name} {command.signature}"
cog_embed.add_field(
name=syntax,
value=f"`{command.help or command.brief or 'No description provided.'}`",
inline=False,
)

cog_embed.set_footer(text=f"{len(cog_cmds)} commands")
return await self.send_embed(cog_embed)