diff options
| -rw-r--r-- | bot/__main__.py | 4 | ||||
| -rw-r--r-- | bot/constants.py | 2 | ||||
| -rw-r--r-- | bot/formatter.py | 102 |
3 files changed, 107 insertions, 1 deletions
diff --git a/bot/__main__.py b/bot/__main__.py index 6d5c2c063..2c9bf4db3 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -4,6 +4,7 @@ import os from discord import Game from discord.ext.commands import AutoShardedBot, when_mentioned_or +from bot.formatter import Formatter from bot.utils import CaseInsensitiveDict bot = AutoShardedBot( @@ -14,7 +15,8 @@ bot = AutoShardedBot( ">>>", ">>", ">" ), # Order matters (and so do commas) game=Game(name="Help: bot.help()"), - help_attrs={"aliases": ["help()"]} + help_attrs={"aliases": ["help()"]}, + formatter=Formatter() ) bot.cogs = CaseInsensitiveDict() diff --git a/bot/constants.py b/bot/constants.py index e11a625ac..9030a100e 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -9,3 +9,5 @@ ADMIN_ROLE = 267628507062992896 MODERATOR_ROLE = 267629731250176001 VERIFIED_ROLE = 352427296948486144 OWNER_ROLE = 267627879762755584 + +HELP_PREFIX = "bot." diff --git a/bot/formatter.py b/bot/formatter.py new file mode 100644 index 000000000..503ae331d --- /dev/null +++ b/bot/formatter.py @@ -0,0 +1,102 @@ +# coding=utf-8 + +""" +Credit to Rapptz's script used as an example: +https://github.com/Rapptz/discord.py/blob/rewrite/discord/ext/commands/formatter.py +Which falls under The MIT License. +""" + +import itertools +from inspect import formatargspec, getfullargspec + +from discord.ext.commands import Command, HelpFormatter, Paginator + +from bot.constants import HELP_PREFIX + + +class Formatter(HelpFormatter): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _add_subcommands_to_page(self, max_width: int, commands: list): + """ + basically the same function from d.py but changed: + - to make the helptext appear as a comment + - to change the indentation to the PEP8 standard: 4 spaces + """ + for name, command in commands: + if name in command.aliases: + # skip aliases + continue + + entry = " {0}{1:<{width}} # {2}".format(HELP_PREFIX, name, command.short_doc, width=max_width) + shortened = self.shorten(entry) + self._paginator.add_line(shortened) + + async def format(self): + """ + rewritten help command to make it more python-y + + example of specific command: + async def <command>(ctx, <args>): + \""" + <help text> + \""" + await do_<command>(ctx, <args>) + + example of standard help page: + class <cog1>: + bot.<command1>() # <command1 help> + class <cog2>: + bot.<command2>() # <command2 help> + + # <ending help note> + """ + self._paginator = Paginator(prefix="```py") + + if isinstance(self.command, Command): + # strip the command of bot. and () + stripped_command = self.command.name.replace(HELP_PREFIX, "").replace("()", "") + + # get the args using the handy inspect module + argspec = getfullargspec(self.command.callback) + arguments = formatargspec(*argspec) + args_no_type_hints = ", ".join(argspec[0]) + + # remove self from the args + arguments = arguments.replace("self, ", "") + args_no_type_hints = args_no_type_hints.replace("self, ", "") + + # prepare the different sections of the help output, and add them to the paginator + definition = f"async def {stripped_command}{arguments}:" + docstring = f" \"\"\"\n {self.command.help}\n \"\"\"" + invocation = f" await do_{stripped_command}({args_no_type_hints})" + self._paginator.add_line(definition) + self._paginator.add_line(docstring) + self._paginator.add_line(invocation) + + return self._paginator.pages + + max_width = self.max_name_size + + def category_check(tup): + cog = tup[1].cog_name + # zero width character to make it appear last when put in alphabetical order + return cog if cog is not None else "\u200bNoCategory" + + command_list = await self.filter_command_list() + data = sorted(command_list, key=category_check) + + for category, commands in itertools.groupby(data, key=category_check): + commands = sorted(commands) + if len(commands) > 0: + self._paginator.add_line(f"class {category}:") + self._add_subcommands_to_page(max_width, commands) + + self._paginator.add_line() + ending_note = self.get_ending_note() + # make the ending note appear as comments + ending_note = "# "+ending_note.replace("\n", "\n# ") + self._paginator.add_line(ending_note) + + return self._paginator.pages |