diff options
author | 2021-09-05 00:31:20 -0400 | |
---|---|---|
committer | 2021-09-05 00:31:20 -0400 | |
commit | 02512e43f3d68ffd89654c5f2e9e3e9a27c0c018 (patch) | |
tree | 4b62a6dbb39601f02aa435c7eb8a10433585c3bb /bot/exts/evergreen/fun.py | |
parent | Move snakes commands into fun folder (diff) |
Move game and fun commands to Fun folder, fix ddg
This moves all the fun commands and games into the fun folder.
This commit also makes changes to the duck_game.
It was setting a footer during an embed init, which is no longer
possible with the version of d.py we use. Additionally, an issue with
editing an embed that had a local image loaded.
The workaround for the time being is to update the message,
not the embed.
Diffstat (limited to 'bot/exts/evergreen/fun.py')
-rw-r--r-- | bot/exts/evergreen/fun.py | 250 |
1 files changed, 0 insertions, 250 deletions
diff --git a/bot/exts/evergreen/fun.py b/bot/exts/evergreen/fun.py deleted file mode 100644 index 4bbfe859..00000000 --- a/bot/exts/evergreen/fun.py +++ /dev/null @@ -1,250 +0,0 @@ -import functools -import json -import logging -import random -from collections.abc import Iterable -from pathlib import Path -from typing import Callable, Optional, Union - -from discord import Embed, Message -from discord.ext import commands -from discord.ext.commands import BadArgument, Cog, Context, MessageConverter, clean_content - -from bot import utils -from bot.bot import Bot -from bot.constants import Client, Colours, Emojis -from bot.utils import helpers - -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", -} - - -def caesar_cipher(text: str, offset: int) -> Iterable[str]: - """ - Implements a lazy Caesar Cipher algorithm. - - Encrypts a `text` given a specific integer `offset`. The sign - of the `offset` dictates the direction in which it shifts to, - with a negative value shifting to the left, and a positive - value shifting to the right. - """ - for char in text: - if not char.isascii() or not char.isalpha() or char.isspace(): - yield char - continue - - case_start = 65 if char.isupper() else 97 - true_offset = (ord(char) - case_start + offset) % 26 - - yield chr(case_start + true_offset) - - -class Fun(Cog): - """A collection of general commands for fun.""" - - def __init__(self, bot: Bot): - self.bot = bot - - self._caesar_cipher_embed = json.loads(Path("bot/resources/evergreen/caesar_info.json").read_text("UTF-8")) - - @staticmethod - def _get_random_die() -> str: - """Generate a random die emoji, ready to be sent on Discord.""" - die_name = f"dice_{random.randint(1, 6)}" - return getattr(Emojis, die_name) - - @commands.command() - async def roll(self, ctx: Context, num_rolls: int = 1) -> None: - """Outputs a number of random dice emotes (up to 6).""" - if 1 <= num_rolls <= 6: - dice = " ".join(self._get_random_die() for _ in range(num_rolls)) - await ctx.send(dice) - else: - raise BadArgument(f"`{Client.prefix}roll` only supports between 1 and 6 rolls.") - - @commands.command(name="uwu", aliases=("uwuwize", "uwuify",)) - async def uwu_command(self, ctx: Context, *, text: clean_content(fix_channel_mentions=True)) -> None: - """Converts a given `text` into it's uwu equivalent.""" - 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) - converted_text = helpers.suppress_links(converted_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: clean_content(fix_channel_mentions=True)) -> None: - """Randomly converts the casing of a given `text`.""" - 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) - converted_text = helpers.suppress_links(converted_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.group(name="caesarcipher", aliases=("caesar", "cc",)) - async def caesarcipher_group(self, ctx: Context) -> None: - """ - Translates a message using the Caesar Cipher. - - See `decrypt`, `encrypt`, and `info` subcommands. - """ - if ctx.invoked_subcommand is None: - await ctx.invoke(self.bot.get_command("help"), "caesarcipher") - - @caesarcipher_group.command(name="info") - async def caesarcipher_info(self, ctx: Context) -> None: - """Information about the Caesar Cipher.""" - embed = Embed.from_dict(self._caesar_cipher_embed) - embed.colour = Colours.dark_green - - await ctx.send(embed=embed) - - @staticmethod - async def _caesar_cipher(ctx: Context, offset: int, msg: str, left_shift: bool = False) -> None: - """ - Given a positive integer `offset`, translates and sends the given `msg`. - - Performs a right shift by default unless `left_shift` is specified as `True`. - - Also accepts a valid Discord Message ID or link. - """ - if offset < 0: - await ctx.send(":no_entry: Cannot use a negative offset.") - return - - if left_shift: - offset = -offset - - def conversion_func(text: str) -> str: - """Encrypts the given string using the Caesar Cipher.""" - return "".join(caesar_cipher(text, offset)) - - text, embed = await Fun._get_text_and_embed(ctx, msg) - - if embed is not None: - embed = Fun._convert_embed(conversion_func, embed) - - converted_text = conversion_func(text) - - if converted_text: - converted_text = f">>> {converted_text.lstrip('> ')}" - - await ctx.send(content=converted_text, embed=embed) - - @caesarcipher_group.command(name="encrypt", aliases=("rightshift", "rshift", "enc",)) - async def caesarcipher_encrypt(self, ctx: Context, offset: int, *, msg: str) -> None: - """ - Given a positive integer `offset`, encrypt the given `msg`. - - Performs a right shift of the letters in the message. - - Also accepts a valid Discord Message ID or link. - """ - await self._caesar_cipher(ctx, offset, msg, left_shift=False) - - @caesarcipher_group.command(name="decrypt", aliases=("leftshift", "lshift", "dec",)) - async def caesarcipher_decrypt(self, ctx: Context, offset: int, *, msg: str) -> None: - """ - Given a positive integer `offset`, decrypt the given `msg`. - - Performs a left shift of the letters in the message. - - Also accepts a valid Discord Message ID or link. - """ - await self._caesar_cipher(ctx, offset, msg, left_shift=True) - - @staticmethod - async def _get_text_and_embed(ctx: Context, text: str) -> tuple[str, Optional[Embed]]: - """ - Attempts to extract the text and embed from a possible link to a discord Message. - - Does not retrieve the text and embed from the Message if it is in a channel the user does - not have read permissions in. - - Returns a tuple of: - str: If `text` is a valid discord Message, the contents of the message, else `text`. - Optional[Embed]: The embed if found in the valid Message, else None - """ - embed = None - - msg = await Fun._get_discord_message(ctx, text) - # Ensure the user has read permissions for the channel the message is in - if isinstance(msg, Message): - permissions = msg.channel.permissions_for(ctx.author) - if permissions.read_messages: - text = msg.clean_content - # Take first embed because we can't send multiple embeds - if msg.embeds: - embed = msg.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: Bot) -> None: - """Load the Fun cog.""" - bot.add_cog(Fun(bot)) |