async def source_command(self, ctx, *, command): """Get the source code for a certain command, cog, or extension...""" try: try: command_obj = await neko3.converters.CommandConverter().convert(ctx, command) code = inspect.getsource(command_obj.callback) object_type = "command" except Exception: try: code = inspect.getsource(type(ctx.bot.cogs[command])) object_type = "cog" except Exception: code = inspect.getsource(ctx.bot.extensions[command]) object_type = "extension" p = pagination.StringNavigatorFactory( prefix="```", suffix="```", max_lines=22, substitutions=[lambda s: s.replace("`", "′")] ) p.add_line(f"# -*-*- Source for {command} {object_type} -*-*-") p.disable_truncation() for line in code.split("\n"): p.add_line(line) p.start(ctx) except Exception: self.logger.exception("Failed to load source.") await ctx.send("No source was found...")
async def unload_command(self, ctx, *, package): extensions = fnmatch.filter(ctx.bot.extensions, package) count = len(extensions) p = pagination.StringNavigatorFactory(prefix="```", suffix="```", max_lines=10) p.add_line( f"Requesting unload of extensions matching pattern {package}") p.add_line(f"Matched {count} extension{'s' if count - 1 else ''}") for extension in extensions: try: with algorithms.TimeIt() as timer: ctx.bot.unload_extension(extension) p.add_line( f"Unloaded {extension} in approx {timer.time_taken * 1_000:.0f}ms." ) except Exception as ex: self.logger.exception("Could not unload %s", extension, exc_info=ex) p.add_line( f"Could not unload {extension} because {type(ex).__name__}: {ex}" ) p.start(ctx)
async def cpp_reference_command(self, ctx, *terms): self.logger.info("Searching for terms %s", terms) try: async with ctx.typing(): results = await self.results(ctx, *terms) except Exception as ex: self.logger.exception("search error", exc_info=ex) return await ctx.send( "CppReference did something unexpected. If this keeps " "happening, contact Esp with the following info: \n\n" f"{type(ex).__qualname__}: {ex!s}" ) if not results: self.logger.info("no results") return await ctx.send("No results were found.", delete_after=10) if len(results) > 1: # Show an option picker try: self.logger.info("waiting for input") result = await pagination.option_picker(*results, ctx=ctx, max_lines=20) except asyncio.TimeoutError: return if result == pagination.NoOptionPicked(): self.logger.info("no option picked") return else: result = results[0] # Fetch the result page. async with ctx.typing(): try: self.logger.info("searching for info from %s", result.href) url, h1, tasters, header, desc = await self.get_information(ctx, result.href) except Exception as ex: self.logger.exception("An exception occurred", exc_info=ex) return await ctx.send("An error was encountered and a duck was shot.") binder = pagination.StringNavigatorFactory(max_lines=50) binder.disable_truncation() binder.add_line(f"**{h1}**\n<{url}>") if header: binder.add_line(f"\n`{header}`") if tasters: for taster in tasters: binder.add_line(f"```cpp\n{taster}\n```") binder.enable_truncation() if desc: binder.add_line(desc.replace("*", "∗")) binder.start(ctx)
async def emoji_library_command(self, ctx, arg=None): """Shows all emojis I can see ever. Pass the --verbose/-v flag to see names.""" if arg: transform = self.transform_verbose else: transform = self.transform_mute emojis = transform(ctx.bot.emojis) p = pagination.StringNavigatorFactory() for emoji in emojis: p += emoji p.start(ctx)
async def r_command(self, ctx, *, source): """ Use the following to highlight your syntax: ``` n.r ˋˋˋr t = (1:625) / 100\n x <- cos(t)\n y <- sin(t)\n plot(x, y)\n ˋˋˋ ``` """ code_block = utils.code_block_re.search(source) if code_block: source = code_block.group(2) with ctx.typing(): result = await cranr.eval_r(source) binder = pagination.StringNavigatorFactory(prefix="```markdown", suffix="```", max_lines=40) # Last line is some error about rm not working. for line in result.output.split("\n"): if line == "sh: 1: rm: Permission denied": continue binder.add_line(line) binder.add_line(f"RESULT: {result.result.title()}") binder.add_line(f"STATE: {result.state.title()}") if result.fail_reason: binder.add_line(f"FAILURE REASON: {result.fail_reason}") booklet = binder.build(ctx) additionals = [] for i in range(0, min(6, len(result.images))): with io.BytesIO(result.images[i][0]) as bio: bio.seek(0) f = discord.File(bio, f"output_{i + 1}.png") additionals.append(await ctx.send(file=f)) await utils.start_and_listen_to_edit(ctx, booklet, *additionals)
async def debug_command(self, ctx, *, content): message = ctx.message command_start = message.content.index(ctx.invoked_with) + len( ctx.invoked_with) message.content = message.content[command_start:].lstrip() if message.content.startswith(("!!", "debug")): await ctx.send( "That would loop recursively, so I am not going to invoke it.") return message.content = ctx.prefix + message.content stream = io.StringIO() reraise = None start = time.perf_counter() with contextlib.redirect_stderr(stream), contextlib.redirect_stdout( stream), cli.STREAM.add_delegate(stream): try: cli.LOGGER_STREAM = stream new_ctx = await ctx.bot.get_context(message) await new_ctx.command.invoke(new_ctx) except BaseException as ex: self.logger.exception("An error occurred executing %s:", new_ctx.message.content, exc_info=ex) reraise = ex finally: elapsed = time.perf_counter() - start stream.seek(0) logs = stream.getvalue() if logs: nav = pagination.StringNavigatorFactory(prefix="```", suffix="```") for line in stream.getvalue().split("\n"): nav.add_line(line) nav.start(new_ctx) await ctx.send(f"> Execution finished in {elapsed * 1_000:.2f}ms") if reraise is not None: raise reraise
async def py_command(self, ctx, member): """Gets some help regarding the given Python member, if it exists...""" with io.StringIO() as buff: with contextlib.redirect_stdout(buff): with contextlib.redirect_stderr(buff): help(member) data = buff.getvalue().splitlines() bb = pagination.StringNavigatorFactory(max_lines=20, prefix="```markdown", suffix="```") for line in data: line = line.replace("`", "′") bb.add_line(line) bb.start(ctx)
def formatify(code, style, ctx, author): code, logs = code spf = pagination.StringNavigatorFactory(max_lines=None, prefix="```py", suffix="```") spf += f"# Using the {style} code-style\n" spf += code.replace("```", "ˋˋˋ") spf.add_page_break() spf += logs # Swap authors. temp = ctx.author # Lets both the invoker and the message being targeted edit by default ctx.author = author nav = spf.build(ctx) nav.owner = temp return nav
async def load_command(self, ctx, *, package): try: self.logger.info("%s requested loading of %s", ctx.author, package) with algorithms.TimeIt() as timer: ctx.bot.load_extension(package) await ctx.send( f"Loaded {package} in approx {timer.time_taken * 1_000:.0f}ms." ) except Exception as ex: self.logger.exception("Failed to load %s", package, exc_info=ex) p = pagination.StringNavigatorFactory(prefix="```", suffix="```", max_lines=10) for line in traceback.format_exception(type(ex), ex, ex.__traceback__): p.add_line(line.rstrip()) p.start(ctx)
async def help_command(self, ctx, *, language: neko3.converters.clean_content = None): """ Shows all supported languages and their markdown highlighting syntax expected to invoke them correctly. """ if not language: booklet = pagination.StringNavigatorFactory(max_lines=20) booklet.add_line("**Supported languages**") for lang in sorted(rextester.Language.__members__.keys()): lang = lang.lower() booklet.add_line(f"- {lang.title()} -- `{ctx.prefix}rxt " f"ˋˋˋ{lang} ...`") booklet.start(ctx) else: await ctx.send( "There is nothing here yet. The developer has been shot as a result." )
async def reload_command(self, ctx, *, package="*"): extensions = fnmatch.filter(ctx.bot.extensions, package) count = len(extensions) p = pagination.StringNavigatorFactory(prefix="```", suffix="```", max_lines=10) p.add_line( f"Requesting reload of extensions matching pattern {package}") p.add_line(f"Matched {count} extension{'s' if count - 1 else ''}") successes = 0 failures = 0 with algorithms.TimeIt() as outer_timer: for extension in extensions: did_unload = False try: with algorithms.TimeIt() as timer: ctx.bot.unload_extension(extension) did_unload = True ctx.bot.load_extension(extension) p.add_line( f"Reloaded {extension} in approx {timer.time_taken * 1_000:.0f}ms." ) successes += 1 except Exception as ex: prefix = "" if did_unload else "un" self.logger.exception("Could not %sload %s", prefix, extension, exc_info=ex) p.add_line(f"Could not {prefix}load {extension} " f"because {type(ex).__name__}: {ex}") failures += 1 p.add_line(f"Reloaded {successes}/{successes + failures} in " f"approx {outer_timer.time_taken * 1_000:.0f}ms.") p.start(ctx)
async def event_loop_command(self, ctx): all_tasks = asyncio.Task.all_tasks(loop=ctx.bot.loop) booklet = pagination.StringNavigatorFactory(prefix="```", suffix="```", max_lines=None) summary = [] for task in all_tasks: with io.StringIO() as fp: task.print_stack(file=fp) booklet.add_line(fp.getvalue()) # noinspection PyProtectedMember # Repr, shorten it as it is obscenely long tup = getattr(task, "_repr_info", lambda: ["", "None"])()[1] summary.append(tup) booklet.add_page_break() booklet.add_page_break(to_back=False) summary = "\n".join(summary) booklet.add(summary, to_back=False) booklet.add_line(f"{len(all_tasks)} coroutines in the loop.", to_back=False) booklet.start(ctx)
async def view_binds_command(self, ctx): if ctx.guild.me.guild_permissions.manage_webhooks: @pagination.embed_generator(max_chars=2048) def generator(_, page, __): return theme.generic_embed(ctx, description=page) binder = pagination.StringNavigatorFactory( max_lines=10, prefix="```", suffix="```", substitutions=[self.scrub] ) for bind_command, value in self.raw_binds.items(): bind_command = bind_command.replace("|", ", ") if isinstance(value, tuple): value = ", ".join(value) binder.add_line(f"{bind_command}: {value}") binder.start(ctx) else: await ctx.send( "I don't seem to have the MANAGE_WEBHOOKS " "permission required for this to work. Please " "grant me that " )
async def _send_table(ctx, *unicodes): """Creates a markdown formatted table of results for characters.""" book = pagination.StringNavigatorFactory(max_lines=None) if len(unicodes) >= 20: did_setify = True unicodes = aggregates.FrozenOrderedSet(unicodes) else: did_setify = False preamble = [ "_Removed duplicate entries_" if did_setify else "\N{ZERO WIDTH SPACE}", f"**Character info (Unicode v{unicodedata.unidata_version})**", "__**`## Ct UTF-CODE DECIMAL DESCRIPTION`**__", ] # Categories for current page categories = set() current_page = [] def dump_page(): nonlocal current_page # Define the categories used. category_amble = "" for category in sorted(categories): desc = _char2category.get(category, "Unknown") category_amble += f"\n`{category}` - {desc}" four_em = " " page = "\n".join((*preamble, *current_page, category_amble)).replace(" ", four_em) book.add_page_break() book.add_block(page) categories.clear() current_page = [] for i, char in enumerate(unicodes): decimal = char.raw hexd = f"U+{decimal:04x}" category = char.category name = char.name lit = chr(char.raw) current_page.append( f"`{i + 1:02} {category} {hexd:>8} {decimal:>7} {name} {lit}` {lit}" ) categories.add(category) if i % 16 == 15: dump_page() if current_page: dump_page() booklet = book.build(ctx) if len(booklet) > 1: await booklet.start() else: await ctx.send(booklet.current_page)
async def coliru_group(self, ctx, *, code): """ Attempts to execute some code by detecting the language in the syntax highlighting. You MUST format the code using markdown-formatted code blocks. Please, please, PLEASE read this before saying "it is broken!" Run `coliru help` to view a list of the supported languages, or `coliru help <lang>` to view the help for a specific language. If you want to upload more than one file, or you wish to specify a custom build routine or flags, see `coliru a`. """ code = utils.code_block_re.search(code) if not code or len(code.groups()) < 2: booklet = pagination.StringNavigatorFactory() booklet.add_line("I couldn't detect a valid language in your " "syntax highlighting... try again by editing " "your initial message.") booklet = booklet.build(ctx) return await utils.start_and_listen_to_edit(ctx, booklet) # Extract the code language, source = code.groups() language = language.lower() try: with ctx.typing(): output = await coliru.targets[language](source) except KeyError: booklet = pagination.StringNavigatorFactory() booklet.add_line(f"That language ({language}) is not yet supported" " by this toolchain. Feel free to edit your" " message if you wish to do something else.") booklet = booklet.build(ctx) return await utils.start_and_listen_to_edit(ctx, booklet) else: booklet = pagination.StringNavigatorFactory(prefix="```markdown", suffix="```", max_lines=25) booklet.add_line(f"Interpreting as {language!r} source.") for line in output.split("\n"): booklet.add_line(line) if ctx.invoked_with in ("ccd", "colirud"): await neko_commands.try_delete(ctx) if len(output.strip()) == 0: await ctx.send("No output...") return booklet = booklet.build(ctx) return await utils.start_and_listen_to_edit(ctx, booklet)
async def rextester_group(self, ctx, *, source): """ Attempts to execute some code by detecting the language in the syntax highlighting. You MUST format the code using markdown-formatted code blocks. Please, please, PLEASE read this before saying "it is broken!" This provides many more languages than coliru does, however, it is mainly untested and will probably break in a lot of places. It also has much less functionality. Many languages have to be formatted in a specific way or have specific variable names or namespaces. Run `cc help` to view a list of the supported languages, or `cc help <lang>` to view the help for a specific language. """ code_block = utils.code_block_re.search(source) if not code_block or len(code_block.groups()) < 2: booklet = pagination.StringNavigatorFactory() booklet.add_line("I couldn't detect a valid language in your " "syntax highlighting... try again by editing " "your initial message.") booklet = booklet.build(ctx) return await utils.start_and_listen_to_edit(ctx, booklet) # Extract the code language, source = code_block.groups() language = language.lower() if language not in rextester.Language.__members__: booklet = pagination.StringNavigatorFactory() booklet.add_line("Doesn't look like I support that language. " "Run `coliru help` for a list.") booklet = booklet.build(ctx) return await utils.start_and_listen_to_edit(ctx, booklet) booklet = pagination.StringNavigatorFactory(prefix="```markdown", suffix="```", max_lines=15) lang_no = rextester.Language.__members__[language] async with ctx.typing(): response = await rextester.execute(lang_no, source) if response.errors: booklet.add_line("> ERRORS:") booklet.add_line(response.errors) if response.warnings: booklet.add_line("> WARNINGS:") booklet.add_line(response.warnings) if response.result: booklet.add_line("> OUTPUT:") booklet.add_line(response.result) booklet.add_line( f"Interpreted as {language.lower()} source; {response.stats}") if response.files: booklet.add_line( f"- {len(response.files)} file(s) included. Bug my dev to implement this properly!" ) booklet = booklet.build(ctx) await utils.start_and_listen_to_edit(ctx, booklet)
async def advanced_command(self, ctx, *, code): """ This tool enables you to specify more than one file, in any supported language on Coliru. It also lets you upload source code files. Advanced code execution will first pool all source files into the current working directory in the sandbox. It will then proceed to execute the build/run command: this is the first argument, and should be enclosed in single back-ticks. The execute command can be something as simple as `make`, or as complicated as you like. You must invoke all of your logic you wish to perform from this argument, however. It is worth noting that this build script WILL be executed as Bash commands. For small programs, it may be as simple as invoking the interpreter or compiler, and then running the output. However, if you have much more complicated input, it is advisable to invoke something like a Makefile and call your logic from that. """ try: # Get the first block as the command. command = utils.inline_block_re.search(code) if not command: raise ValueError("No command was given.") command = command.groups()[0] rest = code[len(command):].lstrip() # Get files: files = [] for m in utils.file_name_and_block_re.findall(rest): files.append(m) for attachment in ctx.message.attachments: with io.StringIO() as buff: attachment.save(buff) buff = buff.getvalue() files.append((attachment.filename, buff)) if len(files) == 0: raise ValueError("Expected one or more source files.") # Map to sourcefile objects files = [coliru.SourceFile(*file) for file in files] # Main file main = coliru.SourceFile(".run.sh", command) # Generate the coliru API client instance. c = coliru.Coliru("bash .run.sh", main, *files, verbose=True) async with self.acquire_http_session() as http: output = await c.execute(http) booklet = pagination.StringNavigatorFactory(prefix="```markdown", suffix="```", max_lines=25) for line in output.split("\n"): booklet.add_line(line) if ctx.invoked_with in ("ccd", "colirud"): await neko_commands.try_delete(ctx) if len(output.strip()) == 0: await ctx.send("No output...") return booklet = booklet.build(ctx) return await utils.start_and_listen_to_edit(ctx, booklet) except IndexError: return await ctx.send("Invalid input format.") except ValueError as ex: return await ctx.send(str(ex))