예제 #1
0
    async def getcode(self,
                      context: Context,
                      child: command_or_plugin_converter = None):
        child: typing.Union[plugins.Plugin,
                            commands.Command] = child or context.command
        if isinstance(child, plugins.Plugin):
            code = inspect.getsource(child.__class__)
        else:
            code = inspect.getsource(child._callback)
        lines = "\n".join([line
                           for line in code.splitlines()]).replace("`", "ˋ")
        paginator = EmbedPaginator(prefix="```py\n",
                                   suffix="```",
                                   max_lines=20)

        @paginator.embed_factory()
        def make_embed(index, page):
            return hikari.Embed(
                title=f"Code for {child.name}",
                description=page,
                colour=randint(0, 0xFFF),
                timestamp=datetime.now(tz=timezone.utc),
            ).set_footer(
                text=
                f"#{index}/{len(paginator)}, Requested by {ctx_name(context)}",
                icon=context.author.avatar_url,
            )

        paginator.add_line(lines)
        navigator = EmbedNavigator(paginator.build_pages())
        await navigator.run(context)
예제 #2
0
    async def send_paginated_help(text: typing.Sequence[str], context: Context) -> None:

        paginator = EmbedPaginator(max_chars=1028, max_lines=27)

        @paginator.embed_factory()
        def make_embed(index, page):
            return (
                hikari.Embed(
                    title="Help",
                    description=f"Use `{context.prefix}help [command/cog]` for more detailed info.",
                    colour=random.randint(0, 0xFFFFFF),
                    timestamp=datetime.now(tz=timezone.utc),
                )
                .set_footer(
                    text=f"#{index}/{len(paginator)}, Requested by {ctx_name(context)}",
                    icon=context.author.avatar_url,
                )
                .add_field(name="**Available Commands**", value=page)
            )

        for line in text:
            paginator.add_line(line)

        navigator = EmbedNavigator(timeout=30.0, pages=paginator.build_pages())

        await navigator.run(context)
예제 #3
0
    async def execute_in_shell(self, context: Context, body):
        start = datetime.now(tz=timezone.utc)
        body = self.clean(body)
        stack = contextlib.ExitStack()
        stream = io.StringIO()
        stack.enter_context(contextlib.redirect_stdout(stream))
        stack.enter_context(contextlib.redirect_stderr(stream))

        with stack:
            process = await asyncio.create_subprocess_shell(
                body,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE,
            )
            stdout, stderr = await process.communicate()
            stream.write(stdout.decode())
            stream.write(stderr.decode())

        stream.write(f"\n- Return code {process.returncode}")
        stream.seek(0)
        lines = ("\n".join(stream.readlines()).replace(context.bot._token,
                                                       "~TOKEN~").replace(
                                                           "`", "´"))

        paginator = EmbedPaginator(max_lines=27,
                                   prefix="```diff\n",
                                   suffix="```",
                                   max_chars=1048)

        @paginator.embed_factory()
        def make_page(index, page):
            return hikari.Embed(
                title=
                f"Executed in {(datetime.now(tz=timezone.utc) - start).total_seconds() * 1000:.2f}ms",
                colour=0x58EF92 if process.returncode == 0 else 0xE74C3C,
                description=f"Result: {page}",
                timestamp=datetime.now(tz=timezone.utc),
            ).set_footer(
                text=
                f"#{index}/{len(paginator)}, Requested by {ctx_name(context)}",
                icon=context.author.avatar_url,
            )

        paginator.add_line(
            f"*** Python {platform.python_version()} - Hikari {hikari.__version__} - lightbulb {lightbulb.__version__}\n"
            + lines)

        navigator = EmbedNavigator(pages=paginator.build_pages())
        await navigator.run(context)
