Example #1
0
 def parse_value(
     cls,
     ctx: MrvnMessageContext,
     args: PreparedArguments,
     translator: Translator = Translator()) -> any:
     try:
         return int(args.next().value)
     except ValueError:
         raise ArgumentParseException.with_pointer(
             translator.translate("mrvn_api_command_parse_integer_error"),
             args)
Example #2
0
    def parse_value(
        cls,
        ctx: MrvnMessageContext,
        args: PreparedArguments,
        translator: Translator = Translator()) -> any:
        value = args.next().value.lower()

        if value in ["yes", "yeah", "true", "da", "+"]:
            return True
        elif value in ["no", "false", "nah", "net", "-"]:
            return False
        else:
            raise ArgumentParseException.with_pointer(
                translator.translate("mrvn_api_command_parse_bool_error"),
                args)
Example #3
0
    def parse_value(
        cls,
        ctx: MrvnMessageContext,
        args: PreparedArguments,
        translator: Translator = Translator()) -> any:
        value = args.next().value.lower()

        try:
            search = MENTION_PATTERN.search(value)

            if not search:
                raise ArgumentParseException.with_pointer(
                    translator.translate(
                        "mrvn_api_command_parse_mention_error"), args)

            snowflake = int(search.group(7)) if value != "@everyone" else None

            if (search.group(5) and
                (cls.option == SlashCommandOptionType.role
                 or cls.option == SlashCommandOptionType.mentionable)
                ) or value == "@everyone":
                if value == "@everyone":
                    return ctx.guild.roles[0]
                else:
                    return ctx.guild.get_role(snowflake)
            elif search.group(6) and (cls.option == SlashCommandOptionType.user
                                      or cls.option
                                      == SlashCommandOptionType.mentionable):
                if ctx.guild:
                    return ctx.guild.get_member(snowflake)
                else:
                    return ctx.bot.get_user(snowflake)
            elif search.group(4) and (
                    cls.option == SlashCommandOptionType.channel
                    or cls.option == SlashCommandOptionType.mentionable):
                return ctx.guild.get_channel(snowflake)
            else:
                raise ArgumentParseException.with_pointer(
                    translator.translate(
                        "mrvn_api_command_parse_mention_error"), args)
        except IndexError:
            logging.error(traceback.format_exc())

            raise ArgumentParseException.with_pointer(
                translator.translate("mrvn_api_command_parse_mention_error"),
                args)
Example #4
0
 def with_pointer(message: str, args: PreparedArguments):
     result_message = "%s\n```\n%s\n%s%s```" % (
         message, args.source.replace(
             "`", "\\`"), " " * args.current().start, "^" *
         (args.current().end - args.current().start))
     return ArgumentParseException(result_message)
