aboutsummaryrefslogtreecommitdiffstats
path: root/bot/seasons
diff options
context:
space:
mode:
Diffstat (limited to 'bot/seasons')
-rw-r--r--bot/seasons/evergreen/fun.py5
-rw-r--r--bot/seasons/valentines/lovecalculator.py97
-rw-r--r--bot/seasons/valentines/valentine_zodiac.py59
-rw-r--r--bot/seasons/valentines/whoisvalentine.py53
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))