예제 #4
0
    async def getcode(self, ctx: Context, child: pluginish_converter):
        body = (inspect.getsource(child.__class__) if isinstance(
            child, lightbulb.Plugin) else inspect.getsource(child._callback))
        paginator = EmbedPaginator(prefix="```py\n",
                                   suffix="```",
                                   max_lines=20)

        @paginator.embed_factory()
        def make_embed(index, page):
            return hikari.Embed(
                title=f"Code for {child.name}",
                description=page,
                colour=randint(0, 0xFFF),
                timestamp=datetime.now(tz=timezone.utc),
            ).set_footer(
                text=f"{index}/{len(paginator)}",
                icon=ctx.author.avatar_url,
            )

        paginator.add_line(body.replace("`", "ˋ"))
        navigator = EmbedNavigator(paginator.build_pages())
        await navigator.run(ctx)
예제 #5
0
파일: bot.py 프로젝트: YodaPY/Builder
    async def source(self, ctx: Context, *, command: command_converter) -> None:
        """
        View the source for a command
        """

        callback = command.callback
        code = textwrap.dedent((inspect.getsource(callback))).replace("\x60", "\u02CB") #so it renders properly

        file_path = inspect.getsourcefile(callback)
        file_ext = file_path.split(".")[-1]
        short_file_path = (file_path.split("Builder"))[1]
        file_path = f"https://github.com/YodaPY/Builder/blob/master{short_file_path}"

        lines, lineno = inspect.getsourcelines(callback)
        line_path = f"L{lineno}-L{lineno + len(lines) - 1}"

        github_path = file_path + "#" + line_path

        paginator = EmbedPaginator(max_lines=20)

        for line in code.splitlines():
            paginator.add_line(line)

        @paginator.embed_factory()
        def _(index: int, content: str) -> hikari.Embed:
            content = f"```{file_ext}\n{content}```"
            embed = hikari.Embed(
                title="Github",
                description=content,
                url=github_path
            )
            embed.set_footer(text=f"Page {index}/{len(paginator)}")

            return embed

        navigator = EmbedNavigator(paginator.build_pages())
        await navigator.run(ctx)
예제 #6
0
    async def evaluate(self, context: Context, body):
        success = False
        start = datetime.now(tz=timezone.utc)
        body = self.wrap(self.clean(body))
        stack = contextlib.ExitStack()
        stream = io.StringIO()
        stack.enter_context(contextlib.redirect_stdout(stream))
        stack.enter_context(contextlib.redirect_stderr(stream))
        stream_handler = logging.StreamHandler(stream)
        self.logger.addHandler(stream_handler)
        with stack:
            try:
                env: typing.Dict[str, typing.Optional[typing.Any]] = {
                    "self":
                    self,
                    "ctx":
                    context,
                    "channel_id":
                    context.channel_id,
                    "channel":
                    context.bot.cache.get_guild_channel(context.guild_id)
                    or context.bot.cache.get_dm(context.author.id)
                    if context.guild_id else None,
                    "author":
                    context.author,
                    "member":
                    context.member,
                    "guild":
                    context.bot.cache.get_available_guild(context.guild_id),
                    "guild_id":
                    context.guild_id,
                    "message":
                    context.message,
                    "_":
                    self.last_result,
                }
                env.update(globals())
                env.update(locals())
                env.update(modules)
                exec(body, env)
                self.last_result = await env["__invoke__"](context.bot,
                                                           context)
                stream.write(f"- Returned: {self.last_result!r}")
            except SyntaxError as e:
                stream.write(self.get_syntax_error(e))
            except Exception as e:
                traceback.print_exception(type(e), e, e.__traceback__)
            else:
                success = True
                self.logger.removeHandler(stream_handler)

        stream.seek(0)
        lines = ("\n".join(stream.readlines()).replace(context.bot._token,
                                                       "~TOKEN~").replace(
                                                           "`", "´"))
        paginator = EmbedPaginator(max_lines=27,
                                   prefix="```diff\n",
                                   suffix="```",
                                   max_chars=1048)

        @paginator.embed_factory()
        def make_page(index, page):
            return hikari.Embed(
                title=
                f"Executed in {(datetime.now(tz=timezone.utc) - start).total_seconds() * 1000:.2f}ms",
                colour=0x58EF92 if success else 0xE74C3C,
                description=f"Result: {page}",
                timestamp=datetime.now(tz=timezone.utc),
            ).set_footer(
                text=
                f"#{index}/{len(paginator)}, Requested by {ctx_name(context)}",
                icon=context.author.avatar_url,
            )

        paginator.add_line(
            f"*** Python {platform.python_version()} - Hikari {hikari.__version__} - lightbulb {lightbulb.__version__}\n"
            + lines)

        navigator = EmbedNavigator(pages=paginator.build_pages())
        await navigator.run(context)
