Skip to content

Commit a5e5cc2

Browse files
H4ckerxx44MaskDuckteaishealthypre-commit-ci[bot]
authored
feat: embedded help command (#4)
Co-authored-by: MaskDuck <[email protected]> Co-authored-by: teaishealthy <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent ce9e029 commit a5e5cc2

File tree

3 files changed

+197
-0
lines changed

3 files changed

+197
-0
lines changed

docs/ext/help_commands/api.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ PaginatedHelpCommand
1616
.. autoclass:: PaginatedHelpCommand
1717
:members:
1818

19+
EmbeddedHelpCommand
20+
~~~~~~~~~~~~~~~~~~~~
21+
22+
.. autoclass:: EmbeddedHelpCommand
23+
:members:
1924

2025
Exceptions
2126
----------

nextcord/ext/help_commands/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from .embedded import EmbeddedHelpCommand
12
from .errors import MissingDependencyError
23
from .paginated import PaginatedHelpCommand
34

@@ -7,4 +8,5 @@
78
__all__ = (
89
"MissingDependencyError",
910
"PaginatedHelpCommand",
11+
"EmbeddedHelpCommand",
1012
)
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
from typing import Mapping, Optional, Union
2+
3+
from nextcord import Embed, Message
4+
from nextcord.ext import commands
5+
6+
7+
class EmbeddedHelpCommand(commands.HelpCommand):
8+
"""A help command implementation using embeds.
9+
This inherits from :class:`HelpCommand`.
10+
It extends it with the following attributes.
11+
12+
Attributes
13+
------------
14+
dm_help: :class:`bool`
15+
A bool that indicates if the output should only be sent via DM instead of the channel.
16+
Defaults to False.
17+
default_color: :class:`int`
18+
The default color of all embeds.
19+
Defaults to 0xFFFFFF (White).
20+
main_embed_title: :class:`str`
21+
The title for the embed which gets sent by invoking `help`.
22+
Defaults to "Overview about Cogs, Groups and Commands".
23+
main_embed_description: Optional[:class:`str`]
24+
The description for the embed which gets sent by invoking `help`.
25+
main_embed_color: Optional[:class:`int`]
26+
The color for the embed which gets sent by invoking `help`.
27+
Defaults to default_color.
28+
command_embed_title: :class:`str`
29+
The title for the embed which gets sent by `help <command>`.
30+
Defaults to "Command help".
31+
command_embed_description: :class:`str`
32+
The description for the embed which gets sent by invoking `help <command>`.
33+
Defaults to "If a parameter is surrounded by `<>`, it is a required parameter\\\\nIf a parameter is surrounded by `[]`, it is an optional parameter."
34+
command_embed_color: Optional[:class:`int`]
35+
The color for the embed which gets sent by invoking `help <command>`.
36+
Defaults to default_color.
37+
group_embed_title: :class:`str`
38+
The title for the embed which gets sent by invoking `help <group>`.
39+
Defaults to "Group help".
40+
group_embed_description: Optional[:class:`str`]
41+
The description for the embed which gets sent by invoking `help <group>`.
42+
group_embed_color: Optional[:class:`int`]
43+
The color for the embed which gets sent by invoking `help <group>`.
44+
Defaults to default_color.
45+
cog_embed_title: :class:`str`
46+
The title for the embed which gets sent by invoking `help <cog>`.
47+
Defaults to "Cog help".
48+
cog_embed_description: Optional[:class:`str`]
49+
The description for the embed which gets sent by invoking `help <cog>`.
50+
cog_embed_color: Optional[:class:`int`]
51+
The color for the embed which gets sent by invoking `help <cog>`.
52+
Defaults to default_color.
53+
"""
54+
55+
def __init__(
56+
self,
57+
*,
58+
dm_help: bool = False,
59+
default_color: int = 0xFFFFFF,
60+
main_embed_title: str = "Overview about Cogs, Groups and Commands",
61+
main_embed_description: Optional[str] = None,
62+
main_embed_color: Optional[int] = None,
63+
command_embed_title: str = "Command help",
64+
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.",
65+
command_embed_color: Optional[int] = None,
66+
group_embed_title: str = "Group help",
67+
group_embed_description: Optional[str] = None,
68+
group_embed_color: Optional[int] = None,
69+
cog_embed_title: str = "Cog help",
70+
cog_embed_description: Optional[str] = None,
71+
cog_embed_color: Optional[int] = None,
72+
):
73+
74+
self.dm_help = dm_help
75+
self.default_color = default_color
76+
77+
self.main_embed_title = main_embed_title
78+
self.main_embed_description = main_embed_description
79+
self.main_embed_color = main_embed_color or self.default_color
80+
81+
self.command_embed_title = command_embed_title
82+
self.command_embed_description = command_embed_description
83+
self.command_embed_color = command_embed_color or self.default_color
84+
85+
self.group_embed_title = group_embed_title
86+
self.group_embed_description = group_embed_description
87+
self.group_embed_color = group_embed_color or self.default_color
88+
89+
self.cog_embed_title = cog_embed_title
90+
self.cog_embed_description = cog_embed_description
91+
self.cog_embed_color = cog_embed_color or self.default_color
92+
93+
super().__init__()
94+
95+
@staticmethod
96+
def determine_group_or_command(obj: Union[commands.Command, commands.Group]):
97+
return f"`{obj.name}[group]`" if isinstance(obj, commands.Group) else f"`{obj.name}`"
98+
99+
async def send_embed(self, emb: Embed):
100+
if self.dm_help:
101+
return await self.context.author.send(embed=emb)
102+
return await self.context.send(embed=emb)
103+
104+
# help
105+
async def send_bot_help(self, mapping: Mapping) -> Message:
106+
total_command_count = len(self.context.bot.commands)
107+
main_embed = Embed(
108+
title=self.main_embed_title,
109+
description=self.main_embed_description,
110+
color=self.main_embed_color,
111+
)
112+
113+
bare_cmd_list = " ".join(
114+
self.determine_group_or_command(bare_cmd)
115+
for bare_cmd in self.context.bot.commands
116+
if not bare_cmd.cog
117+
)
118+
if bare_cmd_list:
119+
bare_cmd_count = len(
120+
[bare_cmd.name for bare_cmd in self.context.bot.commands if not bare_cmd.cog]
121+
)
122+
main_embed.add_field(name=f"Bare [{bare_cmd_count}]", value=bare_cmd_list, inline=False)
123+
124+
for cog in self.context.bot.cogs:
125+
cog = self.context.bot.get_cog(cog)
126+
cog_cmds = cog.get_commands()
127+
cog_cmd_list = " ".join(self.determine_group_or_command(cmd) for cmd in cog_cmds)
128+
if cog_cmd_list:
129+
main_embed.add_field(
130+
name=f"**{cog.qualified_name} Commands [{len(cog_cmds)}]:**",
131+
value=cog_cmd_list,
132+
inline=False,
133+
)
134+
main_embed.set_footer(text=f"{total_command_count} Commands")
135+
return await self.send_embed(main_embed)
136+
137+
# help <command>
138+
async def send_command_help(self, command: commands.Command) -> Message:
139+
syntax = f"{self.context.clean_prefix}{command.qualified_name} {command.signature}"
140+
command_embed = Embed(
141+
title=self.command_embed_title,
142+
description=self.command_embed_description,
143+
color=self.command_embed_color,
144+
)
145+
command_embed.add_field(
146+
name=syntax,
147+
value=f"`{command.help or command.brief or 'No description provided.'}`",
148+
inline=False,
149+
)
150+
151+
return await self.send_embed(command_embed)
152+
153+
# help <group>
154+
async def send_group_help(self, group: commands.Group) -> Message:
155+
group_embed = Embed(
156+
title=self.group_embed_title,
157+
description=self.group_embed_description,
158+
color=self.group_embed_color,
159+
)
160+
161+
for sub_command in group.walk_commands():
162+
syntax = f"{self.context.clean_prefix}{group.qualified_name} {sub_command.name} {sub_command.signature}"
163+
group_embed.add_field(
164+
name=syntax,
165+
value=f"`{sub_command.help or sub_command.brief or 'No description provided.'}`",
166+
inline=False,
167+
)
168+
group_embed.set_footer(text=f"{len(group.commands)} subcommands")
169+
return await self.send_embed(group_embed)
170+
171+
# help <cog>
172+
async def send_cog_help(self, cog: commands.Cog) -> Message:
173+
cog_embed = Embed(
174+
title=self.cog_embed_title,
175+
description=self.cog_embed_description,
176+
color=self.cog_embed_color,
177+
)
178+
179+
cog_cmds = cog.get_commands()
180+
for command in cog.walk_commands():
181+
if not command.parent:
182+
syntax = f"{self.context.clean_prefix}{command.qualified_name} {command.signature}"
183+
cog_embed.add_field(
184+
name=syntax,
185+
value=f"`{command.help or command.brief or 'No description provided.'}`",
186+
inline=False,
187+
)
188+
189+
cog_embed.set_footer(text=f"{len(cog_cmds)} commands")
190+
return await self.send_embed(cog_embed)

0 commit comments

Comments
 (0)