Пример #1
0
    async def repl(self, ctx):
        """
        Open an interactive REPL.

        The REPL will only recognise code as messages which start with a
        backtick. This includes codeblocks, and as such multiple lines can be
        evaluated.
        """
        if ctx.channel.id in self.sessions:
            await ctx.send(
                _("Already running a REPL session in this channel. Exit it with `quit`.")
            )
            return

        variables = Env.from_context(ctx)
        compiler = Compiler()

        self.sessions[ctx.channel.id] = True
        await ctx.send(_("Enter code to execute or evaluate. `exit()` or `quit` to exit."))

        while True:
            response = await ctx.bot.wait_for("message", check=MessagePredicate.regex(r"^`", ctx))

            if ctx.channel.id not in self.sessions:
                return
            if not self.sessions[ctx.channel.id]:
                continue

            cleaned = self.cleanup_code(response.content).strip()

            if cleaned.rstrip("( )") in ("quit", "exit", "stop"):
                del self.sessions[ctx.channel.id]
                await ctx.send(_("Exiting."))
                return

            if cleaned.startswith("from __future__ import"):
                try:
                    cleaned = self.handle_future(cleaned, compiler)
                except SyntaxError as e:
                    asyncio.ensure_future(
                        self.send_interactive(
                            ctx,
                            "# Exception:\nTraceback (most recent call last):\n"
                            + "".join(traceback.format_exception_only(type(e), e)),
                        )
                    )
                    continue

            await self.my_exec(
                ctx,
                cleaned,
                variables,
                "eval",
                "single",
                "exec",
                compiler=compiler,
                message=response,
            )
Пример #2
0
    async def repl(self, ctx: commands.Context):
        if ctx.channel.id in self.sessions:
            if self.sessions[ctx.channel.id]:
                await ctx.send(
                    _("Already running a REPL session in this channel. Exit it with `quit`."
                      ))
            else:
                await ctx.send(
                    _("Already running a REPL session in this channel. Resume the REPL with `{}repl resume`."
                      ).format(ctx.clean_prefix))
            return

        variables = self.get_environment(ctx)
        compiler = Compiler()

        self.sessions[ctx.channel.id] = True
        await ctx.send(
            _("Enter code to execute or evaluate. `exit` or `quit` to exit. `{}repl pause` to pause."
              ).format(ctx.clean_prefix))

        while True:
            response = await ctx.bot.wait_for("message",
                                              check=MessagePredicate.regex(
                                                  r"^`", ctx))

            if ctx.channel.id not in self.sessions:
                return
            if not self.sessions[ctx.channel.id]:
                continue

            cleaned = self.cleanup_code(response.content)

            exited = await self.my_exec(
                ctx,
                cleaned,
                variables,
                compiler=compiler,
                message=response,
            )

            if exited:
                del self.sessions[ctx.channel.id]
                await ctx.send(_("Exiting."))
                return
Пример #3
0
    async def get_option(self, ctx: commands.Context) -> SlashOption:
        name_desc = (
            "What should the argument name be?\n"
            "Slash argument names may not exceed 32 characters and can only contain characters "
            "that are alphanumeric or '_' or '-'.")
        name_pred = MessagePredicate.regex(SLASH_NAME, ctx)
        await self.send_and_query_response(ctx, name_desc, name_pred)
        title = name_pred.result.group(1)
        description = await self.send_and_query_response(
            ctx,
            "What should the argument description be? (maximum 100 characters)",
            MessagePredicate.length_less(101, ctx),
        )

        valid_option_types = [
            name.lower() for name in SlashOptionType.__members__.keys()
            if not name.startswith("SUB")
        ]

        option_query = [
            "What should the argument type be?",
            f"Valid option types: {humanize_list([inline(n) for n in valid_option_types])}",
            "(select `string` if you don't understand)",
        ]
        option_type = await self.send_and_query_response(
            ctx,
            "\n".join(option_query),
            MessagePredicate.lower_contained_in(valid_option_types, ctx),
        )
        option_type = SlashOptionType[option_type.upper()]

        pred = MessagePredicate.yes_or_no(ctx)
        await self.send_and_query_response(ctx,
                                           "Is this argument required? (Y/n)",
                                           pred)
        required = pred.result

        return SlashOption(name=title,
                           description=description,
                           option_type=option_type,
                           required=required)
