aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/evergreen/fun.py
diff options
context:
space:
mode:
Diffstat (limited to 'bot/exts/evergreen/fun.py')
-rw-r--r--bot/exts/evergreen/fun.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/bot/exts/evergreen/fun.py b/bot/exts/evergreen/fun.py
new file mode 100644
index 00000000..889ae079
--- /dev/null
+++ b/bot/exts/evergreen/fun.py
@@ -0,0 +1,148 @@
+import functools
+import logging
+import random
+from typing import Callable, Tuple, Union
+
+from discord import Embed, Message
+from discord.ext import commands
+from discord.ext.commands import Bot, Cog, Context, MessageConverter
+
+from bot import utils
+from bot.constants import Emojis
+
+log = logging.getLogger(__name__)
+
+UWU_WORDS = {
+ "fi": "fwi",
+ "l": "w",
+ "r": "w",
+ "some": "sum",
+ "th": "d",
+ "thing": "fing",
+ "tho": "fo",
+ "you're": "yuw'we",
+ "your": "yur",
+ "you": "yuw",
+}
+
+
+class Fun(Cog):
+ """A collection of general commands for fun."""
+
+ def __init__(self, bot: Bot) -> None:
+ self.bot = bot
+
+ @commands.command()
+ async def roll(self, ctx: Context, num_rolls: int = 1) -> None:
+ """Outputs a number of random dice emotes (up to 6)."""
+ output = ""
+ if num_rolls > 6:
+ num_rolls = 6
+ elif num_rolls < 1:
+ output = ":no_entry: You must roll at least once."
+ for _ in range(num_rolls):
+ terning = f"terning{random.randint(1, 6)}"
+ output += getattr(Emojis, terning, '')
+ await ctx.send(output)
+
+ @commands.command(name="uwu", aliases=("uwuwize", "uwuify",))
+ async def uwu_command(self, ctx: Context, *, text: str) -> None:
+ """
+ Converts a given `text` into it's uwu equivalent.
+
+ Also accepts a valid discord Message ID or link.
+ """
+ conversion_func = functools.partial(
+ utils.replace_many, replacements=UWU_WORDS, ignore_case=True, match_case=True
+ )
+ text, embed = await Fun._get_text_and_embed(ctx, text)
+ # Convert embed if it exists
+ if embed is not None:
+ embed = Fun._convert_embed(conversion_func, embed)
+ converted_text = conversion_func(text)
+ # Don't put >>> if only embed present
+ if converted_text:
+ converted_text = f">>> {converted_text.lstrip('> ')}"
+ await ctx.send(content=converted_text, embed=embed)
+
+ @commands.command(name="randomcase", aliases=("rcase", "randomcaps", "rcaps",))
+ async def randomcase_command(self, ctx: Context, *, text: str) -> None:
+ """
+ Randomly converts the casing of a given `text`.
+
+ Also accepts a valid discord Message ID or link.
+ """
+ def conversion_func(text: str) -> str:
+ """Randomly converts the casing of a given string."""
+ return "".join(
+ char.upper() if round(random.random()) else char.lower() for char in text
+ )
+ text, embed = await Fun._get_text_and_embed(ctx, text)
+ # Convert embed if it exists
+ if embed is not None:
+ embed = Fun._convert_embed(conversion_func, embed)
+ converted_text = conversion_func(text)
+ # Don't put >>> if only embed present
+ if converted_text:
+ converted_text = f">>> {converted_text.lstrip('> ')}"
+ await ctx.send(content=converted_text, embed=embed)
+
+ @staticmethod
+ async def _get_text_and_embed(ctx: Context, text: str) -> Tuple[str, Union[Embed, None]]:
+ """
+ Attempts to extract the text and embed from a possible link to a discord Message.
+
+ Returns a tuple of:
+ str: If `text` is a valid discord Message, the contents of the message, else `text`.
+ Union[Embed, None]: The embed if found in the valid Message, else None
+ """
+ embed = None
+ message = await Fun._get_discord_message(ctx, text)
+ if isinstance(message, Message):
+ text = message.content
+ # Take first embed because we can't send multiple embeds
+ if message.embeds:
+ embed = message.embeds[0]
+ return (text, embed)
+
+ @staticmethod
+ async def _get_discord_message(ctx: Context, text: str) -> Union[Message, str]:
+ """
+ Attempts to convert a given `text` to a discord Message object and return it.
+
+ Conversion will succeed if given a discord Message ID or link.
+ Returns `text` if the conversion fails.
+ """
+ try:
+ text = await MessageConverter().convert(ctx, text)
+ except commands.BadArgument:
+ log.debug(f"Input '{text:.20}...' is not a valid Discord Message")
+ return text
+
+ @staticmethod
+ def _convert_embed(func: Callable[[str, ], str], embed: Embed) -> Embed:
+ """
+ Converts the text in an embed using a given conversion function, then return the embed.
+
+ Only modifies the following fields: title, description, footer, fields
+ """
+ embed_dict = embed.to_dict()
+
+ embed_dict["title"] = func(embed_dict.get("title", ""))
+ embed_dict["description"] = func(embed_dict.get("description", ""))
+
+ if "footer" in embed_dict:
+ embed_dict["footer"]["text"] = func(embed_dict["footer"].get("text", ""))
+
+ if "fields" in embed_dict:
+ for field in embed_dict["fields"]:
+ field["name"] = func(field.get("name", ""))
+ field["value"] = func(field.get("value", ""))
+
+ return Embed.from_dict(embed_dict)
+
+
+def setup(bot: commands.Bot) -> None:
+ """Fun Cog load."""
+ bot.add_cog(Fun(bot))
+ log.info("Fun cog loaded")