aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/bot.py8
-rw-r--r--bot/resources/valentines/love_matches.json52
-rw-r--r--bot/seasons/valentines/lovecalculator.py85
3 files changed, 84 insertions, 61 deletions
diff --git a/bot/bot.py b/bot/bot.py
index 2df550dc..12291a5f 100644
--- a/bot/bot.py
+++ b/bot/bot.py
@@ -5,6 +5,7 @@ from typing import List
from aiohttp import AsyncResolver, ClientSession, TCPConnector
from discord import Embed
+from discord.ext import commands
from discord.ext.commands import Bot
from bot import constants
@@ -61,3 +62,10 @@ class SeasonalBot(Bot):
embed.set_author(name=title, icon_url=icon)
await devlog.send(embed=embed)
+
+ async def on_command_error(self, context, exception):
+ # Don't punish the user for getting the arguments wrong
+ if isinstance(exception, commands.UserInputError):
+ context.command.reset_cooldown(context)
+ else:
+ super().on_command_error(context, exception)
diff --git a/bot/resources/valentines/love_matches.json b/bot/resources/valentines/love_matches.json
index a39c5d6b..8d50cd79 100644
--- a/bot/resources/valentines/love_matches.json
+++ b/bot/resources/valentines/love_matches.json
@@ -1,29 +1,27 @@
{
- "100": {
+ "0": {
"titles": [
- "\ud83d\udc9b When will you two marry? \ud83d\udc9b",
- "\ud83d\udc9b Now kiss already \ud83d\udc9b"
+ "\ud83d\udc94 There's no real connection between you two \ud83d\udc94"
],
- "text": "You two will most likely have the perfect relationship. But don't think that this means you don't have to do anything for it to work. Talking to each other and spending time together is key, even in a seemingly perfect relationship."
+ "text": "The chance of this relationship working out is really low. You can get it to work, but with high costs and no guarantee of working out. Do not sit back, spend as much time together as possible, talk a lot with each other to increase the chances of this relationship's survival."
},
- "95": {
+ "5": {
"titles": [
- "\ud83d\udc96 Love is in the air \ud83d\udc96",
- "\ud83d\udc96 Planned your future yet? \ud83d\udc96"
+ "\ud83d\udc99 A small acquaintance \ud83d\udc99"
],
- "text": "Your relationship will most likely work out perfect. This doesn't mean thought that you don't need to put effort into it. Talk to each other, spend time together, and you two won't have a hard time."
+ "text": "There might be a chance of this relationship working out somewhat well, but it is not very high. With a lot of time and effort you'll get it to work eventually, however don't count on it. It might fall apart quicker than you'd expect."
},
- "80": {
+ "20": {
"titles": [
- "\ud83d\udc95 Aww look you two fit so well together \ud83d\udc95"
+ "\ud83d\udc9c You two seem like casual friends \ud83d\udc9c"
],
- "text": "Your relationship will most likely work out well. Don't hesitate on making contact with each other though, as your relationship might suffer from a lack of time spent together. Talking with each other and spending time together is key."
+ "text": "The chance of this relationship working is not very high. You both need to put time and effort into this relationship, if you want it to work out well for both of you. Talk with each other about everything and don't lock yourself up. Spend time together. This will improve the chances of this relationship's survival by a lot."
},
- "60": {
+ "30": {
"titles": [
- "\u2764 So when will you two go on a date? \u2764"
+ "\ud83d\udc97 You seem like you are good friends \ud83d\udc97"
],
- "text": "Your relationship will most likely work out. It won't be perfect and you two need to spend a lot of time together, but if you keep on having contact, the good times in your relationship will outweigh the bad ones."
+ "text": "The chance of this relationship working is not very high, but its not that low either. If you both want this relationship to work, and put time and effort into it, meaning spending time together, talking to each other etc., than nothing shall stand in your way."
},
"45": {
"titles": [
@@ -31,28 +29,30 @@
],
"text": "Your relationship has a reasonable amount of working out. But do not overestimate yourself there. Your relationship will suffer good and bad times. Make sure to not let the bad times destroy your relationship, so do not hesitate to talk to each other, figure problems out together etc."
},
- "30": {
+ "60": {
"titles": [
- "\ud83d\udc97 You seem like you are good friends \ud83d\udc97"
+ "\u2764 So when will you two go on a date? \u2764"
],
- "text": "The chance of this relationship working is not very high, but its not that low either. If you both want this relationship to work, and put time and effort into it, meaning spending time together, talking to each other etc., than nothing shall stand in your way."
+ "text": "Your relationship will most likely work out. It won't be perfect and you two need to spend a lot of time together, but if you keep on having contact, the good times in your relationship will outweigh the bad ones."
},
- "20": {
+ "80": {
"titles": [
- "\ud83d\udc9c You two seem like casual friends \ud83d\udc9c"
+ "\ud83d\udc95 Aww look you two fit so well together \ud83d\udc95"
],
- "text": "The chance of this relationship working is not very high. You both need to put time and effort into this relationship, if you want it to work out well for both of you. Talk with each other about everything and don't lock yourself up. Spend time together. This will improve the chances of this relationship's survival by a lot."
+ "text": "Your relationship will most likely work out well. Don't hesitate on making contact with each other though, as your relationship might suffer from a lack of time spent together. Talking with each other and spending time together is key."
},
- "5": {
+ "95": {
"titles": [
- "\ud83d\udc99 A small acquaintance \ud83d\udc99"
+ "\ud83d\udc96 Love is in the air \ud83d\udc96",
+ "\ud83d\udc96 Planned your future yet? \ud83d\udc96"
],
- "text": "There might be a chance of this relationship working out somewhat well, but it is not very high. With a lot of time and effort you'll get it to work eventually, however don't count on it. It might fall apart quicker than you'd expect."
+ "text": "Your relationship will most likely work out perfect. This doesn't mean thought that you don't need to put effort into it. Talk to each other, spend time together, and you two won't have a hard time."
},
- "0": {
+ "100": {
"titles": [
- "\ud83d\udc94 There's no real connection between you two \ud83d\udc94"
+ "\ud83d\udc9b When will you two marry? \ud83d\udc9b",
+ "\ud83d\udc9b Now kiss already \ud83d\udc9b"
],
- "text": "The chance of this relationship working out is really low. You can get it to work, but with high costs and no guarantee of working out. Do not sit back, spend as much time together as possible, talk a lot with each other to increase the chances of this relationship's survival."
+ "text": "You two will most likely have the perfect relationship. But don't think that this means you don't have to do anything for it to work. Talking to each other and spending time together is key, even in a seemingly perfect relationship."
}
} \ No newline at end of file
diff --git a/bot/seasons/valentines/lovecalculator.py b/bot/seasons/valentines/lovecalculator.py
index b995aef4..aec72ef8 100644
--- a/bot/seasons/valentines/lovecalculator.py
+++ b/bot/seasons/valentines/lovecalculator.py
@@ -1,70 +1,85 @@
+import bisect
+import hashlib
import json
import logging
+import random
from pathlib import Path
-from random import choice
import discord
+from discord import Member
from discord.ext import commands
+from discord.ext.commands import clean_content
+from typing import Union
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
-
- 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
-
- 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.
-
- *(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
+ Tells you how much the two love each other.
"""
-
- if name_two is None:
+ # TODO better docstring
+ # figure out how to cram info about the intricacies of the command somehow
+ # - member conversion
+ # - asymmetry
+ # - consistency (from hashing)
+ # - need for quotes
+ # - I'm probably forgetting something
+
+ 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)
+
+ # if inputs were members, make sure to show name#discrim
+ # also make sure to escape all discord markdown to prevent mischief
+ cleaner = clean_content(escape_markdown=True, use_nicknames=False)
+ who, whom = [await cleaner.convert(ctx, str(arg)) for arg in (who, whom)]
+
+ # 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
+ # TODO: make it so `a ab` and `aa b` yield different results?
+ 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):