예제 #1
0
    async def on_error_notes(self, exc, ctx):
        cmd_string = message_log_str(ctx.message)

        if ctx is not None and ctx.command is not None:
            usage_str = get_usage_str(ctx)
        else:
            usage_str = '(Unable to retrieve usage information)'

        if isinstance(exc, commands.BadArgument):
            msg = "Bad argument passed in command: {}".format(cmd_string)
            logger.warning(msg)
            await self.bot.send_message(
                ctx.message.channel, ctx.message.author.mention +
                (" Invalid parameter(s). Did you mean `.notes add`?"
                 "\n\n**Usage:** `{}`\n\nUse `{}` for help.").format(
                     usage_str, get_help_str(ctx)))
            # No need to log user errors to mods

        elif isinstance(exc, commands.TooManyArguments):
            msg = "Too many arguments passed in command: {}".format(cmd_string)
            logger.warning(msg)
            await self.bot.send_message(
                ctx.message.channel, ctx.message.author.mention +
                (" Too many parameters. Did you mean `.notes add`?\n\n"
                 "**Usage:** `{}`\n\nUse `{}` for help.").format(
                     usage_str, get_help_str(ctx)))
        else:
            await self.on_error_query_user(exc, ctx)
예제 #2
0
 async def spotlight(self, ctx):
     """
     Manages the World Spotlight event. Users: see `.help spotlight join`.
     """
     command_list = list(self.spotlight.commands.keys())
     await self.bot.say(('Invalid sub-command. Valid sub-commands are {0!s}. '
                         'Use `{1}` or `{1} <subcommand>` for instructions.')
         .format(command_list, get_help_str(ctx)))
예제 #3
0
 async def queue(self, ctx):
     """
     [MOD ONLY] The `.spotlight queue` sub-command contains sub-sub-commands that let moderators
     manage a queue of upcoming spotlights.
     """
     command_list = list(self.spotlight.commands.keys())
     await self.bot.say(('Invalid sub-command. Valid sub-commands are {0}. '
                         'Use `{1}` or `{1} <subcommand>` for instructions.')
         .format(command_list, get_help_str(ctx)))
예제 #4
0
    async def word_filter(self, ctx):
        """
        [MOD ONLY] Manages the filter lists. This feature is used to notify moderators of keywords
        and phrases in messages, and optionally auto-delete them.

        All commands permit single-letter mnemonics for convenience, e.g. `.filter l` is
        equivalent to `.filter list`.
        """
        command_list = list(self.word_filter.commands.keys())
        await self.bot.say(
            ('Invalid sub-command. Valid sub-commands are {0!s}. '
             'Use `{1}` or `{1} <subcommand>` for instructions.').format(
                 command_list, get_help_str(ctx)))
예제 #5
0
    async def filter_add_error(self, exc, ctx: commands.Context):
        cmd_string = message_log_str(ctx.message)

        if isinstance(exc, commands.TooManyArguments):
            msg = "Too many arguments passed in command: {}".format(cmd_string)
            logger.warning(msg)
            await self.bot.send_message(ctx.message.channel, (
                "Too many arguments.\n\n**Usage:** `{} <warn|del> \"<filter text>\"`\n\n"
                "Did you forget quotation marks around the filter text? "
                "Use `{}` for instructions.").format(get_command_str(ctx),
                                                     get_help_str(ctx)))
        else:
            core_cog = self.bot.get_cog("CoreCog")
            await core_cog.on_command_error(exc, ctx, force=True
                                            )  # Other errors can bubble up
