This repository has been archived by the owner on Mar 14, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathhelp.py
252 lines (218 loc) · 10.6 KB
/
help.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
import logging
import discord
from discord.ext import commands
from classes.bot import SnedBot
from classes import components
from etc.help_menu_strings import help_menu_dropdown
logger = logging.getLogger(__name__)
class HelpView(components.AuthorOnlyView):
async def on_timeout(self):
for item in self.children:
item.disabled = True
await self.message.edit(view=self) # Disable timed out view
class HelpSelect(discord.ui.Select):
def __init__(self, cog_embeds: dict, *args, **kwargs):
super().__init__(*args, **kwargs)
self.cog_embeds = cog_embeds
async def callback(self, interaction: discord.Interaction):
for option in self.options:
if option.value == interaction.data["values"][0]:
option.default = True
else:
option.default = False
await interaction.response.edit_message(embed=self.cog_embeds[interaction.data["values"][0]], view=self.view)
class SnedHelp(commands.HelpCommand):
"""
The custom help command subclassing the dpy one.
See the docs or this guide (https://gist.github.com/InterStella0/b78488fb28cadf279dfd3164b9f0cf96) on how this was made.
"""
# Method to get information about a command to display in send_bot_help
def get_command_signature(self, ctx, command):
return "**`{prefix}{parent}{command}`** - {commandbrief}".format(
prefix=ctx.clean_prefix,
parent=command.full_parent_name,
command=command.name,
commandbrief=command.short_doc,
) # short_doc goes to brief first, otherwise gets first line of help
def get_subcommand_signature(
self, ctx, group, command
): # Essentially the same as get_command_signature but appends the group name in front of the command
return "**`{prefix}{group} {command}`** - {commandbrief}".format(
prefix=ctx.clean_prefix,
group=group.name,
command=command.name,
commandbrief=command.short_doc,
)
# Send generic help message with all commands included
async def send_bot_help(self, mapping):
ctx = self.context # Obtaining ctx
help_home_embed = discord.Embed(
title="🏠 " + "__Help Home__",
color=ctx.bot.embed_blue,
description="""**How to navigate this help dialogue**
Navigate to different sections of this help dialogue via the **dropdown** below!
If you need support, please join the [support server](https://discord.gg/KNKr8FPmJa)!
**Command Usage & Syntax**
`<argument>` is a __required__ parameter
`[argument]` is an __optional__ parameter
`<foo|bar>` means foo __OR__ bar
*Do not include the brackets in your commands!*
Thank you for using Sned!
""",
)
embed = ctx.bot.add_embed_footer(ctx, help_home_embed)
help_pages = []
help_pages.append(help_home_embed)
all_commands = {} # Key: cog_name, Value: all command_signatures for cog
cog_embeds = {} # Key: cog_name, Value: embed
# We retrieve all the commands from the mapping of cog,commands
select_options = []
for cog, cmds in mapping.items():
filtered = await self.filter_commands(
cmds, sort=True
) # This will filter commands to those the user can actually execute
command_signatures = [
self.get_command_signature(ctx, command) for command in filtered
] # Get command signature in format as specified above
# If we have any, put them in categories according to cogs, fallback is "Other"
if command_signatures:
cog_name = getattr(cog, "qualified_name", "Other") # Append items into a list of str, one item per cog
all_commands[cog_name] = "\n".join(command_signatures)
for cog_name in all_commands.keys():
emoji = (
help_menu_dropdown[cog_name]["emoji"]
if cog_name in help_menu_dropdown.keys()
and help_menu_dropdown[cog_name]["emoji"]
and isinstance(help_menu_dropdown[cog_name]["emoji"], str)
else "⚙️"
)
embed = discord.Embed(
title=f"{emoji} __Help Page for {cog_name}:__",
description="**Tip:** You can also type **`{prefix}help [command]`** to get more information about a specific command, see usage syntax, and see any subcommands a command may have.\n\n {commands}".format(
prefix=ctx.prefix, commands=all_commands[cog_name]
),
color=ctx.bot.embed_blue,
)
embed = ctx.bot.add_embed_footer(ctx, embed)
cog_embeds[cog_name] = embed
select_options.append(
discord.SelectOption(
label=cog_name,
value=cog_name,
description=help_menu_dropdown[cog_name]["description"]
if cog_name in help_menu_dropdown.keys()
else None,
emoji=help_menu_dropdown[cog_name]["emoji"] if cog_name in help_menu_dropdown.keys() else None,
)
)
view = HelpView(ctx)
view.add_item(HelpSelect(cog_embeds, placeholder="Select a category...", options=select_options))
view.message = await ctx.send(embed=help_home_embed, view=view)
async def send_command_help(self, command):
ctx = self.context
if command.parents:
detail_embed = discord.Embed(
title="⚙️ "
+ "Command: {prefix}{parent} {command}".format(
prefix=ctx.clean_prefix,
parent=command.full_parent_name,
command=command.name,
),
color=ctx.bot.embed_blue,
)
else:
detail_embed = discord.Embed(
title="⚙️ " + "Command: {prefix}{command}".format(prefix=ctx.clean_prefix, command=command.name),
color=ctx.bot.embed_blue,
)
if command.description:
detail_embed.add_field(name="Description:", value=command.description) # Getting command description
elif command.help:
detail_embed.add_field(
name="Description:", value=command.help
) # Fallback to help attribute if description does not exist
if command.usage:
detail_embed.add_field(
name="Usage:",
value=f"**`{ctx.clean_prefix}{command.usage}`**",
inline=False,
) # Getting command usage & formatting it
aliases = []
for alias in command.aliases:
if command.parents:
aliases.append(f"**`{ctx.clean_prefix}{command.full_parent_name} {alias}`**")
else:
aliases.append(f"**`{ctx.clean_prefix}{alias}`**") # Adding some custom formatting to each alias
if aliases:
detail_embed.add_field(
name="Aliases:", value=", ".join(aliases), inline=False
) # If any aliases exist, we add those to the embed in new field
detail_embed = ctx.bot.add_embed_footer(ctx, detail_embed)
channel = self.get_destination() # Send it to destination
await channel.send(embed=detail_embed)
async def send_cog_help(self, cog):
# I chose not to implement help for cogs, but if you want to do something, do it here
ctx = self.context
embed = discord.Embed(
title="❓ Unknown command!",
description="Use `{prefix}help` for a list of available commands.".format(prefix=ctx.prefix),
color=ctx.bot.unknown_color,
)
embed = ctx.bot.add_embed_footer(ctx, embed)
channel = self.get_destination()
await channel.send(embed=embed)
async def send_group_help(self, group):
ctx = self.context
group_embed = discord.Embed(
title="⚙️ " + "Group: {prefix}{group}".format(prefix=ctx.prefix, group=group.name),
description="**Note:**\nTo see detailed information about one of the subcommands, type **`{prefix}help {group} [subcommand]`**".format(
prefix=ctx.prefix, group=group.name
),
color=ctx.bot.embed_blue,
)
if group.description:
group_embed.add_field(name="Description:", value=group.description) # Getting command description
elif group.help:
group_embed.add_field(
name="Description:", value=group.help
) # Fallback to help attribute if description does not exist
if group.usage:
group_embed.add_field(
name="Usage:",
value=f"**`{ctx.clean_prefix}{group.usage}`**",
inline=False,
) # Getting command usage & formatting it
aliases = []
for alias in group.aliases:
aliases.append(f"**`{ctx.clean_prefix}{alias}`**") # Adding some custom formatting to each alias
if aliases:
group_embed.add_field(
name="Aliases:", value=", ".join(aliases), inline=False
) # If any aliases exist, we add those to the embed in new field
sub_cmds = []
filtered = await self.filter_commands(group.walk_commands(), sort=True)
for command in filtered:
sub_cmds.append(self.get_subcommand_signature(ctx, group, command))
if sub_cmds:
sub_cmds = "\n".join(sub_cmds)
group_embed.add_field(name="Sub-commands:", value=f"{sub_cmds}")
channel = self.get_destination()
await channel.send(embed=group_embed)
async def send_error_message(self, error): # Overriding the default help error message
ctx = self.context
embed = discord.Embed(
title="❓ Unknown command!",
description="Use `{prefix}help` for a list of available commands.".format(prefix=ctx.prefix),
color=ctx.bot.unknown_color,
)
embed = ctx.bot.add_embed_footer(ctx, embed)
channel = self.get_destination()
await channel.send(embed=embed)
class Help(commands.Cog):
"""Cog that implements a custom help command"""
def __init__(self, bot: SnedBot):
bot.help_command = SnedHelp()
self.bot = bot
def setup(bot: SnedBot):
logger.info("Adding cog: Help...")
bot.add_cog(Help(bot))