diff options
-rw-r--r-- | bot/bot.py | 8 | ||||
-rw-r--r-- | bot/constants.py | 7 | ||||
-rw-r--r-- | bot/resources/valentines/love_matches.json | 52 | ||||
-rw-r--r-- | bot/resources/valentines/valentine_facts.json | 24 | ||||
-rw-r--r-- | bot/seasons/evergreen/fun.py | 5 | ||||
-rw-r--r-- | bot/seasons/valentines/lovecalculator.py | 97 | ||||
-rw-r--r-- | bot/seasons/valentines/whoisvalentine.py | 53 |
7 files changed, 188 insertions, 58 deletions
@@ -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/constants.py b/bot/constants.py index ec8a1a4d..cb191da9 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -72,6 +72,13 @@ class Emojis: christmas_tree = "\U0001F384" check = "\u2611" + terning1 = "<:terning1:431249668983488527>" + terning2 = "<:terning2:462339216987127808>" + terning3 = "<:terning3:431249694467948544>" + terning4 = "<:terning4:431249704769290241>" + terning5 = "<:terning5:431249716328792064>" + terning6 = "<:terning6:431249726705369098>" + class Lovefest: channel_id = int(environ.get("LOVEFEST_CHANNEL_ID", 542272993192050698)) 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/resources/valentines/valentine_facts.json b/bot/resources/valentines/valentine_facts.json new file mode 100644 index 00000000..d2ffa980 --- /dev/null +++ b/bot/resources/valentines/valentine_facts.json @@ -0,0 +1,24 @@ +{ + "whois": "Saint Valentine, officially Saint Valentine of Rome, was a widely recognized 3rd-century christian saint, commemorated on February 14. He was a priest and bishop, ministering persecuted Christians in the Roman Empire, and is associated with a tradition of courtly love since the High Middle Ages, a period commenced around the year 1000AD and lasting until around 1250AD. He was martyred and buried at a Christian cemetery on the Via Flaminia on February 14.\n\nThere are a bunch of inconsistencies in the identification of the saint, however there are evidences for 3 saints that appear in connection with February 14. One of them, Saint Valentine of Terni, is believed to be the one associated with a vision restoration miracle, which happening during his imprisonment. In that, he restored the eyesight of his jailer's daughter, and, on the evening before his execution, supposedly sent her a letter signed with 'Your Valentine' (tuum valentinum). This makes this saint the one we today associate with Saint Valentine's Day.\n\nThe artist Cicero Moraes attempted a facial reconstruction of Saint Valentine, which can be seen in the thumbnail.", + "titles": [ + "\u2764 Facts \u00e1 la carte \u2764", + "\u2764 Would you like some cheese with your wi... facts? \u2764", + "\u2764 Facts to raise your pulse \u2764", + "\u2764 Love Facts, Episode #42 \u2764", + "\u2764 It's a fact not a fact, duh \u2764", + "\u2764 Candlelight din... facts! \u2764" + ], + "text": [ + "The expression 'From your Valentine' derives from a legend in which Saint Valentine, imprisoned after persecution and not wanting to convert to Roman paganism, performed a miracle on Julia, his jailer Asterius's blind daughter, restoring her eyesight. On the evening before his execution, he is supposed to have written a letter to the jailers daughter, signing as 'Your Valentine' (tuum valentinum).", + "Valentine's Day wasn't really associated with anything romantic, until the 14th century England where it's association with romantic love had begun from within the circle of Geoffrey Chaucer, a famous english poet and author, also called 'Father of English literature' for his work. He is best known for 'The Caunterbury Tales', a collection of 24 stories, which are presented as part of a story-telling contest by a group of pilgrims on their travel from London to Canterbury.", + "It's only been roughly 300 years, that the Valentine's Day evolved into what we know today.", + "The wide usage of hearts on Valentine's day derived from a legend, in which Saint Valentine cut hearts from parchment, giving them to persecuted Christians and soldiers married by him. He did that \"to remind these man of their vows and God's love\"", + "In 1797, a British publisher developed \"The Young Man's Valentine Writer\", to assist young men in composing their own sentimental verses to ladies they felt attracted to.", + "If you've never gotten any handwritten Valentine cards, this may be due to the fact, that in the 19th century, handwritten notes have given away to mass-produced greeting cards.", + "In 1868, a British chocolate company called Cadbury created so called 'Fancy Boxes', which essentially were a decorated box of chocolates in the shape of a heart. This set a trend, such that these boxes were quickly associated with Valentine's Day.", + "Roses are red,\nviolet's are blue,\nI can't rhyme,\nbut I still do.\n\u200b\nThis poem in particular,\nit will stay forever,\nderives from The Faerie Queene,\nan epic poem you probably have never seen.\n\n\"She bath'd with roses red, and violets blew,\nAnd all the sweetest flowres, that in the forrest grew.\"\n\nThese verses, with most immense sway,\nlead to the poem we still hear today.", + "The earliest Valentine poem known is a rondeau, a form of medieval/renaissance French poetry, composed by Charles, Duke of Orl\u00e9ans to his wife:\n\n\"Je suis desja d'amour tann\u00e9,\nMa tres doulce Valentin\u00e9e\"", + "There's a form of cryptological communication called 'Floriography', in which you communicate through flowers. Meaning has been attributed to flowers for thousands of years, and some form of floriography has been practiced in traditional cultures throughout Europe, Asia, and Africa. Here are some meanings for roses you might want to take a look at, if you plan on gifting your loved one a bouquet of roses on Valentine's Day:\n\u200b\nRed: eternal love\nPink: young, developing love\nWhite: innocence, fervor, loyalty\nOrange: happiness, security\nViolet: love at first sight\nBlue: unfulfilled longing, quiet desire\nYellow: friendship, jealousy, envy, infidelity\nBlack: unfulfilled longing, quiet desire, grief, hatred, misfortune, death", + "Traditionally, young girls in the U.S. and the U.K. believed they could tell what type of man they would marry depending on the type of bird they saw first on Valentine's Day. If they saw a blackbird, they would marry a clergyman, a robin redbreast indicated a sailor, and a goldfinch indicated a rich man. A sparrow meant they would marry a farmer, a bluebird indicated a happy man, and a crossbill meant an argumentative man. If they saw a dove, they would marry a good man, but seeing a woodpecker meant they would not marry at all." + ] +}
\ No newline at end of file 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/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)) |