예제 #6
0
    async def on_command_error(self, exc, ctx, force=False):
        """
        Handles all command errors (see the ``discord.ext.commands.errors`` module).
        This method will do nothing if a command is detected to have an error
        handler ("on_error"); if you want on_command_error's default behaviour to
        take over, within a command error handler, you can call this method and
        pass ``force=True``.

        If you define custom command error handlers, note that CommandInvokeError
        is the one you want to handle for arbitrary errors (i.e. any exception
        raised that isn't derived from CommandError will cause discord.py to raise
        a CommandInvokeError from it).
        """
        cmd_string = message_log_str(ctx.message)
        author_mention = ctx.message.author.mention + ' '

        if not force and hasattr(ctx.command, "on_error"):
            return

        if ctx is not None and ctx.command is not None:
            usage_str = get_usage_str(ctx)
        else:
            usage_str = '(Unable to retrieve usage information)'

        if isinstance(exc, DeleteMessage):
            try:
                await self.bot.delete_message(exc.message)
                logger.info("on_command_error: Deleted invoking message")
            except discord.errors.DiscordException:
                logger.exception("Can't delete invoking message!")
            exc = exc.cause
        # and continue on to handle the cause of the DeleteMessage...

        if isinstance(exc, commands.CommandOnCooldown):
            await self.bot.send_message(ctx.message.channel, author_mention +
                "`{}` is on cooldown! Try again in {:.0f} seconds."
                    .format(get_command_str(ctx), max(exc.retry_after, 1.0)))

        elif isinstance(exc, commands.CommandInvokeError):
            root_exc = exc.__cause__ if exc.__cause__ is not None else exc
            if isinstance(root_exc, KeyboardInterrupt):
                logger.warning("Interrupted by user (SIGINT)")
                raise root_exc
            elif isinstance(root_exc, discord.HTTPException):  # API errors
                err_msg = 'While executing {c}\n\nDiscord API error {e!s}' \
                    .format(c=cmd_string, e=root_exc)
                logger.error(err_msg + "\n\n{}".format(tb_log_str(root_exc)))
                await self.send_output(
                    "[ERROR] " + err_msg + "\n\nSee log for details")
            else:
                logger.error("An error occurred while processing the command: {}\n\n{}"
                    .format(cmd_string, tb_log_str(root_exc)))
                await self.send_output(
                    "[ERROR] While executing {}\n\n{}\n\nSee logs for details"
                    .format(cmd_string, exc_log_str(root_exc)))

            # In all cases (except if return early/re-raise)
            await self.bot.send_message(ctx.message.channel, author_mention +
                "An error occurred! Details have been logged. Let a mod know so we can "
                "investigate.")

        elif isinstance(exc, commands.DisabledCommand):
            msg = "Attempt to use disabled command: {}".format(cmd_string)
            logger.warning(msg)
            # No need to log this on Discord - not something mods need to be aware of
            # No need to inform user of this - prevents spam, "disabled" commands could just not
            # exist

        elif isinstance(exc, ModOnlyError):
            err_msg = "Unauthorised user for this command (not a moderator): {!r}".format(
                cmd_string)
            logger.warning(err_msg)
            await self.send_output('[WARNING] ' + err_msg)
            await self.bot.send_message(ctx.message.channel,
                author_mention + "Only mods can use that command.")

        elif isinstance(exc, AdminOnlyError):
            err_msg = "Unauthorised user for this command (not an admin): {!r}".format(
                cmd_string)
            logger.warning(err_msg)
            await self.send_output('[WARNING] ' + err_msg)
            await self.bot.send_message(ctx.message.channel,
                author_mention + "Only admins can use that command.")

        elif isinstance(exc, (UnauthorizedUserError, commands.CheckFailure)):
            logger.warning(
                "Check failed on command: {!r}\n\n{}".format(cmd_string, tb_log_str(exc)))
            await self.bot.send_message(ctx.message.channel, author_mention +
                "You're not allowed to use that command. "
                " *(Dev note: Implement error handler with more precise reason)*")

        elif isinstance(exc, UnauthorizedChannelError):
            err_msg = "Unauthorised channel for this command: {!r}".format(
                cmd_string)
            logger.warning(err_msg)
            await self.send_output('[WARNING] ' + err_msg)
            await self.bot.send_message(ctx.message.channel,
                author_mention + "You can't use that command here.")

        elif isinstance(exc, commands.NoPrivateMessage):
            msg = "Attempt to use non-PM command in PM: {}".format(cmd_string)
            logger.warning(msg)
            await self.bot.send_message(ctx.message.channel,
                "Sorry, you can't use that command in PM.")
            # No need to log this on Discord, spammy and isn't something mods need to be aware of

        elif isinstance(exc, commands.BadArgument):
            exc_msg = exc.args[0] if len(exc.args) > 0 else '(No error message).'
            msg = "Bad argument passed in command: {}\n{}".format(cmd_string, exc_msg)
            logger.warning(msg)
            await self.bot.send_message(ctx.message.channel, author_mention +
                ("Invalid argument(s): {}\n\n**Usage:** `{}`\n\n"
                 "Use `{}` for help.")
                    .format(exc_msg, usage_str, get_help_str(ctx)))
            # No need to log user errors to mods

        elif isinstance(exc, commands.TooManyArguments):
            msg = "Too many arguments passed in command: {}".format(cmd_string)
            logger.warning(msg)
            await self.bot.send_message(ctx.message.channel, author_mention +
                "Too many arguments.\n\n**Usage:** `{}`\n\nUse `{}` for help."
                    .format(usage_str, get_help_str(ctx)))
            # No need to log user errors to mods

        elif isinstance(exc, commands.MissingRequiredArgument):
            msg = "Missing required arguments in command: {}".format(cmd_string)
            logger.warning(msg)
            await self.bot.send_message(ctx.message.channel, author_mention +
                "Missing argument(s).\n\n**Usage:** `{}`\n\nUse `{}` for help."
                    .format(usage_str, get_help_str(ctx)))
            # No need to log user errors to mods

        elif isinstance(exc, BotNotReady):
            try:
                cog_name = exc.args[0]
            except IndexError:
                cog_name = 'unknown'
            logger.warning("Attempted to use command while cog is not ready: {}".format(cmd_string))
            await self.bot.send_message(
                ctx.message.channel, author_mention +
                "Sorry, I'm still loading the {} module! Try again in a few seconds."
                .format(cog_name)
            )

        elif isinstance(exc, commands.CommandNotFound):
            msg = "Unknown command: {}".format(cmd_string)
            # safe to assume commands usually words - symbolic commands are rare
            # and we want to avoid emoticons ('._.', etc.), punctuation ('...') and decimal numbers
            # without leading 0 (.12) being detected
            if ctx.invoked_with and all(c.isalnum() for c in ctx.invoked_with) \
                    and not ctx.invoked_with[0].isdigit():
                logger.warning(msg)
                await self.bot.send_message(ctx.message.channel, author_mention +
                    "Sorry, I don't know the command `{}{.invoked_with}`"
                        .format(get_command_prefix(ctx), ctx))

        else:
            logger.exception("Unknown exception occurred")
            await self.bot.send_message(ctx.message.channel, author_mention +
                "An unexpected error occurred! Details have been logged. Let a mod know so we can "
                "investigate.")
            await self.send_output(
                ("[ERROR] Unknown error while trying to process command {}\n"
                 "Error: {!s}\n\nSee logs for details").format(cmd_string, exc))