diff options
author | 2019-07-31 18:49:40 -0400 | |
---|---|---|
committer | 2019-07-31 18:49:40 -0400 | |
commit | 4644a5fc4dac067b148e8bef525ae49c6cceec31 (patch) | |
tree | cdabfd60e99993728eecfd5f4554e3e82158107d | |
parent | Merge pull request #233 from Refisio/dpy-1.2 (diff) | |
parent | Additional review comment resolution (diff) |
Merge pull request #234 from python-discord/temp-branch
Implement Outstanding Feedback on PRs
-rw-r--r-- | bot/resources/easter/bunny_names.json | 29 | ||||
-rw-r--r-- | bot/resources/easter/easter_egg_facts.json | 17 | ||||
-rw-r--r-- | bot/resources/easter/easter_riddle.json | 82 | ||||
-rw-r--r-- | bot/resources/easter/egghead_questions.json | 4 | ||||
-rw-r--r-- | bot/seasons/easter/april_fools_vids.py | 2 | ||||
-rw-r--r-- | bot/seasons/easter/bunny_name_generator.py | 92 | ||||
-rw-r--r-- | bot/seasons/easter/easter_riddle.py | 101 | ||||
-rw-r--r-- | bot/seasons/easter/egg_facts.py | 62 | ||||
-rw-r--r-- | bot/seasons/evergreen/issues.py | 53 |
9 files changed, 439 insertions, 3 deletions
diff --git a/bot/resources/easter/bunny_names.json b/bot/resources/easter/bunny_names.json new file mode 100644 index 00000000..8c97169c --- /dev/null +++ b/bot/resources/easter/bunny_names.json @@ -0,0 +1,29 @@ +{ + "names": [ + "Flopsy", + "Hopsalot", + "Thumper", + "Nibbles", + "Daisy", + "Fuzzy", + "Cottontail", + "Carrot Top", + "Marshmallow", + "Lucky", + "Clover", + "Daffodil", + "Buttercup", + "Goldie", + "Dizzy", + "Trixie", + "Snuffles", + "Hopscotch", + "Skipper", + "Thunderfoot", + "Bigwig", + "Dandelion", + "Pipkin", + "Buckthorn", + "Skipper" + ] +} diff --git a/bot/resources/easter/easter_egg_facts.json b/bot/resources/easter/easter_egg_facts.json new file mode 100644 index 00000000..b0650b84 --- /dev/null +++ b/bot/resources/easter/easter_egg_facts.json @@ -0,0 +1,17 @@ +[ + "The first story of a rabbit (later named the \"Easter Bunny\") hiding eggs in a garden was published in 1680.", + "Rabbits are known to be prolific pro creators and are an ancient symbol of fertility and new life. The German immigrants brought the tale of Easter Bunny in the 1700s with the tradition of an egg-laying hare called \"Osterhase\". The kids then would make nests in which the creature would lay coloured eggs. The tradition has been revolutionized in the form of candies and gifts instead of eggs.", + "In earlier days, a festival of egg throwing was held in church, when the priest would throw a hard-boiled egg to one of the choirboys. It was then tossed from one choirboy to the next and whoever held the egg when the clock struck 12 on Easter, was the winner and could keep it.", + "In medieval times, Easter eggs were boiled with onions to give them a golden sheen. Edward I went beyond this tradition in 1290 and ordered 450 eggs to be covered in gold leaf and given as Easter gifts.", + "Decorating Easter eggs is an ancient tradition that dates back to 13th century. One of the explanations for this custom is that eggs were considered as a forbidden food during the Lenten season (40 days before Easter). Therefore, people would paint and decorate them to mark an end of the period of penance and fasting and later eat them on Easter. The tradition of decorating eggs is called Pysanka which is creating a traditional Ukrainian folk design using wax-resist method.", + "Members of the Greek Orthodox faith often paint their Easter eggs red, which symbolizes Jesus' blood and his victory over death. The color red, symbolizes renewal of life, such as, Jesus' resurrection.", + "Eggs rolling take place in many parts of the world which symbolizes stone which was rolled away from the tomb where Jesus' body was laid after his death.", + "Easter eggs have been considered as a symbol of fertility, rebirth and new life. The custom of giving eggs has been derived from Egyptians, Persians, Gauls, Greeks, and Romans.", + "The first chocolate Easter egg was made by Fry's in 1873. Before this, people would give hollow cardboard eggs, filled with gifts.", + "The tallest chocolate Easter egg was made in Italy in 2011. Standing 10.39 metres tall and weighing 7,200 kg, it was taller than a giraffe and heavier than an elephant.", + "The largest ever Easter egg hunt was in Florida, where 9,753 children searched for 501,000 eggs.", + "In 2007, an Easter egg covered in diamonds sold for almost £9 million. Every hour, a cockerel made of jewels pops up from the top of the Faberge egg, flaps its wings four times, nods its head three times and makes a crowing noise. The gold-and-pink enamel egg was made by the Russian royal family as an engagement gift for French aristocrat Baron Edouard de Rothschild.", + "The White House held their first official egg roll in 1878 when Rutherford B. Hayes was the President. It is a race in which children push decorated, hard-boiled eggs across the White House lawn as an annual event held the Monday after Easter. In 2009, the Obamas hosted their first Easter egg roll with the theme, \"Let's go play\" which was meant to encourage young people to lead healthy and active lives.", + "80 million chocolate Easter eggs are sold each year. This accounts for 10% of Britain's annual spending on chocolate!", + "John Cadbury soon followed suit and made his first Cadbury Easter egg in 1875. By 1892 the company was producing 19 different lines, all made from dark chocolate." +] diff --git a/bot/resources/easter/easter_riddle.json b/bot/resources/easter/easter_riddle.json new file mode 100644 index 00000000..e93f6dad --- /dev/null +++ b/bot/resources/easter/easter_riddle.json @@ -0,0 +1,82 @@ +[ + { + "question": "What kind of music do bunnies like?", + "riddles": [ + "Two words", + "Jump to the beat" + ], + "correct_answer": "Hip hop" + }, + { + "question": "What kind of jewelry do rabbits wear?", + "riddles": [ + "They can eat it too", + "14 ___ gold" + ], + "correct_answer": "14 carrot gold" + }, + { + "question": "What does the easter bunny get for making a basket?", + "riddles": [ + "KOBE!", + "1+1 = ?" + ], + "correct_answer": "2 points" + }, + { + "question": "Where does the easter bunny eat breakfast?", + "riddles": [ + "No waffles here", + "An international home" + ], + "correct_answer": "IHOP" + }, + { + "question": "What do you call a rabbit with fleas?", + "riddles": [ + "A bit of a looney tune", + "What's up Doc?" + ], + "correct_answer": "Bugs Bunny" + }, + { + "question": "Why was the little girl sad after the race?", + "riddles": [ + "2nd place?", + "Who beat her?" + ], + "correct_answer": "Because an egg beater" + }, + { + "question": "What happened to the Easter Bunny when he misbehaved at school?", + "riddles": [ + "Won't be back anymore", + "Worse than suspension" + ], + "correct_answer": "He was eggspelled" + }, + { + "question": "What kind of bunny can't hop?", + "riddles": [ + "Might melt in the sun", + "Fragile and yummy" + ], + "correct_answer": "A chocolate one" + }, + { + "question": "Where does the Easter Bunny get his eggs?", + "riddles": [ + "Not a bush or tree", + "Emoji for a body part" + ], + "correct_answer": "Eggplants" + }, + { + "question": "Why did the Easter Bunny have to fire the duck?", + "riddles": [ + "Quack", + "MY EGGS!!" + ], + "correct_answer": "He kept quacking the eggs" + } +] diff --git a/bot/resources/easter/egghead_questions.json b/bot/resources/easter/egghead_questions.json index e4e21ebe..5535f8e0 100644 --- a/bot/resources/easter/egghead_questions.json +++ b/bot/resources/easter/egghead_questions.json @@ -47,7 +47,7 @@ "1999", "1970" ], - "correct_answer": 2 + "correct_answer": 3 }, { "question": "Who is considered to be the founder of Earth Day?", @@ -178,4 +178,4 @@ ], "correct_answer": 0 } -]
\ No newline at end of file +] diff --git a/bot/seasons/easter/april_fools_vids.py b/bot/seasons/easter/april_fools_vids.py index 9fbe87a0..d921d07c 100644 --- a/bot/seasons/easter/april_fools_vids.py +++ b/bot/seasons/easter/april_fools_vids.py @@ -19,7 +19,7 @@ class AprilFoolVideos(commands.Cog): @staticmethod def load_json(): """A function to load JSON data.""" - p = Path('bot/resources/easterapril_fools_vids.json') + p = Path('bot/resources/easter/april_fools_vids.json') with p.open() as json_file: all_vids = load(json_file) return all_vids diff --git a/bot/seasons/easter/bunny_name_generator.py b/bot/seasons/easter/bunny_name_generator.py new file mode 100644 index 00000000..76d5c478 --- /dev/null +++ b/bot/seasons/easter/bunny_name_generator.py @@ -0,0 +1,92 @@ +import json +import logging +import random +import re +from pathlib import Path + +from discord.ext import commands + +log = logging.getLogger(__name__) + +with Path("bot/resources/easter/bunny_names.json").open("r", encoding="utf8") as f: + BUNNY_NAMES = json.load(f) + + +class BunnyNameGenerator(commands.Cog): + """Generate a random bunny name, or bunnify your Discord username!""" + + def __init__(self, bot): + self.bot = bot + + def find_separators(self, displayname): + """Check if Discord name contains spaces so we can bunnify an individual word in the name.""" + new_name = re.split(r'[_.\s]', displayname) + if displayname not in new_name: + return new_name + + def find_vowels(self, displayname): + """ + Finds vowels in the user's display name. + + If the Discord name contains a vowel and the letter y, + it will match one or more of these patterns. + Only the most recently matched pattern will apply the changes. + """ + expressions = [ + (r'a.+y', 'patchy'), + (r'e.+y', 'ears'), + (r'i.+y', 'ditsy'), + (r'o.+y', 'oofy'), + (r'u.+y', 'uffy'), + ] + + for exp, vowel_sub in expressions: + new_name = re.sub(exp, vowel_sub, displayname) + if new_name != displayname: + return new_name + + def append_name(self, displayname): + """Adds a suffix to the end of the Discord name""" + extensions = ['foot', 'ear', 'nose', 'tail'] + suffix = random.choice(extensions) + appended_name = displayname + suffix + + return appended_name + + @commands.command() + async def bunnyname(self, ctx): + """Picks a random bunny name from a JSON file""" + await ctx.send(random.choice(BUNNY_NAMES["names"])) + + @commands.command() + async def bunnifyme(self, ctx): + """Gets your Discord username and bunnifies it""" + username = ctx.message.author.display_name + + # If name contains spaces or other separators, get the individual words to randomly bunnify + spaces_in_name = self.find_separators(username) + + # If name contains vowels, see if it matches any of the patterns in this function + # If there are matches, the bunnified name is returned. + vowels_in_name = self.find_vowels(username) + + # Default if the checks above return None + unmatched_name = self.append_name(username) + + if spaces_in_name is not None: + replacements = ['Cotton', 'Fluff', 'Floof' 'Bounce', 'Snuffle', 'Nibble', 'Cuddle', 'Velvetpaw', 'Carrot'] + word_to_replace = random.choice(spaces_in_name) + substitute = random.choice(replacements) + bunnified_name = username.replace(word_to_replace, substitute) + elif vowels_in_name is not None: + bunnified_name = vowels_in_name + elif unmatched_name: + bunnified_name = unmatched_name + + await ctx.send(bunnified_name) + + +def setup(bot): + """Bunny Name Generator Cog load.""" + bot.add_cog(BunnyNameGenerator(bot)) + log.info("BunnyNameGenerator cog loaded.") diff --git a/bot/seasons/easter/easter_riddle.py b/bot/seasons/easter/easter_riddle.py new file mode 100644 index 00000000..56555586 --- /dev/null +++ b/bot/seasons/easter/easter_riddle.py @@ -0,0 +1,101 @@ +import asyncio +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__) + +with Path("bot/resources/easter/easter_riddle.json").open("r", encoding="utf8") as f: + RIDDLE_QUESTIONS = load(f) + +TIMELIMIT = 10 + + +class EasterRiddle(commands.Cog): + """This cog contains the command for the Easter quiz!""" + + def __init__(self, bot): + self.bot = bot + self.winners = [] + self.correct = "" + self.current_channel = None + + @commands.command(aliases=["riddlemethis", "riddleme"]) + async def riddle(self, ctx): + """ + Gives a random riddle, then provides 2 hints at certain intervals before revealing the answer. + + The duration of the hint interval can be configured by changing the TIMELIMIT constant in this file. + """ + if self.current_channel: + return await ctx.send(f"A riddle is already being solved in {self.current_channel.mention}!") + + self.current_channel = ctx.message.channel + + random_question = random.choice(RIDDLE_QUESTIONS) + question = random_question["question"] + hints = random_question["riddles"] + self.correct = random_question["correct_answer"] + + description = f"You have {TIMELIMIT} seconds before the first hint." + + riddle_embed = discord.Embed(title=question, description=description, colour=Colours.pink) + + await ctx.send(embed=riddle_embed) + await asyncio.sleep(TIMELIMIT) + + hint_embed = discord.Embed( + title=f"Here's a hint: {hints[0]}!", + colour=Colours.pink + ) + + await ctx.send(embed=hint_embed) + await asyncio.sleep(TIMELIMIT) + + hint_embed = discord.Embed( + title=f"Here's a hint: {hints[1]}!", + colour=Colours.pink + ) + + await ctx.send(embed=hint_embed) + await asyncio.sleep(TIMELIMIT) + + if self.winners: + win_list = " ".join(self.winners) + content = f"Well done {win_list} for getting it right!" + else: + content = "Nobody got it right..." + + answer_embed = discord.Embed( + title=f"The answer is: {self.correct}!", + colour=Colours.pink + ) + + await ctx.send(content, embed=answer_embed) + + self.winners = [] + self.current_channel = None + + @commands.Cog.listener() + async def on_message(self, message): + """If a non-bot user enters a correct answer, their username gets added to self.winners""" + if self.current_channel != message.channel: + return + + if self.bot.user == message.author: + return + + if message.content.lower() == self.correct.lower(): + self.winners.append(message.author.mention) + + +def setup(bot): + """Easter Riddle Cog load.""" + bot.add_cog(EasterRiddle(bot)) + log.info("Easter Riddle bot loaded") diff --git a/bot/seasons/easter/egg_facts.py b/bot/seasons/easter/egg_facts.py new file mode 100644 index 00000000..ae08ccd4 --- /dev/null +++ b/bot/seasons/easter/egg_facts.py @@ -0,0 +1,62 @@ +import asyncio +import logging +import random +from json import load +from pathlib import Path + +import discord +from discord.ext import commands + +from bot.constants import Channels +from bot.constants import Colours + + +log = logging.getLogger(__name__) + + +class EasterFacts(commands.Cog): + """ + A cog contains a command that will return an easter egg fact when called. + + It also contains a background task which sends an easter egg fact in the event channel everyday. + """ + + def __init__(self, bot): + self.bot = bot + self.facts = self.load_json() + + @staticmethod + def load_json(): + """Load a list of easter egg facts from the resource JSON file.""" + p = Path("bot/resources/easter/easter_egg_facts.json") + with p.open(encoding="utf8") as f: + return load(f) + + async def send_egg_fact_daily(self): + """A background task that sends an easter egg fact in the event channel everyday.""" + channel = self.bot.get_channel(Channels.seasonalbot_chat) + while True: + embed = self.make_embed() + await channel.send(embed=embed) + await asyncio.sleep(24 * 60 * 60) + + @commands.command(name='eggfact', aliases=['fact']) + async def easter_facts(self, ctx): + """Get easter egg facts.""" + embed = self.make_embed() + await ctx.send(embed=embed) + + def make_embed(self): + """Makes a nice embed for the message to be sent.""" + return discord.Embed( + colour=Colours.soft_red, + title="Easter Egg Fact", + description=random.choice(self.facts) + ) + + +def setup(bot): + """Easter Egg facts cog load.""" + bot.loop.create_task(EasterFacts(bot).send_egg_fact_daily()) + bot.add_cog(EasterFacts(bot)) + log.info("EasterFacts cog loaded") diff --git a/bot/seasons/evergreen/issues.py b/bot/seasons/evergreen/issues.py new file mode 100644 index 00000000..2a31a2e1 --- /dev/null +++ b/bot/seasons/evergreen/issues.py @@ -0,0 +1,53 @@ +import logging + +import discord +from discord.ext import commands + +from bot.constants import Colours + +log = logging.getLogger(__name__) + + +class Issues(commands.Cog): + """Cog that allows users to retrieve issues from GitHub.""" + + def __init__(self, bot): + self.bot = bot + + @commands.command(aliases=("issues",)) + async def issue(self, ctx, number: int, repository: str = "seasonalbot", user: str = "python-discord"): + """Command to retrieve issues from a GitHub repository.""" + api_url = f"https://api.github.com/repos/{user}/{repository}/issues/{number}" + failed_status = { + 404: f"Issue #{number} doesn't exist in the repository {user}/{repository}.", + 403: f"Rate limit exceeded. Please wait a while before trying again!" + } + + async with self.bot.http_session.get(api_url) as r: + json_data = await r.json() + response_code = r.status + + if response_code in failed_status: + return await ctx.send(failed_status[response_code]) + + repo_url = f"https://github.com/{user}/{repository}" + issue_embed = discord.Embed(colour=Colours.bright_green) + issue_embed.add_field(name="Repository", value=f"[{user}/{repository}]({repo_url})", inline=False) + issue_embed.add_field(name="Issue Number", value=f"#{number}", inline=False) + issue_embed.add_field(name="Status", value=json_data["state"].title()) + issue_embed.add_field(name="Link", value=json_data["html_url"], inline=False) + + description = json_data["body"] + if len(description) > 1024: + placeholder = " [...]" + description = f"{description[:1024 - len(placeholder)]}{placeholder}" + + issue_embed.add_field(name="Description", value=description, inline=False) + + await ctx.send(embed=issue_embed) + + +def setup(bot): + """Github Issues Cog Load.""" + bot.add_cog(Issues(bot)) + log.info("Issues cog loaded") |