Пример #4
0
    async def get_option(
        self, ctx: commands.Context, *, added_required: bool = False
    ) -> SlashOption:
        name_desc = [
            "What should the argument name be and description be?",
            "The argument name and description should be split by a `:`.",
            "Example: `member:A member of this server.`\n",
            "*Slash argument names may not exceed 32 characters and can only contain characters "
            "that are alphanumeric or '_' or '-'.",
            "The argument description must be less than or equal to 100 characters.*",
        ]
        name_pred = MessagePredicate.regex(ARGUMENT_NAME_DESCRIPTION, ctx)
        await self.send_and_query_response(ctx, "\n".join(name_desc), name_pred)
        match = name_pred.result
        name, description = match.group(1), match.group(2)

        valid_option_types = [
            name.lower()
            for name in SlashOptionType.__members__.keys()
            if not name.startswith("SUB")
        ]
        valid_option_types.append("choices")

        option_query = [
            "What should the argument type be?",
            f"Valid option types: {humanize_list([inline(n) for n in valid_option_types])}",
            "(select `string` if you don't understand)",
        ]
        option_type = await self.send_and_query_response(
            ctx,
            "\n".join(option_query),
            MessagePredicate.lower_contained_in(valid_option_types, ctx),
        )
        if option_type == "choices":
            choices = await self.get_choices(ctx)
            option_type = "STRING"
        else:
            choices = []
        option_type = SlashOptionType[option_type.upper()]

        if not added_required:
            pred = MessagePredicate.yes_or_no(ctx)
            await self.send_and_query_response(
                ctx,
                "Is this argument required? (Y/n)\n*Keep in mind that if you choose to make this argument optional, all following arguments must also be optional.*",
                pred,
            )
            required = pred.result
        else:
            await ctx.send(
                "This argument was automatically made optional as the previous one was optional.",
                delete_after=15,
            )
            required = False

        return SlashOption(
            name=name,
            description=description,
            option_type=option_type,
            required=required,
            choices=choices,
        )
Пример #5
0
    async def repl(self, ctx):
        """Open an interactive REPL.

        The REPL will only recognise code as messages which start with a
        backtick. This includes codeblocks, and as such multiple lines can be
        evaluated.

        You may not await any code in this REPL unless you define it inside an
        async function.
        """
        variables = {
            "ctx": ctx,
            "bot": ctx.bot,
            "message": ctx.message,
            "guild": ctx.guild,
            "channel": ctx.channel,
            "author": ctx.author,
            "_": None,
        }

        if ctx.channel.id in self.sessions:
            await ctx.send(
                _("Already running a REPL session in this channel. Exit it with `quit`."
                  ))
            return

        self.sessions.add(ctx.channel.id)
        await ctx.send(
            _("Enter code to execute or evaluate. `exit()` or `quit` to exit.")
        )

        while True:
            response = await ctx.bot.wait_for("message",
                                              check=MessagePredicate.regex(
                                                  r"^`", ctx))

            cleaned = self.cleanup_code(response.content)

            if cleaned in ("quit", "exit", "exit()"):
                await ctx.send(_("Exiting."))
                self.sessions.remove(ctx.channel.id)
                return

            executor = exec
            if cleaned.count("\n") == 0:
                # single statement, potentially 'eval'
                try:
                    code = compile(cleaned, "<repl session>", "eval")
                except SyntaxError:
                    pass
                else:
                    executor = eval

            if executor is exec:
                try:
                    code = compile(cleaned, "<repl session>", "exec")
                except SyntaxError as e:
                    await ctx.send(self.get_syntax_error(e))
                    continue

            variables["message"] = response

            stdout = io.StringIO()

            msg = ""

            try:
                with redirect_stdout(stdout):
                    result = executor(code, variables)
                    if inspect.isawaitable(result):
                        result = await result
            except:
                value = stdout.getvalue()
                msg = "{}{}".format(value, traceback.format_exc())
            else:
                value = stdout.getvalue()
                if result is not None:
                    msg = "{}{}".format(value, result)
                    variables["_"] = result
                elif value:
                    msg = "{}".format(value)

            msg = self.sanitize_output(ctx, msg)

            try:
                await ctx.send_interactive(self.get_pages(msg), box_lang="py")
            except discord.Forbidden:
                pass
            except discord.HTTPException as e:
                await ctx.send(_("Unexpected error: `{}`").format(e))
