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)
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)
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)
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)
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)
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)
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)