Example #5
0
    async def on_message(self, message: Message):
        if message.webhook_id or message.author.bot or not message.content or message.content[
                0] not in PREFIX_LIST:
            return

        prefix = message.content[0]

        if message.guild is not None and not env.debug:
            setting = (await SettingEnableMessageCommands.get_or_create(
                guild_id=message.guild.id))[0]

            if not setting.value:
                return

        args = PreparedArguments(message.content)
        cmd_name = args.next().value[1:].lower()

        ctx = MrvnMessageContext(self, message)

        guild_id = message.guild.id if message.guild else None

        if message.guild:
            await ctx.set_from_guild(guild_id)
        else:
            ctx.set_lang(translations.FALLBACK_LANGUAGE)

        try:
            command = next(
                filter(
                    lambda it: isinstance(it, (SlashCommand, SlashCommandGroup)
                                          ) and it.name == cmd_name and
                    (bool(len(env.debug_guilds)) or not it.guild_ids or
                     guild_id in it.guild_ids), self.application_commands))

            # Bad code. Maybe. The result of filter should always be of SlashCommand*Group*, but IDE doesn't think so
            assert isinstance(command, (SlashCommand, SlashCommandGroup))
        except StopIteration:
            return

        ctx.command = command

        if not guild_id and await self.process_dm(ctx):
            return

        if guild_id:
            override = await CommandOverride.get_or_none(
                command_name=command.name, guild_id=guild_id)

            override_prefix = override and override.prefix == prefix

            if not override_prefix and prefix != (
                    await SettingMessageCmdPrefix.get_or_create(
                        guild_id=ctx.guild_id))[0].value:
                return
        else:
            override = None

            if prefix != DEFAULT_PREFIX:
                return

        if not await self.has_permission(ctx.author, ctx.command, override):
            await ctx.respond_embed(
                Style.ERROR,
                ctx.translate("mrvn_core_command_permission_error"))

            return
        elif override and not await self.process_override(ctx, override):
            return

        try:
            while isinstance(command, SlashCommandGroup):
                sub_cmd_name = args.next().value

                command = next(
                    filter(lambda it: it.name == sub_cmd_name,
                           command.subcommands))
        except StopIteration:
            await ctx.respond_embed(
                Style.ERROR,
                self.get_command_desc(ctx.command, ctx, as_tree=True),
                ctx.translate("mrvn_core_commands_subcommand_error"))
            return

        ctx.command = command

        options = command.options
        parsers = []

        for option in options:
            parser = element.parsers.get(option.input_type, None)

            if parser is None and option.input_type != SlashCommandOptionType.attachment:
                await ctx.respond_embed(
                    Style.ERROR,
                    ctx.translate("mrvn_core_commands_slash_only"))

                return

            parsers.append(parser)

        kwargs = {}
        attachment_index = 0

        try:
            for i, parser in enumerate(parsers):
                option = options[i]
                key = option.name

                if option.input_type == SlashCommandOptionType.attachment:
                    try:
                        kwargs[key] = message.attachments[attachment_index]
                    except IndexError:
                        await ctx.respond_embed(
                            Style.ERROR,
                            ctx.translate("mrvn_core_commands_attach_error"),
                            ctx.translate("mrvn_core_commands_parse_error"))
                        return

                    attachment_index += 1

                    continue

                if isinstance(option, ParseUntilEndsOption):
                    values = []

                    if not args.has_next():
                        embed = ctx.get_embed(
                            Style.ERROR,
                            title=ctx.translate(
                                "mrvn_core_commands_arguments_not_enough"))
                        embed.add_field(
                            name=self.get_command_desc(command, ctx),
                            value=self.get_translatable_desc(command, ctx))

                        await ctx.respond(embed=embed)

                        return

                    while args.has_next():
                        values.append(parser.parse(ctx, args))

                    kwargs[key] = " ".join([str(x) for x in values])

                    break

                if not option.required:
                    if key in args.keys:
                        value = parser.parse(ctx,
                                             args.keys[key],
                                             translator=ctx)
                    else:
                        value = option.default
                else:
                    try:
                        value = parser.parse(ctx, args, translator=ctx)
                    except StopIteration:
                        embed = ctx.get_embed(
                            Style.ERROR,
                            title=ctx.translate(
                                "mrvn_core_commands_arguments_not_enough"))
                        embed.add_field(
                            name=self.get_command_desc(command, ctx),
                            value=self.get_translatable_desc(command, ctx))

                        await ctx.respond(embed=embed)

                        return

                if option.input_type == SlashCommandOptionType.string and (
                        converter := option.converter) is not None:
                    value = await converter.convert(converter, ctx, value)

                if len(option.choices) and value not in [
                        x.value for x in option.choices
                ]:
                    choices_desc = "\n".join([
                        "`%s`: **%s**" % (x.name, x.value)
                        for x in option.choices
                    ])

                    await ctx.respond_embed(
                        Style.ERROR,
                        ctx.format("mrvn_core_commands_not_in_choices", value,
                                   choices_desc))

                    return

                kwargs[key] = value
        except ArgumentParseException as e:
            await ctx.respond_embed(
                Style.ERROR, e.message,
                ctx.translate("mrvn_core_commands_parse_error"))

            return

        try:
            await command(ctx, **kwargs)
        except Exception as e:
            await self.send_command_exception_message(ctx, e)
        else:
            self.dispatch("application_command_completion", ctx)
Example #6
0
 def parse_value(
     cls,
     ctx: MrvnMessageContext,
     args: PreparedArguments,
     translator: Translator = Translator()) -> any:
     return args.next().value