def _gen_kanji_embed(self, payloads: list[JishoKanji]) -> list[discord.Embed]: returns = [] for data in payloads: print(type(data)) stroke = discord.Embed(title=data.kanji, url=data.url) stroke.set_image(url=data.stroke_url) strokes = data.stroke_count or "Not a Kanji" stroke.add_field(name="Stroke Count", value=strokes) stroke.add_field(name="JLPT Level", value=data.jlpt_level) if data.radical: stroke.add_field( name="Radical", value=f"({data.radical[1]}) {data.radical[0]}") returns.append(stroke) if data.on_symbols: on_embed = discord.Embed(title=data.kanji, url=data.url) on_sym = "\n".join(f"[{item[0]}]({item[1]})" for item in data.on_symbols) on_embed.add_field(name="On symbols", value=on_sym) if data.on_readings: on = "\n".join(data.on_readings) on_embed.add_field( name="On readings", value=to_codeblock(f"{dedent(on)}", language="", escape_md=False), inline=False, ) returns.append(on_embed) if data.kun_symbols: kun_embed = discord.Embed(title=data.kanji, url=data.url) kun_sym = "\n".join(f"[{item[0]}]({item[1]})" for item in data.kun_symbols) kun_embed.add_field(name="Kun symbols", value=kun_sym) if data.kun_readings: kun = "\n".join(data.kun_readings) kun_embed.add_field( name="Kun readings", value=to_codeblock(f"{dedent(kun)}", language="", escape_md=False), inline=False, ) returns.append(kun_embed) return returns
async def _gen_edit_embeds( self, records: typing.List[typing.Dict[str, typing.Any]] ) -> typing.List[discord.Embed]: embeds = [] for record in records: channel = self.bot.get_channel(record["channel_id"]) author = self.bot.get_user( record["user_id"]) or await self.bot.fetch_user( record["user_id"]) jump = record["jump_url"] embed = discord.Embed() if not author: embed.set_author(name="A deleted user...") else: embed.set_author(name=author.name, icon_url=author.avatar_url) embed.title = f"Edited in {channel.name}" diff_text = self.get_diff(record["before_content"], record["after_content"]) if len(diff_text) > 2048: url = await self.bot.mb_client.post(diff_text, syntax="diff") embed.description = ( f"Diff is too large, so I put it on [MystB.in]({url}).") else: embed.description = (formats.to_codeblock( diff_text, language="diff") if diff_text else None) fmt = f"Result {records.index(record)+1}/{len(records)}" author_id = getattr(author, "id", str(record["user_id"])) embed.set_footer(text=f"{fmt} | Author ID: {author_id}") embed.add_field(name="Jump to this message", value=f"[Here!]({jump})") embed.timestamp = datetime.datetime.fromtimestamp( record["edited_time"]) embeds.append(embed) return embeds
async def roll(self, ctx: commands.Context, *dice: DiceRoll): """ Roll DnD die! """ if len(dice) >= 25: return await ctx.send("No more than 25 rolls per invoke, please.") embed = discord.Embed(title="Rolls", colour=discord.Colour.random()) for i in dice: fmt = "" total = i["totals"] die = i["die"] rolls = i["rolls"] # split = [total[x:x+5] for x in range(0, len(total), 5)] builder = [] roll_sum = 0 for count, roll in enumerate(total, start=1): builder.append(f"{count}: {roll}") roll_sum += roll fmt += "\n".join(builder) fmt += f"\nSum: {roll_sum}\n" embed.add_field(name=f"{rolls}d{die}", value=to_codeblock(fmt, language="prolog")) # embed.description = to_codeblock(fmt, language="prolog") embed.set_footer(text=ctx.author.display_name, icon_url=ctx.author.avatar_url) await ctx.send(embed=embed)
async def _cogs(self, ctx: commands.Context) -> discord.Message: """ Main command for Extension manipulation. """ embed = discord.Embed(title="R. Umbra's loaded cogs.") embed.description = formats.to_codeblock("\n".join( map(str, self.bot.cogs))) embed.timestamp = datetime.datetime.utcnow() return await ctx.send(embed=embed)
async def blacklist(self, ctx: Context) -> None: """Blacklist management for booru command and nhentai auto-six-digits.""" if not ctx.invoked_subcommand: config = await self.get_booru_config(ctx.guild.id) if config.blacklist: fmt = "\n".join(config.blacklist) else: fmt = "No blacklist recorded." embed = discord.Embed( description=to_codeblock(fmt, language=""), colour=self.bot.colour, ) await ctx.send(embed=embed, delete_after=6.0)
async def on_loop_error(self, error: BaseException) -> None: import traceback error = getattr(error, "original", error) lines = traceback.format_exception(type(error), error, error.__traceback__) fmt = "<@!155863164544614402> \n" to_send = formats.to_codeblock("".join(lines), escape_md=False) await self.webhook.send( (fmt + to_send), allowed_mentions=discord.AllowedMentions(users=True)) self.bot.manga_client.dump_refresh_token()
async def akane_error(self, error: Exception): error = getattr(error, "original", error) if isinstance(error, discord.HTTPException): await self.webhook_send("You are ratelimited on profile edits.") self.akane_task.cancel() self.akane_task.start() else: embed = discord.Embed(title="Akane Error", colour=discord.Colour.red()) lines = traceback.format_exception(type(error), error, error.__traceback__, 4) embed.description = to_codeblock("".join(lines)) await self.webhook_send(embed=embed)
async def rtfs(self, ctx: Context, *, target: Optional[SourceConverter] = None) -> None: if target is None: await ctx.send(embed=discord.Embed( title="Available sources of rtfs", description="\n".join(RTFS)) ) return new_target = dedent(target) fmt = to_codeblock(new_target, language="py", escape_md=False) await ctx.send(fmt)
def from_kanji(cls, payload: KanjiPayload) -> "KanjiEmbed": embed = cls(title=payload.kanji, colour=discord.Colour(0xBF51B2)) embed.add_field(name="(School) Grade learned:", value=f"**__{payload.grade}__**") embed.add_field(name="Stroke count:", value=f"**__{payload.stroke_count}__**") embed.add_field(name="Kun Readings", value=("\n".join(payload.kun_readings) or "N/A")) embed.add_field(name="On Readings", value=("\n".join(payload.on_readings) or "N/A")) embed.add_field(name="Name Readings", value=("\n".join(payload.name_readings) or "N/A")) embed.add_field(name="Unicode", value=payload.unicode) embed.description = to_codeblock( ("\n".join(payload.meanings) or "N/A"), language="") embed.set_footer(text=f"JLPT Grade: {payload.jlpt or 'N/A'}") return embed
def from_words(cls, character: str, payload: WordsPayload) -> "KanjiEmbed": embeds = [] variants = payload.variants meanings = payload.meanings[0] for variant in variants: embed = cls(title=character, colour=discord.Colour(0x4AFAFC)) embed.add_field(name="Written:", value=variant["written"]) embed.add_field(name="Pronounced:", value=variant["pronounced"]) priorities = (to_codeblock("".join(variant["priorities"]), language="") if variant["priorities"] else "N/A") embed.add_field(name="Priorities:", value=priorities) for _ in range(3): embed.add_field(name="\u200b", value="\u200b") meaning = "\n".join(meanings["glosses"] or "N/A") embed.add_field(name="Kanji meaning(s):", value=meaning) embeds.append(embed) return embeds
async def timeit( self, ctx: Context, iterations: Optional[int] = 100, *, body: codeblock_converter, ) -> None: await ctx.message.add_reaction(self.bot.emoji[None]) timeit_globals = { "ctx": ctx, "guild": ctx.guild, "author": ctx.author, "bot": ctx.bot, "channel": ctx.channel, "discord": discord, "commands": commands, } timeit_globals.update(globals()) func = partial(timeit.timeit, body.content, number=iterations, globals=timeit_globals) run = await self.bot.loop.run_in_executor(None, func) await ctx.message.add_reaction(self.bot.emoji[True]) embed = discord.Embed( title=f"timeit of {iterations} iterations took {run:.20f}.", colour=self.bot.colour["dsc"], ) embed.add_field( name="Body", value=to_codeblock(body.content, language=body.language, escape_md=False), ) await ctx.send(embed=embed)
def from_jisho(cls, query: str, payload: JishoPayload) -> "KanjiEmbed": embed = cls(title=f"Jisho data on {query}.", colour=discord.Colour(0x4AFAFC)) attributions = [] for key, value in payload.attribution.items(): if value in (True, False): attributions.append(key.title()) elif value: attributions.append(f"{key.title()}: {value}") if attributions: attributions_cb = to_codeblock("\n".join(attributions), language="prolog", escape_md=False) embed.add_field(name="Attributions", value=attributions_cb, inline=False) jp = word_to_reading(payload.japanese) japanese = "\n\n".join(jp) embed.add_field( name="Writing 【Reading】", value=to_codeblock(japanese, language="prolog", escape_md=False), inline=False, ) sense: Dict[str, List[Optional[str]]] = payload.senses[0] senses = "" links = "" embed.description = "" for key, value in sense.items(): if key == "links": if value: subdict = value[0] links += f"[{subdict.get('text')}]({subdict.get('url')})\n" else: continue else: if value: senses += f"{JISHO_REPLACEMENTS.get(key, key).title()}: {', '.join(value)}\n" if senses: embed.description += to_codeblock(senses, language="prolog", escape_md=False) if links: embed.description += links embed.add_field( name="Is it common?", value=("Yes" if payload.is_common else "No"), inline=False, ) if payload.jlpt: embed.add_field(name="JLPT Level", value=payload.jlpt[0], inline=False) embed.set_footer(text=f"Slug: {payload.slug}") return embed
async def _pyright(self, ctx: Context, *, codeblock: codeblock_converter) -> None: """ Evaluates Python code through the latest (installed) version of Pyright on my system. """ code = codeblock.content pyright_dump = pathlib.Path("./_pyright/") if not pyright_dump.exists(): pyright_dump.mkdir(mode=0o0755, parents=True, exist_ok=True) conf = pyright_dump / "pyrightconfig.json" conf.touch() with open(conf, "w") as f: f.write( json.dumps({ "pythonVersion": "3.9", "typeCheckingMode": "basic", "useLibraryCodeForTypes": False, "reportMissingImports": True, })) await ctx.trigger_typing() rand = os.urandom(16).hex() with_file = pyright_dump / f"{rand}_tmp_pyright.py" with_file.touch(mode=0o0777, exist_ok=True) with open(with_file, "w") as f: f.write(code) output: str = "" with ShellReader( f"cd _pyright && pyright --outputjson {with_file.name}" ) as reader: async for line in reader: if not line.startswith("[stderr] "): output += line with_file.unlink(missing_ok=True) counts = {"error": 0, "warn": 0, "info": 0} data = json.loads(output) diagnostics = [] for diagnostic in data["generalDiagnostics"]: start = diagnostic["range"]["start"] start = f"{start['line']}:{start['character']}" severity = diagnostic["severity"] if severity != "error": severity = severity[:4] counts[severity] += 1 prefix = " " if severity == "info" else "-" message = diagnostic["message"].replace("\n", f"\n{prefix} ") diagnostics.append(f"{prefix} {start} - {severity}: {message}") version = data["version"] diagnostics = "\n".join(diagnostics) totals = ", ".join(f"{count} {name}" for name, count in counts.items()) fmt = to_codeblock( f"Pyright v{version}:\n\n{diagnostics}\n\n{totals}\n", language="diff", escape_md=False) await ctx.send(fmt)