예제 #7
0
class Code:
    PATTERN = re.compile(r"```(?P<syntax>.*)\n(?P<body>[^`]+?)```")

    def __init__(self, arg: lightbulb.WrappedArg):
        self.context = arg.context
        self.original = arg.data
        self.language, code = self.clean(arg.data)
        self.code = self.wrap(code)
        self.success = False
        self.run: typing.Callable[[], typing.Coroutine] = (
            self._shell
            if self.context.invoked_with in ("sh", "shell") else self._execute)

    @staticmethod
    def clean(body):
        match = Code.PATTERN.search(body)
        return match.groups() if match else (None, body)

    @staticmethod
    def get_syntax_error(error: SyntaxError) -> str:
        """return syntax error string from error"""
        if error.text is None:
            return f"{error.__class__.__name__}: {error}\n"
        return f'{error.text}{"^":>{error.offset}}\n{type(error).__name__}: {error}'

    @staticmethod
    def wrap(body):
        return "async def __invoke__(bot):\n" + textwrap.indent(body, " " * 4)

    async def _execute(self):
        start = datetime.now(tz=timezone.utc)
        stack = contextlib.AsyncExitStack()
        stream = io.StringIO()
        stack.enter_context(contextlib.redirect_stdout(stream))
        stack.enter_context(contextlib.redirect_stderr(stream))
        stream_handler = logging.StreamHandler(stream)

        if logger := getattr(self.context.command.plugin, "logger"):
            logger.addHandler(stream_handler)

        async with stack:
            try:
                env: typing.Dict[str, typing.Any] = {
                    "self": self.context.command.plugin,
                    "ctx": self.context,
                    "context": self.context,
                    "channel": self.context.channel,
                    "channel_id": self.context.channel_id,
                    "author": self.context.member or self.context.author,
                    "guild": self.context.guild,
                    "guild_id": self.context.guild_id,
                    "message": self.context.message,
                    "_": getattr(self.context.command.plugin, "last_result",
                                 None),
                }
                env.update(globals())
                env.update(locals())
                exec(str(self), env)
                func = env["__invoke__"]
                res = await func(self.context.bot)
                setattr(self.context.command.plugin, "last_result", res)
                print(f"- Returned {res}")
            except SyntaxError as e:
                print(self.get_syntax_error(e))
            except Exception as e:
                traceback.print_exception(type(e), e, e.__traceback__)
            else:
                self.success = True
        if logger:
            logger.removeHandler(stream_handler)

        stream.seek(0)
        lines = ("\n".join(stream.readlines()).replace(self.context.bot._token,
                                                       "~TOKEN~").replace(
                                                           "`", "´"))
        paginator = EmbedPaginator(max_lines=27,
                                   prefix="```diff\n",
                                   suffix="```",
                                   max_chars=1048)

        @paginator.embed_factory()
        def make_page(index, page):
            return hikari.Embed(
                title=
                f"Executed in {(datetime.now(tz=timezone.utc) - start).total_seconds() * 1000:.2f}ms",
                colour=0x58EF92 if self.success else 0xE74C3C,
                description=f"Result: {page}",
                timestamp=datetime.now(tz=timezone.utc),
            ).set_footer(
                text=f"Page {index}/{len(paginator)}",
                icon=self.context.author.avatar_url,
            )

        paginator.add_line(
            f"*** Python {platform.python_version()} - Hikari {hikari.__version__} - lightbulb {lightbulb.__version__}\n"
            + lines)

        navigator = EmbedNavigator(pages=paginator.build_pages())
        await navigator.run(self.context)