Пример #6
0
    async def command_equalizer_save(self, ctx: commands.Context, eq_preset: str = None):
        """Save the current eq settings to a preset."""
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
        )
        if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
            ctx.command.reset_cooldown(ctx)
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Save Preset"),
                description=_("You need the DJ role to save equalizer presets."),
            )
        if not eq_preset:
            await self.send_embed_msg(
                ctx, title=_("Please enter a name for this equalizer preset.")
            )
            try:
                eq_name_msg = await self.bot.wait_for(
                    "message",
                    timeout=15.0,
                    check=MessagePredicate.regex(fr"^(?!{re.escape(ctx.prefix)})", ctx),
                )
                eq_preset = eq_name_msg.content.split(" ")[0].strip('"').lower()
            except asyncio.TimeoutError:
                ctx.command.reset_cooldown(ctx)
                return await self.send_embed_msg(
                    ctx,
                    title=_("Unable To Save Preset"),
                    description=_(
                        "No equalizer preset name entered, try the command again later."
                    ),
                )
        eq_preset = eq_preset or ""
        eq_exists_msg = None
        eq_preset = eq_preset.lower().lstrip(ctx.prefix)
        eq_presets = await self.config.custom("EQUALIZER", ctx.guild.id).eq_presets()
        eq_list = list(eq_presets.keys())

        if len(eq_preset) > 20:
            ctx.command.reset_cooldown(ctx)
            return await self.send_embed_msg(
                ctx,
                title=_("Unable To Save Preset"),
                description=_("Try the command again with a shorter name."),
            )
        if eq_preset in eq_list:
            eq_exists_msg = await self.send_embed_msg(
                ctx, title=_("Preset name already exists, do you want to replace it?")
            )
            start_adding_reactions(eq_exists_msg, ReactionPredicate.YES_OR_NO_EMOJIS)
            pred = ReactionPredicate.yes_or_no(eq_exists_msg, ctx.author)
            await self.bot.wait_for("reaction_add", check=pred)
            if not pred.result:
                await self._clear_react(eq_exists_msg)
                embed2 = discord.Embed(
                    colour=await ctx.embed_colour(), title=_("Not saving preset.")
                )
                ctx.command.reset_cooldown(ctx)
                return await eq_exists_msg.edit(embed=embed2)

        player = lavalink.get_player(ctx.guild.id)
        player.store("notify_channel", ctx.channel.id)
        eq = player.fetch("eq", Equalizer())
        to_append = {eq_preset: {"author": ctx.author.id, "bands": eq.bands}}
        new_eq_presets = {**eq_presets, **to_append}
        await self.config.custom("EQUALIZER", ctx.guild.id).eq_presets.set(new_eq_presets)
        embed3 = discord.Embed(
            colour=await ctx.embed_colour(),
            title=_("Current equalizer saved to the {preset_name} preset.").format(
                preset_name=eq_preset
            ),
        )
        if eq_exists_msg:
            await self._clear_react(eq_exists_msg)
            await eq_exists_msg.edit(embed=embed3)
        else:
            await self.send_embed_msg(ctx, embed=embed3)
Пример #7
0
    async def repl(self, ctx):
        """Open an interactive REPL.
        The REPL will only recognise code as messages which start with a
        backtick. This includes codeblocks, and as such multiple lines can be
        evaluated.
        """
        if ctx.channel.id in self.sessions:
            if self.sessions[ctx.channel.id]:
                await ctx.send(
                    _("Already running a REPL session in this channel. Exit it with `quit`."
                      ))
            else:
                await ctx.send(
                    _("Already running a REPL session in this channel. Resume the REPL with `{}repl resume`."
                      ).format(ctx.prefix))
            return

        env = self.get_environment(ctx)
        env["__builtins__"] = __builtins__
        env["_"] = None
        self.sessions[ctx.channel.id] = True
        await ctx.send(
            _("Enter code to execute or evaluate. `exit()` or `quit` to exit. `{}repl pause` to pause."
              ).format(ctx.prefix))

        while True:
            response = await ctx.bot.wait_for("message",
                                              check=MessagePredicate.regex(
                                                  r"^`", ctx))

            if not self.sessions[ctx.channel.id]:
                continue

            cleaned = self.cleanup_code(response.content)

            if cleaned in ("quit", "exit", "exit()"):
                await ctx.send(_("Exiting."))
                del self.sessions[ctx.channel.id]
                return

            executor = None
            if cleaned.count("\n") == 0:
                # single statement, potentially 'eval'
                try:
                    code = self.async_compile(cleaned, "<repl session>",
                                              "eval")
                except SyntaxError:
                    pass
                else:
                    executor = eval

            if executor is None:
                try:
                    code = self.async_compile(cleaned, "<repl session>",
                                              "exec")
                except SyntaxError as e:
                    await ctx.send_interactive(self.get_syntax_error(e),
                                               box_lang="py")
                    continue

            env["message"] = response
            stdout = io.StringIO()

            msg = ""

            try:
                with redirect_stdout(stdout):
                    if executor is None:
                        result = types.FunctionType(code, env)()
                    else:
                        result = executor(code, env)
                    result = await self.maybe_await(result)
            except:
                value = stdout.getvalue()
                msg = "{}{}".format(value, traceback.format_exc())
            else:
                value = stdout.getvalue()
                if result is not None:
                    msg = "{}{}".format(value, result)
                    env["_"] = result
                elif value:
                    msg = "{}".format(value)

            msg = self.sanitize_output(ctx, msg)

            try:
                await ctx.send_interactive(self.get_pages(msg), box_lang="py")
            except discord.Forbidden:
                pass
            except discord.HTTPException as e:
                await ctx.send(_("Unexpected error: `{}`").format(e))