Easter eggs

This commit is contained in:
stijndcl 2022-09-20 00:31:33 +02:00
parent 2638c5a3c4
commit 181118aa1d
7 changed files with 151 additions and 13 deletions

View file

@ -17,6 +17,7 @@ from didier.data.embeds.error_embed import create_error_embed
from didier.data.embeds.schedules import Schedule, parse_schedule
from didier.exceptions import HTTPException, NoMatch
from didier.utils.discord.prefix import get_prefix
from didier.utils.easter_eggs import detect_easter_egg
__all__ = ["Didier"]
@ -213,8 +214,9 @@ class Didier(commands.Bot):
await self.process_commands(message)
# TODO easter eggs
# TODO stats
easter_egg = await detect_easter_egg(self, message, self.database_caches.easter_eggs)
if easter_egg is not None:
await message.reply(easter_egg, mention_author=False)
async def _try_invoke_custom_command(self, message: discord.Message) -> bool:
"""Check if the message tries to invoke a custom command

View file

@ -1,18 +1,19 @@
import re
from typing import Optional
from discord import Message
from discord.ext import commands
from didier.data import constants
__all__ = ["get_prefix"]
__all__ = ["get_prefix", "match_prefix"]
def get_prefix(client: commands.Bot, message: Message) -> str:
"""Match a prefix against a message
def match_prefix(client: commands.Bot, message: Message) -> Optional[str]:
"""Try to match a prefix against a message, returning None instead of a default value
This is done dynamically to allow variable amounts of whitespace,
and through regexes to allow case-insensitivity among other things.
This is done dynamically through regexes to allow case-insensitivity
and variable amounts of whitespace among other things.
"""
mention = f"<@!?{client.user.id}>"
regex = r"^({})\s*"
@ -26,5 +27,13 @@ def get_prefix(client: commands.Bot, message: Message) -> str:
# .group() is inconsistent with whitespace, so that can't be used
return message.content[: match.end()]
# Matched nothing
return "didier"
return None
def get_prefix(client: commands.Bot, message: Message) -> str:
"""Match a prefix against a message, with a fallback
This is the main prefix function that is used by the bot
"""
# If nothing was matched, return "didier" as a fallback
return match_prefix(client, message) or "didier"

View file

@ -0,0 +1,48 @@
import random
from typing import Optional
import discord
from discord.ext import commands
from database.utils.caches import EasterEggCache
from didier.utils.discord.prefix import match_prefix
__all__ = ["detect_easter_egg"]
def _roll_easter_egg(response: str) -> Optional[str]:
"""Roll a random chance for an easter egg to be responded with
The chance for an easter egg to be used is 33%
"""
rolled = random.randint(0, 100) < 33
return response if rolled else None
async def detect_easter_egg(client: commands.Bot, message: discord.Message, cache: EasterEggCache) -> Optional[str]:
"""Try to detect an easter egg in a message"""
prefix = match_prefix(client, message)
content = message.content.strip().lower()
# Message calls Didier
if prefix is not None:
prefix = prefix.strip().lower()
# Message is only "Didier"
if content == prefix:
return "Hmm?"
else:
# Message invokes a command: do nothing
return None
for easter_egg in cache.easter_eggs:
# Exact matches
if easter_egg.exact and easter_egg.match == content:
return _roll_easter_egg(easter_egg.response)
# Matches that start with a certain term
if easter_egg.startswith and content.startswith(easter_egg.match):
return _roll_easter_egg(easter_egg.response)
return None