diff options
Diffstat (limited to 'bot')
| -rw-r--r-- | bot/constants.py | 1 | ||||
| -rw-r--r-- | bot/exts/fun/battleship.py | 4 | ||||
| -rw-r--r-- | bot/exts/fun/connect_four.py | 5 | ||||
| -rw-r--r-- | bot/exts/fun/fun.py | 10 | ||||
| -rw-r--r-- | bot/exts/fun/latex.py | 1 | ||||
| -rw-r--r-- | bot/exts/fun/uwu.py | 50 | ||||
| -rw-r--r-- | bot/exts/utilities/githubinfo.py | 6 | 
7 files changed, 69 insertions, 8 deletions
| diff --git a/bot/constants.py b/bot/constants.py index bc0b5931..eb9ee4b3 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -109,6 +109,7 @@ class Cats:  class Channels(NamedTuple):      advent_of_code = int(environ.get("AOC_CHANNEL_ID", 897932085766004786))      advent_of_code_commands = int(environ.get("AOC_COMMANDS_CHANNEL_ID", 897932607545823342)) +    algos_and_data_structs = 650401909852864553      bot_commands = 267659945086812160      community_meta = 267659945086812160      organisation = 551789653284356126 diff --git a/bot/exts/fun/battleship.py b/bot/exts/fun/battleship.py index beff196f..77e38427 100644 --- a/bot/exts/fun/battleship.py +++ b/bot/exts/fun/battleship.py @@ -110,8 +110,8 @@ class Game:          self.gameover: bool = False -        self.turn: Optional[discord.Member] = None -        self.next: Optional[discord.Member] = None +        self.turn: Optional[Player] = None +        self.next: Optional[Player] = None          self.match: Optional[re.Match] = None          self.surrender: bool = False diff --git a/bot/exts/fun/connect_four.py b/bot/exts/fun/connect_four.py index f53695d5..1b88d065 100644 --- a/bot/exts/fun/connect_four.py +++ b/bot/exts/fun/connect_four.py @@ -5,6 +5,7 @@ from typing import Optional, Union  import discord  import emojis +from discord import ClientUser, Member  from discord.ext import commands  from bot.bot import Bot @@ -71,7 +72,9 @@ class Game:              await self.message.add_reaction(CROSS_EMOJI)              await self.message.edit(content=None, embed=embed) -    async def game_over(self, action: str, player1: discord.user, player2: discord.user) -> None: +    async def game_over( +        self, action: str, player1: Union[ClientUser, Member], player2: Union[ClientUser, Member] +    ) -> None:          """Announces to public chat."""          if action == "win":              await self.channel.send(f"Game Over! {player1.mention} won against {player2.mention}") diff --git a/bot/exts/fun/fun.py b/bot/exts/fun/fun.py index a27ad85f..9ec9b9ee 100644 --- a/bot/exts/fun/fun.py +++ b/bot/exts/fun/fun.py @@ -3,8 +3,9 @@ import logging  import random  from collections.abc import Iterable  from pathlib import Path -from typing import Callable, Optional, Union +from typing import Callable, Literal, Optional, Union +import pyjokes  from discord import Embed, Message  from discord.ext import commands  from discord.ext.commands import BadArgument, Cog, Context, MessageConverter, clean_content @@ -41,7 +42,6 @@ class Fun(Cog):      def __init__(self, bot: Bot):          self.bot = bot -          self._caesar_cipher_embed = json.loads(Path("bot/resources/fun/caesar_info.json").read_text("UTF-8"))      @staticmethod @@ -212,6 +212,12 @@ class Fun(Cog):          return Embed.from_dict(embed_dict) +    @commands.command() +    async def joke(self, ctx: commands.Context, category: Literal["neutral", "chuck", "all"] = "all") -> None: +        """Retrieves a joke of the specified `category` from the pyjokes api.""" +        joke = pyjokes.get_joke(category=category) +        await ctx.send(joke) +  def setup(bot: Bot) -> None:      """Load the Fun cog.""" diff --git a/bot/exts/fun/latex.py b/bot/exts/fun/latex.py index f0f2f8c0..aeabcd20 100644 --- a/bot/exts/fun/latex.py +++ b/bot/exts/fun/latex.py @@ -35,6 +35,7 @@ PAD = 10  LATEX_ALLOWED_CHANNNELS = WHITELISTED_CHANNELS + (      Channels.data_science_and_ai, +    Channels.algos_and_data_structs,  ) diff --git a/bot/exts/fun/uwu.py b/bot/exts/fun/uwu.py index 0d650de0..0d75b0e2 100644 --- a/bot/exts/fun/uwu.py +++ b/bot/exts/fun/uwu.py @@ -1,6 +1,7 @@  import random  import re  import typing as t +from dataclasses import dataclass  from functools import partial  import discord @@ -46,7 +47,7 @@ EMOJIS = [      "^^;;",  ] -REGEX_WORD_REPLACE = re.compile(r"(?<![w])[lr](?![w])") +REGEX_WORD_REPLACE = re.compile(r"(?<!w)[lr](?!w)")  REGEX_PUNCTUATION = re.compile(r"[.!?\r\n\t]") @@ -56,6 +57,32 @@ SUBSTITUTE_STUTTER = r"\g<1>\g<2>-\g<2>"  REGEX_NYA = re.compile(r"n([aeou][^aeiou])")  SUBSTITUTE_NYA = r"ny\1" +REGEX_EMOJI = re.compile(r"<(a)?:(\w+?):(\d{15,21}?)>", re.ASCII) + + +@dataclass(frozen=True, eq=True) +class Emoji: +    """Data class for an Emoji.""" + +    name: str +    uid: int +    animated: bool = False + +    def __str__(self): +        anim_bit = "a" if self.animated else "" +        return f"<{anim_bit}:{self.name}:{self.uid}>" + +    def can_display(self, bot: Bot) -> bool: +        """Determines if a bot is in a server with the emoji.""" +        return bot.get_emoji(self.uid) is not None + +    @classmethod +    def from_match(cls, match: tuple[str, str, str]) -> t.Optional['Emoji']: +        """Creates an Emoji from a regex match tuple.""" +        if not match or len(match) != 3 or not match[2].isdecimal(): +            return None +        return cls(match[1], int(match[2]), match[0] == "a") +  class Uwu(Cog):      """Cog for the uwu command.""" @@ -99,6 +126,26 @@ class Uwu(Cog):              return f" {random.choice(EMOJIS)} "          return match_string +    def _ext_emoji_replace(self, input_string: str) -> str: +        """Replaces any emoji the bot cannot send in input_text with a random emoticons.""" +        groups = REGEX_EMOJI.findall(input_string) +        emojis = {Emoji.from_match(match) for match in groups} +        # Replace with random emoticon if unable to display +        emojis_map = { +            re.escape(str(e)): random.choice(EMOJIS) +            for e in emojis if e and not e.can_display(self.bot) +        } +        if emojis_map: +            # Pattern for all emoji markdowns to be replaced +            emojis_re = re.compile("|".join(emojis_map.keys())) +            # Replace matches with random emoticon +            return emojis_re.sub( +                lambda m: emojis_map[re.escape(m.group())], +                input_string +            ) +        # Return original if no replacement +        return input_string +      def _uwuify(self, input_string: str, *, stutter_strength: float = 0.2, emoji_strength: float = 0.1) -> str:          """Takes a string and returns an uwuified version of it."""          input_string = input_string.lower() @@ -107,6 +154,7 @@ class Uwu(Cog):          input_string = self._char_replace(input_string)          input_string = self._stutter(stutter_strength, input_string)          input_string = self._emoji(emoji_strength, input_string) +        input_string = self._ext_emoji_replace(input_string)          return input_string      @commands.command(name="uwu", aliases=("uwuwize", "uwuify",)) diff --git a/bot/exts/utilities/githubinfo.py b/bot/exts/utilities/githubinfo.py index 963f54e5..046f67df 100644 --- a/bot/exts/utilities/githubinfo.py +++ b/bot/exts/utilities/githubinfo.py @@ -149,7 +149,9 @@ class GithubInfo(commands.Cog):          for result in results:              if isinstance(result, IssueState): -                description_list.append(f"{result.emoji} [{result.title}]({result.url})") +                description_list.append( +                    f"{result.emoji} [[{result.repository}] #{result.number} {result.title}]({result.url})" +                )              elif isinstance(result, FetchError):                  description_list.append(f":x: [{result.return_code}] {result.message}") @@ -192,7 +194,7 @@ class GithubInfo(commands.Cog):              log.trace(f"Found {issues = }")              # Remove duplicates -            issues = set(issues) +            issues = list(dict.fromkeys(issues))              if len(issues) > MAXIMUM_ISSUES:                  embed = discord.Embed( | 
