diff options
Diffstat (limited to 'bot/seasons')
| -rw-r--r-- | bot/seasons/evergreen/fun.py | 5 | ||||
| -rw-r--r-- | bot/seasons/valentines/lovecalculator.py | 97 | ||||
| -rw-r--r-- | bot/seasons/valentines/valentine_zodiac.py | 59 | ||||
| -rw-r--r-- | bot/seasons/valentines/whoisvalentine.py | 53 |
4 files changed, 182 insertions, 32 deletions
diff --git a/bot/seasons/evergreen/fun.py b/bot/seasons/evergreen/fun.py index afe37b75..4da01dd1 100644 --- a/bot/seasons/evergreen/fun.py +++ b/bot/seasons/evergreen/fun.py @@ -3,6 +3,8 @@ import random from discord.ext import commands +from bot.constants import Emojis + log = logging.getLogger(__name__) @@ -25,7 +27,8 @@ class Fun: elif num_rolls < 1: output = ":no_entry: You must roll at least once." for _ in range(num_rolls): - output += ":terning%d: " % random.randint(1, 6) + terning = f"terning{random.randint(1, 6)}" + output += getattr(Emojis, terning, '') await ctx.send(output) diff --git a/bot/seasons/valentines/lovecalculator.py b/bot/seasons/valentines/lovecalculator.py index b995aef4..4df33b93 100644 --- a/bot/seasons/valentines/lovecalculator.py +++ b/bot/seasons/valentines/lovecalculator.py @@ -1,70 +1,105 @@ +import bisect +import hashlib import json import logging +import random from pathlib import Path -from random import choice +from typing import Union import discord +from discord import Member from discord.ext import commands +from discord.ext.commands import BadArgument, clean_content from bot.constants import Roles log = logging.getLogger(__name__) -with open(Path("bot", "resources", "valentines", "love_matches.json"), "r") as file: +with Path('bot', 'resources', 'valentines', 'love_matches.json').open() as file: LOVE_DATA = json.load(file) -LOVE_LEVELS = [int(x) for x in LOVE_DATA] + LOVE_DATA = sorted((int(key), value) for key, value in LOVE_DATA.items()) class LoveCalculator: """ A cog for calculating the love between two people """ + def __init__(self, bot): self.bot = bot @commands.command(aliases=('love_calculator', 'love_calc')) - @commands.cooldown(rate=1, per=5.0, type=commands.BucketType.user) - async def love(self, ctx, name_one: discord.Member, name_two: discord.Member = None): + @commands.cooldown(rate=1, per=5, type=commands.BucketType.user) + async def love(self, ctx, who: Union[Member, str], whom: Union[Member, str] = None): """ - Calculates the love between two given names + Tells you how much the two love each other. + + This command accepts users or arbitrary strings as arguments. + Users are converted from: + - User ID + - Mention + - name#discrim + - name + - nickname - DO NOT SPAM @mentions! There are five ways to hand over a name to this command: - 1. ID of the user - 2. Name + Discriminator of the user (name#discrim) (1) - 3. Username (1) - 4. Nickname (1) - 5. @mention + Any two arguments will always yield the same result, though the order of arguments matters: + Running .love joseph erlang will always yield the same result. + Running .love erlang joseph won't yield the same result as .love joseph erlang - Using method 1-4 is highly encouraged, as nobody likes unwanted pings + they'll count as spam. - Skipping the second name will lead to something awesome. + If you want to use multiple words for one argument, you must include quotes. + .love "Zes Vappa" "morning coffee" - *(1): If the name has any form of spacing, the name must be wrapped inside quotes. Example: - .love Ves Zappa Niko Laus -> Will not work - .love "Ves Zappa" "Niko Laus" -> Will work + If only one argument is provided, the subject will become one of the helpers at random. """ - if name_two is None: + if whom is None: staff = ctx.guild.get_role(Roles.helpers).members - name_two = choice(staff) - - love_meter = (name_one.id + name_two.id) % 101 - love_idx = str(sorted(x for x in LOVE_LEVELS if x <= love_meter)[-1]) - love_status = choice(LOVE_DATA[love_idx]["titles"]) - + whom = random.choice(staff) + + def normalize(arg): + if isinstance(arg, Member): + # if we are given a member, return name#discrim without any extra changes + arg = str(arg) + else: + # otherwise normalise case and remove any leading/trailing whitespace + arg = arg.strip().title() + # this has to be done manually to be applied to usernames + return clean_content(escape_markdown=True).convert(ctx, arg) + + who, whom = [await normalize(arg) for arg in (who, whom)] + + # make sure user didn't provide something silly such as 10 spaces + if not (who and whom): + raise BadArgument('Arguments be non-empty strings.') + + # hash inputs to guarantee consistent results (hashing algorithm choice arbitrary) + # + # hashlib is used over the builtin hash() function + # to guarantee same result over multiple runtimes + m = hashlib.sha256(who.encode() + whom.encode()) + # mod 101 for [0, 100] + love_percent = sum(m.digest()) % 101 + + # We need the -1 due to how bisect returns the point + # see the documentation for further detail + # https://docs.python.org/3/library/bisect.html#bisect.bisect + index = bisect.bisect(LOVE_DATA, (love_percent,)) - 1 + # we already have the nearest "fit" love level + # we only need the dict, so we can ditch the first element + _, data = LOVE_DATA[index] + + status = random.choice(data['titles']) embed = discord.Embed( - title=love_status, - description=( - f'{name_one.display_name} \u2764 {name_two.display_name}' - f' scored {love_meter}%!\n\u200b' - ), + title=status, + description=f'{who} \N{HEAVY BLACK HEART} {whom} scored {love_percent}%!\n\u200b', color=discord.Color.dark_magenta() ) embed.add_field( name='A letter from Dr. Love:', - value=LOVE_DATA[love_idx]["text"] + value=data['text'] ) - await ctx.message.channel.send(embed=embed) + await ctx.send(embed=embed) def setup(bot): diff --git a/bot/seasons/valentines/valentine_zodiac.py b/bot/seasons/valentines/valentine_zodiac.py new file mode 100644 index 00000000..06c0237d --- /dev/null +++ b/bot/seasons/valentines/valentine_zodiac.py @@ -0,0 +1,59 @@ +import logging +import random +from json import load +from pathlib import Path + +import discord +from discord.ext import commands + +from bot.constants import Colours + +log = logging.getLogger(__name__) + +LETTER_EMOJI = ':love_letter:' +HEART_EMOJIS = [":heart:", ":gift_heart:", ":revolving_hearts:", ":sparkling_heart:", ":two_hearts:"] + + +class ValentineZodiac: + """ + A cog that returns a counter compatible zodiac sign to the given user's zodiac sign. + """ + def __init__(self, bot): + self.bot = bot + self.zodiacs = self.load_json() + + @staticmethod + def load_json(): + p = Path('bot', 'resources', 'valentines', 'zodiac_compatibility.json') + with p.open() as json_data: + zodiacs = load(json_data) + return zodiacs + + @commands.command(name="partnerzodiac") + async def counter_zodiac(self, ctx, zodiac_sign): + """ + Provides a counter compatible zodiac sign to the given user's zodiac sign. + """ + try: + compatible_zodiac = random.choice(self.zodiacs[zodiac_sign.lower()]) + except KeyError: + return await ctx.send(zodiac_sign.capitalize() + " zodiac sign does not exist.") + + emoji1 = random.choice(HEART_EMOJIS) + emoji2 = random.choice(HEART_EMOJIS) + embed = discord.Embed( + title="Zodic Compatibility", + description=f'{zodiac_sign.capitalize()}{emoji1}{compatible_zodiac["Zodiac"]}\n' + f'{emoji2}Compatibility meter : {compatible_zodiac["compatibility_score"]}{emoji2}', + color=Colours.pink + ) + embed.add_field( + name=f'A letter from Dr.Zodiac {LETTER_EMOJI}', + value=compatible_zodiac['description'] + ) + await ctx.send(embed=embed) + + +def setup(bot): + bot.add_cog(ValentineZodiac(bot)) + log.debug("Valentine Zodiac cog loaded") diff --git a/bot/seasons/valentines/whoisvalentine.py b/bot/seasons/valentines/whoisvalentine.py new file mode 100644 index 00000000..2fe07aba --- /dev/null +++ b/bot/seasons/valentines/whoisvalentine.py @@ -0,0 +1,53 @@ +import json +import logging +from pathlib import Path +from random import choice + +import discord +from discord.ext import commands + +from bot.constants import Colours + +log = logging.getLogger(__name__) + +with open(Path("bot", "resources", "valentines", "valentine_facts.json"), "r") as file: + FACTS = json.load(file) + + +class ValentineFacts: + def __init__(self, bot): + self.bot = bot + + @commands.command(aliases=('whoisvalentine', 'saint_valentine')) + async def who_is_valentine(self, ctx): + """ + Displays info about Saint Valentine. + """ + embed = discord.Embed( + title="Who is Saint Valentine?", + description=FACTS['whois'], + color=Colours.pink + ) + embed.set_thumbnail( + url='https://upload.wikimedia.org/wikipedia/commons/thumb/f/f1/Saint_Valentine_-_' + 'facial_reconstruction.jpg/1024px-Saint_Valentine_-_facial_reconstruction.jpg' + ) + + await ctx.channel.send(embed=embed) + + @commands.command() + async def valentine_fact(self, ctx): + """ + Shows a random fact about Valentine's Day. + """ + embed = discord.Embed( + title=choice(FACTS['titles']), + description=choice(FACTS['text']), + color=Colours.pink + ) + + await ctx.channel.send(embed=embed) + + +def setup(bot): + bot.add_cog(ValentineFacts(bot)) |