async def invite(self, ctx): '''Posts invite links for Hawking, and its Discord server.''' self.dynamo_db.put(dynamo_manager.CommandItem( ctx, ctx.message.content, inspect.currentframe().f_code.co_name, True)) paginator = Paginator() paginator.add_line('Add Hawking to your server with this link: https://discordapp.com/oauth2/authorize?client_id=334894709292007424&scope=bot&permissions=53803072') paginator.close_page() paginator.add_line('Also, join my Discord server via: https://discord.gg/JJqx8C4') paginator.add_line('- Help me test unstable versions of Hawking and my other bots') paginator.add_line('- Let me know if something\'s broken') paginator.add_line('- Post suggestions for improving Hawking and my other bots') paginator.add_line('- Got a funny phrase you want added? Suggest it in there!') paginator.close_page() await self.send_pages(ctx, paginator)
class DogbotHelpFormatter(HelpFormatter): def get_ending_note(self): if self.context.bot.is_private: return super().get_ending_note() note = super().get_ending_note() invite = self.context.bot.cfg['bot']['woof']['invite'] return note if not self.is_bot() else note + '\nNeed help? Visit the support server: ' + invite def format_help(self, description): # for each paragraph in the description, replace a newline with a space. return '\n\n'.join(para.replace('\n', ' ') for para in description.split('\n\n')) async def format(self): """ A modified copy of Discord.py rewrite's vanilla HelpFormatter.format(). """ self._paginator = Paginator() # we need a padding of ~80 or so description = self.command.description if not self.is_cog() else inspect.getdoc(self.command) if description: # <description> portion self._paginator.add_line(description, empty=True) if isinstance(self.command, Command): # <signature portion> signature = self.get_command_signature() self._paginator.add_line(signature, empty=True) # <long doc> section if self.command.help: self._paginator.add_line(self.format_help(self.command.help), empty=True) # end it here if it's just a regular command if not self.has_subcommands(): self._paginator.close_page() return self._paginator.pages max_width = self.max_name_size def category(tup): cog = tup[1].cog_name # we insert the zero width space there to give it approximate # last place sorting position. return cog + ':' if cog is not None else '\u200bCommands:' filtered = await self.filter_command_list() if self.is_bot(): data = sorted(filtered, key=category) for category, commands in itertools.groupby(data, key=category): # there simply is no prettier way of doing this. commands = sorted(commands) if len(commands) > 0: self._paginator.add_line(category) self._add_subcommands_to_page(max_width, commands) else: filtered = sorted(filtered) if filtered: self._paginator.add_line('Commands:') self._add_subcommands_to_page(max_width, filtered) # add the ending note self._paginator.add_line() ending_note = self.get_ending_note() self._paginator.add_line(ending_note) return self._paginator.pages
class CustomHelpFormatter(HelpFormatter): def __init__(self, show_hidden=False, show_check_failure=False, width=80): self.width = width self.show_hidden = show_hidden self.show_check_failure = show_check_failure def format(self): """Handles the actual behaviour involved with formatting. To change the behaviour, this method should be overridden. Returns -------- list A paginated output of the help command. """ self._paginator = Paginator() # we need a padding of ~80 or so description = self.command.description if not self.is_cog() else inspect.getdoc(self.command) if description: # <description> portion self._paginator.add_line(description, empty=True) if isinstance(self.command, Command): # <signature portion> signature = self.get_command_signature() self._paginator.add_line(signature, empty=True) # <long doc> section if self.command.help: self._paginator.add_line(self.command.help, empty=True) # end it here if it's just a regular command if not self.has_subcommands(): self._paginator.close_page() return self._paginator.pages max_width = self.max_name_size def category(tup): cog = tup[1].cog_name # we insert the zero width space there to give it approximate # last place sorting position. return cog + ':' if cog is not None else '\u200bNo Category:' if self.is_bot(): data = sorted(self.filter_command_list(), key=category) for category, commands in itertools.groupby(data, key=category): # there simply is no prettier way of doing this. if category == '\u200bNo Category:': continue commands = list(commands) if len(commands) > 0: fmt = "{0}\n {1:>{width}}" doc = inspect.getdoc(commands[0][1].instance) if doc: self._paginator.add_line('') self._paginator.add_line(fmt.format(category, doc, width=max_width)) else: self._paginator.add_line('') self._paginator.add_line(fmt.format(category, 'No Description.', width=max_width)) else: self._paginator.add_line('Commands:') self._add_subcommands_to_page(max_width, self.filter_command_list()) # add the ending note self._paginator.add_line() ending_note = self.get_ending_note() self._paginator.add_line(ending_note) return self._paginator.pages
class NabHelpFormat(HelpFormatter): def get_ending_note(self): command_name = self.context.invoked_with if self.has_subcommands() and not self.is_bot(): return "Type {0} <subcommand> for more info on a command.".format( self.context.message.content) else: return "Type {0}{1} <command> for more info on a command.\n" \ "You can also type {0}{1} category for more info on a category.".format(self.clean_prefix, command_name) async def format(self): """Handles the actual behaviour involved with formatting. To change the behaviour, this method should be overridden. Returns -------- list A paginated output of the help command. """ self._paginator = Paginator() # we need a padding of ~80 or so description = self.command.description if not self.is_cog( ) else inspect.getdoc(self.command) if description: # <description> portion self._paginator.add_line(description, empty=True) if isinstance(self.command, Command): # <signature portion> signature = self.get_command_signature() self._paginator.add_line(signature, empty=True) # <long doc> section if self.command.help: self._paginator.add_line(self.command.help, empty=True) # end it here if it's just a regular command if not self.has_subcommands(): self._paginator.close_page() return self._paginator.pages max_width = self.max_name_size def category(tup): cog = tup[1].cog_name # we insert the zero width space there to give it approximate # last place sorting position. return cog + ':' if cog is not None else '\u200bNo Category:' filtered = await self.filter_command_list() if self.is_bot(): data = sorted(filtered, key=category) for category, commands in itertools.groupby(data, key=category): # there simply is no prettier way of doing this. commands = sorted(commands) if len(commands) > 0: self._paginator.add_line(category) self._add_subcommands_to_page(max_width, commands) else: filtered = sorted(filtered) self._add_subcommands_to_page(max_width, self.filter_command_list()) if filtered: self._paginator.add_line( 'Subcommands:' if self.has_subcommands() else 'Commands:') self._add_subcommands_to_page(max_width, filtered) # add the ending note self._paginator.add_line() ending_note = self.get_ending_note() self._paginator.add_line(ending_note) return self._paginator.pages
class HelpFormatter(HelpF): """Custom override for the default help command""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._paginator = None async def format(self): """Handles the actual behaviour involved with formatting. To change the behaviour, this method should be overridden. Returns -------- list A paginated output of the help command. """ self._paginator = Paginator() # we need a padding of ~80 or so description = self.command.description if not self.is_cog() else inspect.getdoc(self.command) if description: # <description> portion self._paginator.add_line(description, empty=True) if isinstance(self.command, Command): # <signature portion> if self.command.params.get("args", None) and type(self.command.params['args'].annotation) == ArgPC: self.command.usage = create_help(self.command, self.command.params['args'].annotation.parser) signature = self.get_command_signature() self._paginator.add_line(signature, empty=True) # <long doc> section if self.command.help: self._paginator.add_line(self.command.help, empty=True) # end it here if it's just a regular command if not self.has_subcommands(): self._paginator.close_page() return self._paginator.pages max_width = self.max_name_size def category(tup): """Splits the help command into categories for easier readability""" cog = tup[1].cog_name # we insert the zero width space there to give it approximate # last place sorting position. return cog + ':' if cog is not None else '\u200bNo Category:' filtered = await self.filter_command_list() if self.is_bot(): data = sorted(filtered, key=category) for category, commands in itertools.groupby(data, key=category): # there simply is no prettier way of doing this. commands = sorted(commands) if len(commands) > 0: self._paginator.add_line(category) self._add_subcommands_to_page(max_width, commands) else: filtered = sorted(filtered) if filtered: self._paginator.add_line('Commands:') self._add_subcommands_to_page(max_width, filtered) # add the ending note self._paginator.add_line() ending_note = self.get_ending_note() self._paginator.add_line(ending_note) return self._paginator.pages
class KiaraFormatter(HelpFormatter): def __init__(self): super().__init__() def get_ending_note(self): return '' @asyncio.coroutine def format(self): """Handles the actual behaviour involved with formatting. To change the behaviour, this method should be overridden. Returns -------- list A paginated output of the help command. """ self._paginator = Paginator(prefix='```md') # we need a padding of ~80 or so description = self.command.description if not self.is_cog( ) else inspect.getdoc(self.command) if description: # <description> portion self._paginator.add_line(f'[ {description} ][-!`.]', empty=True) if isinstance(self.command, Command): # <long doc> section if self.command.help: self._paginator.add_line(self.command.help, empty=True) # <signature portion> signature = self.get_command_signature() self._paginator.add_line(f"<Usage>") self._paginator.add_line(f"{signature}", empty=True) # end it here if it's just a regular command if not self.has_subcommands(): self._paginator.close_page() return self._paginator.pages max_width = self.max_name_size def category(tup): cog = tup[1].cog_name # we insert the zero width space there to give it approximate # last place sorting position. return f'<{cog}>' if cog is not None else '<Other>' filtered = yield from self.filter_command_list() if self.is_bot(): data = sorted(filtered, key=category) for category, commands in itertools.groupby(data, key=category): # there simply is no prettier way of doing this. commands = sorted(commands) if len(commands) > 0: self._paginator.add_line(category) self._add_subcommands_to_page(max_width, commands) else: filtered = sorted(filtered) if filtered: self._paginator.add_line('<Commands>') self._add_subcommands_to_page(max_width, filtered) # add the ending note self._paginator.add_line() ending_note = self.get_ending_note() self._paginator.add_line(ending_note) return self._paginator.pages def get_command_signature(self): """Retrieves the signature portion of the help page.""" prefix = self.clean_prefix cmd = self.command return prefix + signature(cmd) def _add_subcommands_to_page(self, max_width, commands): for name, command in commands: if name in command.aliases: # skip aliases continue entry = ' {0:>{width}} : {1}'.format(name, command.short_doc, width=max_width) shortened = self.shorten(entry) self._paginator.add_line(shortened)
class ClipsterHelpCommand(commands.DefaultHelpCommand): @property def max_name_size(self): """ int : Returns the largest name length of the bot's commands. """ size = 0 try: commands = self.context.bot.commands if commands: size = max( map( lambda c: len(c.name) if self.show_hidden or not c.hidden else 0, commands)) except AttributeError as e: size = 15 return size + len(CONFIG_OPTIONS.get('activation_string', '')) def dump_header_boilerplate(self): """ Adds the header boilerplate text (Description, Version, How to activate) to the paginator """ self.paginator.add_line(CONFIG_OPTIONS.get("description"), empty=False) ## Append the version info into the help screen version_note = "Clipster version: {}".format( CONFIG_OPTIONS.get("version", "Beta")) self.paginator.add_line(version_note, empty=True) ## Append (additional) activation note activation_note = "Activate with the '{0}' character (ex. '{0}help')".format( self.clean_prefix) self.paginator.add_line(activation_note, empty=True) def dump_footer_boilerplate(self, categories): """ Adds the footer boilerplate text (Using the help interface) to the paginator """ # Ending note logic from HelpFormatter.format command_name = self.context.invoked_with ending_note = "Check out the other clip categories! Why not try '{0}{1} {2}'?".format( self.clean_prefix, command_name, random.choice(categories)) self.paginator.add_line(ending_note) def dump_commands(self): """ Adds information about the bot's available commands (unrelated to the clip commands) to the paginator """ self.paginator.add_line("Basic Commands:") for command in sorted(self.context.bot.commands, key=lambda cmd: cmd.name): if ((command.module != "clips" or command.name == 'random' or command.name == 'find') and not command.hidden): entry = ' {0}{1:<{width}} {2}'.format( CONFIG_OPTIONS.get('activation_string', ''), command.name, command.short_doc, width=self.max_name_size) self.paginator.add_line(self.shorten_text(entry)) self.paginator.add_line() def dump_clip_group(self, clip_group, width=None): """ Adds information about the supplied clip group (Group name, tabbed list of clip commands) to the paginator """ if (not width): width = self.max_name_size self.paginator.add_line(clip_group.name + ":") for name, clip in sorted(clip_group.clips.items(), key=lambda tup: tup[0]): entry = ' {0}{1:<{width}} {2}'.format(CONFIG_OPTIONS.get( 'activation_string', ''), name, clip.kwargs.get("help"), width=width) self.paginator.add_line(self.shorten_text(entry)) self.paginator.add_line() def dump_clip_categories(self, clip_groups, width=None): """ Adds information about the bot's clip categories, that the user can drill down into with the help interface, to the paginator """ if (not width): width = self.max_name_size help_string = '{}help '.format( CONFIG_OPTIONS.get('activation_string', '')) width += len(help_string) self.paginator.add_line('Clip Category Help:') for name, group in sorted(clip_groups.items(), key=lambda tup: tup[0]): ## Don't insert empty groups if (len(group.clips) > 0): entry = ' {0}{1:<{width}} {2}'.format(help_string, group.key, group.description, width=width) self.paginator.add_line(self.shorten_text(entry)) self.paginator.add_line() async def send_clip_category_help(self, command): '''Sends help information for a given command representing a Clip Category''' ## Initial setup max_width = self.max_name_size clip_groups = self.context.bot.get_cog("Clips").clip_groups self.dump_header_boilerplate() # self.dump_commands() self.dump_clip_group(clip_groups[command.name], max_width) self.dump_clip_categories(clip_groups, max_width) self.dump_footer_boilerplate(list(clip_groups.keys())) self.paginator.close_page() await self.send_pages() async def send_bot_help(self, mapping): '''The main bot help command (overridden)''' ## Initial setup self.paginator = Paginator() clip_groups = self.context.bot.get_cog("Clips").clip_groups self.dump_header_boilerplate() ## Dump the non-clip commands self.dump_commands() ## Dump the base clip commands clips_group = clip_groups["internet"] if (clips_group): self.dump_clip_group(clips_group) ## Dump the names of the additional clips. Don't print their commands because that's too much info. ## This is a help interface, not a CVS receipt self.dump_clip_categories(clip_groups) self.dump_footer_boilerplate(list(clip_groups.keys())) await self.send_pages() async def send_command_help(self, command): '''Help interface for the commands themselves (Overridden)''' ## Initial setup self.paginator = Paginator() clip_groups = self.context.bot.get_cog("Clips").clip_groups ## Is the help command a category? If so only dump the relv command_str = command.__str__() if (command.name in clip_groups): await self.send_clip_category_help(command) return # <signature> section signature = self.get_command_signature(command) self.paginator.add_line(signature, empty=True) # <long doc> section help_section = command.help if help_section: if (len(help_section) > self.paginator.max_size): for line in help_section.splitlines(): self.paginator.add_line(line) else: self.paginator.add_line(help_section, empty=True) self.paginator.close_page() await self.send_pages()
class MyHelpFormatter(HelpFormatter): def _add_subcommands_to_page(self, max_width, commands, mobile_format): for name, command in commands: if name in command.aliases: # skip aliases continue if mobile_format: entry = ' {0}'.format(name) else: entry = ' {0:<{width}} {1}'.format(name, command.short_doc, width=max_width) shortened = self.shorten(entry) self._paginator.add_line(shortened) def format_help_for(self, context, command_or_bot, mobileFormat): self.context = context self.command = command_or_bot return self.format(mobileFormat) def format(self, mobileFormat): """Handles the actual behaviour involved with formatting. To change the behaviour, this method should be overridden. Returns -------- list A paginated output of the help command. """ self._paginator = Paginator() # we need a padding of ~80 or so description = self.command.description if not self.is_cog( ) else inspect.getdoc(self.command) if description: # <description> portion self._paginator.add_line(description, empty=True) if isinstance(self.command, Command): # <signature portion> signature = self.get_command_signature() self._paginator.add_line(signature, empty=True) # <long doc> section if self.command.help: self._paginator.add_line(self.command.help, empty=True) elif self.command.brief: self._paginator.add_line(self.command.brief, empty=True) # end it here if it's just a regular command if not self.has_subcommands(): self._paginator.close_page() return self._paginator.pages max_width = self.max_name_size def category(tup): cog = tup[1].cog_name # we insert the zero width space there to give it approximate # last place sorting position. return cog + ':' if cog is not None else '\u200bNo Category:' if self.is_bot(): data = sorted(self.filter_command_list(), key=category) for category, commands in itertools.groupby(data, key=category): # there simply is no prettier way of doing this. commands = list(commands) if len(commands) > 0: self._paginator.add_line(category) self._add_subcommands_to_page(max_width, commands, mobileFormat) else: self._paginator.add_line('Commands:') self._add_subcommands_to_page(max_width, self.filter_command_list(), mobileFormat) if not mobileFormat: # add the ending note self._paginator.add_line() ending_note = self.get_ending_note() self._paginator.add_line(ending_note) return self._paginator.pages
class NewHelpFormatter(commands.HelpFormatter): """ Much of the code in the following functions has been taken from https://github.com/Rapptz/discord.py and modified to suit the purposes of this bot. """ def get_max_alias_length(self): """Returns the longest list of aliases possible for formatting purposes.""" max_len = 0 def category(tup): cog = tup[1].cog_name # we insert the zero width space there to give it approximate # last place sorting position. return cog + ':' if cog is not None else '\u200bUncategorized:' if self.is_bot(): data = sorted(self.filter_command_list(), key=category) for category, commands in itertools.groupby(data, key=category): commands = list(commands) if len(commands) > 0: for name, command in commands: aliases = '|'.join(command.aliases) if len(aliases) > max_len: max_len = len(aliases) return (max_len) def _add_subcommands_to_page(self, max_width, max_alias_width, commands): """An overridden function that changes up the formatting of commands that are to be added to a paginator.""" for name, command in commands: if name in command.aliases: # skip aliases continue aliases = '|'.join(command.aliases) if len(aliases) > 0: entry = ' {0:<{width}} [{2:<{alias_width}} {1}'.format( name, command.short_doc, aliases + "]", width=max_width, alias_width=max_alias_width + 3) else: entry = ' {0:<{width}} {2:<{alias_width}} {1}'.format( name, command.short_doc, " ", width=max_width, alias_width=max_alias_width + 4) shortened = self.shorten(entry) self._paginator.add_line(shortened) def format(self): """An overridden function that adds a few little aesthetic changes to the default help commands""" self._paginator = Paginator() description = self.command.description if not self.is_cog( ) else inspect.getdoc(self.command) if description: # <description> portion self._paginator.add_line(description, empty=True) if isinstance(self.command, Command): # <signature portion> signature = self.get_command_signature() self._paginator.add_line(signature, empty=True) # <long doc> section if self.command.help: self._paginator.add_line(self.command.help, empty=True) # end it here if it's just a regular command if not self.has_subcommands(): self._paginator.close_page() return self._paginator.pages max_width = self.max_name_size def category(tup): cog = tup[1].cog_name # we insert the zero width space there to give it approximate # last place sorting position. return cog + ':' if cog is not None else '\u200bUncategorized:' max_alias_length = self.get_max_alias_length() key_line = ' {0:<{width}} {2:<{alias_width}} {1}'.format( "Command", "Description", "Aliases", width=max_width, alias_width=max_alias_length + 4) self._paginator.add_line(key_line) bar_line = '{0:-<{key_line_len}}'.format("", key_line_len=self.width) self._paginator.add_line(bar_line) if self.is_bot(): data = sorted(self.filter_command_list(), key=category) for category, commands in itertools.groupby(data, key=category): # there simply is no prettier way of doing this. commands = list(commands) if len(commands) > 0: self._paginator.add_line(category) self._add_subcommands_to_page(max_width, max_alias_length, commands) else: self._paginator.add_line('Commands:') self._add_subcommands_to_page(max_width, self.filter_command_list()) # add the ending note self._paginator.add_line() ending_note = self.get_ending_note() self._paginator.add_line(ending_note) return self._paginator.pages
class HelpFormat(HelpCommand): def __init__(self, **options): self.sort_commands = options.pop('sort_commands', True) self.commands_heading = options.pop('commands_heading', "Commands") self.dm_help = options.pop('dm_help', False) self.dm_help_threshold = options.pop('dm_help_threshold', 1000) self.aliases_heading = options.pop('aliases_heading', "Aliases:") self.no_category = options.pop('no_category', '') self.paginator = options.pop('paginator', None) if self.paginator is None: self.paginator = Paginator(suffix=None, prefix=None) super().__init__(**options) def get_destination(self, no_pm: bool = False): if no_pm: return self.context.channel else: return self.context.author async def send_error_message(self, error): destination = self.get_destination(no_pm=True) await destination.send(error) async def send_command_help(self, command): self.add_command_formatting(command) self.paginator.close_page() await self.send_pages(no_pm=True) async def send_pages(self, no_pm: bool = False): try: destination = self.get_destination(no_pm=no_pm) if isinstance(self.context.channel, discord.channel.TextChannel): await self.context.send(f"{self.context.author.mention}, Check your DM!") await self.context.message.add_reaction(chr(0x2709)) em = discord.Embed(color=discord.Colour.green()) for page in self.paginator.pages: em.description = page await destination.send(embed=em) except discord.Forbidden: destination = self.get_destination(no_pm=True) await destination.send("Couldn't send help, have you blocked me? D:") def get_opening_note(self): """Returns help command's opening note. This is mainly useful to override for i18n purposes. The default implementation returns :: Use `{prefix}{command_name} [command]` for more info on a command. You can also use `{prefix}{command_name} [category]` for more info on a category. """ command_name = self.invoked_with return "Use `{0}{1} [command]` for more info on a command.\n You can also use `{0}{1} [category]` for more info on a category.".format(self.clean_prefix, command_name) def get_command_signature(self, command): return '%s%s %s' % (self.clean_prefix, command.qualified_name, command.signature) def get_ending_note(self): """Return the help command's ending note. This is mainly useful to override for i18n purposes. The default implementation does nothing. """ return None def add_bot_commands_formatting(self, commands, heading):#todo """Adds the minified bot heading with commands to the output. The formatting should be added to the :attr:`paginator`. The default implementation is a bold underline heading followed by commands separated by an EN SPACE (U+2002) in the next line. Parameters ----------- commands: Sequence[:class:`Command`] A list of commands that belong to the heading. heading: :class:`str` The heading to add to the line. """ if commands: # U+2002 Middle Dot joined = '\u2002'.join(c.name for c in commands) self.paginator.add_line('__**%s**__' % heading) self.paginator.add_line(joined) def add_subcommand_formatting(self, command): """Adds formatting information on a subcommand. The formatting should be added to the :attr:`paginator`. The default implementation is the prefix and the :attr:`Command.qualified_name` optionally followed by an En dash and the command's :attr:`Command.short_doc`. Parameters ----------- command: :class:`Command` The command to show information of. """ fmt = '{0}{1} \N{EN DASH} {2}' if command.short_doc else '{0}{1}' self.paginator.add_line(fmt.format(self.clean_prefix, command.qualified_name, command.short_doc)) def add_aliases_formatting(self, aliases): """Adds the formatting information on a command's aliases. The formatting should be added to the :attr:`paginator`. The default implementation is the :attr:`aliases_heading` bolded followed by a comma separated list of aliases. This is not called if there are no aliases to format. Parameters ----------- aliases: Sequence[:class:`str`] A list of aliases to format. """ self.paginator.add_line('**%s** %s' % (self.aliases_heading, ', '.join(aliases)), empty=True) def add_command_formatting(self, command): """A utility function to format commands and groups. Parameters ------------ command: :class:`Command` The command to format. """ if command.description: self.paginator.add_line(command.description, empty=True) signature = self.get_command_signature(command) if command.aliases: self.paginator.add_line(signature) self.add_aliases_formatting(command.aliases) else: self.paginator.add_line(signature, empty=True) if command.help: try: self.paginator.add_line(command.help, empty=True) except RuntimeError: for line in command.help.splitlines(): self.paginator.add_line(line) self.paginator.add_line() async def send_bot_help(self, mapping): ctx = self.context bot = ctx.bot if bot.description: self.paginator.add_line(bot.description, empty=True) note = self.get_opening_note() if note: self.paginator.add_line(note, empty=True) no_category = '\u200b{0.no_category}'.format(self) def get_category(command, *, no_category=no_category): cog = command.cog return cog.qualified_name if cog is not None else no_category filtered = await self.filter_commands(bot.commands, sort=True, key=get_category) to_iterate = itertools.groupby(filtered, key=get_category) for category, commands in to_iterate: if len(category) == 1: continue commands = sorted(commands, key=lambda c: c.name) if self.sort_commands else list(commands) self.add_bot_commands_formatting(commands, category) note = self.get_ending_note() if note: self.paginator.add_line() self.paginator.add_line(note) await self.send_pages() async def send_cog_help(self, cog): bot = self.context.bot if bot.description: self.paginator.add_line(bot.description, empty=True) note = self.get_opening_note() if note: self.paginator.add_line(note, empty=True) if cog.description: self.paginator.add_line(cog.description, empty=True) filtered = await self.filter_commands(cog.get_commands(), sort=self.sort_commands) if filtered: self.paginator.add_line('**%s %s**' % (cog.qualified_name, self.commands_heading)) for command in filtered: self.add_subcommand_formatting(command) note = self.get_ending_note() if note: self.paginator.add_line() self.paginator.add_line(note) await self.send_pages() async def send_group_help(self, group): self.add_command_formatting(group) filtered = await self.filter_commands(group.commands, sort=self.sort_commands) if filtered: note = self.get_opening_note() if note: self.paginator.add_line(note, empty=True) self.paginator.add_line('**%s**' % self.commands_heading) for command in filtered: self.add_subcommand_formatting(command) note = self.get_ending_note() if note: self.paginator.add_line() self.paginator.add_line(note) await self.send_pages() async def send_command_help(self, command): self.add_command_formatting(command) self.paginator.close_page() await self.send_pages()
class EmbedPaginator: class Navigation(IntEnum): FIRST = 0 BACK = 1 NEXT = 2 LAST = 3 EMOJIS = OrderedDict(( ('⏮', Navigation.FIRST), ('⏪', Navigation.BACK), ('⏩', Navigation.NEXT), ('⏭', Navigation.LAST), )) def __init__(self, ctx: Context, base_title: str, color=None): self.ctx = ctx self.title = base_title self.attrs = {} if color: self.attrs['color'] = color self.paginator = Paginator(prefix='', suffix='', max_size=2048) def add_line(self, line='', *, empty=False): self.paginator.add_line(line, empty=empty) def close_page(self): self.paginator.close_page() def _check(self, page, pages, reaction, user): reaction = reaction.emoji if user.id != self.ctx.author.id: return False if reaction not in self.EMOJIS: return False if page == 1 and self.EMOJIS[reaction] <= self.Navigation.BACK: return False if page == pages and self.EMOJIS[reaction] >= self.Navigation.NEXT: return False return True async def send_to(self, dest: Messageable = None): if not dest: dest = self.ctx pages = self.paginator.pages page = 1 title = self.title if len(pages) > 1: title = title + f' ({page}/{len(pages)})' msg = await dest.send(embed=Embed( title=title, description=pages[page - 1], **self.attrs, )) if len(pages) == 1: return for emoji in self.EMOJIS: await msg.add_reaction(emoji) try: while True: check = partial(self._check, page, len(pages)) reaction, user = await self.ctx.bot.wait_for( 'reaction_add', check=check, timeout=30.0, ) action = self.EMOJIS[reaction.emoji] if action is self.Navigation.FIRST: page = 1 elif action is self.Navigation.BACK: page -= 1 elif action is self.Navigation.NEXT: page += 1 elif action is self.Navigation.LAST: page = len(pages) await msg.edit(embed=Embed( title=f'{self.title} ({page}/{len(pages)})', description=pages[page - 1], **self.attrs, )) except asyncio.TimeoutError: for emoji in self.EMOJIS: await msg.remove_reaction(emoji, msg.author)