Source code for errbot.core_plugins.help

import textwrap
import subprocess

from dulwich import errors as dulwich_errors
from errbot import BotPlugin, botcmd
from errbot.utils import git_tag_list
from errbot.version import VERSION


[docs]class Help(BotPlugin): MSG_HELP_TAIL = 'Type help <command name> to get more info ' \ 'about that specific command.' MSG_HELP_UNDEFINED_COMMAND = 'That command is not defined.'
[docs] def is_git_directory(self, path='.'): try: tags = git_tag_list(path) except dulwich_errors.NotGitRepository: tags = None except Exception as _: # we might want to handle other exceptions another way. For now leaving this general tags = None return tags.pop(-1) if tags is not None else None
# noinspection PyUnusedLocal
[docs] @botcmd(template='about') def about(self, msg, args): """Return information about this Errbot instance and version""" git_version = self.is_git_directory() if git_version: return dict(version=f"{git_version.decode('utf-8')} GIT CHECKOUT") else: return {'version': VERSION}
# noinspection PyUnusedLocal
[docs] @botcmd def apropos(self, msg, args): """ Returns a help string listing available options. Automatically assigned to the "help" command.""" if not args: return 'Usage: ' + self._bot.prefix + 'apropos search_term' description = 'Available commands:\n' cls_commands = {} for (name, command) in self._bot.all_commands.items(): cls = self._bot.get_plugin_class_from_method(command) cls = str.__module__ + '.' + cls.__name__ # makes the fuul qualified name commands = cls_commands.get(cls, []) if not self.bot_config.HIDE_RESTRICTED_COMMANDS or self._bot.check_command_access(msg, name)[0]: commands.append((name, command)) cls_commands[cls] = commands usage = '' for cls in sorted(cls_commands): commands = [] for (name, command) in cls_commands[cls]: if name == 'help': continue if command._err_command_hidden: continue doc = command.__doc__ if doc is not None and args.lower() not in doc.lower(): continue name_with_spaces = name.replace('_', ' ', 1) doc = (doc or '(undocumented)').strip().split('\n', 1)[0] commands.append('\t' + self._bot.prefix + name_with_spaces + ': ' + doc) usage += '\n'.join(commands) usage += '\n\n' return ''.join(filter(None, [description, usage])).strip()
[docs] @botcmd def help(self, msg, args): """Returns a help string listing available options. Automatically assigned to the "help" command.""" def may_access_command(m, cmd): m, _, _ = self._bot._process_command_filters( msg=m, cmd=cmd, args=None, dry_run=True ) return m is not None def get_name(named): return named.__name__.lower() # Normalize args to lowercase for ease of use args = args.lower() if args else '' usage = '' description = '### All commands\n' cls_obj_commands = {} for (name, command) in self._bot.all_commands.items(): cls = self._bot.get_plugin_class_from_method(command) obj = command.__self__ _, commands = cls_obj_commands.get(cls, (None, [])) if not self.bot_config.HIDE_RESTRICTED_COMMANDS or may_access_command(msg, name): commands.append((name, command)) cls_obj_commands[cls] = (obj, commands) # show all if not args: for cls in sorted(cls_obj_commands.keys(), key=lambda c: cls_obj_commands[c][0].name): obj, commands = cls_obj_commands[cls] name = obj.name # shows class and description usage += f'\n**{name}**\n\n*{cls.__errdoc__.strip() or ""}*\n\n' for name, command in sorted(commands): if command._err_command_hidden: continue # show individual commands usage += self._cmd_help_line(name, command) usage += '\n\n' # end cls section elif args: for cls, (obj, cmds) in cls_obj_commands.items(): if obj.name.lower() == args: break else: cls, obj, cmds = None, None, None if cls is None: # Plugin not found. description = '' all_commands = dict(self._bot.all_commands) all_commands.update( {k.replace('_', ' '): v for k, v in all_commands.items()}) if args in all_commands: usage += self._cmd_help_line(args, all_commands[args], True) else: usage += self.MSG_HELP_UNDEFINED_COMMAND else: # filter out the commands related to this class description = f'\n**{obj.name}**\n\n*{cls.__errdoc__.strip() or ""}*\n\n' pairs = [] for (name, command) in cmds: if self.bot_config.HIDE_RESTRICTED_COMMANDS: if command._err_command_hidden: continue if not may_access_command(msg, name): continue pairs.append((name, command)) pairs = sorted(pairs) for (name, command) in pairs: usage += self._cmd_help_line(name, command) return ''.join(filter(None, [description, usage]))
def _cmd_help_line(self, name, command, show_doc=False): """ Returns: str. a single line indicating the help representation of a command. """ cmd_name = name.replace('_', ' ') cmd_doc = textwrap.dedent(self._bot.get_doc(command)).strip() prefix = self._bot.prefix if getattr(command, '_err_command_prefix_required', True) else '' name = cmd_name patt = getattr(command, '_err_command_re_pattern', None) if patt: re_help_name = getattr(command, '_err_command_re_name_help', None) name = re_help_name if re_help_name else patt.pattern if not show_doc: cmd_doc = cmd_doc.split('\n')[0] if len(cmd_doc) > 80: cmd_doc = f'{cmd_doc[:77]}...' help_str = f'- **{prefix}{name}** - {cmd_doc}\n' return help_str