From 5e73471999330b4bfd12437c90ee33c9b0c02656 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Mon, 7 Oct 2019 21:29:34 +0530 Subject: Corrected a few typos in the json file and also the following refinements for the quiz game: New scoreboard for every game. Store overall score board which refreshs when bot restarts. --- bot/resources/evergreen/trivia_quiz.json | 3 +- bot/seasons/evergreen/trivia_quiz.py | 82 ++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 27 deletions(-) (limited to 'bot') diff --git a/bot/resources/evergreen/trivia_quiz.json b/bot/resources/evergreen/trivia_quiz.json index 1ad2a1e1..66df3df7 100644 --- a/bot/resources/evergreen/trivia_quiz.json +++ b/bot/resources/evergreen/trivia_quiz.json @@ -71,6 +71,7 @@ { "id": 106, "question": "Which country is known as the \"Land of Thunderbolt\"?", + "answer": "Bhutan", "info": "Bhutan is known as the \"Land of Thunder Dragon\" or \"Land of Thunderbolt\" due to the violent and large thunderstorms that whip down through the valleys from the Himalayas. The dragon reference was due to people thinking the sparkling light of thunderbolts was the red fire of a dragon." }, { @@ -129,7 +130,7 @@ }, { "id": 116, - "question": "The Vally Of The Kings is located in which country?", + "question": "The Valley Of The Kings is located in which country?", "answer": "Egypt", "info": "The Valley of the Kings, also known as the Valley of the Gates of the Kings, is a valley in Egypt where, for a period of nearly 500 years from the 16th to 11th century BC, rock cut tombs were excavated for the pharaohs and powerful nobles of the New Kingdom (the Eighteenth to the Twentieth Dynasties of Ancient Egypt)." }, diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 798523e6..1c2ba969 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -28,10 +28,11 @@ class TriviaQuiz(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot = bot self.questions = self.load_questions() - self.game_status = {} - self.game_owners = {} + self.game_status = {} # A variable to store the game status: either running or not running. + self.game_owners = {} # A variable to store the person's ID who started the quiz game in a channel. self.question_limit = 4 - self.player_dict = {} + self.player_scores = {} # A variable to store all player's scores for a bot session. + self.game_player_scores = {} # A variable to store temporary game player's scores. self.categories = { "general": "Test your general knowledge" # "retro": "Questions related to retro gaming." @@ -50,21 +51,22 @@ class TriviaQuiz(commands.Cog): """ Start/Stop a quiz! - arguments: - option: - - start : to start a quiz in a channel - - stop : stop the quiz running in that channel. + If the quiz game is running, then the owner or a mod can stop it by using this command + without providing any arguments and vice versa. Questions for the quiz can be selected from the following categories: - general : Test your general knowledge. (default) - (we wil be adding more later) + (we wil be adding more later.) """ category = category.lower() if ctx.channel.id not in self.game_status: self.game_status[ctx.channel.id] = False - self.player_dict[ctx.channel.id] = {} + if ctx.channel.id not in self.game_player_scores: + self.game_player_scores[ctx.channel.id] = {} + + # Start game if not running. if not self.game_status[ctx.channel.id]: self.game_owners[ctx.channel.id] = ctx.author self.game_status[ctx.channel.id] = True @@ -77,16 +79,18 @@ class TriviaQuiz(commands.Cog): ) await ctx.send(embed=start_embed) # send an embed with the rules await asyncio.sleep(1) - + # Stop game is running. else: + # Check if the author is the owner or a mod. if ( ctx.author == self.game_owners[ctx.channel.id] or Roles.moderator in [role.id for role in ctx.author.roles] ): await ctx.send("Quiz is no longer running.") - await self.declare_winner(ctx.channel, self.player_dict[ctx.channel.id]) + await self.declare_winner(ctx.channel, self.game_player_scores[ctx.channel.id]) self.game_status[ctx.channel.id] = False del self.game_owners[ctx.channel.id] + self.game_player_scores[ctx.channel.id] = {} else: await ctx.send(f"{ctx.author.mention}, you are not authorised to stop this game :ghost: !") @@ -94,21 +98,23 @@ class TriviaQuiz(commands.Cog): embed = self.category_embed await ctx.send(embed=embed) return + topic = self.questions[category] - unanswered = 0 done_question = [] hint_no = 0 answer = None while self.game_status[ctx.channel.id]: + + # Exit quiz if number of questions for a round are already sent. if len(done_question) > self.question_limit and hint_no == 0: await ctx.send("The round ends here.") - await self.declare_winner(ctx.channel, self.player_dict[ctx.channel.id]) - break - if unanswered > 3: - await ctx.send("Game stopped due to inactivity.") - await self.declare_winner(ctx.channel, self.player_dict[ctx.channel.id]) + await self.declare_winner(ctx.channel, self.game_player_scores[ctx.channel.id]) + self.game_status[ctx.channel.id] = False + del self.game_owners[ctx.channel.id] + self.game_player_scores[ctx.channel.id] = {} break + # If no hint has been sent or any time alert. Basically if hint_no = 0 means it is a new question. if hint_no == 0: while True: question_dict = random.choice(topic) @@ -121,16 +127,20 @@ class TriviaQuiz(commands.Cog): embed = discord.Embed(colour=discord.Colour.gold()) embed.title = f"Question #{len(done_question)}" embed.description = q - await ctx.send(embed=embed) + await ctx.send(embed=embed) # Send question embed. + # A function to check whether user input is the correct answer(close to the right answer) def check(m: discord.Message) -> bool: ratio = fuzz.ratio(answer.lower(), m.content.lower()) return ratio > 85 and m.channel == ctx.channel try: msg = await self.bot.wait_for('message', check=check, timeout=10) except asyncio.TimeoutError: + # In case of TimeoutError and the game has been stopped, then do nothing. if self.game_status[ctx.channel.id] is False: break + + # if number of hints sent or time alerts sent is less than 2, then send one. if hint_no < 2: hint_no += 1 if "hints" in question_dict: @@ -139,36 +149,56 @@ class TriviaQuiz(commands.Cog): else: await ctx.send(f"Cmon guys, {30-hint_no*10}s left!") + # Once hint or time alerts has been sent 2 times, the hint_no value will be 3 + # If hint_no > 2, then it means that all hints/time alerts have been sent. + # Also means that the answer is not yet given and the bot sends the answer and the next question. else: response = random.choice(WRONG_ANS_RESPONSE) expression = random.choice(ANNOYED_EXPRESSIONS) await ctx.send(f"{response} {expression}") await self.send_answer(ctx.channel, question_dict) await asyncio.sleep(1) - hint_no = 0 - unanswered += 1 - await self.send_score(ctx.channel, self.player_dict[ctx.channel.id]) + + hint_no = 0 # init hint_no = 0 so that 2 hints/time alerts can be sent for the new question. + + await self.send_score(ctx.channel, self.game_player_scores[ctx.channel.id]) await asyncio.sleep(2) else: + # Reduce points by 25 for every hint/time alert that has been sent. points = 100 - 25*hint_no - if msg.author in self.player_dict[ctx.channel.id]: - self.player_dict[ctx.channel.id][msg.author] += points + if msg.author in self.game_player_scores[ctx.channel.id]: + self.game_player_scores[ctx.channel.id][msg.author] += points + else: + self.game_player_scores[ctx.channel.id][msg.author] = points + + # Also updating the overall scoreboard. + if msg.author in self.player_scores: + self.player_scores[msg.author] += points else: - self.player_dict[ctx.channel.id][msg.author] = points + self.player_scores[msg.author] = points + hint_no = 0 - unanswered = 0 + await ctx.send(f"{msg.author.mention} got the correct answer :tada: {points} points for ya.") await self.send_answer(ctx.channel, question_dict) - await self.send_score(ctx.channel, self.player_dict[ctx.channel.id]) + await self.send_score(ctx.channel, self.game_player_scores[ctx.channel.id]) await asyncio.sleep(2) + @commands.command(name="scoreboard") + async def overall_scoreboard(self, ctx): + """View everyone's score for this bot session.""" + await self.send_score(ctx.channel, self.player_scores) + @staticmethod async def send_score(channel: discord.TextChannel, player_data: dict) -> None: """A function which sends the score.""" embed = discord.Embed(colour=discord.Colour.blue()) embed.title = "Score Board" embed.description = "" + if len(player_data) == 0: + await channel.send("No one has made it to the scoreboard yet.") + return for k, v in player_data.items(): embed.description += f"{k} : {v}\n" await channel.send(embed=embed) -- cgit v1.2.3 From d7510a32f408c7cdca3355051987e7df0806b3b4 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Mon, 7 Oct 2019 21:38:24 +0530 Subject: added function annotations to new command --- bot/seasons/evergreen/trivia_quiz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 1c2ba969..5b8eb65e 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -186,7 +186,7 @@ class TriviaQuiz(commands.Cog): await asyncio.sleep(2) @commands.command(name="scoreboard") - async def overall_scoreboard(self, ctx): + async def overall_scoreboard(self, ctx: commands.Context)-> None: """View everyone's score for this bot session.""" await self.send_score(ctx.channel, self.player_scores) -- cgit v1.2.3 From da1596f983e5ef19a56da5f9a62ffcbd8969283d Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Mon, 7 Oct 2019 21:43:15 +0530 Subject: fixed lint errors --- bot/seasons/evergreen/trivia_quiz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 5b8eb65e..9a5cf43c 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -186,7 +186,7 @@ class TriviaQuiz(commands.Cog): await asyncio.sleep(2) @commands.command(name="scoreboard") - async def overall_scoreboard(self, ctx: commands.Context)-> None: + async def overall_scoreboard(self, ctx: commands.Context) -> None: """View everyone's score for this bot session.""" await self.send_score(ctx.channel, self.player_scores) -- cgit v1.2.3 From 137a90c323364f8e521a9843cb8b929d7e2b90b4 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Sun, 13 Oct 2019 21:47:25 +0530 Subject: Updated the code as per the suggestions and they are the following: - Corrected all typos. - the quiz command is now a command group to allocate the leaderboard command(a command which shows the leaderboard for the current bot session). - Few other refinements with language and stuff. --- bot/seasons/evergreen/trivia_quiz.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 9a5cf43c..f7ad9f3a 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -46,7 +46,7 @@ class TriviaQuiz(commands.Cog): questions = json.load(json_data) return questions - @commands.command(name="quiz", aliases=["trivia"]) + @commands.group(name="quiz", aliases=["trivia"], invoke_without_command=True) async def quiz_game(self, ctx: commands.Context, category: str = "general") -> None: """ Start/Stop a quiz! @@ -56,7 +56,7 @@ class TriviaQuiz(commands.Cog): Questions for the quiz can be selected from the following categories: - general : Test your general knowledge. (default) - (we wil be adding more later.) + (More to come!) """ category = category.lower() @@ -79,12 +79,12 @@ class TriviaQuiz(commands.Cog): ) await ctx.send(embed=start_embed) # send an embed with the rules await asyncio.sleep(1) - # Stop game is running. + # Stop game if running. else: - # Check if the author is the owner or a mod. + # Check if the author is the game starter or a moderator. if ( ctx.author == self.game_owners[ctx.channel.id] - or Roles.moderator in [role.id for role in ctx.author.roles] + or any(Roles.moderator == role.id for role in ctx.author.roles) ): await ctx.send("Quiz is no longer running.") await self.declare_winner(ctx.channel, self.game_player_scores[ctx.channel.id]) @@ -185,8 +185,8 @@ class TriviaQuiz(commands.Cog): await self.send_score(ctx.channel, self.game_player_scores[ctx.channel.id]) await asyncio.sleep(2) - @commands.command(name="scoreboard") - async def overall_scoreboard(self, ctx: commands.Context) -> None: + @quiz_game.command(name="leaderboard") + async def leaderboard(self, ctx: commands.Context) -> None: """View everyone's score for this bot session.""" await self.send_score(ctx.channel, self.player_scores) @@ -197,10 +197,12 @@ class TriviaQuiz(commands.Cog): embed.title = "Score Board" embed.description = "" if len(player_data) == 0: - await channel.send("No one has made it to the scoreboard yet.") + await channel.send("No one has made it to the leaderboard yet.") return - for k, v in player_data.items(): - embed.description += f"{k} : {v}\n" + sorted_dict = sorted(player_data.items(), key=lambda a: a[1], reverse=True) + for item in sorted_dict: + + embed.description += f"{item[0]} : {item[1]}\n" await channel.send(embed=embed) @staticmethod -- cgit v1.2.3 From 1332d9e5eaf9e2d7fafa8f6c90216c2b012f3743 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Thu, 17 Oct 2019 18:03:25 +0530 Subject: fixed bugs such as incorrect time to send the category embed, game will no longer run again if stopped n stuff. --- bot/seasons/evergreen/trivia_quiz.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index f7ad9f3a..d4e582af 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -58,29 +58,14 @@ class TriviaQuiz(commands.Cog): - general : Test your general knowledge. (default) (More to come!) """ - category = category.lower() - if ctx.channel.id not in self.game_status: self.game_status[ctx.channel.id] = False if ctx.channel.id not in self.game_player_scores: self.game_player_scores[ctx.channel.id] = {} - # Start game if not running. - if not self.game_status[ctx.channel.id]: - self.game_owners[ctx.channel.id] = ctx.author - self.game_status[ctx.channel.id] = True - start_embed = discord.Embed(colour=discord.Colour.red()) - start_embed.title = "Quiz game Starting!!" - start_embed.description = "Each game consists of 5 questions.\n" - start_embed.description += "**Rules :**\nNo cheating and have fun!" - start_embed.set_footer( - text="Points for a question reduces by 25 after 10s or after a hint. Total time is 30s per question" - ) - await ctx.send(embed=start_embed) # send an embed with the rules - await asyncio.sleep(1) # Stop game if running. - else: + if self.game_status[ctx.channel.id] is True: # Check if the author is the game starter or a moderator. if ( ctx.author == self.game_owners[ctx.channel.id] @@ -93,12 +78,29 @@ class TriviaQuiz(commands.Cog): self.game_player_scores[ctx.channel.id] = {} else: await ctx.send(f"{ctx.author.mention}, you are not authorised to stop this game :ghost: !") + return + category = category.lower() + # Send embed showing available categories if inputted category is invalid. if category not in self.categories: embed = self.category_embed await ctx.send(embed=embed) return + # Start game if not running. + if self.game_status[ctx.channel.id] is False: + self.game_owners[ctx.channel.id] = ctx.author + self.game_status[ctx.channel.id] = True + start_embed = discord.Embed(colour=discord.Colour.red()) + start_embed.title = "Quiz game Starting!!" + start_embed.description = "Each game consists of 5 questions.\n" + start_embed.description += "**Rules :**\nNo cheating and have fun!" + start_embed.set_footer( + text="Points for a question reduces by 25 after 10s or after a hint. Total time is 30s per question" + ) + await ctx.send(embed=start_embed) # send an embed with the rules + await asyncio.sleep(1) + topic = self.questions[category] done_question = [] -- cgit v1.2.3 From 21fdbdb4ee062e4a7b59320b64da773a42dad6e0 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Fri, 18 Oct 2019 22:35:24 +0530 Subject: Made some language corrections in the json file and also made seperate functions for the start and end quiz. Added another check to check if the game is still running before sending the answer. --- bot/resources/evergreen/trivia_quiz.json | 4 +-- bot/seasons/evergreen/trivia_quiz.py | 58 ++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 23 deletions(-) (limited to 'bot') diff --git a/bot/resources/evergreen/trivia_quiz.json b/bot/resources/evergreen/trivia_quiz.json index 66df3df7..48ee2ce4 100644 --- a/bot/resources/evergreen/trivia_quiz.json +++ b/bot/resources/evergreen/trivia_quiz.json @@ -113,7 +113,7 @@ { "id": 113, "question": "What's the name of the tallest waterfall in the world.", - "answer": "Angel", + "answer": "Angel Falls", "info": "Angel Falls (Salto Ángel) in Venezuela is the highest waterfall in the world. The falls are 3230 feet in height, with an uninterrupted drop of 2647 feet. Angel Falls is located on a tributary of the Rio Caroni." }, { @@ -143,7 +143,7 @@ { "id": 118, "question": "Where is the \"International Court Of Justice\" located at?", - "answer": "Hague", + "answer": "The Hague", "info": "" }, { diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index d4e582af..efc3cd98 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -24,7 +24,6 @@ WRONG_ANS_RESPONSE = [ class TriviaQuiz(commands.Cog): """A cog for all quiz commands.""" - def __init__(self, bot: commands.Bot) -> None: self.bot = bot self.questions = self.load_questions() @@ -66,19 +65,7 @@ class TriviaQuiz(commands.Cog): # Stop game if running. if self.game_status[ctx.channel.id] is True: - # Check if the author is the game starter or a moderator. - if ( - ctx.author == self.game_owners[ctx.channel.id] - or any(Roles.moderator == role.id for role in ctx.author.roles) - ): - await ctx.send("Quiz is no longer running.") - await self.declare_winner(ctx.channel, self.game_player_scores[ctx.channel.id]) - self.game_status[ctx.channel.id] = False - del self.game_owners[ctx.channel.id] - self.game_player_scores[ctx.channel.id] = {} - else: - await ctx.send(f"{ctx.author.mention}, you are not authorised to stop this game :ghost: !") - return + await self.stop_quiz(ctx.author, ctx.channel) category = category.lower() # Send embed showing available categories if inputted category is invalid. @@ -89,15 +76,11 @@ class TriviaQuiz(commands.Cog): # Start game if not running. if self.game_status[ctx.channel.id] is False: + self.game_owners[ctx.channel.id] = ctx.author self.game_status[ctx.channel.id] = True - start_embed = discord.Embed(colour=discord.Colour.red()) - start_embed.title = "Quiz game Starting!!" - start_embed.description = "Each game consists of 5 questions.\n" - start_embed.description += "**Rules :**\nNo cheating and have fun!" - start_embed.set_footer( - text="Points for a question reduces by 25 after 10s or after a hint. Total time is 30s per question" - ) + start_embed = self.make_start_embed() + await ctx.send(embed=start_embed) # send an embed with the rules await asyncio.sleep(1) @@ -116,8 +99,10 @@ class TriviaQuiz(commands.Cog): del self.game_owners[ctx.channel.id] self.game_player_scores[ctx.channel.id] = {} break + # If no hint has been sent or any time alert. Basically if hint_no = 0 means it is a new question. if hint_no == 0: + # Select a random question which has not been used yet. while True: question_dict = random.choice(topic) if question_dict["id"] not in done_question: @@ -155,6 +140,8 @@ class TriviaQuiz(commands.Cog): # If hint_no > 2, then it means that all hints/time alerts have been sent. # Also means that the answer is not yet given and the bot sends the answer and the next question. else: + if self.game_status[ctx.channel.id] is False: + break response = random.choice(WRONG_ANS_RESPONSE) expression = random.choice(ANNOYED_EXPRESSIONS) await ctx.send(f"{response} {expression}") @@ -167,6 +154,8 @@ class TriviaQuiz(commands.Cog): await asyncio.sleep(2) else: + if self.game_status[ctx.channel.id] is False: + break # Reduce points by 25 for every hint/time alert that has been sent. points = 100 - 25*hint_no if msg.author in self.game_player_scores[ctx.channel.id]: @@ -187,6 +176,33 @@ class TriviaQuiz(commands.Cog): await self.send_score(ctx.channel, self.game_player_scores[ctx.channel.id]) await asyncio.sleep(2) + @staticmethod + def make_start_embed(): + """Generate a starting/introduction embed for the quiz.""" + start_embed = discord.Embed(colour=discord.Colour.red()) + start_embed.title = "Quiz game Starting!!" + start_embed.description = "Each game consists of 5 questions.\n" + start_embed.description += "**Rules :**\nNo cheating and have fun!" + start_embed.set_footer( + text="Points for a question reduces by 25 after 10s or after a hint. Total time is 30s per question" + ) + return start_embed + + async def stop_quiz(self, author, channel): + # Check if the author is the game starter or a moderator. + if ( + author == self.game_owners[channel.id] + or any(Roles.moderator == role.id for role in author.roles) + ): + await channel.send("Quiz is no longer running.") + await self.declare_winner(channel, self.game_player_scores[channel.id]) + self.game_status[channel.id] = False + del self.game_owners[channel.id] + self.game_player_scores[channel.id] = {} + else: + await channel.send(f"{author.mention}, you are not authorised to stop this game :ghost: !") + return + @quiz_game.command(name="leaderboard") async def leaderboard(self, ctx: commands.Context) -> None: """View everyone's score for this bot session.""" -- cgit v1.2.3 From e63cc06bd8287467a6eaffd00360fc6b75ea4169 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Sat, 19 Oct 2019 23:27:35 +0530 Subject: added a cool down per channel to the quiz command --- bot/seasons/evergreen/trivia_quiz.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index efc3cd98..2398cb40 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -6,6 +6,8 @@ from pathlib import Path import discord from discord.ext import commands +from discord.ext.commands import cooldown +from discord.ext.commands.cooldowns import BucketType from fuzzywuzzy import fuzz from bot.constants import Roles @@ -45,6 +47,7 @@ class TriviaQuiz(commands.Cog): questions = json.load(json_data) return questions + @cooldown(1, 20, BucketType.channel) @commands.group(name="quiz", aliases=["trivia"], invoke_without_command=True) async def quiz_game(self, ctx: commands.Context, category: str = "general") -> None: """ @@ -177,7 +180,7 @@ class TriviaQuiz(commands.Cog): await asyncio.sleep(2) @staticmethod - def make_start_embed(): + def make_start_embed() -> discord.Embed: """Generate a starting/introduction embed for the quiz.""" start_embed = discord.Embed(colour=discord.Colour.red()) start_embed.title = "Quiz game Starting!!" @@ -188,7 +191,8 @@ class TriviaQuiz(commands.Cog): ) return start_embed - async def stop_quiz(self, author, channel): + async def stop_quiz(self, author: discord.Member, channel: discord.TextChannel) -> None: + """Stop the quiz.""" # Check if the author is the game starter or a moderator. if ( author == self.game_owners[channel.id] -- cgit v1.2.3 From d24bc073b32887a060eb1f9f17b9e2076984859a Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Sun, 20 Oct 2019 08:39:10 +0530 Subject: added cooldown to the quiz command and more refinement and also tested. --- bot/seasons/evergreen/trivia_quiz.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 2398cb40..9a7738a4 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -26,6 +26,7 @@ WRONG_ANS_RESPONSE = [ class TriviaQuiz(commands.Cog): """A cog for all quiz commands.""" + def __init__(self, bot: commands.Bot) -> None: self.bot = bot self.questions = self.load_questions() @@ -69,6 +70,7 @@ class TriviaQuiz(commands.Cog): # Stop game if running. if self.game_status[ctx.channel.id] is True: await self.stop_quiz(ctx.author, ctx.channel) + return category = category.lower() # Send embed showing available categories if inputted category is invalid. @@ -205,7 +207,6 @@ class TriviaQuiz(commands.Cog): self.game_player_scores[channel.id] = {} else: await channel.send(f"{author.mention}, you are not authorised to stop this game :ghost: !") - return @quiz_game.command(name="leaderboard") async def leaderboard(self, ctx: commands.Context) -> None: -- cgit v1.2.3 From 322a6ae1b505d919a62d18a8c901da33e2233d9a Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Fri, 22 Nov 2019 18:29:15 +0000 Subject: Grammar fixes --- bot/seasons/evergreen/trivia_quiz.py | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 9a7738a4..bf304644 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -16,10 +16,8 @@ from bot.constants import Roles logger = logging.getLogger(__name__) -ANNOYED_EXPRESSIONS = ["-_-", "-.-"] - WRONG_ANS_RESPONSE = [ - "No one gave the correct answer", + "No answered correctly!", "Better luck next time" ] @@ -42,7 +40,7 @@ class TriviaQuiz(commands.Cog): @staticmethod def load_questions() -> dict: - """Load the questions from json file.""" + """Load the questions from the JSON file.""" p = Path("bot", "resources", "evergreen", "trivia_quiz.json") with p.open() as json_data: questions = json.load(json_data) @@ -55,7 +53,7 @@ class TriviaQuiz(commands.Cog): Start/Stop a quiz! If the quiz game is running, then the owner or a mod can stop it by using this command - without providing any arguments and vice versa. + without providing any arguments or vice versa. Questions for the quiz can be selected from the following categories: - general : Test your general knowledge. (default) @@ -98,7 +96,7 @@ class TriviaQuiz(commands.Cog): # Exit quiz if number of questions for a round are already sent. if len(done_question) > self.question_limit and hint_no == 0: - await ctx.send("The round ends here.") + await ctx.send("The round has ended.") await self.declare_winner(ctx.channel, self.game_player_scores[ctx.channel.id]) self.game_status[ctx.channel.id] = False del self.game_owners[ctx.channel.id] @@ -139,7 +137,7 @@ class TriviaQuiz(commands.Cog): hints = question_dict["hints"] await ctx.send(f"**Hint #{hint_no+1}\n**{hints[hint_no]}") else: - await ctx.send(f"Cmon guys, {30-hint_no*10}s left!") + await ctx.send(f"{30-hint_no*10}s left!") # Once hint or time alerts has been sent 2 times, the hint_no value will be 3 # If hint_no > 2, then it means that all hints/time alerts have been sent. @@ -148,8 +146,7 @@ class TriviaQuiz(commands.Cog): if self.game_status[ctx.channel.id] is False: break response = random.choice(WRONG_ANS_RESPONSE) - expression = random.choice(ANNOYED_EXPRESSIONS) - await ctx.send(f"{response} {expression}") + await ctx.send(response) await self.send_answer(ctx.channel, question_dict) await asyncio.sleep(1) @@ -176,7 +173,7 @@ class TriviaQuiz(commands.Cog): hint_no = 0 - await ctx.send(f"{msg.author.mention} got the correct answer :tada: {points} points for ya.") + await ctx.send(f"{msg.author.mention} got the correct answer :tada: {points} points!") await self.send_answer(ctx.channel, question_dict) await self.send_score(ctx.channel, self.game_player_scores[ctx.channel.id]) await asyncio.sleep(2) @@ -189,7 +186,7 @@ class TriviaQuiz(commands.Cog): start_embed.description = "Each game consists of 5 questions.\n" start_embed.description += "**Rules :**\nNo cheating and have fun!" start_embed.set_footer( - text="Points for a question reduces by 25 after 10s or after a hint. Total time is 30s per question" + text="Points for each question reduces by 25 after 10s or after a hint. Total time is 30s per question" ) return start_embed @@ -200,13 +197,13 @@ class TriviaQuiz(commands.Cog): author == self.game_owners[channel.id] or any(Roles.moderator == role.id for role in author.roles) ): - await channel.send("Quiz is no longer running.") + await channel.send("Quiz stopped.") await self.declare_winner(channel, self.game_player_scores[channel.id]) self.game_status[channel.id] = False del self.game_owners[channel.id] self.game_player_scores[channel.id] = {} else: - await channel.send(f"{author.mention}, you are not authorised to stop this game :ghost: !") + await channel.send(f"{author.mention}, you are not authorised to stop this game :ghost:!") @quiz_game.command(name="leaderboard") async def leaderboard(self, ctx: commands.Context) -> None: @@ -220,7 +217,7 @@ class TriviaQuiz(commands.Cog): embed.title = "Score Board" embed.description = "" if len(player_data) == 0: - await channel.send("No one has made it to the leaderboard yet.") + await channel.send("No one has made it onto the leaderboard yet.") return sorted_dict = sorted(player_data.items(), key=lambda a: a[1], reverse=True) for item in sorted_dict: @@ -247,15 +244,15 @@ class TriviaQuiz(commands.Cog): winners_mention = None for winner in winners: winners_mention += f"{winner.mention} " - else: word = "You" author_index = list(player_data.values()).index(highest_points) winner = list(player_data.keys())[author_index] winners_mention = winner.mention + await channel.send( - f"Congratz {winners_mention} :tada: " - f"{word} have won this quiz game with a grand total of {highest_points} points!!" + f"Congratulations {winners_mention} :tada: " + f"{word} have won this quiz game with a grand total of {highest_points} points!" ) @property @@ -279,11 +276,11 @@ class TriviaQuiz(commands.Cog): embed.description = "" if info != "": embed.description += f"**Information**\n{info}\n\n" - embed.description += "Lets move to the next question.\nRemaining questions: " + embed.description += "Let's move to the next question.\nRemaining questions: " await channel.send(embed=embed) def setup(bot: commands.Bot) -> None: - """Loading the cog.""" + """Load the cog.""" bot.add_cog(TriviaQuiz(bot)) logger.debug("TriviaQuiz cog loaded") -- cgit v1.2.3 From 14d723731122108b06d3d0648118c0ab25c8e6c7 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Fri, 29 Nov 2019 17:25:55 +0530 Subject: added a new command to stop the quiz and removed the cooldown on the quiz command --- bot/seasons/evergreen/trivia_quiz.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index bf304644..69fecb3a 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -6,8 +6,6 @@ from pathlib import Path import discord from discord.ext import commands -from discord.ext.commands import cooldown -from discord.ext.commands.cooldowns import BucketType from fuzzywuzzy import fuzz from bot.constants import Roles @@ -17,7 +15,7 @@ logger = logging.getLogger(__name__) WRONG_ANS_RESPONSE = [ - "No answered correctly!", + "No one answered correctly!", "Better luck next time" ] @@ -46,11 +44,10 @@ class TriviaQuiz(commands.Cog): questions = json.load(json_data) return questions - @cooldown(1, 20, BucketType.channel) @commands.group(name="quiz", aliases=["trivia"], invoke_without_command=True) async def quiz_game(self, ctx: commands.Context, category: str = "general") -> None: """ - Start/Stop a quiz! + Start a quiz! If the quiz game is running, then the owner or a mod can stop it by using this command without providing any arguments or vice versa. @@ -67,6 +64,10 @@ class TriviaQuiz(commands.Cog): # Stop game if running. if self.game_status[ctx.channel.id] is True: + return await ctx.send( + f"Game is already running..." + f"do `{self.bot.command_prefix}quiz stop`" + ) await self.stop_quiz(ctx.author, ctx.channel) return @@ -190,7 +191,15 @@ class TriviaQuiz(commands.Cog): ) return start_embed - async def stop_quiz(self, author: discord.Member, channel: discord.TextChannel) -> None: + @quiz_game.command(name="stop") + async def stop_quiz(self, ctx: commands.Context) -> None: + """Stop a quiz game if its running in the channel.""" + if self.game_status[ctx.channel.id] is True: + await self.stop(ctx.author, ctx.channel) + else: + await ctx.send("No quiz running.") + + async def stop(self, author: discord.Member, channel: discord.TextChannel) -> None: """Stop the quiz.""" # Check if the author is the game starter or a moderator. if ( -- cgit v1.2.3 From 23e59f291ba0b186bdbcdc30d6e846837b504ad4 Mon Sep 17 00:00:00 2001 From: Rohan_Iceman Date: Mon, 2 Dec 2019 15:46:16 +0530 Subject: Update bot/seasons/evergreen/trivia_quiz.py adding space around special chars Co-Authored-By: Mark --- bot/seasons/evergreen/trivia_quiz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 69fecb3a..4e465052 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -138,7 +138,7 @@ class TriviaQuiz(commands.Cog): hints = question_dict["hints"] await ctx.send(f"**Hint #{hint_no+1}\n**{hints[hint_no]}") else: - await ctx.send(f"{30-hint_no*10}s left!") + await ctx.send(f"{30 - hint_no * 10}s left!") # Once hint or time alerts has been sent 2 times, the hint_no value will be 3 # If hint_no > 2, then it means that all hints/time alerts have been sent. -- cgit v1.2.3 From 2f98ec1055d5948237c0a36456e0744ecec9befa Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Wed, 4 Dec 2019 20:01:27 +0530 Subject: Introduced `.bm` command for personal bookmarking message via message jump url Pretty much the main file for the command `.bm` used to make bookmark in a heavy server for personal use later, along with hints to organize it easily. --- bot/seasons/evergreen/bookmark.py | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 bot/seasons/evergreen/bookmark.py (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py new file mode 100644 index 00000000..226b55c2 --- /dev/null +++ b/bot/seasons/evergreen/bookmark.py @@ -0,0 +1,78 @@ +import logging + +import discord +from discord.ext import commands + +log = logging.getLogger(__name__) + + +class Bookmark(commands.Cog): + """A cog for Bookmarking a message.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.command(name="bookmark", aliases=("bm", "pin")) + async def bookmark(self, ctx: commands.Context, jump_url: str = None, *args) -> None: + """Bookmarks a message.""" + if jump_url is not None and jump_url != "*": + if "discordapp.com/channels" not in jump_url: + await ctx.send("INVALID URL") + await ctx.send("An example of the command can be \n" + "!bm https://discordapp.com/channels" + "/267624335836053506/267631170882240512/" + "554639398130548746" + " Some of the hints here") + return + if jump_url is None or jump_url == "*": + channel = ctx.channel + async for x in channel.history(limit=2): + message_id = x.id + try: + message = await channel.fetch_message(message_id) + except discord.NotFound: + await ctx.send(">>> Message not in this" + " channel\nOr\nYou are trying to Pin" + " your own message,\nPlease use the channel" + " where message is.") + return + jump_url = f"https://discordapp.com/channels/" \ + f"{ctx.guild.id}/{channel.id}/{message.id}" + + embed = discord.Embed( + title="Your Bookmark", + description="You used the commands so here it is.", + colour=0x2ecc71 + ) + hint = args + list(hint) + x = hint + hint = "" + for a in x: + hint = hint + " " + a + if hint == "": + hint = "No hint Provided" + + embed.set_footer(text="Why everything so heavy ?") + embed.set_thumbnail(url="https://emojipedia-us.s3." + "dualstack.us-west-1.amazonaws.com" + "/thumbs/240/twitter/" + "233/incoming-envelope_1f4e8.png") + embed.set_author(name=ctx.author) + embed.add_field(name='Hints', value=hint, inline=False) + embed.add_field(name='Link', value=jump_url, inline=False) + try: + await ctx.author.send(embed=embed) + except discord.Forbidden: + await ctx.send("Something not right ," + " you have either blocked me or" + " you have disabled direct message " + "message from this server.") + return + await ctx.send("Sent you that DM") + + +def setup(bot: commands.Bot) -> None: + """Uptime Cog load.""" + bot.add_cog(Bookmark(bot)) + log.info("Bookmark cog loaded") -- cgit v1.2.3 From 5414619068eb958b09fb78030f06b25c741a9b44 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Wed, 4 Dec 2019 21:07:38 +0530 Subject: Fixed grammatical errors, and simplified the code a bit. --- bot/seasons/evergreen/bookmark.py | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 226b55c2..3e890fcf 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -17,12 +17,9 @@ class Bookmark(commands.Cog): """Bookmarks a message.""" if jump_url is not None and jump_url != "*": if "discordapp.com/channels" not in jump_url: - await ctx.send("INVALID URL") - await ctx.send("An example of the command can be \n" - "!bm https://discordapp.com/channels" - "/267624335836053506/267631170882240512/" - "554639398130548746" - " Some of the hints here") + await ctx.send("I can't find the associated message," + " the command support the following syntax:\n" + " `.bm [message url] (bookmark name)`") return if jump_url is None or jump_url == "*": channel = ctx.channel @@ -32,26 +29,27 @@ class Bookmark(commands.Cog): message = await channel.fetch_message(message_id) except discord.NotFound: await ctx.send(">>> Message not in this" - " channel\nOr\nYou are trying to Pin" - " your own message,\nPlease use the channel" + " channel\n" + "Or\n" + "You are trying to Pin" + " your own message,\n" + "Please use the channel" " where message is.") return jump_url = f"https://discordapp.com/channels/" \ f"{ctx.guild.id}/{channel.id}/{message.id}" embed = discord.Embed( - title="Your Bookmark", - description="You used the commands so here it is.", + title="Your bookmark", + description=None, colour=0x2ecc71 ) - hint = args - list(hint) - x = hint + x = args hint = "" - for a in x: - hint = hint + " " + a + for word in x: + hint = hint + " " + word if hint == "": - hint = "No hint Provided" + hint = "No hint provided" embed.set_footer(text="Why everything so heavy ?") embed.set_thumbnail(url="https://emojipedia-us.s3." @@ -64,10 +62,10 @@ class Bookmark(commands.Cog): try: await ctx.author.send(embed=embed) except discord.Forbidden: - await ctx.send("Something not right ," + await ctx.send("Something is not right," " you have either blocked me or" - " you have disabled direct message " - "message from this server.") + " you have disabled direct messages " + "from this server.") return await ctx.send("Sent you that DM") -- cgit v1.2.3 From ef324c0bed4f255c5721658243e99f20e5989afd Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 16:09:17 +0530 Subject: Fixed a lot of issues. Fixed the coding not satisfying `K&R` code styling Fixed most of the grammatical issues Removed unnecessary `try except` code block , not gonna trigger anyways. --- bot/seasons/evergreen/bookmark.py | 53 ++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 29 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 3e890fcf..662e285a 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -7,7 +7,7 @@ log = logging.getLogger(__name__) class Bookmark(commands.Cog): - """A cog for Bookmarking a message.""" + """A cog for Bookmarking a message. helps personal pinning a message in a busy server.""" def __init__(self, bot: commands.Bot): self.bot = bot @@ -15,62 +15,57 @@ class Bookmark(commands.Cog): @commands.command(name="bookmark", aliases=("bm", "pin")) async def bookmark(self, ctx: commands.Context, jump_url: str = None, *args) -> None: """Bookmarks a message.""" + global message_id if jump_url is not None and jump_url != "*": if "discordapp.com/channels" not in jump_url: - await ctx.send("I can't find the associated message," - " the command support the following syntax:\n" - " `.bm [message url] (bookmark name)`") + await ctx.send( + "I can't find the associated message." + " this command supports the following syntax:\n" + "`[command alias] [message url] (bookmark name)`" + ) return if jump_url is None or jump_url == "*": channel = ctx.channel async for x in channel.history(limit=2): message_id = x.id - try: - message = await channel.fetch_message(message_id) - except discord.NotFound: - await ctx.send(">>> Message not in this" - " channel\n" - "Or\n" - "You are trying to Pin" - " your own message,\n" - "Please use the channel" - " where message is.") - return - jump_url = f"https://discordapp.com/channels/" \ - f"{ctx.guild.id}/{channel.id}/{message.id}" + message = await channel.fetch_message(message_id) + jump_url = ( + "https://discordapp.com/channels/" + f"{ctx.guild.id}/{channel.id}/{message.id}" + ) embed = discord.Embed( title="Your bookmark", description=None, colour=0x2ecc71 ) - x = args hint = "" - for word in x: + for word in args: hint = hint + " " + word if hint == "": hint = "No hint provided" embed.set_footer(text="Why everything so heavy ?") - embed.set_thumbnail(url="https://emojipedia-us.s3." - "dualstack.us-west-1.amazonaws.com" - "/thumbs/240/twitter/" - "233/incoming-envelope_1f4e8.png") + embed.set_thumbnail( + url="https://emojipedia-us.s3." + "dualstack.us-west-1.amazonaws.com" + "/thumbs/240/twitter/" + "233/incoming-envelope_1f4e8.png" + ) embed.set_author(name=ctx.author) embed.add_field(name='Hints', value=hint, inline=False) embed.add_field(name='Link', value=jump_url, inline=False) try: await ctx.author.send(embed=embed) except discord.Forbidden: - await ctx.send("Something is not right," - " you have either blocked me or" - " you have disabled direct messages " - "from this server.") + await ctx.send( + ">>> You have to enable direct messages from this server to receive DM's from me." + ) return - await ctx.send("Sent you that DM") + await ctx.send("Sent you a DM!") def setup(bot: commands.Bot) -> None: - """Uptime Cog load.""" + """Bookmark Cog load.""" bot.add_cog(Bookmark(bot)) log.info("Bookmark cog loaded") -- cgit v1.2.3 From ea8dbc768d80359f8358892879046f42fd3225d8 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 17:03:05 +0530 Subject: Fixed cog string issue -Finally got a string that `describe` the cog Bookmark I love you Ves Zappa <3 . -Fixed no punctuation after `No hint provided` string. -Made it so it follow colo(u)ring theme of the bot. --- bot/seasons/evergreen/bookmark.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 662e285a..1eadaaa8 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -3,11 +3,13 @@ import logging import discord from discord.ext import commands +from bot.constants import Colours + log = logging.getLogger(__name__) class Bookmark(commands.Cog): - """A cog for Bookmarking a message. helps personal pinning a message in a busy server.""" + """A cog that creates personal bookmarks by relaying a message to the user's DMs.""" def __init__(self, bot: commands.Bot): self.bot = bot @@ -15,7 +17,6 @@ class Bookmark(commands.Cog): @commands.command(name="bookmark", aliases=("bm", "pin")) async def bookmark(self, ctx: commands.Context, jump_url: str = None, *args) -> None: """Bookmarks a message.""" - global message_id if jump_url is not None and jump_url != "*": if "discordapp.com/channels" not in jump_url: await ctx.send( @@ -26,24 +27,19 @@ class Bookmark(commands.Cog): return if jump_url is None or jump_url == "*": channel = ctx.channel - async for x in channel.history(limit=2): - message_id = x.id - message = await channel.fetch_message(message_id) - jump_url = ( - "https://discordapp.com/channels/" - f"{ctx.guild.id}/{channel.id}/{message.id}" - ) + async for message in channel.history(limit=2): + jump_url = message.jump_url embed = discord.Embed( title="Your bookmark", description=None, - colour=0x2ecc71 + colour=Colours.soft_green ) hint = "" for word in args: hint = hint + " " + word if hint == "": - hint = "No hint provided" + hint = "No hint provided." embed.set_footer(text="Why everything so heavy ?") embed.set_thumbnail( -- cgit v1.2.3 From 475754379856469b5a6a55a2f901250a018302ee Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 17:09:15 +0530 Subject: Update bot/seasons/evergreen/bookmark.py Fixed the description of the command itself Co-Authored-By: Matteo Bertucci --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 1eadaaa8..8b0d32f3 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -16,7 +16,7 @@ class Bookmark(commands.Cog): @commands.command(name="bookmark", aliases=("bm", "pin")) async def bookmark(self, ctx: commands.Context, jump_url: str = None, *args) -> None: - """Bookmarks a message.""" + """Send you a link to the provided message in DM.""" if jump_url is not None and jump_url != "*": if "discordapp.com/channels" not in jump_url: await ctx.send( -- cgit v1.2.3 From 72f41f5bfb110b8550aa98a3b53d6afe9e95eebc Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 17:50:06 +0530 Subject: Added embeds to error messages, new way of joining hints. --- bot/seasons/evergreen/bookmark.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 8b0d32f3..c778a8d1 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -1,9 +1,10 @@ import logging +import random import discord from discord.ext import commands -from bot.constants import Colours +from bot.constants import ERROR_REPLIES, Colours log = logging.getLogger(__name__) @@ -16,14 +17,17 @@ class Bookmark(commands.Cog): @commands.command(name="bookmark", aliases=("bm", "pin")) async def bookmark(self, ctx: commands.Context, jump_url: str = None, *args) -> None: - """Send you a link to the provided message in DM.""" + """Bookmarks a message.""" if jump_url is not None and jump_url != "*": if "discordapp.com/channels" not in jump_url: - await ctx.send( - "I can't find the associated message." - " this command supports the following syntax:\n" - "`[command alias] [message url] (bookmark name)`" + embed_error_1 = discord.Embed( + title=random.choice(ERROR_REPLIES), + description="I can't find the associated message. " + "This command supports the following syntax:\n" + "`[command alias] [message url] (bookmark name)`", + colour=Colours.soft_red ) + await ctx.send(embed=embed_error_1) return if jump_url is None or jump_url == "*": channel = ctx.channel @@ -35,9 +39,8 @@ class Bookmark(commands.Cog): description=None, colour=Colours.soft_green ) - hint = "" - for word in args: - hint = hint + " " + word + hint = ' '.join(args) + if hint == "": hint = "No hint provided." @@ -54,9 +57,12 @@ class Bookmark(commands.Cog): try: await ctx.author.send(embed=embed) except discord.Forbidden: - await ctx.send( - ">>> You have to enable direct messages from this server to receive DM's from me." + embed_error_2 = discord.Embed( + title=random.choice(ERROR_REPLIES), + description="You have to enable direct messages from this server to receive DM's from me.", + colour=Colours.soft_red ) + await ctx.send(embed=embed_error_2) return await ctx.send("Sent you a DM!") -- cgit v1.2.3 From 76951aff4eeee516f0a401bb9c1f2e1434fbf38f Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 17:54:01 +0530 Subject: Fixed wrong order of import syntax --- bot/seasons/evergreen/bookmark.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index c778a8d1..5bcb8030 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -4,7 +4,7 @@ import random import discord from discord.ext import commands -from bot.constants import ERROR_REPLIES, Colours +from bot.constants import Colours, ERROR_REPLIES log = logging.getLogger(__name__) @@ -40,7 +40,7 @@ class Bookmark(commands.Cog): colour=Colours.soft_green ) hint = ' '.join(args) - + if hint == "": hint = "No hint provided." -- cgit v1.2.3 From d69812da436143e6abc321f6f76e7a71021588da Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 18:45:20 +0530 Subject: Saying goodbye to a easteregg RIP `embed.set_footer(text="Why everything so heavy ?")` --- bot/seasons/evergreen/bookmark.py | 1 - 1 file changed, 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 5bcb8030..732132b4 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -44,7 +44,6 @@ class Bookmark(commands.Cog): if hint == "": hint = "No hint provided." - embed.set_footer(text="Why everything so heavy ?") embed.set_thumbnail( url="https://emojipedia-us.s3." "dualstack.us-west-1.amazonaws.com" -- cgit v1.2.3 From 7d8c47481535f6e1e1a604ba4b8e15b8b2005594 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 19:58:27 +0530 Subject: Renamed error names Co-Authored-By: Matteo Bertucci --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 732132b4..6b8de6e1 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -20,7 +20,7 @@ class Bookmark(commands.Cog): """Bookmarks a message.""" if jump_url is not None and jump_url != "*": if "discordapp.com/channels" not in jump_url: - embed_error_1 = discord.Embed( + embed_error = discord.Embed( title=random.choice(ERROR_REPLIES), description="I can't find the associated message. " "This command supports the following syntax:\n" -- cgit v1.2.3 From aa7eeec38b387f14a4fdd58c8610c54f65e2da5f Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 19:58:37 +0530 Subject: Renamed error names Co-Authored-By: Matteo Bertucci --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 6b8de6e1..eb35372d 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -56,7 +56,7 @@ class Bookmark(commands.Cog): try: await ctx.author.send(embed=embed) except discord.Forbidden: - embed_error_2 = discord.Embed( + embed_error = discord.Embed( title=random.choice(ERROR_REPLIES), description="You have to enable direct messages from this server to receive DM's from me.", colour=Colours.soft_red -- cgit v1.2.3 From fb315387c1b03be3b62454759c3d62ebec8969ee Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 19:59:45 +0530 Subject: Simple change in a if string Co-Authored-By: Matteo Bertucci --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index eb35372d..aeeb30ac 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -41,7 +41,7 @@ class Bookmark(commands.Cog): ) hint = ' '.join(args) - if hint == "": + if not hint: hint = "No hint provided." embed.set_thumbnail( -- cgit v1.2.3 From 573667aece1eae84b4a6ed43880eb6cbf270a30e Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 20:00:07 +0530 Subject: Fixed typo of DMs Co-Authored-By: Matteo Bertucci --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index aeeb30ac..ca06711a 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -58,7 +58,7 @@ class Bookmark(commands.Cog): except discord.Forbidden: embed_error = discord.Embed( title=random.choice(ERROR_REPLIES), - description="You have to enable direct messages from this server to receive DM's from me.", + description="You have to enable direct messages from this server to receive DMs from me.", colour=Colours.soft_red ) await ctx.send(embed=embed_error_2) -- cgit v1.2.3 From ba5d80c396a92f6e261a74e3af7bd4ad07c73d84 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Thu, 5 Dec 2019 20:04:12 +0530 Subject: renamed error completely --- bot/seasons/evergreen/bookmark.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index ca06711a..d1077bd3 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -27,7 +27,7 @@ class Bookmark(commands.Cog): "`[command alias] [message url] (bookmark name)`", colour=Colours.soft_red ) - await ctx.send(embed=embed_error_1) + await ctx.send(embed=embed_error) return if jump_url is None or jump_url == "*": channel = ctx.channel @@ -61,7 +61,7 @@ class Bookmark(commands.Cog): description="You have to enable direct messages from this server to receive DMs from me.", colour=Colours.soft_red ) - await ctx.send(embed=embed_error_2) + await ctx.send(embed=embed_error) return await ctx.send("Sent you a DM!") -- cgit v1.2.3 From bce2b8bbcb082784b7cc4710f37a30271a26bf2b Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Sat, 7 Dec 2019 19:56:35 +0530 Subject: Added better info, Added usage logging. --- bot/seasons/evergreen/bookmark.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index d1077bd3..01214f98 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -17,7 +17,7 @@ class Bookmark(commands.Cog): @commands.command(name="bookmark", aliases=("bm", "pin")) async def bookmark(self, ctx: commands.Context, jump_url: str = None, *args) -> None: - """Bookmarks a message.""" + """Send you a link to the provided message in DM.""" if jump_url is not None and jump_url != "*": if "discordapp.com/channels" not in jump_url: embed_error = discord.Embed( @@ -64,6 +64,7 @@ class Bookmark(commands.Cog): await ctx.send(embed=embed_error) return await ctx.send("Sent you a DM!") + log.info(f"{ctx.author} Added a personal bookmark of {jump_url}.") def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 392aa5bcacf7c8d7f90b6c45a91fe78fcddf0ec2 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Sun, 8 Dec 2019 21:56:07 +0530 Subject: Reworked on the whole structure completely. Removed error_embeds No more selecting last message if * or None is specified Redone how DM's Look like --- bot/seasons/evergreen/bookmark.py | 48 +++++++++++---------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 01214f98..dfbca5bd 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -16,43 +16,22 @@ class Bookmark(commands.Cog): self.bot = bot @commands.command(name="bookmark", aliases=("bm", "pin")) - async def bookmark(self, ctx: commands.Context, jump_url: str = None, *args) -> None: + async def bookmark(self, ctx: commands.Context, target_message: discord.Message, *, + title: str = "Bookmark") -> None: """Send you a link to the provided message in DM.""" - if jump_url is not None and jump_url != "*": - if "discordapp.com/channels" not in jump_url: - embed_error = discord.Embed( - title=random.choice(ERROR_REPLIES), - description="I can't find the associated message. " - "This command supports the following syntax:\n" - "`[command alias] [message url] (bookmark name)`", - colour=Colours.soft_red - ) - await ctx.send(embed=embed_error) - return - if jump_url is None or jump_url == "*": - channel = ctx.channel - async for message in channel.history(limit=2): - jump_url = message.jump_url + log.info(f"{ctx.author} bookmarked {target_message.jump_url} with hints {title}.") - embed = discord.Embed( - title="Your bookmark", - description=None, - colour=Colours.soft_green - ) - hint = ' '.join(args) + embed = discord.Embed(title="Your bookmark", colour=Colours.soft_green) - if not hint: - hint = "No hint provided." + if not title: + title = "No hint provided." - embed.set_thumbnail( - url="https://emojipedia-us.s3." - "dualstack.us-west-1.amazonaws.com" - "/thumbs/240/twitter/" - "233/incoming-envelope_1f4e8.png" - ) - embed.set_author(name=ctx.author) - embed.add_field(name='Hints', value=hint, inline=False) - embed.add_field(name='Link', value=jump_url, inline=False) + embed.set_author(name=target_message.author) + embed.add_field(name='Content', value=target_message.content, inline=False) + embed.add_field(name='Hints', value=title, inline=False) + embed.add_field(name='Link', value=target_message.jump_url, inline=False) + embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) + # embed.set_image() try: await ctx.author.send(embed=embed) except discord.Forbidden: @@ -63,8 +42,7 @@ class Bookmark(commands.Cog): ) await ctx.send(embed=embed_error) return - await ctx.send("Sent you a DM!") - log.info(f"{ctx.author} Added a personal bookmark of {jump_url}.") + await ctx.send("Bookmark sent to your DMs.") def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 507863c2ca1ef5be0911cb08f0cabcf7661a256b Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Sun, 8 Dec 2019 22:47:36 +0530 Subject: Improved DM message Simplified the DM , example in the original post --- bot/seasons/evergreen/bookmark.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index dfbca5bd..2ace4723 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -21,17 +21,19 @@ class Bookmark(commands.Cog): """Send you a link to the provided message in DM.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with hints {title}.") - embed = discord.Embed(title="Your bookmark", colour=Colours.soft_green) - if not title: title = "No hint provided." + embed = discord.Embed( + title=title, + colour=Colours.soft_green, + description=f"{target_message.content} \n\n[Give it a visit.]({target_message.jump_url})" + ) embed.set_author(name=target_message.author) - embed.add_field(name='Content', value=target_message.content, inline=False) - embed.add_field(name='Hints', value=title, inline=False) - embed.add_field(name='Link', value=target_message.jump_url, inline=False) embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) - # embed.set_image() + embed.set_thumbnail(url="https://img.icons8.com/color/48/FF3333/" + "bookmark-ribbon.png") + embed.set_footer(text=f"{ctx.author}") try: await ctx.author.send(embed=embed) except discord.Forbidden: @@ -42,7 +44,7 @@ class Bookmark(commands.Cog): ) await ctx.send(embed=embed_error) return - await ctx.send("Bookmark sent to your DMs.") + await ctx.send("Bookmark sent to your DM.") def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 4627d0f066efbd69e5ad1c752775796eb36de3d1 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Mon, 9 Dec 2019 00:30:27 +0530 Subject: Removed footer , Unnecessary line. Edited a string --- bot/seasons/evergreen/bookmark.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 2ace4723..8d541ab6 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -22,18 +22,16 @@ class Bookmark(commands.Cog): log.info(f"{ctx.author} bookmarked {target_message.jump_url} with hints {title}.") if not title: - title = "No hint provided." + title = "No Title provided." embed = discord.Embed( title=title, colour=Colours.soft_green, description=f"{target_message.content} \n\n[Give it a visit.]({target_message.jump_url})" ) - embed.set_author(name=target_message.author) embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) embed.set_thumbnail(url="https://img.icons8.com/color/48/FF3333/" "bookmark-ribbon.png") - embed.set_footer(text=f"{ctx.author}") try: await ctx.author.send(embed=embed) except discord.Forbidden: -- cgit v1.2.3 From 42b39b83ec6fb593b655e8b36a88e5f135c94de0 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Mon, 9 Dec 2019 00:55:42 +0530 Subject: Changed how title behave when None --- bot/seasons/evergreen/bookmark.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 8d541ab6..10ea4fe9 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -17,13 +17,10 @@ class Bookmark(commands.Cog): @commands.command(name="bookmark", aliases=("bm", "pin")) async def bookmark(self, ctx: commands.Context, target_message: discord.Message, *, - title: str = "Bookmark") -> None: + title: str = None) -> None: """Send you a link to the provided message in DM.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with hints {title}.") - if not title: - title = "No Title provided." - embed = discord.Embed( title=title, colour=Colours.soft_green, -- cgit v1.2.3 From 148750f3e7194ed142a78a677cf82bf93e84aece Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Mon, 9 Dec 2019 19:20:05 +0530 Subject: K and R styling. replaced title with hints --- bot/seasons/evergreen/bookmark.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 10ea4fe9..bbe362aa 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -16,10 +16,11 @@ class Bookmark(commands.Cog): self.bot = bot @commands.command(name="bookmark", aliases=("bm", "pin")) - async def bookmark(self, ctx: commands.Context, target_message: discord.Message, *, + async def bookmark(self, ctx: commands.Context, + target_message: discord.Message, *, title: str = None) -> None: """Send you a link to the provided message in DM.""" - log.info(f"{ctx.author} bookmarked {target_message.jump_url} with hints {title}.") + log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title {title}.") embed = discord.Embed( title=title, -- cgit v1.2.3 From 1bcfe11aa5b49242f7a0a9ae433b5e110007384a Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Mon, 9 Dec 2019 19:26:04 +0530 Subject: lint test change --- bot/seasons/evergreen/bookmark.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index bbe362aa..52d2d362 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -17,8 +17,8 @@ class Bookmark(commands.Cog): @commands.command(name="bookmark", aliases=("bm", "pin")) async def bookmark(self, ctx: commands.Context, - target_message: discord.Message, *, - title: str = None) -> None: + target_message: discord.Message, *, + title: str = None) -> None: """Send you a link to the provided message in DM.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title {title}.") -- cgit v1.2.3 From 5a732586b775b54d282bb9470795ca64a477fb4c Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 9 Dec 2019 21:45:02 +0100 Subject: Fix indentation The bookmark method's function signature is reformatted, bookmark image url is reduced to a single line, and the embed's description is broken into separate lines. --- bot/seasons/evergreen/bookmark.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 52d2d362..c8b53f71 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -16,20 +16,25 @@ class Bookmark(commands.Cog): self.bot = bot @commands.command(name="bookmark", aliases=("bm", "pin")) - async def bookmark(self, ctx: commands.Context, - target_message: discord.Message, *, - title: str = None) -> None: + async def bookmark( + self, + ctx: commands.Context, + target_message: discord.Message, + *, title: str = None + ) -> None: """Send you a link to the provided message in DM.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title {title}.") - embed = discord.Embed( title=title, colour=Colours.soft_green, - description=f"{target_message.content} \n\n[Give it a visit.]({target_message.jump_url})" + description=( + f"{target_message.content}\n\n" + f"[Give it a visit.]({target_message.jump_url})" + ) ) embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) - embed.set_thumbnail(url="https://img.icons8.com/color/48/FF3333/" - "bookmark-ribbon.png") + embed.set_thumbnail(url="https://img.icons8.com/color/48/FF3333/bookmark-ribbon.png") + try: await ctx.author.send(embed=embed) except discord.Forbidden: -- cgit v1.2.3 From e123f41a3e49558ffbfc944db86e23fc659b468a Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 9 Dec 2019 21:55:02 +0100 Subject: Improve wording of log and response messages Improves the wording of both docstrings, strips trailing dot from log and response messages for consistency. Refactors the error embed and renames the variable. --- bot/seasons/evergreen/bookmark.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index c8b53f71..d64c0068 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -22,8 +22,8 @@ class Bookmark(commands.Cog): target_message: discord.Message, *, title: str = None ) -> None: - """Send you a link to the provided message in DM.""" - log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title {title}.") + """Send the author a link to `target_message` via DMs.""" + log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title {title}") embed = discord.Embed( title=title, colour=Colours.soft_green, @@ -38,17 +38,17 @@ class Bookmark(commands.Cog): try: await ctx.author.send(embed=embed) except discord.Forbidden: - embed_error = discord.Embed( + error_embed = discord.Embed( title=random.choice(ERROR_REPLIES), - description="You have to enable direct messages from this server to receive DMs from me.", + description=f"{ctx.author.mention}, please enable your DMs to receive the bookmark", colour=Colours.soft_red ) - await ctx.send(embed=embed_error) + await ctx.send(embed=error_embed) return - await ctx.send("Bookmark sent to your DM.") + await ctx.send("Bookmark sent to your DM") def setup(bot: commands.Bot) -> None: - """Bookmark Cog load.""" + """Load the Bookmark cog.""" bot.add_cog(Bookmark(bot)) log.info("Bookmark cog loaded") -- cgit v1.2.3 From 8122bf0c06cbd984f28f509525c58340c0a29959 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 9 Dec 2019 22:05:36 +0100 Subject: Respond with a reaction on success Instead of returning on error we add an else clause to the try-except block and add a reaction on success to reduce needless visual clutter. --- bot/seasons/evergreen/bookmark.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index d64c0068..0c720e7e 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -4,7 +4,7 @@ import random import discord from discord.ext import commands -from bot.constants import Colours, ERROR_REPLIES +from bot.constants import Colours, ERROR_REPLIES, Emojis log = logging.getLogger(__name__) @@ -44,8 +44,8 @@ class Bookmark(commands.Cog): colour=Colours.soft_red ) await ctx.send(embed=error_embed) - return - await ctx.send("Bookmark sent to your DM") + else: + await ctx.message.add_reaction(Emojis.envelope) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 03c546d0324db112b802327462cfeb9b466ea70f Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 9 Dec 2019 22:13:42 +0100 Subject: Improve default title value and log message The title now defaults to Bookmark and is logged surrounded by single quotes to make it clear which part is the title. --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 0c720e7e..f4d9b1b9 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -20,7 +20,7 @@ class Bookmark(commands.Cog): self, ctx: commands.Context, target_message: discord.Message, - *, title: str = None + *, title: str = "Bookmark" ) -> None: """Send the author a link to `target_message` via DMs.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title {title}") -- cgit v1.2.3 From f1a61782d45db6d65c63ba62e88e86134b871347 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 9 Dec 2019 22:15:04 +0100 Subject: Log title wrapped in single quotes for readability --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index f4d9b1b9..bf21b318 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -23,7 +23,7 @@ class Bookmark(commands.Cog): *, title: str = "Bookmark" ) -> None: """Send the author a link to `target_message` via DMs.""" - log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title {title}") + log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title '{title}'") embed = discord.Embed( title=title, colour=Colours.soft_green, -- cgit v1.2.3 From f2c9b5340680a7d9ba6c60064ac82b472246838d Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 9 Dec 2019 22:28:42 +0100 Subject: Improve wording of cog docstring --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index bf21b318..f71d3bbd 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -10,7 +10,7 @@ log = logging.getLogger(__name__) class Bookmark(commands.Cog): - """A cog that creates personal bookmarks by relaying a message to the user's DMs.""" + """Creates personal bookmarks by relaying a message link to the user's DMs.""" def __init__(self, bot: commands.Bot): self.bot = bot -- cgit v1.2.3 From b6690f24f966d29872c8a418c30b0f69b11f0cdd Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 9 Dec 2019 23:27:21 +0100 Subject: Adjust hyperlink text --- bot/seasons/evergreen/bookmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index f71d3bbd..bd40993a 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -29,7 +29,7 @@ class Bookmark(commands.Cog): colour=Colours.soft_green, description=( f"{target_message.content}\n\n" - f"[Give it a visit.]({target_message.jump_url})" + f"[Visit original message]({target_message.jump_url})" ) ) embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) -- cgit v1.2.3 From 7fd3ac9ecac7926744e5ec1c194085a62bc4bc22 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 10 Dec 2019 19:39:58 +0100 Subject: Refactor function signature Code style is now consistent with the bot repo. --- bot/seasons/evergreen/bookmark.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index bd40993a..ccff149c 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -17,10 +17,11 @@ class Bookmark(commands.Cog): @commands.command(name="bookmark", aliases=("bm", "pin")) async def bookmark( - self, - ctx: commands.Context, - target_message: discord.Message, - *, title: str = "Bookmark" + self, + ctx: commands.Context, + target_message: discord.Message, + *, + title: str = "Bookmark" ) -> None: """Send the author a link to `target_message` via DMs.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title '{title}'") -- cgit v1.2.3 From 98c2b6789ccbadd786ecb316d2dde412629459f4 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 10 Dec 2019 23:27:35 +0100 Subject: Add bookmark icon url to constants --- bot/constants.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index c09d8369..71f56a09 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -4,6 +4,7 @@ from typing import NamedTuple from datetime import datetime __all__ = ( + "bookmark_icon_url", "AdventOfCode", "Channels", "Client", "Colours", "Emojis", "Hacktoberfest", "Roles", "Tokens", "WHITELISTED_CHANNELS", "STAFF_ROLES", "MODERATION_ROLES", "POSITIVE_REPLIES", "NEGATIVE_REPLIES", "ERROR_REPLIES", @@ -11,6 +12,11 @@ __all__ = ( log = logging.getLogger(__name__) +bookmark_icon_url = ( + "https://images-ext-2.discordapp.net/external/zl4oDwcmxUILY7sD9ZWE2fU5R7n6QcxEmPYSE5eddbg/" + "%3Fv%3D1/https/cdn.discordapp.com/emojis/654080405988966419.png?width=20&height=20" +) + class AdventOfCode: leaderboard_cache_age_threshold_seconds = 3600 -- cgit v1.2.3 From a580dd550bcf787934ef7901f03f670e2df842cf Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 10 Dec 2019 23:28:35 +0100 Subject: Use bookmark icon url from constants --- bot/seasons/evergreen/bookmark.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index ccff149c..9962186f 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -4,7 +4,7 @@ import random import discord from discord.ext import commands -from bot.constants import Colours, ERROR_REPLIES, Emojis +from bot.constants import Colours, ERROR_REPLIES, Emojis, bookmark_icon_url log = logging.getLogger(__name__) @@ -34,7 +34,7 @@ class Bookmark(commands.Cog): ) ) embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) - embed.set_thumbnail(url="https://img.icons8.com/color/48/FF3333/bookmark-ribbon.png") + embed.set_thumbnail(url=bookmark_icon_url) try: await ctx.author.send(embed=embed) -- cgit v1.2.3 From 7ce66ef375c330b4913f35f6700a32080de8bb26 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Thu, 12 Dec 2019 12:37:10 +1000 Subject: Use error_embed for errors, tidy code, show cmd signature for user errors. --- bot/seasons/evergreen/error_handler.py | 225 ++++++++++++++++----------------- 1 file changed, 106 insertions(+), 119 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/error_handler.py b/bot/seasons/evergreen/error_handler.py index 120462ee..cf6dc087 100644 --- a/bot/seasons/evergreen/error_handler.py +++ b/bot/seasons/evergreen/error_handler.py @@ -1,119 +1,106 @@ -import logging -import math -import random -import sys -import traceback - -from discord import Colour, Embed, Message -from discord.ext import commands - -from bot.constants import NEGATIVE_REPLIES -from bot.decorators import InChannelCheckFailure - -log = logging.getLogger(__name__) - - -class CommandErrorHandler(commands.Cog): - """A error handler for the PythonDiscord server.""" - - def __init__(self, bot: commands.Bot): - self.bot = bot - - @staticmethod - def revert_cooldown_counter(command: commands.Command, message: Message) -> None: - """Undoes the last cooldown counter for user-error cases.""" - if command._buckets.valid: - bucket = command._buckets.get_bucket(message) - bucket._tokens = min(bucket.rate, bucket._tokens + 1) - logging.debug( - "Cooldown counter reverted as the command was not used correctly." - ) - - @commands.Cog.listener() - async def on_command_error(self, ctx: commands.Context, error: commands.CommandError) -> None: - """Activates when a command opens an error.""" - if hasattr(ctx.command, 'on_error'): - return logging.debug( - "A command error occured but the command had it's own error handler." - ) - - error = getattr(error, 'original', error) - - if isinstance(error, InChannelCheckFailure): - logging.debug( - f"{ctx.author} the command '{ctx.command}', but they did not have " - f"permissions to run commands in the channel {ctx.channel}!" - ) - embed = Embed(colour=Colour.red()) - embed.title = random.choice(NEGATIVE_REPLIES) - embed.description = str(error) - return await ctx.send(embed=embed) - - if isinstance(error, commands.CommandNotFound): - return logging.debug( - f"{ctx.author} called '{ctx.message.content}' but no command was found." - ) - - if isinstance(error, commands.UserInputError): - logging.debug( - f"{ctx.author} called the command '{ctx.command}' but entered invalid input!" - ) - - self.revert_cooldown_counter(ctx.command, ctx.message) - - return await ctx.send( - ":no_entry: The command you specified failed to run. " - "This is because the arguments you provided were invalid." - ) - - if isinstance(error, commands.CommandOnCooldown): - logging.debug( - f"{ctx.author} called the command '{ctx.command}' but they were on cooldown!" - ) - remaining_minutes, remaining_seconds = divmod(error.retry_after, 60) - - return await ctx.send( - "This command is on cooldown, please retry in " - f"{int(remaining_minutes)} minutes {math.ceil(remaining_seconds)} seconds." - ) - - if isinstance(error, commands.DisabledCommand): - logging.debug( - f"{ctx.author} called the command '{ctx.command}' but the command was disabled!" - ) - return await ctx.send(":no_entry: This command has been disabled.") - - if isinstance(error, commands.NoPrivateMessage): - logging.debug( - f"{ctx.author} called the command '{ctx.command}' " - "in a private message however the command was guild only!" - ) - return await ctx.author.send(":no_entry: This command can only be used in the server.") - - if isinstance(error, commands.BadArgument): - self.revert_cooldown_counter(ctx.command, ctx.message) - - logging.debug( - f"{ctx.author} called the command '{ctx.command}' but entered a bad argument!" - ) - return await ctx.send("The argument you provided was invalid.") - - if isinstance(error, commands.CheckFailure): - logging.debug(f"{ctx.author} called the command '{ctx.command}' but the checks failed!") - return await ctx.send(":no_entry: You are not authorized to use this command.") - - print(f"Ignoring exception in command {ctx.command}:", file=sys.stderr) - - logging.warning( - f"{ctx.author} called the command '{ctx.command}' " - "however the command failed to run with the error:" - f"-------------\n{error}" - ) - - traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) - - -def setup(bot: commands.Bot) -> None: - """Error handler Cog load.""" - bot.add_cog(CommandErrorHandler(bot)) - log.info("CommandErrorHandler cog loaded") +import logging +import math +import random +from typing import Iterable, Union + +from discord import Embed, Message +from discord.ext import commands + +from bot.constants import Colours, ERROR_REPLIES, NEGATIVE_REPLIES +from bot.decorators import InChannelCheckFailure + +log = logging.getLogger(__name__) + + +class CommandErrorHandler(commands.Cog): + """A error handler for the PythonDiscord server.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + @staticmethod + def revert_cooldown_counter(command: commands.Command, message: Message) -> None: + """Undoes the last cooldown counter for user-error cases.""" + if command._buckets.valid: + bucket = command._buckets.get_bucket(message) + bucket._tokens = min(bucket.rate, bucket._tokens + 1) + logging.debug("Cooldown counter reverted as the command was not used correctly.") + + @staticmethod + def error_embed(message: str, title: Union[Iterable, str] = ERROR_REPLIES) -> Embed: + """Build a basic embed with red colour and either a random error title or a title provided.""" + embed = Embed(colour=Colours.soft_red) + if isinstance(title, str): + embed.title = title + else: + embed.title = random.choice(title) + embed.description = message + return embed + + @commands.Cog.listener() + async def on_command_error(self, ctx: commands.Context, error: commands.CommandError) -> None: + """Activates when a command opens an error.""" + if hasattr(ctx.command, 'on_error'): + logging.debug("A command error occured but the command had it's own error handler.") + return + + error = getattr(error, 'original', error) + logging.debug( + f"Error Encountered: {type(error).__name__} - {str(error)}, " + f"Command: {ctx.command}, " + f"Author: {ctx.author}, " + f"Channel: {ctx.channel}" + ) + + if isinstance(error, commands.CommandNotFound): + return + + if isinstance(error, InChannelCheckFailure): + await ctx.send(embed=self.error_embed(str(error), NEGATIVE_REPLIES)) + return + + if isinstance(error, commands.UserInputError): + self.revert_cooldown_counter(ctx.command, ctx.message) + embed = self.error_embed( + f"Your input was invalid: {error}\n\nUsage:\n```{ctx.prefix}{ctx.command} {ctx.command.signature}```" + ) + await ctx.send(embed=embed) + return + + if isinstance(error, commands.CommandOnCooldown): + mins, secs = divmod(math.ceil(error.retry_after), 60) + embed = self.error_embed( + f"This command is on cooldown:\nPlease retry in {mins} minutes {secs} seconds.", + NEGATIVE_REPLIES + ) + await ctx.send(embed=embed) + return + + if isinstance(error, commands.DisabledCommand): + await ctx.send(embed=self.error_embed("This command has been disabled.", NEGATIVE_REPLIES)) + return + + if isinstance(error, commands.NoPrivateMessage): + await ctx.send(embed=self.error_embed("This command can only be used in the server.", NEGATIVE_REPLIES)) + return + + if isinstance(error, commands.BadArgument): + self.revert_cooldown_counter(ctx.command, ctx.message) + embed = self.error_embed( + "The argument you provided was invalid: " + f"{error}\n\nUsage:\n```{ctx.prefix}{ctx.command} {ctx.command.signature}```" + ) + await ctx.send(embed=embed) + return + + if isinstance(error, commands.CheckFailure): + await ctx.send(embed=self.error_embed("You are not authorized to use this command.", NEGATIVE_REPLIES)) + return + + log.exception(f"Unhandled command error: {str(error)}") + + +def setup(bot: commands.Bot) -> None: + """Error handler Cog load.""" + bot.add_cog(CommandErrorHandler(bot)) + log.info("CommandErrorHandler cog loaded") -- cgit v1.2.3 From ff2e152642d1d586553357758aa9bdb8c3dd1cd9 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Thu, 12 Dec 2019 12:59:39 +1000 Subject: Add exc_info to log.exception to display traceback. --- bot/seasons/evergreen/error_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/error_handler.py b/bot/seasons/evergreen/error_handler.py index cf6dc087..8e7cc8d3 100644 --- a/bot/seasons/evergreen/error_handler.py +++ b/bot/seasons/evergreen/error_handler.py @@ -97,7 +97,7 @@ class CommandErrorHandler(commands.Cog): await ctx.send(embed=self.error_embed("You are not authorized to use this command.", NEGATIVE_REPLIES)) return - log.exception(f"Unhandled command error: {str(error)}") + log.exception(f"Unhandled command error: {str(error)}", exc_info=error) def setup(bot: commands.Bot) -> None: -- cgit v1.2.3 From 631c89e84fa233bba30af29df5d9e98793a79a65 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Thu, 12 Dec 2019 21:08:08 +1000 Subject: Auto-delete channel check error after a period of time. --- bot/seasons/evergreen/error_handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/error_handler.py b/bot/seasons/evergreen/error_handler.py index 8e7cc8d3..0d8bb0bb 100644 --- a/bot/seasons/evergreen/error_handler.py +++ b/bot/seasons/evergreen/error_handler.py @@ -56,7 +56,7 @@ class CommandErrorHandler(commands.Cog): return if isinstance(error, InChannelCheckFailure): - await ctx.send(embed=self.error_embed(str(error), NEGATIVE_REPLIES)) + await ctx.send(embed=self.error_embed(str(error), NEGATIVE_REPLIES), delete_after=7.5) return if isinstance(error, commands.UserInputError): @@ -73,7 +73,7 @@ class CommandErrorHandler(commands.Cog): f"This command is on cooldown:\nPlease retry in {mins} minutes {secs} seconds.", NEGATIVE_REPLIES ) - await ctx.send(embed=embed) + await ctx.send(embed=embed, delete_after=7.5) return if isinstance(error, commands.DisabledCommand): -- cgit v1.2.3 From c55342ff0cc65b603378382372d3a29d232e02bd Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Mon, 16 Dec 2019 20:40:31 +0530 Subject: Fixed indentation, the category_embed function is no longer a property. --- bot/seasons/evergreen/trivia_quiz.py | 50 ++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 28 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 69fecb3a..38bd3f72 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -74,7 +74,7 @@ class TriviaQuiz(commands.Cog): category = category.lower() # Send embed showing available categories if inputted category is invalid. if category not in self.categories: - embed = self.category_embed + embed = self.category_embed() await ctx.send(embed=embed) return @@ -124,12 +124,12 @@ class TriviaQuiz(commands.Cog): def check(m: discord.Message) -> bool: ratio = fuzz.ratio(answer.lower(), m.content.lower()) return ratio > 85 and m.channel == ctx.channel - try: - msg = await self.bot.wait_for('message', check=check, timeout=10) - except asyncio.TimeoutError: - # In case of TimeoutError and the game has been stopped, then do nothing. - if self.game_status[ctx.channel.id] is False: - break + try: + msg = await self.bot.wait_for('message', check=check, timeout=10) + except asyncio.TimeoutError: + # In case of TimeoutError and the game has been stopped, then do nothing. + if self.game_status[ctx.channel.id] is False: + break # if number of hints sent or time alerts sent is less than 2, then send one. if hint_no < 2: @@ -195,25 +195,21 @@ class TriviaQuiz(commands.Cog): async def stop_quiz(self, ctx: commands.Context) -> None: """Stop a quiz game if its running in the channel.""" if self.game_status[ctx.channel.id] is True: - await self.stop(ctx.author, ctx.channel) + # Check if the author is the game starter or a moderator. + if ( + ctx.author == self.game_owners[ctx.channel.id] + or any(Roles.moderator == role.id for role in ctx.author.roles) + ): + await ctx.send("Quiz stopped.") + await self.declare_winner(ctx.channel, self.game_player_scores[ctx.channel.id]) + self.game_status[ctx.channel.id] = False + del self.game_owners[ctx.channel.id] + self.game_player_scores[ctx.channel.id] = {} + else: + await ctx.send(f"{ctx.author.mention}, you are not authorised to stop this game :ghost:!") else: await ctx.send("No quiz running.") - async def stop(self, author: discord.Member, channel: discord.TextChannel) -> None: - """Stop the quiz.""" - # Check if the author is the game starter or a moderator. - if ( - author == self.game_owners[channel.id] - or any(Roles.moderator == role.id for role in author.roles) - ): - await channel.send("Quiz stopped.") - await self.declare_winner(channel, self.game_player_scores[channel.id]) - self.game_status[channel.id] = False - del self.game_owners[channel.id] - self.game_player_scores[channel.id] = {} - else: - await channel.send(f"{author.mention}, you are not authorised to stop this game :ghost:!") - @quiz_game.command(name="leaderboard") async def leaderboard(self, ctx: commands.Context) -> None: """View everyone's score for this bot session.""" @@ -222,15 +218,14 @@ class TriviaQuiz(commands.Cog): @staticmethod async def send_score(channel: discord.TextChannel, player_data: dict) -> None: """A function which sends the score.""" - embed = discord.Embed(colour=discord.Colour.blue()) - embed.title = "Score Board" - embed.description = "" if len(player_data) == 0: await channel.send("No one has made it onto the leaderboard yet.") return + embed = discord.Embed(colour=discord.Colour.blue()) + embed.title = "Score Board" + embed.description = "" sorted_dict = sorted(player_data.items(), key=lambda a: a[1], reverse=True) for item in sorted_dict: - embed.description += f"{item[0]} : {item[1]}\n" await channel.send(embed=embed) @@ -264,7 +259,6 @@ class TriviaQuiz(commands.Cog): f"{word} have won this quiz game with a grand total of {highest_points} points!" ) - @property def category_embed(self) -> discord.Embed: """Build an embed showing all available trivia categories.""" embed = discord.Embed(colour=discord.Colour.blue()) -- cgit v1.2.3 From f9530fc0a3e09a5d6be159831fe63b9cb70209ba Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Mon, 16 Dec 2019 20:53:22 +0530 Subject: fixed a indent error --- bot/seasons/evergreen/trivia_quiz.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 70e28e4b..fb7c4ba8 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -124,12 +124,12 @@ class TriviaQuiz(commands.Cog): def check(m: discord.Message) -> bool: ratio = fuzz.ratio(answer.lower(), m.content.lower()) return ratio > 85 and m.channel == ctx.channel - try: - msg = await self.bot.wait_for('message', check=check, timeout=10) - except asyncio.TimeoutError: - # In case of TimeoutError and the game has been stopped, then do nothing. - if self.game_status[ctx.channel.id] is False: - break + try: + msg = await self.bot.wait_for('message', check=check, timeout=10) + except asyncio.TimeoutError: + # In case of TimeoutError and the game has been stopped, then do nothing. + if self.game_status[ctx.channel.id] is False: + break # if number of hints sent or time alerts sent is less than 2, then send one. if hint_no < 2: @@ -155,7 +155,6 @@ class TriviaQuiz(commands.Cog): await self.send_score(ctx.channel, self.game_player_scores[ctx.channel.id]) await asyncio.sleep(2) - else: if self.game_status[ctx.channel.id] is False: break -- cgit v1.2.3 From 529fc617dae7636eb5948bc79f51da9afceb1710 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 17 Dec 2019 08:24:34 -0800 Subject: Trivia: space out some of lines of code --- bot/seasons/evergreen/trivia_quiz.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index fb7c4ba8..2470ec0f 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -80,7 +80,6 @@ class TriviaQuiz(commands.Cog): # Start game if not running. if self.game_status[ctx.channel.id] is False: - self.game_owners[ctx.channel.id] = ctx.author self.game_status[ctx.channel.id] = True start_embed = self.make_start_embed() @@ -94,14 +93,15 @@ class TriviaQuiz(commands.Cog): hint_no = 0 answer = None while self.game_status[ctx.channel.id]: - # Exit quiz if number of questions for a round are already sent. if len(done_question) > self.question_limit and hint_no == 0: await ctx.send("The round has ended.") await self.declare_winner(ctx.channel, self.game_player_scores[ctx.channel.id]) + self.game_status[ctx.channel.id] = False del self.game_owners[ctx.channel.id] self.game_player_scores[ctx.channel.id] = {} + break # If no hint has been sent or any time alert. Basically if hint_no = 0 means it is a new question. @@ -112,6 +112,7 @@ class TriviaQuiz(commands.Cog): if question_dict["id"] not in done_question: done_question.append(question_dict["id"]) break + q = question_dict["question"] answer = question_dict["answer"] @@ -124,6 +125,7 @@ class TriviaQuiz(commands.Cog): def check(m: discord.Message) -> bool: ratio = fuzz.ratio(answer.lower(), m.content.lower()) return ratio > 85 and m.channel == ctx.channel + try: msg = await self.bot.wait_for('message', check=check, timeout=10) except asyncio.TimeoutError: @@ -146,6 +148,7 @@ class TriviaQuiz(commands.Cog): else: if self.game_status[ctx.channel.id] is False: break + response = random.choice(WRONG_ANS_RESPONSE) await ctx.send(response) await self.send_answer(ctx.channel, question_dict) @@ -158,6 +161,7 @@ class TriviaQuiz(commands.Cog): else: if self.game_status[ctx.channel.id] is False: break + # Reduce points by 25 for every hint/time alert that has been sent. points = 100 - 25*hint_no if msg.author in self.game_player_scores[ctx.channel.id]: @@ -201,6 +205,7 @@ class TriviaQuiz(commands.Cog): ): await ctx.send("Quiz stopped.") await self.declare_winner(ctx.channel, self.game_player_scores[ctx.channel.id]) + self.game_status[ctx.channel.id] = False del self.game_owners[ctx.channel.id] self.game_player_scores[ctx.channel.id] = {} @@ -220,12 +225,15 @@ class TriviaQuiz(commands.Cog): if len(player_data) == 0: await channel.send("No one has made it onto the leaderboard yet.") return + embed = discord.Embed(colour=discord.Colour.blue()) embed.title = "Score Board" embed.description = "" + sorted_dict = sorted(player_data.items(), key=lambda a: a[1], reverse=True) for item in sorted_dict: embed.description += f"{item[0]} : {item[1]}\n" + await channel.send(embed=embed) @staticmethod @@ -240,10 +248,12 @@ class TriviaQuiz(commands.Cog): word = "You guys" winners = [] points_copy = list(player_data.values()).copy() + for _ in range(no_of_winners): index = points_copy.index(highest_points) winners.append(list(player_data.keys())[index]) points_copy[index] = 0 + winners_mention = None for winner in winners: winners_mention += f"{winner.mention} " @@ -262,10 +272,12 @@ class TriviaQuiz(commands.Cog): """Build an embed showing all available trivia categories.""" embed = discord.Embed(colour=discord.Colour.blue()) embed.title = "The available question categories are:" + embed.set_footer(text="If not category is chosen, then a random one will be selected.") embed.description = "" + for cat, description in self.categories.items(): embed.description += f"**- {cat.capitalize()}**\n{description.capitalize()}\n" - embed.set_footer(text="If not category is chosen, then a random one will be selected.") + return embed @staticmethod @@ -276,8 +288,10 @@ class TriviaQuiz(commands.Cog): embed = discord.Embed(color=discord.Colour.red()) embed.title = f"The correct answer is **{answer}**\n" embed.description = "" + if info != "": embed.description += f"**Information**\n{info}\n\n" + embed.description += "Let's move to the next question.\nRemaining questions: " await channel.send(embed=embed) -- cgit v1.2.3 From 27d65c155681a0c720ce405909527fadb8b54b31 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 17 Dec 2019 08:30:48 -0800 Subject: Trivia: fix concatenation of winner mentions --- bot/seasons/evergreen/trivia_quiz.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 2470ec0f..345f1abd 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -254,9 +254,7 @@ class TriviaQuiz(commands.Cog): winners.append(list(player_data.keys())[index]) points_copy[index] = 0 - winners_mention = None - for winner in winners: - winners_mention += f"{winner.mention} " + winners_mention = " ".join(winner.mention for winner in winners) else: word = "You" author_index = list(player_data.values()).index(highest_points) -- cgit v1.2.3 From 145eda56bedb105428822264e10305c1bc0c2114 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Tue, 17 Dec 2019 08:51:59 -0800 Subject: Trivia: fix spelling error in category embed footer --- bot/seasons/evergreen/trivia_quiz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 345f1abd..49e75b79 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -270,7 +270,7 @@ class TriviaQuiz(commands.Cog): """Build an embed showing all available trivia categories.""" embed = discord.Embed(colour=discord.Colour.blue()) embed.title = "The available question categories are:" - embed.set_footer(text="If not category is chosen, then a random one will be selected.") + embed.set_footer(text="If a category is not chosen, a random one will be selected.") embed.description = "" for cat, description in self.categories.items(): -- cgit v1.2.3 From 1993fe6c77faaabcaf847abbedd9cc126e459556 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Fri, 20 Dec 2019 11:02:49 +0530 Subject: In this commit: - I cleaned up some residue code - The quiz now selects a random category if None provided - Updated doc strings - Displaying the category when the quiz is starting --- bot/seasons/evergreen/trivia_quiz.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index fb7c4ba8..ebb9077a 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -45,13 +45,10 @@ class TriviaQuiz(commands.Cog): return questions @commands.group(name="quiz", aliases=["trivia"], invoke_without_command=True) - async def quiz_game(self, ctx: commands.Context, category: str = "general") -> None: + async def quiz_game(self, ctx: commands.Context, category: str = None) -> None: """ Start a quiz! - If the quiz game is running, then the owner or a mod can stop it by using this command - without providing any arguments or vice versa. - Questions for the quiz can be selected from the following categories: - general : Test your general knowledge. (default) (More to come!) @@ -68,22 +65,22 @@ class TriviaQuiz(commands.Cog): f"Game is already running..." f"do `{self.bot.command_prefix}quiz stop`" ) - await self.stop_quiz(ctx.author, ctx.channel) - return - category = category.lower() - # Send embed showing available categories if inputted category is invalid. - if category not in self.categories: + # Send embed showing available categori es if inputted category is invalid. + if category is None: + category = random.choice(list(self.categories)) + if category.lower() not in self.categories: embed = self.category_embed() await ctx.send(embed=embed) return + # Start game if not running. if self.game_status[ctx.channel.id] is False: self.game_owners[ctx.channel.id] = ctx.author self.game_status[ctx.channel.id] = True - start_embed = self.make_start_embed() + start_embed = self.make_start_embed(category) await ctx.send(embed=start_embed) # send an embed with the rules await asyncio.sleep(1) @@ -179,12 +176,13 @@ class TriviaQuiz(commands.Cog): await asyncio.sleep(2) @staticmethod - def make_start_embed() -> discord.Embed: + def make_start_embed(category: str) -> discord.Embed: """Generate a starting/introduction embed for the quiz.""" start_embed = discord.Embed(colour=discord.Colour.red()) start_embed.title = "Quiz game Starting!!" start_embed.description = "Each game consists of 5 questions.\n" start_embed.description += "**Rules :**\nNo cheating and have fun!" + start_embed.description += f"\n **Category** : {category}" start_embed.set_footer( text="Points for each question reduces by 25 after 10s or after a hint. Total time is 30s per question" ) @@ -192,7 +190,10 @@ class TriviaQuiz(commands.Cog): @quiz_game.command(name="stop") async def stop_quiz(self, ctx: commands.Context) -> None: - """Stop a quiz game if its running in the channel.""" + """ + Stop a quiz game if its running in the channel. + Note: Only mods or the owner of the quiz can stop it. + """ if self.game_status[ctx.channel.id] is True: # Check if the author is the game starter or a moderator. if ( -- cgit v1.2.3 From 303128f4b5bd31764bd02ec98a0d1f3ec226ed2c Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Fri, 20 Dec 2019 11:04:52 +0530 Subject: fixed lint errors --- bot/seasons/evergreen/trivia_quiz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 770402e5..2b43bb8b 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -73,7 +73,6 @@ class TriviaQuiz(commands.Cog): embed = self.category_embed() await ctx.send(embed=embed) return - # Start game if not running. if self.game_status[ctx.channel.id] is False: @@ -196,6 +195,7 @@ class TriviaQuiz(commands.Cog): async def stop_quiz(self, ctx: commands.Context) -> None: """ Stop a quiz game if its running in the channel. + Note: Only mods or the owner of the quiz can stop it. """ if self.game_status[ctx.channel.id] is True: -- cgit v1.2.3 From c9e6bf2ac3fe85086a4d1ca69d8b37469d47d095 Mon Sep 17 00:00:00 2001 From: Rohan_Iceman Date: Fri, 20 Dec 2019 13:58:54 +0530 Subject: Update bot/seasons/evergreen/trivia_quiz.py Co-Authored-By: Mark --- bot/seasons/evergreen/trivia_quiz.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 2b43bb8b..67c202f0 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -69,7 +69,9 @@ class TriviaQuiz(commands.Cog): # Send embed showing available categori es if inputted category is invalid. if category is None: category = random.choice(list(self.categories)) - if category.lower() not in self.categories: + + category = category.lower() + if category not in self.categories: embed = self.category_embed() await ctx.send(embed=embed) return -- cgit v1.2.3 From 0758be812d40dd64f33262ef366fdfb5917bb1fc Mon Sep 17 00:00:00 2001 From: Rohan_Iceman Date: Fri, 20 Dec 2019 13:59:13 +0530 Subject: Update bot/seasons/evergreen/trivia_quiz.py Co-Authored-By: Mark --- bot/seasons/evergreen/trivia_quiz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/trivia_quiz.py b/bot/seasons/evergreen/trivia_quiz.py index 67c202f0..99b64497 100644 --- a/bot/seasons/evergreen/trivia_quiz.py +++ b/bot/seasons/evergreen/trivia_quiz.py @@ -66,7 +66,7 @@ class TriviaQuiz(commands.Cog): f"do `{self.bot.command_prefix}quiz stop`" ) - # Send embed showing available categori es if inputted category is invalid. + # Send embed showing available categories if inputted category is invalid. if category is None: category = random.choice(list(self.categories)) -- cgit v1.2.3 From 67d126ea3c66b1c2df2412e3cd9dd96cfb6beb04 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Tue, 7 Jan 2020 00:15:22 +0530 Subject: Add exception where relayed message.content length exceed 2048 characters --- bot/seasons/evergreen/bookmark.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 9962186f..5b399739 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -25,11 +25,14 @@ class Bookmark(commands.Cog): ) -> None: """Send the author a link to `target_message` via DMs.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title '{title}'") + content = target_message.content + if len(content) > 250: + content = content[:250]+'......' embed = discord.Embed( title=title, colour=Colours.soft_green, description=( - f"{target_message.content}\n\n" + f"{content}\n\n" f"[Visit original message]({target_message.jump_url})" ) ) -- cgit v1.2.3 From 9735b0ad3bbfc98df5f48b0fe3e0c7fdf3c4be6c Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Tue, 7 Jan 2020 20:30:44 +0530 Subject: Moved jump url into a field. --- bot/seasons/evergreen/bookmark.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 5b399739..56c436d6 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -26,16 +26,12 @@ class Bookmark(commands.Cog): """Send the author a link to `target_message` via DMs.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title '{title}'") content = target_message.content - if len(content) > 250: - content = content[:250]+'......' embed = discord.Embed( title=title, colour=Colours.soft_green, - description=( - f"{content}\n\n" - f"[Visit original message]({target_message.jump_url})" - ) + description=content ) + embed.add_field(name="Wanna give it a visit?", value=f"[Visit original message]({target_message.jump_url})") embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) embed.set_thumbnail(url=bookmark_icon_url) -- cgit v1.2.3 From b4846a9e5262f0b86045d81da5ccb1be33f294e8 Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Tue, 7 Jan 2020 20:31:46 +0530 Subject: Removed unnacessary `content` variable usage --- bot/seasons/evergreen/bookmark.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 56c436d6..0197f9f4 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -25,11 +25,10 @@ class Bookmark(commands.Cog): ) -> None: """Send the author a link to `target_message` via DMs.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title '{title}'") - content = target_message.content embed = discord.Embed( title=title, colour=Colours.soft_green, - description=content + description=target_message.content ) embed.add_field(name="Wanna give it a visit?", value=f"[Visit original message]({target_message.jump_url})") embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) -- cgit v1.2.3 From 9c4cf670fff767569fb4d29c7c4108f88e82015b Mon Sep 17 00:00:00 2001 From: AG_1436 <45149585+AG4lyf@users.noreply.github.com> Date: Sat, 25 Jan 2020 15:33:59 +0530 Subject: Added permission check for staff channels message leak. --- bot/seasons/evergreen/bookmark.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 0197f9f4..3fe1d12c 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -25,6 +25,18 @@ class Bookmark(commands.Cog): ) -> None: """Send the author a link to `target_message` via DMs.""" log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title '{title}'") + permissions = ctx.author.permissions_in(target_message.channel) + if not permissions.read_messages: + embed = discord.Embed( + title=random.choice(ERROR_REPLIES), + color=Colours.soft_red, + description="You don't have permission to see what's in the channel so you can't " + "bookmark a message from it." + ) + embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar_url) + await ctx.send(embed=embed) + return + embed = discord.Embed( title=title, colour=Colours.soft_green, -- cgit v1.2.3 From c600c9b136e5618da1656615de7e4914bf0cfb35 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Sun, 26 Jan 2020 20:45:38 +0530 Subject: installed buttons and implemented embed pagination --- Pipfile | 1 + Pipfile.lock | 347 ++++++++++++++++++++++------------------ bot/seasons/evergreen/reddit.py | 130 +++++++++++++++ 3 files changed, 321 insertions(+), 157 deletions(-) create mode 100644 bot/seasons/evergreen/reddit.py (limited to 'bot') diff --git a/Pipfile b/Pipfile index c066958e..82f1103d 100644 --- a/Pipfile +++ b/Pipfile @@ -11,6 +11,7 @@ discord-py = "~=1.2" fuzzywuzzy = "~=0.17" pillow = "~=6.2" pytz = "~=2019.2" +buttons = "*" [dev-packages] flake8 = "~=3.7" diff --git a/Pipfile.lock b/Pipfile.lock index 3252f36f..af8b646e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "40f23ea08504def8d3d5f56379820221088d93e9bf81d739850dc97ea8a4b7dc" + "sha256": "769234aeffdf5a6e781dc783a903771f6100f80450244d5211f0f1a11ec79814" }, "pipfile-spec": 6, "requires": { @@ -53,11 +53,11 @@ }, "arrow": { "hashes": [ - "sha256:01a16d8a93eddf86a29237f32ae36b29c27f047e79312eb4df5d55fd5a2b3183", - "sha256:e1a318a4c0b787833ae46302c02488b6eeef413c6a13324b3261ad320f21ec1e" + "sha256:5390e464e2c5f76971b60ffa7ee29c598c7501a294bc9f5e6dadcb251a5d027b", + "sha256:70729bcc831da496ca3cb4b7e89472c8e2d27d398908155e0796179f6d2d41ee" ], "index": "pypi", - "version": "==0.15.4" + "version": "==0.15.5" }, "async-timeout": { "hashes": [ @@ -75,12 +75,20 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:5279c36b4b2ec2cb4298d723791467e3000e5384a43ea0cdf5d45207c7e97169", - "sha256:6135db2ba678168c07950f9a16c4031822c6f4aec75a65e0a97bc5ca09789931", - "sha256:dcdef580e18a76d54002088602eba453eec38ebbcafafeaabd8cab12b6155d57" + "sha256:05fd825eb01c290877657a56df4c6e4c311b3965bda790c613a3d6fb01a5462a", + "sha256:9fbb4d6e48ecd30bcacc5b63b94088192dcda178513b2ae3c394229f8911b887", + "sha256:e1505eeed31b0f4ce2dbb3bc8eb256c04cc2b3b72af7d551a4ab6efd5cbe5dae" ], "index": "pypi", - "version": "==4.8.1" + "version": "==4.8.2" + }, + "buttons": { + "hashes": [ + "sha256:b58fe39c4995db9209443efb6799e22ae43a026d01989d84be033ce4d933cb96", + "sha256:ebf7349ff0e6173ac26f3cfdb92b9fe0c01e73c5dbe5e2874950ed4e6e45bb98" + ], + "index": "pypi", + "version": "==0.1.8" }, "cffi": { "hashes": [ @@ -134,6 +142,12 @@ "index": "pypi", "version": "==1.2.5" }, + "discord.py": { + "hashes": [ + "sha256:7c843b523bb011062b453864e75c7b675a03faf573c58d14c9f096e85984329d" + ], + "version": "==1.2.5" + }, "fuzzywuzzy": { "hashes": [ "sha256:5ac7c0b3f4658d2743aa17da53a55598144edbc5bee3c6863840636e6926f254", @@ -151,82 +165,99 @@ }, "multidict": { "hashes": [ - "sha256:07f9a6bf75ad675d53956b2c6a2d4ef2fa63132f33ecc99e9c24cf93beb0d10b", - "sha256:0ffe4d4d28cbe9801952bfb52a8095dd9ffecebd93f84bdf973c76300de783c5", - "sha256:1b605272c558e4c659dbaf0fb32a53bfede44121bcf77b356e6e906867b958b7", - "sha256:205a011e636d885af6dd0029e41e3514a46e05bb2a43251a619a6e8348b96fc0", - "sha256:250632316295f2311e1ed43e6b26a63b0216b866b45c11441886ac1543ca96e1", - "sha256:2bc9c2579312c68a3552ee816311c8da76412e6f6a9cf33b15152e385a572d2a", - "sha256:318aadf1cfb6741c555c7dd83d94f746dc95989f4f106b25b8a83dfb547f2756", - "sha256:42cdd649741a14b0602bf15985cad0dd4696a380081a3319cd1ead46fd0f0fab", - "sha256:5159c4975931a1a78bf6602bbebaa366747fce0a56cb2111f44789d2c45e379f", - "sha256:87e26d8b89127c25659e962c61a4c655ec7445d19150daea0759516884ecb8b4", - "sha256:891b7e142885e17a894d9d22b0349b92bb2da4769b4e675665d0331c08719be5", - "sha256:8d919034420378132d074bf89df148d0193e9780c9fe7c0e495e895b8af4d8a2", - "sha256:9c890978e2b37dd0dc1bd952da9a5d9f245d4807bee33e3517e4119c48d66f8c", - "sha256:a37433ce8cdb35fc9e6e47e1606fa1bfd6d70440879038dca7d8dd023197eaa9", - "sha256:c626029841ada34c030b94a00c573a0c7575fe66489cde148785b6535397d675", - "sha256:cfec9d001a83dc73580143f3c77e898cf7ad78b27bb5e64dbe9652668fcafec7", - "sha256:efaf1b18ea6c1f577b1371c0159edbe4749558bfe983e13aa24d0a0c01e1ad7b" - ], - "version": "==4.6.1" + "sha256:13f3ebdb5693944f52faa7b2065b751cb7e578b8dd0a5bb8e4ab05ad0188b85e", + "sha256:26502cefa86d79b86752e96639352c7247846515c864d7c2eb85d036752b643c", + "sha256:4fba5204d32d5c52439f88437d33ad14b5f228e25072a192453f658bddfe45a7", + "sha256:527124ef435f39a37b279653ad0238ff606b58328ca7989a6df372fd75d7fe26", + "sha256:5414f388ffd78c57e77bd253cf829373721f450613de53dc85a08e34d806e8eb", + "sha256:5eee66f882ab35674944dfa0d28b57fa51e160b4dce0ce19e47f495fdae70703", + "sha256:63810343ea07f5cd86ba66ab66706243a6f5af075eea50c01e39b4ad6bc3c57a", + "sha256:6bd10adf9f0d6a98ccc792ab6f83d18674775986ba9bacd376b643fe35633357", + "sha256:83c6ddf0add57c6b8a7de0bc7e2d656be3eefeff7c922af9a9aae7e49f225625", + "sha256:93166e0f5379cf6cd29746989f8a594fa7204dcae2e9335ddba39c870a287e1c", + "sha256:9a7b115ee0b9b92d10ebc246811d8f55d0c57e82dbb6a26b23c9a9a6ad40ce0c", + "sha256:a38baa3046cce174a07a59952c9f876ae8875ef3559709639c17fdf21f7b30dd", + "sha256:a6d219f49821f4b2c85c6d426346a5d84dab6daa6f85ca3da6c00ed05b54022d", + "sha256:a8ed33e8f9b67e3b592c56567135bb42e7e0e97417a4b6a771e60898dfd5182b", + "sha256:d7d428488c67b09b26928950a395e41cc72bb9c3d5abfe9f0521940ee4f796d4", + "sha256:dcfed56aa085b89d644af17442cdc2debaa73388feba4b8026446d168ca8dad7", + "sha256:f29b885e4903bd57a7789f09fe9d60b6475a6c1a4c0eca874d8558f00f9d4b51" + ], + "version": "==4.7.4" }, "pillow": { "hashes": [ - "sha256:047d9473cf68af50ac85f8ee5d5f21a60f849bc17d348da7fc85711287a75031", - "sha256:0f66dc6c8a3cc319561a633b6aa82c44107f12594643efa37210d8c924fc1c71", - "sha256:12c9169c4e8fe0a7329e8658c7e488001f6b4c8e88740e76292c2b857af2e94c", - "sha256:248cffc168896982f125f5c13e9317c059f74fffdb4152893339f3be62a01340", - "sha256:27faf0552bf8c260a5cee21a76e031acaea68babb64daf7e8f2e2540745082aa", - "sha256:285edafad9bc60d96978ed24d77cdc0b91dace88e5da8c548ba5937c425bca8b", - "sha256:384b12c9aa8ef95558abdcb50aada56d74bc7cc131dd62d28c2d0e4d3aadd573", - "sha256:38950b3a707f6cef09cd3cbb142474357ad1a985ceb44d921bdf7b4647b3e13e", - "sha256:4aad1b88933fd6dc2846552b89ad0c74ddbba2f0884e2c162aa368374bf5abab", - "sha256:4ac6148008c169603070c092e81f88738f1a0c511e07bd2bb0f9ef542d375da9", - "sha256:4deb1d2a45861ae6f0b12ea0a786a03d19d29edcc7e05775b85ec2877cb54c5e", - "sha256:59aa2c124df72cc75ed72c8d6005c442d4685691a30c55321e00ed915ad1a291", - "sha256:5a47d2123a9ec86660fe0e8d0ebf0aa6bc6a17edc63f338b73ea20ba11713f12", - "sha256:5cc901c2ab9409b4b7ac7b5bcc3e86ac14548627062463da0af3b6b7c555a871", - "sha256:6c1db03e8dff7b9f955a0fb9907eb9ca5da75b5ce056c0c93d33100a35050281", - "sha256:7ce80c0a65a6ea90ef9c1f63c8593fcd2929448613fc8da0adf3e6bfad669d08", - "sha256:809c19241c14433c5d6135e1b6c72da4e3b56d5c865ad5736ab99af8896b8f41", - "sha256:83792cb4e0b5af480588601467c0764242b9a483caea71ef12d22a0d0d6bdce2", - "sha256:846fa202bd7ee0f6215c897a1d33238ef071b50766339186687bd9b7a6d26ac5", - "sha256:9f5529fc02009f96ba95bea48870173426879dc19eec49ca8e08cd63ecd82ddb", - "sha256:a423c2ea001c6265ed28700df056f75e26215fd28c001e93ef4380b0f05f9547", - "sha256:ac4428094b42907aba5879c7c000d01c8278d451a3b7cccd2103e21f6397ea75", - "sha256:b1ae48d87f10d1384e5beecd169c77502fcc04a2c00a4c02b85f0a94b419e5f9", - "sha256:bf4e972a88f8841d8fdc6db1a75e0f8d763e66e3754b03006cbc3854d89f1cb1", - "sha256:c6414f6aad598364aaf81068cabb077894eb88fed99c6a65e6e8217bab62ae7a", - "sha256:c710fcb7ee32f67baf25aa9ffede4795fd5d93b163ce95fdc724383e38c9df96", - "sha256:c7be4b8a09852291c3c48d3c25d1b876d2494a0a674980089ac9d5e0d78bd132", - "sha256:c9e5ffb910b14f090ac9c38599063e354887a5f6d7e6d26795e916b4514f2c1a", - "sha256:e0697b826da6c2472bb6488db4c0a7fa8af0d52fa08833ceb3681358914b14e5", - "sha256:e9a3edd5f714229d41057d56ac0f39ad9bdba6767e8c888c951869f0bdd129b0" + "sha256:00e0bbe9923adc5cc38a8da7d87d4ce16cde53b8d3bba8886cb928e84522d963", + "sha256:03457e439d073770d88afdd90318382084732a5b98b0eb6f49454746dbaae701", + "sha256:0d5c99f80068f13231ac206bd9b2e80ea357f5cf9ae0fa97fab21e32d5b61065", + "sha256:1a3bc8e1db5af40a81535a62a591fafdb30a8a1b319798ea8052aa65ef8f06d2", + "sha256:2b4a94be53dff02af90760c10a2e3634c3c7703410f38c98154d5ce71fe63d20", + "sha256:3ba7d8f1d962780f86aa747fef0baf3211b80cb13310fff0c375da879c0656d4", + "sha256:3e81485cec47c24f5fb27acb485a4fc97376b2b332ed633867dc68ac3077998c", + "sha256:43ef1cff7ee57f9c8c8e6fa02a62eae9fa23a7e34418c7ce88c0e3fe09d1fb38", + "sha256:4adc3302df4faf77c63ab3a83e1a3e34b94a6a992084f4aa1cb236d1deaf4b39", + "sha256:535e8e0e02c9f1fc2e307256149d6ee8ad3aa9a6e24144b7b6e6fb6126cb0e99", + "sha256:5ccfcb0a34ad9b77ad247c231edb781763198f405a5c8dc1b642449af821fb7f", + "sha256:5dcbbaa3a24d091a64560d3c439a8962866a79a033d40eb1a75f1b3413bfc2bc", + "sha256:6e2a7e74d1a626b817ecb7a28c433b471a395c010b2a1f511f976e9ea4363e64", + "sha256:82859575005408af81b3e9171ae326ff56a69af5439d3fc20e8cb76cd51c8246", + "sha256:834dd023b7f987d6b700ad93dc818098d7eb046bd445e9992b3093c6f9d7a95f", + "sha256:87ef0eca169f7f0bc050b22f05c7e174a65c36d584428431e802c0165c5856ea", + "sha256:900de1fdc93764be13f6b39dc0dd0207d9ff441d87ad7c6e97e49b81987dc0f3", + "sha256:92b83b380f9181cacc994f4c983d95a9c8b00b50bf786c66d235716b526a3332", + "sha256:aa1b0297e352007ec781a33f026afbb062a9a9895bb103c8f49af434b1666880", + "sha256:aa4792ab056f51b49e7d59ce5733155e10a918baf8ce50f64405db23d5627fa2", + "sha256:b72c39585f1837d946bd1a829a4820ccf86e361f28cbf60f5d646f06318b61e2", + "sha256:bb7861e4618a0c06c40a2e509c1bea207eea5fd4320d486e314e00745a402ca5", + "sha256:bc149dab804291a18e1186536519e5e122a2ac1316cb80f506e855a500b1cdd4", + "sha256:c424d35a5259be559b64490d0fd9e03fba81f1ce8e5b66e0a59de97547351d80", + "sha256:cbd5647097dc55e501f459dbac7f1d0402225636deeb9e0a98a8d2df649fc19d", + "sha256:ccf16fe444cc43800eeacd4f4769971200982200a71b1368f49410d0eb769543", + "sha256:d3a98444a00b4643b22b0685dbf9e0ddcaf4ebfd4ea23f84f228adf5a0765bb2", + "sha256:d6b4dc325170bee04ca8292bbd556c6f5398d52c6149ca881e67daf62215426f", + "sha256:db9ff0c251ed066d367f53b64827cc9e18ccea001b986d08c265e53625dab950", + "sha256:e3a797a079ce289e59dbd7eac9ca3bf682d52687f718686857281475b7ca8e6a" ], "index": "pypi", - "version": "==6.2.1" + "version": "==6.2.2" }, "pycares": { "hashes": [ - "sha256:2ca080db265ea238dc45f997f94effb62b979a617569889e265c26a839ed6305", - "sha256:6f79c6afb6ce603009db2042fddc2e348ad093ece9784cbe2daa809499871a23", - "sha256:70918d06eb0603016d37092a5f2c0228509eb4e6c5a3faacb4184f6ab7be7650", - "sha256:755187d28d24a9ea63aa2b4c0638be31d65fbf7f0ce16d41261b9f8cb55a1b99", - "sha256:7baa4b1f2146eb8423ff8303ebde3a20fb444a60db761fba0430d104fe35ddbf", - "sha256:90b27d4df86395f465a171386bc341098d6d47b65944df46518814ae298f6cc6", - "sha256:9e090dd6b2afa65cb51c133883b2bf2240fd0f717b130b0048714b33fb0f47ce", - "sha256:a11b7d63c3718775f6e805d6464cb10943780395ab042c7e5a0a7a9f612735dd", - "sha256:b253f5dcaa0ac7076b79388a3ac80dd8f3bd979108f813baade40d3a9b8bf0bd", - "sha256:c7f4f65e44ba35e35ad3febc844270665bba21cfb0fb7d749434e705b556e087", - "sha256:cdb342e6a254f035bd976d95807a2184038fc088d957a5104dcaab8be602c093", - "sha256:cf08e164f8bfb83b9fe633feb56f2754fae6baefcea663593794fa0518f8f98c", - "sha256:df9bc694cf03673878ea8ce674082c5acd134991d64d6c306d4bd61c0c1df98f" - ], - "version": "==3.0.0" + "sha256:050f00b39ed77ea8a4e555f09417d4b1a6b5baa24bb9531a3e15d003d2319b3f", + "sha256:0a24d2e580a8eb567140d7b69f12cb7de90c836bd7b6488ec69394d308605ac3", + "sha256:0c5bd1f6f885a219d5e972788d6eef7b8043b55c3375a845e5399638436e0bba", + "sha256:11c628402cc8fc8ef461076d4e47f88afc1f8609989ebbff0dbffcd54c97239f", + "sha256:18dfd4fd300f570d6c4536c1d987b7b7673b2a9d14346592c5d6ed716df0d104", + "sha256:1917b82494907a4a342db420bc4dd5bac355a5fa3984c35ba9bf51422b020b48", + "sha256:1b90fa00a89564df059fb18e796458864cc4e00cb55e364dbf921997266b7c55", + "sha256:1d8d177c40567de78108a7835170f570ab04f09084bfd32df9919c0eaec47aa1", + "sha256:236286f81664658b32c141c8e79d20afc3d54f6e2e49dfc8b702026be7265855", + "sha256:2e4f74677542737fb5af4ea9a2e415ec5ab31aa67e7b8c3c969fdb15c069f679", + "sha256:48a7750f04e69e1f304f4332b755728067e7c4b1abe2760bba1cacd9ff7a847a", + "sha256:7d86e62b700b21401ffe7fd1bbfe91e08489416fecae99c6570ab023c6896022", + "sha256:7e2d7effd08d2e5a3cb95d98a7286ebab71ab2fbce84fa93cc2dd56caf7240dd", + "sha256:81edb016d9e43dde7473bc3999c29cdfee3a6b67308fed1ea21049f458e83ae0", + "sha256:96c90e11b4a4c7c0b8ff5aaaae969c5035493136586043ff301979aae0623941", + "sha256:9a0a1845f8cb2e62332bca0aaa9ad5494603ac43fb60d510a61d5b5b170d7216", + "sha256:a05bbfdfd41f8410a905a818f329afe7510cbd9ee65c60f8860a72b6c64ce5dc", + "sha256:a5089fd660f0b0d228b14cdaa110d0d311edfa5a63f800618dbf1321dcaef66b", + "sha256:c457a709e6f2befea7e2996c991eda6d79705dd075f6521593ba6ebc1485b811", + "sha256:c5cb72644b04e5e5abfb1e10a0e7eb75da6684ea0e60871652f348e412cf3b11", + "sha256:cce46dd4717debfd2aab79d6d7f0cbdf6b1e982dc4d9bebad81658d59ede07c2", + "sha256:cfdd1f90bcf373b00f4b2c55ea47868616fe2f779f792fc913fa82a3d64ffe43", + "sha256:d88a279cbc5af613f73e86e19b3f63850f7a2e2736e249c51995dedcc830b1bb", + "sha256:eba9a9227438da5e78fc8eee32f32eb35d9a50cf0a0bd937eb6275c7cc3015fe", + "sha256:eee7b6a5f5b5af050cb7d66ab28179287b416f06d15a8974ac831437fec51336", + "sha256:f41ac1c858687e53242828c9f59c2e7b0b95dbcd5bdd09c7e5d3c48b0f89a25a", + "sha256:f8deaefefc3a589058df1b177275f79233e8b0eeee6734cf4336d80164ecd022", + "sha256:fa78e919f3bd7d6d075db262aa41079b4c02da315c6043c6f43881e2ebcdd623", + "sha256:fadb97d2e02dabdc15a0091591a972a938850d79ddde23d385d813c1731983f0" + ], + "version": "==3.1.1" }, "pycparser": { "hashes": [ + "sha256:9c5019374bb4239e468774725c00be02377cff63cd3f5226af69461ecd5bcdd1", "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3" ], "version": "==2.19" @@ -248,10 +279,10 @@ }, "six": { "hashes": [ - "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", - "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.13.0" + "version": "==1.14.0" }, "soupsieve": { "hashes": [ @@ -288,25 +319,25 @@ }, "yarl": { "hashes": [ - "sha256:031e8f56cf085d3b3df6b6bce756369ea7052b82d35ea07b6045f209c819e0e5", - "sha256:074958fe4578ef3a3d0bdaf96bbc25e4c4db82b7ff523594776fcf3d3f16c531", - "sha256:2db667ee21f620b446a54a793e467714fc5a446fcc82d93a47e8bde01d69afab", - "sha256:326f2dbaaa17b858ae86f261ae73a266fd820a561fc5142cee9d0fc58448fbd7", - "sha256:32a3885f542f74d0f4f87057050c6b45529ebd79d0639f56582e741521575bfe", - "sha256:56126ef061b913c3eefecace3404ca88917265d0550b8e32bbbeab29e5c830bf", - "sha256:589ac1e82add13fbdedc04eb0a83400db728e5f1af2bd273392088ca90de7062", - "sha256:6076bce2ecc6ebf6c92919d77762f80f4c9c6ecc9c1fbaa16567ec59ad7d6f1d", - "sha256:63be649c535d18ab6230efbc06a07f7779cd4336a687672defe70c025349a47b", - "sha256:6642cbc92eaffa586180f669adc772f5c34977e9e849e93f33dc142351e98c9c", - "sha256:6fa05a25f2280e78a514041d4609d39962e7d51525f2439db9ad7a2ae7aac163", - "sha256:7ed006a220422c33ff0889288be24db56ff0a3008ffe9eaead58a690715ad09b", - "sha256:80c9c213803b50899460cc355f47e66778c3c868f448b7b7de5b1f1858c82c2a", - "sha256:8bae18e2129850e76969b57869dacc72a66cccdbeebce1a28d7f3d439c21a7a3", - "sha256:ab112fba996a8f48f427e26969f2066d50080df0c24007a8cc6d7ae865e19013", - "sha256:b1c178ef813940c9a5cbad42ab7b8b76ac08b594b0a6bad91063c968e0466efc", - "sha256:d6eff151c3b23a56a5e4f496805619bc3bdf4f749f63a7a95ad50e8267c17475" - ], - "version": "==1.4.1" + "sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce", + "sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6", + "sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce", + "sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae", + "sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d", + "sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f", + "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b", + "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b", + "sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb", + "sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462", + "sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea", + "sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70", + "sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1", + "sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a", + "sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b", + "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080", + "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2" + ], + "version": "==1.4.2" } }, "develop": { @@ -348,11 +379,11 @@ }, "flake8-annotations": { "hashes": [ - "sha256:6ac7ca1e706307686b60af8043ff1db31dc2cfc1233c8210d67a3d9b8f364736", - "sha256:b51131007000d67217608fa028a35ff80aa400b474e5972f1f99c2cf9d26bd2e" + "sha256:05b85538014c850a86dce7374bb6621c64481c24e35e8e90af1315f4d7a3dbaa", + "sha256:43e5233a76fda002b91a54a7cc4510f099c4bfd6279502ec70164016250eebd1" ], "index": "pypi", - "version": "==1.1.0" + "version": "==1.1.3" }, "flake8-bugbear": { "hashes": [ @@ -403,18 +434,18 @@ }, "identify": { "hashes": [ - "sha256:4f1fe9a59df4e80fcb0213086fcf502bc1765a01ea4fe8be48da3b65afd2a017", - "sha256:d8919589bd2a5f99c66302fec0ef9027b12ae150b0b0213999ad3f695fc7296e" + "sha256:418f3b2313ac0b531139311a6b426854e9cbdfcfb6175447a5039aa6291d8b30", + "sha256:8ad99ed1f3a965612dcb881435bf58abcfbeb05e230bb8c352b51e8eac103360" ], - "version": "==1.4.7" + "version": "==1.4.10" }, "importlib-metadata": { "hashes": [ - "sha256:b044f07694ef14a6683b097ba56bd081dbc7cdc7c7fe46011e499dfecc082f21", - "sha256:e6ac600a142cf2db707b1998382cc7fc3b02befb7273876e01b8ad10b9652742" + "sha256:bdd9b7c397c273bcc9a11d6629a38487cd07154fa255a467bf704cd2c258e359", + "sha256:f17c015735e1a88296994c0697ecea7e11db24290941983b08c9feb30921e6d8" ], "markers": "python_version < '3.8'", - "version": "==1.1.0" + "version": "==1.4.0" }, "mccabe": { "hashes": [ @@ -425,24 +456,24 @@ }, "more-itertools": { "hashes": [ - "sha256:53ff73f186307d9c8ef17a9600309154a6ae27f25579e80af4db8f047ba14bc2", - "sha256:a0ea684c39bc4315ba7aae406596ef191fd84f873d2d2751f84d64e81a7a2d45" + "sha256:1a2a32c72400d365000412fe08eb4a24ebee89997c18d3d147544f70f5403b39", + "sha256:c468adec578380b6281a114cb8a5db34eb1116277da92d7c46f904f0b52d3288" ], - "version": "==8.0.0" + "version": "==8.1.0" }, "nodeenv": { "hashes": [ - "sha256:ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a" + "sha256:561057acd4ae3809e665a9aaaf214afff110bbb6a6d5c8a96121aea6878408b3" ], - "version": "==1.3.3" + "version": "==1.3.4" }, "pre-commit": { "hashes": [ - "sha256:9f152687127ec90642a2cc3e4d9e1e6240c4eb153615cb02aa1ad41d331cbb6e", - "sha256:c2e4810d2d3102d354947907514a78c5d30424d299dc0fe48f5aa049826e9b50" + "sha256:8f48d8637bdae6fa70cc97db9c1dd5aa7c5c8bf71968932a380628c25978b850", + "sha256:f92a359477f3252452ae2e8d3029de77aec59415c16ae4189bcfba40b757e029" ], "index": "pypi", - "version": "==1.20.0" + "version": "==1.21.0" }, "pycodestyle": { "hashes": [ @@ -453,10 +484,10 @@ }, "pydocstyle": { "hashes": [ - "sha256:04c84e034ebb56eb6396c820442b8c4499ac5eb94a3bda88951ac3dc519b6058", - "sha256:66aff87ffe34b1e49bff2dd03a88ce6843be2f3346b0c9814410d34987fbab59" + "sha256:da7831660b7355307b32778c4a0dbfb137d89254ef31a2b2978f50fc0b4d7586", + "sha256:f4f5d210610c2d153fae39093d44224c17429e2ad7da12a8b419aba5c2f614b5" ], - "version": "==4.0.1" + "version": "==5.0.2" }, "pyflakes": { "hashes": [ @@ -467,26 +498,26 @@ }, "pyyaml": { "hashes": [ - "sha256:0e7f69397d53155e55d10ff68fdfb2cf630a35e6daf65cf0bdeaf04f127c09dc", - "sha256:2e9f0b7c5914367b0916c3c104a024bb68f269a486b9d04a2e8ac6f6597b7803", - "sha256:35ace9b4147848cafac3db142795ee42deebe9d0dad885ce643928e88daebdcc", - "sha256:38a4f0d114101c58c0f3a88aeaa44d63efd588845c5a2df5290b73db8f246d15", - "sha256:483eb6a33b671408c8529106df3707270bfacb2447bf8ad856a4b4f57f6e3075", - "sha256:4b6be5edb9f6bb73680f5bf4ee08ff25416d1400fbd4535fe0069b2994da07cd", - "sha256:7f38e35c00e160db592091751d385cd7b3046d6d51f578b29943225178257b31", - "sha256:8100c896ecb361794d8bfdb9c11fce618c7cf83d624d73d5ab38aef3bc82d43f", - "sha256:c0ee8eca2c582d29c3c2ec6e2c4f703d1b7f1fb10bc72317355a746057e7346c", - "sha256:e4c015484ff0ff197564917b4b4246ca03f411b9bd7f16e02a2f586eb48b6d04", - "sha256:ebc4ed52dcc93eeebeae5cf5deb2ae4347b3a81c3fa12b0b8c976544829396a4" + "sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6", + "sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf", + "sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5", + "sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e", + "sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811", + "sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e", + "sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d", + "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20", + "sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689", + "sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994", + "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615" ], - "version": "==5.2" + "version": "==5.3" }, "six": { "hashes": [ - "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", - "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.13.0" + "version": "==1.14.0" }, "snowballstemmer": { "hashes": [ @@ -504,42 +535,44 @@ }, "typed-ast": { "hashes": [ - "sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161", - "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", - "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", - "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", - "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", - "sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47", - "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", - "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", - "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", - "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", - "sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2", - "sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e", - "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", - "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", - "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", - "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", - "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", - "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", - "sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66", - "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" + "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", + "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", + "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", + "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", + "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", + "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", + "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", + "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", + "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", + "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", + "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", + "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", + "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", + "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", + "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", + "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", + "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", + "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", + "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", + "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", + "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" ], - "version": "==1.4.0" + "markers": "python_version < '3.8'", + "version": "==1.4.1" }, "virtualenv": { "hashes": [ - "sha256:116655188441670978117d0ebb6451eb6a7526f9ae0796cc0dee6bd7356909b0", - "sha256:b57776b44f91511866594e477dd10e76a6eb44439cdd7f06dcd30ba4c5bd854f" + "sha256:0d62c70883c0342d59c11d0ddac0d954d0431321a41ab20851facf2b222598f3", + "sha256:55059a7a676e4e19498f1aad09b8313a38fcc0cdbe4fdddc0e9b06946d21b4bb" ], - "version": "==16.7.8" + "version": "==16.7.9" }, "zipp": { "hashes": [ - "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", - "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + "sha256:57147f6b0403b59f33fd357f169f860e031303415aeb7d04ede4839d23905ab8", + "sha256:7ae5ccaca427bafa9760ac3cd8f8c244bfc259794b5b6bb9db4dda2241575d09" ], - "version": "==0.6.0" + "version": "==2.0.0" } } } diff --git a/bot/seasons/evergreen/reddit.py b/bot/seasons/evergreen/reddit.py new file mode 100644 index 00000000..79b40900 --- /dev/null +++ b/bot/seasons/evergreen/reddit.py @@ -0,0 +1,130 @@ +import asyncio +import logging +import random +import discord + +from collections import deque + +from discord.ext import commands +from discord.ext import buttons +from discord.ext.commands.cooldowns import BucketType + +log = logging.getLogger(__name__) + + +class Paginator(buttons.Paginator): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + +class Reddit(commands.Cog): + """Fetches reddit posts.""" + def __init__(self, bot): + self.bot = bot + self.img_cache = deque(maxlen=10) + # self.cache_clear_task = bot.loop.create_task(self.clear_cache()) + + # async def clear_cache(self): + # self.img_cache.clear() + # await asyncio.sleep(43200) # clear cache every 12 hours + + async def fetch(self, session, url): + params = { + 'limit': 50 + } + headers = { + 'User-Agent': 'Iceman' + } + + async with session.get(url=url, params=params, headers=headers) as response: + return await response.json() + + @commands.command(name='reddit') + @commands.cooldown(1, 10, BucketType.user) + async def get_reddit(self, ctx, subreddit='python', sort="hot"): + """ + Fetch reddit posts by using this command. + Gets a post from r/dndmemes by default. + """ + pages=[] + sort_list = ["hot", "new", "top", "rising"] + if sort.lower() not in sort_list: + await ctx.send(f"Invalid sorting: {sort}\nUsing default sorting: `Hot`") + sort = "hot" + + session = self.bot.http_session + data = await self.fetch(session, f'https://www.reddit.com/r/{subreddit}/{sort}/.json') + + try: + posts = data["data"]["children"] + except KeyError: + return await ctx.send('Subreddit not found!') + if not posts: + return await ctx.send('No posts available!') + + if posts[1]["data"]["over_18"] == True: + return await ctx.send("You cannot access this Subreddit.") + + upvote_emoji = self.bot.get_emoji(565557799040319508) + comment_emoji = self.bot.get_emoji(565576076483624960) + user_emoji = "🎅" + + embed_titles = discord.Embed(colour=0xf9f586) + embed_titles.title = f"Posts from {posts[0]['data']['subreddit']} Subreddit\n" + embed_titles.description = "" + + random_posts = [] + while True: + if len(random_posts) == 5: + break + rand_post = random.choice(posts) + if rand_post not in random_posts: + random_posts.append(rand_post) + + + for i, post in enumerate(random_posts, start=1): + post_title = post["data"]["title"][0:50] + post_url = post['data']['url'] + if post_title == "": + post_title = "No Title." + elif post_title == post_url: + post_title = "Title is itself a link." + + embed_titles.description += f"**{i}.**[{post_title}]({post_url})\n" + post_stats = ( + f'{upvote_emoji}{post["data"]["ups"]} ' + f'{comment_emoji}{post["data"]["num_comments"]} ' + f'{user_emoji}{post["data"]["author"]}\n\n' + ) + + embed_titles.description += post_stats + new_embed = discord.Embed() + new_embed.title = post_title + "\n" + new_embed.description = post_stats + "\n\n" + new_embed.description = post['data']['selftext'][0:100] + + if post["data"]["media_embed"] != {}: + content = post["data"]["media_embed"]["content"] + i1 = content.index("src") + i2 = content.index("frameborder") + print(content) + print(i1, i2) + imageURL = content[i1+4:i2] + print(imageURL) + # new_embed.set_image(url=imageURL) + + new_embed.url = post_url + pages.append(new_embed) + + pages.append(embed_titles) + pages.reverse() + embed = Paginator(embed=True, timeout=200, use_defaults=True, + extra_pages=pages) + + await embed.start(ctx) + + +def setup(bot): + bot.add_cog(Reddit(bot)) + log.debug('Loaded') -- cgit v1.2.3 From a5f74d417c665c8ac5699d557aebf19c61d0f588 Mon Sep 17 00:00:00 2001 From: "S. Co1" Date: Mon, 27 Jan 2020 18:08:19 -0500 Subject: Shorten description & remove author override in permission error embed Update logging events so they follow the correct chain of execution --- bot/seasons/evergreen/bookmark.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index 3fe1d12c..7bdd362c 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -24,16 +24,15 @@ class Bookmark(commands.Cog): title: str = "Bookmark" ) -> None: """Send the author a link to `target_message` via DMs.""" - log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title '{title}'") + # Prevent users from bookmarking a message in a channel they don't have access to permissions = ctx.author.permissions_in(target_message.channel) if not permissions.read_messages: + log.info(f"{ctx.author} tried to bookmark a message in #{target_message.channel} but has no permissions") embed = discord.Embed( title=random.choice(ERROR_REPLIES), color=Colours.soft_red, - description="You don't have permission to see what's in the channel so you can't " - "bookmark a message from it." + description="You don't have permission to view this channel." ) - embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar_url) await ctx.send(embed=embed) return @@ -56,6 +55,7 @@ class Bookmark(commands.Cog): ) await ctx.send(embed=error_embed) else: + log.info(f"{ctx.author} bookmarked {target_message.jump_url} with title '{title}'") await ctx.message.add_reaction(Emojis.envelope) -- cgit v1.2.3 From 64d1e9e2d3bfb2a2f296c7231ffcec5e0dc51ddf Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 5 Feb 2020 20:24:33 +0530 Subject: finished implementing the reddit command --- bot/seasons/evergreen/reddit.py | 96 ++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 45 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/reddit.py b/bot/seasons/evergreen/reddit.py index 79b40900..90ca57af 100644 --- a/bot/seasons/evergreen/reddit.py +++ b/bot/seasons/evergreen/reddit.py @@ -1,35 +1,24 @@ -import asyncio import logging import random import discord -from collections import deque from discord.ext import commands -from discord.ext import buttons from discord.ext.commands.cooldowns import BucketType -log = logging.getLogger(__name__) - +from bot.pagination import ImagePaginator -class Paginator(buttons.Paginator): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) +log = logging.getLogger(__name__) class Reddit(commands.Cog): """Fetches reddit posts.""" def __init__(self, bot): self.bot = bot - self.img_cache = deque(maxlen=10) - # self.cache_clear_task = bot.loop.create_task(self.clear_cache()) - - # async def clear_cache(self): - # self.img_cache.clear() - # await asyncio.sleep(43200) # clear cache every 12 hours async def fetch(self, session, url): + """Send a get request to the reddit API and get json response""" params = { 'limit': 50 } @@ -45,7 +34,9 @@ class Reddit(commands.Cog): async def get_reddit(self, ctx, subreddit='python', sort="hot"): """ Fetch reddit posts by using this command. - Gets a post from r/dndmemes by default. + Gets a post from r/python by default. + Usage: + --> .reddit [subreddit_name] [hot/top/new] """ pages=[] sort_list = ["hot", "new", "top", "rising"] @@ -70,9 +61,8 @@ class Reddit(commands.Cog): comment_emoji = self.bot.get_emoji(565576076483624960) user_emoji = "🎅" - embed_titles = discord.Embed(colour=0xf9f586) - embed_titles.title = f"Posts from {posts[0]['data']['subreddit']} Subreddit\n" - embed_titles.description = "" + # embed_titles = discord.Embed(colour=0xf9f586) + embed_titles = "" random_posts = [] while True: @@ -82,6 +72,18 @@ class Reddit(commands.Cog): if rand_post not in random_posts: random_posts.append(rand_post) + # ----------------------------------------------------------- + # This code below is bound of change when the emojis are added. + + upvote_emoji = self.bot.get_emoji(674608910656733185) + comment_emoji = self.bot.get_emoji(674608751784755200) + user_emoji = self.bot.get_emoji(674608692418707467) + text_emoji = self.bot.get_emoji(674608836312825877) + video_emoji = self.bot.get_emoji(674608791450550272) + image_emoji = self.bot.get_emoji(674594916655169536) + reddit_emoji = self.bot.get_emoji(674087978628284417) + + # ------------------------------------------------------------ for i, post in enumerate(random_posts, start=1): post_title = post["data"]["title"][0:50] @@ -91,40 +93,44 @@ class Reddit(commands.Cog): elif post_title == post_url: post_title = "Title is itself a link." - embed_titles.description += f"**{i}.**[{post_title}]({post_url})\n" - post_stats = ( - f'{upvote_emoji}{post["data"]["ups"]} ' - f'{comment_emoji}{post["data"]["num_comments"]} ' - f'{user_emoji}{post["data"]["author"]}\n\n' - ) + # ------------------------------------------------------------------ + # Embed building. + + embed_titles += f"**{i}.[{post_title}]({post_url})**\n" + image_url = " " + post_stats = f"{text_emoji}" # Set default content type to text. + + if post["data"]["is_video"] is True or "youtube" in post_url.split("."): + # This means the content type in the post is a video. + post_stats = f"{video_emoji} " - embed_titles.description += post_stats - new_embed = discord.Embed() - new_embed.title = post_title + "\n" - new_embed.description = post_stats + "\n\n" - new_embed.description = post['data']['selftext'][0:100] + elif post_url.endswith("jpg") or post_url.endswith("png") or post_url.endswith("gif"): + # This means the content type in the post is an image. + post_stats = f"{image_emoji} " + image_url = post_url - if post["data"]["media_embed"] != {}: - content = post["data"]["media_embed"]["content"] - i1 = content.index("src") - i2 = content.index("frameborder") - print(content) - print(i1, i2) - imageURL = content[i1+4:i2] - print(imageURL) - # new_embed.set_image(url=imageURL) + votes = f'{upvote_emoji}{post["data"]["ups"]}' + comments = f'{comment_emoji}\u2002{ post["data"]["num_comments"]}' + post_stats += ( + f"\u2002{votes}\u2003" + f"{comments}" + f'\u2003{user_emoji}\u2002{post["data"]["author"]}\n' + ) + embed_titles += f"{post_stats}\n" + page_text = f"**[{post_title}]({post_url})**\n{post_stats}\n{post['data']['selftext'][0:200]}" - new_embed.url = post_url - pages.append(new_embed) + embed = discord.Embed() + page_tuple = (page_text, image_url) + pages.append(page_tuple) - pages.append(embed_titles) - pages.reverse() - embed = Paginator(embed=True, timeout=200, use_defaults=True, - extra_pages=pages) + # ------------------------------------------------------------------ - await embed.start(ctx) + pages.insert(0, (embed_titles, " ")) + embed.set_author(name=f"r/{posts[0]['data']['subreddit']} - {sort}", icon_url=reddit_emoji.url) + await ImagePaginator.paginate(pages, ctx, embed) def setup(bot): + """Load the Cog""" bot.add_cog(Reddit(bot)) log.debug('Loaded') -- cgit v1.2.3 From ec93125eab8a4ec8577f13f81d697a50824a5bd0 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 5 Feb 2020 20:44:45 +0530 Subject: uninstalled the buttons lib and corrected lint errors --- Pipfile | 1 - Pipfile.lock | 165 ++++++++------------------- bot/seasons/evergreen/reddit.py | 247 ++++++++++++++++++++-------------------- 3 files changed, 170 insertions(+), 243 deletions(-) (limited to 'bot') diff --git a/Pipfile b/Pipfile index 82f1103d..c066958e 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,6 @@ discord-py = "~=1.2" fuzzywuzzy = "~=0.17" pillow = "~=6.2" pytz = "~=2019.2" -buttons = "*" [dev-packages] flake8 = "~=3.7" diff --git a/Pipfile.lock b/Pipfile.lock index af8b646e..ee1398e9 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "769234aeffdf5a6e781dc783a903771f6100f80450244d5211f0f1a11ec79814" + "sha256": "40f23ea08504def8d3d5f56379820221088d93e9bf81d739850dc97ea8a4b7dc" }, "pipfile-spec": 6, "requires": { @@ -26,30 +26,20 @@ }, "aiohttp": { "hashes": [ - "sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55", - "sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed", - "sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10", - "sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5", - "sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1", - "sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939", - "sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390", - "sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa", - "sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc", - "sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5", - "sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d", - "sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf", - "sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6", - "sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72", - "sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12", - "sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366", - "sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4", - "sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300", - "sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d", - "sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303", - "sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6", - "sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889" - ], - "version": "==3.5.4" + "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e", + "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326", + "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a", + "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654", + "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a", + "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4", + "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17", + "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec", + "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd", + "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48", + "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59", + "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965" + ], + "version": "==3.6.2" }, "arrow": { "hashes": [ @@ -82,14 +72,6 @@ "index": "pypi", "version": "==4.8.2" }, - "buttons": { - "hashes": [ - "sha256:b58fe39c4995db9209443efb6799e22ae43a026d01989d84be033ce4d933cb96", - "sha256:ebf7349ff0e6173ac26f3cfdb92b9fe0c01e73c5dbe5e2874950ed4e6e45bb98" - ], - "index": "pypi", - "version": "==0.1.8" - }, "cffi": { "hashes": [ "sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42", @@ -137,16 +119,10 @@ }, "discord-py": { "hashes": [ - "sha256:7c843b523bb011062b453864e75c7b675a03faf573c58d14c9f096e85984329d" + "sha256:8bfe5628d31771744000f19135c386c74ac337479d7282c26cc1627b9d31f360" ], "index": "pypi", - "version": "==1.2.5" - }, - "discord.py": { - "hashes": [ - "sha256:7c843b523bb011062b453864e75c7b675a03faf573c58d14c9f096e85984329d" - ], - "version": "==1.2.5" + "version": "==1.3.1" }, "fuzzywuzzy": { "hashes": [ @@ -257,7 +233,6 @@ }, "pycparser": { "hashes": [ - "sha256:9c5019374bb4239e468774725c00be02377cff63cd3f5226af69461ecd5bcdd1", "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3" ], "version": "==2.19" @@ -293,29 +268,30 @@ }, "websockets": { "hashes": [ - "sha256:0e2f7d6567838369af074f0ef4d0b802d19fa1fee135d864acc656ceefa33136", - "sha256:2a16dac282b2fdae75178d0ed3d5b9bc3258dabfae50196cbb30578d84b6f6a6", - "sha256:5a1fa6072405648cb5b3688e9ed3b94be683ce4a4e5723e6f5d34859dee495c1", - "sha256:5c1f55a1274df9d6a37553fef8cff2958515438c58920897675c9bc70f5a0538", - "sha256:669d1e46f165e0ad152ed8197f7edead22854a6c90419f544e0f234cc9dac6c4", - "sha256:695e34c4dbea18d09ab2c258994a8bf6a09564e762655408241f6a14592d2908", - "sha256:6b2e03d69afa8d20253455e67b64de1a82ff8612db105113cccec35d3f8429f0", - "sha256:79ca7cdda7ad4e3663ea3c43bfa8637fc5d5604c7737f19a8964781abbd1148d", - "sha256:7fd2dd9a856f72e6ed06f82facfce01d119b88457cd4b47b7ae501e8e11eba9c", - "sha256:82c0354ac39379d836719a77ee360ef865377aa6fdead87909d50248d0f05f4d", - "sha256:8f3b956d11c5b301206382726210dc1d3bee1a9ccf7aadf895aaf31f71c3716c", - "sha256:91ec98640220ae05b34b79ee88abf27f97ef7c61cf525eec57ea8fcea9f7dddb", - "sha256:952be9540d83dba815569d5cb5f31708801e0bbfc3a8c5aef1890b57ed7e58bf", - "sha256:99ac266af38ba1b1fe13975aea01ac0e14bb5f3a3200d2c69f05385768b8568e", - "sha256:9fa122e7adb24232247f8a89f2d9070bf64b7869daf93ac5e19546b409e47e96", - "sha256:a0873eadc4b8ca93e2e848d490809e0123eea154aa44ecd0109c4d0171869584", - "sha256:cb998bd4d93af46b8b49ecf5a72c0a98e5cc6d57fdca6527ba78ad89d6606484", - "sha256:e02e57346f6a68523e3c43bbdf35dde5c440318d1f827208ae455f6a2ace446d", - "sha256:e79a5a896bcee7fff24a788d72e5c69f13e61369d055f28113e71945a7eb1559", - "sha256:ee55eb6bcf23ecc975e6b47c127c201b913598f38b6a300075f84eeef2d3baff", - "sha256:f1414e6cbcea8d22843e7eafdfdfae3dd1aba41d1945f6ca66e4806c07c4f454" - ], - "version": "==6.0" + "sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5", + "sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5", + "sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308", + "sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb", + "sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a", + "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c", + "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170", + "sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422", + "sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8", + "sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485", + "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f", + "sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8", + "sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc", + "sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779", + "sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989", + "sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1", + "sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092", + "sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824", + "sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d", + "sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55", + "sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36", + "sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b" + ], + "version": "==8.1" }, "yarl": { "hashes": [ @@ -434,18 +410,10 @@ }, "identify": { "hashes": [ - "sha256:418f3b2313ac0b531139311a6b426854e9cbdfcfb6175447a5039aa6291d8b30", - "sha256:8ad99ed1f3a965612dcb881435bf58abcfbeb05e230bb8c352b51e8eac103360" - ], - "version": "==1.4.10" - }, - "importlib-metadata": { - "hashes": [ - "sha256:bdd9b7c397c273bcc9a11d6629a38487cd07154fa255a467bf704cd2c258e359", - "sha256:f17c015735e1a88296994c0697ecea7e11db24290941983b08c9feb30921e6d8" + "sha256:1222b648251bdcb8deb240b294f450fbf704c7984e08baa92507e4ea10b436d5", + "sha256:d824ebe21f38325c771c41b08a95a761db1982f1fc0eee37c6c97df3f1636b96" ], - "markers": "python_version < '3.8'", - "version": "==1.4.0" + "version": "==1.4.11" }, "mccabe": { "hashes": [ @@ -454,18 +422,11 @@ ], "version": "==0.6.1" }, - "more-itertools": { - "hashes": [ - "sha256:1a2a32c72400d365000412fe08eb4a24ebee89997c18d3d147544f70f5403b39", - "sha256:c468adec578380b6281a114cb8a5db34eb1116277da92d7c46f904f0b52d3288" - ], - "version": "==8.1.0" - }, "nodeenv": { "hashes": [ - "sha256:561057acd4ae3809e665a9aaaf214afff110bbb6a6d5c8a96121aea6878408b3" + "sha256:5b2438f2e42af54ca968dd1b374d14a1194848955187b0e5e4be1f73813a5212" ], - "version": "==1.3.4" + "version": "==1.3.5" }, "pre-commit": { "hashes": [ @@ -533,46 +494,12 @@ ], "version": "==0.10.0" }, - "typed-ast": { - "hashes": [ - "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", - "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", - "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", - "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", - "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", - "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", - "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", - "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", - "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", - "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", - "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", - "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", - "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", - "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", - "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", - "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", - "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", - "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", - "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", - "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", - "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" - ], - "markers": "python_version < '3.8'", - "version": "==1.4.1" - }, "virtualenv": { "hashes": [ "sha256:0d62c70883c0342d59c11d0ddac0d954d0431321a41ab20851facf2b222598f3", "sha256:55059a7a676e4e19498f1aad09b8313a38fcc0cdbe4fdddc0e9b06946d21b4bb" ], "version": "==16.7.9" - }, - "zipp": { - "hashes": [ - "sha256:57147f6b0403b59f33fd357f169f860e031303415aeb7d04ede4839d23905ab8", - "sha256:7ae5ccaca427bafa9760ac3cd8f8c244bfc259794b5b6bb9db4dda2241575d09" - ], - "version": "==2.0.0" } } } diff --git a/bot/seasons/evergreen/reddit.py b/bot/seasons/evergreen/reddit.py index 90ca57af..8a7ebf26 100644 --- a/bot/seasons/evergreen/reddit.py +++ b/bot/seasons/evergreen/reddit.py @@ -1,8 +1,7 @@ import logging import random -import discord - +import discord from discord.ext import commands from discord.ext.commands.cooldowns import BucketType @@ -13,124 +12,126 @@ log = logging.getLogger(__name__) class Reddit(commands.Cog): - """Fetches reddit posts.""" - def __init__(self, bot): - self.bot = bot - - async def fetch(self, session, url): - """Send a get request to the reddit API and get json response""" - params = { - 'limit': 50 - } - headers = { - 'User-Agent': 'Iceman' - } - - async with session.get(url=url, params=params, headers=headers) as response: - return await response.json() - - @commands.command(name='reddit') - @commands.cooldown(1, 10, BucketType.user) - async def get_reddit(self, ctx, subreddit='python', sort="hot"): - """ - Fetch reddit posts by using this command. - Gets a post from r/python by default. - Usage: - --> .reddit [subreddit_name] [hot/top/new] - """ - pages=[] - sort_list = ["hot", "new", "top", "rising"] - if sort.lower() not in sort_list: - await ctx.send(f"Invalid sorting: {sort}\nUsing default sorting: `Hot`") - sort = "hot" - - session = self.bot.http_session - data = await self.fetch(session, f'https://www.reddit.com/r/{subreddit}/{sort}/.json') - - try: - posts = data["data"]["children"] - except KeyError: - return await ctx.send('Subreddit not found!') - if not posts: - return await ctx.send('No posts available!') - - if posts[1]["data"]["over_18"] == True: - return await ctx.send("You cannot access this Subreddit.") - - upvote_emoji = self.bot.get_emoji(565557799040319508) - comment_emoji = self.bot.get_emoji(565576076483624960) - user_emoji = "🎅" - - # embed_titles = discord.Embed(colour=0xf9f586) - embed_titles = "" - - random_posts = [] - while True: - if len(random_posts) == 5: - break - rand_post = random.choice(posts) - if rand_post not in random_posts: - random_posts.append(rand_post) - - # ----------------------------------------------------------- - # This code below is bound of change when the emojis are added. - - upvote_emoji = self.bot.get_emoji(674608910656733185) - comment_emoji = self.bot.get_emoji(674608751784755200) - user_emoji = self.bot.get_emoji(674608692418707467) - text_emoji = self.bot.get_emoji(674608836312825877) - video_emoji = self.bot.get_emoji(674608791450550272) - image_emoji = self.bot.get_emoji(674594916655169536) - reddit_emoji = self.bot.get_emoji(674087978628284417) - - # ------------------------------------------------------------ - - for i, post in enumerate(random_posts, start=1): - post_title = post["data"]["title"][0:50] - post_url = post['data']['url'] - if post_title == "": - post_title = "No Title." - elif post_title == post_url: - post_title = "Title is itself a link." - - # ------------------------------------------------------------------ - # Embed building. - - embed_titles += f"**{i}.[{post_title}]({post_url})**\n" - image_url = " " - post_stats = f"{text_emoji}" # Set default content type to text. - - if post["data"]["is_video"] is True or "youtube" in post_url.split("."): - # This means the content type in the post is a video. - post_stats = f"{video_emoji} " - - elif post_url.endswith("jpg") or post_url.endswith("png") or post_url.endswith("gif"): - # This means the content type in the post is an image. - post_stats = f"{image_emoji} " - image_url = post_url - - votes = f'{upvote_emoji}{post["data"]["ups"]}' - comments = f'{comment_emoji}\u2002{ post["data"]["num_comments"]}' - post_stats += ( - f"\u2002{votes}\u2003" - f"{comments}" - f'\u2003{user_emoji}\u2002{post["data"]["author"]}\n' - ) - embed_titles += f"{post_stats}\n" - page_text = f"**[{post_title}]({post_url})**\n{post_stats}\n{post['data']['selftext'][0:200]}" - - embed = discord.Embed() - page_tuple = (page_text, image_url) - pages.append(page_tuple) - - # ------------------------------------------------------------------ - - pages.insert(0, (embed_titles, " ")) - embed.set_author(name=f"r/{posts[0]['data']['subreddit']} - {sort}", icon_url=reddit_emoji.url) - await ImagePaginator.paginate(pages, ctx, embed) - - -def setup(bot): - """Load the Cog""" - bot.add_cog(Reddit(bot)) - log.debug('Loaded') + """Fetches reddit posts.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + + async def fetch(self, url: str) -> dict: + """Send a get request to the reddit API and get json response.""" + session = self.bot.http_session + params = { + 'limit': 50 + } + headers = { + 'User-Agent': 'Iceman' + } + + async with session.get(url=url, params=params, headers=headers) as response: + return await response.json() + + @commands.command(name='reddit') + @commands.cooldown(1, 10, BucketType.user) + async def get_reddit(self, ctx: commands.Context, subreddit: str = 'python', sort: str = "hot") -> None: + """ + Fetch reddit posts by using this command. + + Gets a post from r/python by default. + Usage: + --> .reddit [subreddit_name] [hot/top/new] + """ + pages = [] + sort_list = ["hot", "new", "top", "rising"] + if sort.lower() not in sort_list: + await ctx.send(f"Invalid sorting: {sort}\nUsing default sorting: `Hot`") + sort = "hot" + + data = await self.fetch(f'https://www.reddit.com/r/{subreddit}/{sort}/.json') + + try: + posts = data["data"]["children"] + except KeyError: + return await ctx.send('Subreddit not found!') + if not posts: + return await ctx.send('No posts available!') + + if posts[1]["data"]["over_18"] is True: + return await ctx.send("You cannot access this Subreddit.") + + upvote_emoji = self.bot.get_emoji(565557799040319508) + comment_emoji = self.bot.get_emoji(565576076483624960) + user_emoji = "🎅" + + # embed_titles = discord.Embed(colour=0xf9f586) + embed_titles = "" + + random_posts = [] + while True: + if len(random_posts) == 5: + break + rand_post = random.choice(posts) + if rand_post not in random_posts: + random_posts.append(rand_post) + + # ----------------------------------------------------------- + # This code below is bound of change when the emojis are added. + + upvote_emoji = self.bot.get_emoji(674608910656733185) + comment_emoji = self.bot.get_emoji(674608751784755200) + user_emoji = self.bot.get_emoji(674608692418707467) + text_emoji = self.bot.get_emoji(674608836312825877) + video_emoji = self.bot.get_emoji(674608791450550272) + image_emoji = self.bot.get_emoji(674594916655169536) + reddit_emoji = self.bot.get_emoji(674087978628284417) + + # ------------------------------------------------------------ + + for i, post in enumerate(random_posts, start=1): + post_title = post["data"]["title"][0:50] + post_url = post['data']['url'] + if post_title == "": + post_title = "No Title." + elif post_title == post_url: + post_title = "Title is itself a link." + + # ------------------------------------------------------------------ + # Embed building. + + embed_titles += f"**{i}.[{post_title}]({post_url})**\n" + image_url = " " + post_stats = f"{text_emoji}" # Set default content type to text. + + if post["data"]["is_video"] is True or "youtube" in post_url.split("."): + # This means the content type in the post is a video. + post_stats = f"{video_emoji} " + + elif post_url.endswith("jpg") or post_url.endswith("png") or post_url.endswith("gif"): + # This means the content type in the post is an image. + post_stats = f"{image_emoji} " + image_url = post_url + + votes = f'{upvote_emoji}{post["data"]["ups"]}' + comments = f'{comment_emoji}\u2002{ post["data"]["num_comments"]}' + post_stats += ( + f"\u2002{votes}\u2003" + f"{comments}" + f'\u2003{user_emoji}\u2002{post["data"]["author"]}\n' + ) + embed_titles += f"{post_stats}\n" + page_text = f"**[{post_title}]({post_url})**\n{post_stats}\n{post['data']['selftext'][0:200]}" + + embed = discord.Embed() + page_tuple = (page_text, image_url) + pages.append(page_tuple) + + # ------------------------------------------------------------------ + + pages.insert(0, (embed_titles, " ")) + embed.set_author(name=f"r/{posts[0]['data']['subreddit']} - {sort}", icon_url=reddit_emoji.url) + await ImagePaginator.paginate(pages, ctx, embed) + + +def setup(bot: commands.Bot) -> None: + """Load the Cog.""" + bot.add_cog(Reddit(bot)) + log.debug('Loaded') -- cgit v1.2.3 From d823a3c582040e0d8b2f8f43ff8da752388bbd3d Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Sun, 9 Feb 2020 11:31:58 +0530 Subject: Removed un-wanted code and using random.simple() to select 5 random unique reddit posts insted of using a while loop --- bot/seasons/evergreen/reddit.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/reddit.py b/bot/seasons/evergreen/reddit.py index 8a7ebf26..811f5781 100644 --- a/bot/seasons/evergreen/reddit.py +++ b/bot/seasons/evergreen/reddit.py @@ -56,22 +56,15 @@ class Reddit(commands.Cog): return await ctx.send('No posts available!') if posts[1]["data"]["over_18"] is True: - return await ctx.send("You cannot access this Subreddit.") - - upvote_emoji = self.bot.get_emoji(565557799040319508) - comment_emoji = self.bot.get_emoji(565576076483624960) - user_emoji = "🎅" + return await ctx.send( + "You cannot access this Subreddit as it is ment for those who " + "are 18 years or older." + ) - # embed_titles = discord.Embed(colour=0xf9f586) embed_titles = "" - random_posts = [] - while True: - if len(random_posts) == 5: - break - rand_post = random.choice(posts) - if rand_post not in random_posts: - random_posts.append(rand_post) + # Chooses k unique random elements from a population sequence or set. + random_posts = random.sample(posts, k=5) # ----------------------------------------------------------- # This code below is bound of change when the emojis are added. -- cgit v1.2.3 From e21938e663b4a210c059d3875ca4d3c92b76eeb7 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Sun, 9 Feb 2020 13:26:37 +0100 Subject: Add correct emoji IDs to Evergreen reddit cog The emoji IDs in the Reddit cog were for emojis that are not available to Seasonal Bot. While I think a proper solution using constants is to be preferred, I've edited in IDs for emojis that can be used by the bot in the mean time. I've reused three of the emojis that we were already using for our Reddit webhook and added four new emojis to the `PyDis Emoji II` server. Reused emojis: :user: 638729835442602003 :upvotes: 638729835245731840 :comments: 638729835073765387 New emojis available on PyDis Emoji II: :reddit_logo: 676030265734332427 :reddit_post_photo: 676030265734201344 :reddit_post_text: 676030265910493204 :reddit_post_video: 676030265839190047 The latter four may need to be restyled to match the first three in the future. --- bot/seasons/evergreen/reddit.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/reddit.py b/bot/seasons/evergreen/reddit.py index 811f5781..32ca419a 100644 --- a/bot/seasons/evergreen/reddit.py +++ b/bot/seasons/evergreen/reddit.py @@ -69,13 +69,13 @@ class Reddit(commands.Cog): # ----------------------------------------------------------- # This code below is bound of change when the emojis are added. - upvote_emoji = self.bot.get_emoji(674608910656733185) - comment_emoji = self.bot.get_emoji(674608751784755200) - user_emoji = self.bot.get_emoji(674608692418707467) - text_emoji = self.bot.get_emoji(674608836312825877) - video_emoji = self.bot.get_emoji(674608791450550272) - image_emoji = self.bot.get_emoji(674594916655169536) - reddit_emoji = self.bot.get_emoji(674087978628284417) + upvote_emoji = self.bot.get_emoji(638729835245731840) + comment_emoji = self.bot.get_emoji(638729835073765387) + user_emoji = self.bot.get_emoji(638729835442602003) + text_emoji = self.bot.get_emoji(676030265910493204) + video_emoji = self.bot.get_emoji(676030265839190047) + image_emoji = self.bot.get_emoji(676030265734201344) + reddit_emoji = self.bot.get_emoji(676030265734332427) # ------------------------------------------------------------ -- cgit v1.2.3 From 90dc6da4c1460a4f6c5d3ef5ea8bb8a403e28785 Mon Sep 17 00:00:00 2001 From: ks123 Date: Wed, 12 Feb 2020 20:47:17 +0200 Subject: Added .movie command with what when specifing genre you get random movies, depending how much movies you define. This use TMDB API. --- bot/seasons/evergreen/movie.py | 481 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 481 insertions(+) create mode 100644 bot/seasons/evergreen/movie.py (limited to 'bot') diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py new file mode 100644 index 00000000..1256cb45 --- /dev/null +++ b/bot/seasons/evergreen/movie.py @@ -0,0 +1,481 @@ +import logging +import random +from os import environ +from typing import List, Tuple +from urllib.parse import urlencode + +from aiohttp import ClientSession +from discord import Embed +from discord.ext.commands import Bot, Cog, Context, group + +from bot.pagination import ImagePaginator + +# Get TMDB API key from .env +TMDB_API_KEY = environ.get('TMDB_API_KEY') + +# Define base URL of TMDB +BASE_URL = "https://api.themoviedb.org/3/" + +# Get logger +logger = logging.getLogger(__name__) + + +async def get_random_movies(client: ClientSession, + count: int, + genre_id: int, + genre_name: str,) \ + -> Tuple[List[Tuple[str, str]], Embed]: + """Get random movies by genre from TMDB.""" + pages = [] + + # Create embed + embed = Embed(title=f"Random {genre_name} Movies") + embed.set_footer(text='Powered by TMDB (themoviedb.org)') + + # Get random page between 1 and 600 + page = random.randint(1, 200) + + # Define TMDB request parameters + # (API key, exclusions, inclusions, sort) + params = { + "api_key": TMDB_API_KEY, + "language": "en-US", + "sort_by": "popularity.desc", + "include_adult": "false", + "include_video": "false", + "page": page, + "with_genres": str(genre_id) + } + + # Create request URL + url = BASE_URL + "discover/movie" + "?" + urlencode(params) + + # Do discover request to TMDB API and fetch information + async with client.get(url) as res: + try: + # Parse response data from JSON to dictionary + movie_list_data = await res.json() + + # Loop and fetch movies + for i in range(count): + # Get movie ID + movie_id = movie_list_data["results"][i]["id"] + + # Create movie params + movie_params = { + "api_key": TMDB_API_KEY, + "language": "en-US" + } + + # Generate URL + movie_url = BASE_URL + f"movie/{movie_id}?" + urlencode( + movie_params) + + # Fetch movie + async with client.get(movie_url) as m_res: + # Parse JSON to dict + movie_data = await m_res.json() + + # Create embed text + movie_text = "" + + # Add Title and tagline + movie_text += f"**{movie_data['title']}**\n" + if movie_data['tagline'] != "": + movie_text += movie_data['tagline'] + "\n\n" + else: + movie_text += "\n" + + # Add movie rating and release date + movie_text += f"**Rating:** {movie_data['vote_average']}/10 :star:\n" + movie_text += f"**Release Date:** {movie_data['release_date']}\n\n" + + # Add production title + movie_text += "__**Production Information**__\n" + + companies = movie_data['production_companies'] + countries = movie_data['production_countries'] + + # Add production information + movie_text += f"""**Made by:** {', '.join([comp['name'] + for comp in companies])}\n""" + movie_text += f"""**Made in:** {', '.join([country['name'] + for country in countries])}\n\n""" + + # Add Some Numbers title + movie_text += "__**Some Numbers**__\n" + + # Add Budget, Revenue and Duration + movie_text += f"**Budget:** ${movie_data['budget'] if movie_data['budget'] != 0 else '?'}\n" + movie_text += f"**Revenue:** ${movie_data['revenue'] if movie_data['revenue'] != 0 else '?'}\n" + movie_text += f"**Duration:** {movie_data['runtime']} minutes\n\n" + + # Add description + movie_text += movie_data['overview'] + + # Define Movie Image URL + movie_img_url = f"http://image.tmdb.org/t/p/w200{movie_data['poster_path']}" + + # Append this page to pages + pages.append((movie_text, movie_img_url)) + except KeyError as err: + # Create error message + msg = f"There was KeyError while executing HTTP request. API may " \ + f"down or API key may be incorrect, however, some movies " \ + f"have some missing fields, and this error will raise this " \ + f"too. Problematic Key: \n```{err}``` " + + # Create error embed + err_embed = Embed(title=":no_entry: Error :no_entry:") + + # Log error + logger.warning(msg) + + # Return error message + embed + return [(msg, "")], err_embed + + # Return all movies pages + return pages, embed + + +class Movie(Cog): + """Movie Cog contains movies command that grab random movies from TMDB.""" + + def __init__(self, bot: Bot): + self.bot = bot + self.http_session: ClientSession = bot.http_session + + @group(name='movies', invoke_without_command=True) + async def movies(self, ctx: Context) -> None: + """Get random movies by specifing genre.""" + await ctx.send_help('movies') + + @movies.command(name='action') + async def action(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Action genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 28, "Action") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='adventure') + async def adventure(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Adventure genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 12, "Adventure") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='animation') + async def animation(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Animation genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 16, "Animation") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='comedy') + async def comedy(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Comedy genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 35, "Comedy") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='crime') + async def crime(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Crime genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 80, "Crime") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='documentary') + async def documentary(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Documentary genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 99, "Documentary") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='drama') + async def drama(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Drama genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 18, "Drama") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='family') + async def family(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Drama genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 10751, "Family") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='fantasy') + async def fantasy(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Fantasy genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 14, "Fantasy") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='history') + async def history(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random History genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 36, "History") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='horror') + async def horror(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Horror genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 27, "Horror") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='music') + async def music(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Music genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 10402, "Music") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='mystery') + async def mystery(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Mystery genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 9648, "Mystery") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='romance') + async def romance(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Romance genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 10749, "Romance") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='science') + async def science(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Science Fiction genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 878, "Science Fiction") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='thriller') + async def thriller(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Thriller genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 53, + "Thriller") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + @movies.command(name='western') + async def western(self, ctx: Context, movies_amount: int = 5) -> None: + """Get random Western genre movies.""" + # Count can't be higher than 20, due one page return 20 items + # And also this can't be lower than 1, just logic + if movies_amount > 20: + await ctx.send("Max allowed amount of movies is 20.") + return + elif movies_amount < 1: + await ctx.send("You can't get less movies than 1.") + return + + # Get pages and embed + pages, embed = await get_random_movies(self.http_session, + movies_amount, 37, + "Western") + + # Paginate + await ImagePaginator.paginate(pages, ctx, embed) + + +def setup(bot: Bot) -> None: + """Load Movie Cog.""" + bot.add_cog(Movie(bot)) -- cgit v1.2.3 From bf80c41ee63b9f0dccc6fbb1b1e4aa9ee2b10eb1 Mon Sep 17 00:00:00 2001 From: ks123 Date: Fri, 14 Feb 2020 18:47:31 +0200 Subject: Moved .movies command genres from subcommands to if-elif-else statement, added alias .movie --- bot/seasons/evergreen/movie.py | 424 ++++++++++------------------------------- 1 file changed, 96 insertions(+), 328 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py index 1256cb45..96c43469 100644 --- a/bot/seasons/evergreen/movie.py +++ b/bot/seasons/evergreen/movie.py @@ -6,7 +6,7 @@ from urllib.parse import urlencode from aiohttp import ClientSession from discord import Embed -from discord.ext.commands import Bot, Cog, Context, group +from discord.ext.commands import Bot, Cog, Context, command from bot.pagination import ImagePaginator @@ -32,7 +32,7 @@ async def get_random_movies(client: ClientSession, embed = Embed(title=f"Random {genre_name} Movies") embed.set_footer(text='Powered by TMDB (themoviedb.org)') - # Get random page between 1 and 600 + # Get random page between 1 and 200 page = random.randint(1, 200) # Define TMDB request parameters @@ -145,334 +145,102 @@ class Movie(Cog): self.bot = bot self.http_session: ClientSession = bot.http_session - @group(name='movies', invoke_without_command=True) - async def movies(self, ctx: Context) -> None: - """Get random movies by specifing genre.""" - await ctx.send_help('movies') - - @movies.command(name='action') - async def action(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Action genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") + @command(name='movies', aliases=['movie']) + async def movies(self, ctx: Context, genre: str = "", amount: int = 5) -> None: + """ + Get random movies by specifing genre. + + Also support amount parameter, + that define how much movies will be shown. Default 5 + + Available genres: + - Action + - Adventure + - Animation + - Comedy + - Crime + - Documentary + - Drama + - Family + - Fantasy + - History + - Horror + - Music + - Mystery + - Romance + - Science + - Thriller + - Western + """ + # Check is there more than 20 movies specified, due TMDB return 20 movies + # per page, so this is max. Also you can't get less movies than 1, just logic + if amount > 20: + await ctx.send('You can\'t get more than 20 movies at once. (TMDB limits)') + return + elif amount < 1: + await ctx.send('You can\'t get less than 1 movies. Just logic.') + return + + # Make genre to lower characters due then users may use also like Genre + # or GENRE formats + genre = genre.lower() + + # Check genres, get pages and embed + if genre == 'action': + pages, embed = await get_random_movies(self.http_session, + amount, 28, "Action") + elif genre == 'adventure': + pages, embed = await get_random_movies(self.http_session, + amount, 12, "Adventure") + elif genre == 'animation': + pages, embed = await get_random_movies(self.http_session, + amount, 16, "Animation") + elif genre == 'comedy': + pages, embed = await get_random_movies(self.http_session, + amount, 35, "Comedy") + elif genre == 'crime': + pages, embed = await get_random_movies(self.http_session, + amount, 80, "Crime") + elif genre == 'documentary': + pages, embed = await get_random_movies(self.http_session, + amount, 99, "Documentary") + elif genre == 'drama': + pages, embed = await get_random_movies(self.http_session, + amount, 18, "Drama") + elif genre == 'family': + pages, embed = await get_random_movies(self.http_session, + amount, 10751, "Family") + elif genre == 'fantasy': + pages, embed = await get_random_movies(self.http_session, + amount, 14, "Fantasy") + elif genre == 'history': + pages, embed = await get_random_movies(self.http_session, + amount, 36, "History") + elif genre == 'horror': + pages, embed = await get_random_movies(self.http_session, + amount, 27, "Horror") + elif genre == 'music': + pages, embed = await get_random_movies(self.http_session, + amount, 10402, "Music") + elif genre == 'mystery': + pages, embed = await get_random_movies(self.http_session, + amount, 9648, "Mystery") + elif genre == 'romance': + pages, embed = await get_random_movies(self.http_session, + amount, 10749, "Romance") + elif genre == 'science': + pages, embed = await get_random_movies(self.http_session, + amount, 878, "Science Fiction") + elif genre == 'thriller': + pages, embed = await get_random_movies(self.http_session, + amount, 53, "Thriller") + elif genre == 'western': + pages, embed = await get_random_movies(self.http_session, + amount, 37, "Western") + else: + await ctx.send_help('movies') return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 28, "Action") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='adventure') - async def adventure(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Adventure genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 12, "Adventure") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='animation') - async def animation(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Animation genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 16, "Animation") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='comedy') - async def comedy(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Comedy genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 35, "Comedy") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='crime') - async def crime(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Crime genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 80, "Crime") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='documentary') - async def documentary(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Documentary genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 99, "Documentary") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='drama') - async def drama(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Drama genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 18, "Drama") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='family') - async def family(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Drama genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 10751, "Family") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='fantasy') - async def fantasy(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Fantasy genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 14, "Fantasy") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='history') - async def history(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random History genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 36, "History") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='horror') - async def horror(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Horror genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 27, "Horror") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='music') - async def music(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Music genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 10402, "Music") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='mystery') - async def mystery(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Mystery genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 9648, "Mystery") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='romance') - async def romance(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Romance genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 10749, "Romance") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='science') - async def science(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Science Fiction genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 878, "Science Fiction") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='thriller') - async def thriller(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Thriller genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 53, - "Thriller") - - # Paginate - await ImagePaginator.paginate(pages, ctx, embed) - - @movies.command(name='western') - async def western(self, ctx: Context, movies_amount: int = 5) -> None: - """Get random Western genre movies.""" - # Count can't be higher than 20, due one page return 20 items - # And also this can't be lower than 1, just logic - if movies_amount > 20: - await ctx.send("Max allowed amount of movies is 20.") - return - elif movies_amount < 1: - await ctx.send("You can't get less movies than 1.") - return - - # Get pages and embed - pages, embed = await get_random_movies(self.http_session, - movies_amount, 37, - "Western") - # Paginate await ImagePaginator.paginate(pages, ctx, embed) -- cgit v1.2.3 From 02aa5119a930c522fb56834c4b3727f0722d7b38 Mon Sep 17 00:00:00 2001 From: ks123 Date: Fri, 14 Feb 2020 19:21:29 +0200 Subject: Made .movies command genres getting ID and name check to Enum, also made things more dynamical. --- bot/seasons/evergreen/movie.py | 90 ++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 57 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py index 96c43469..8ae49cd2 100644 --- a/bot/seasons/evergreen/movie.py +++ b/bot/seasons/evergreen/movie.py @@ -1,5 +1,6 @@ import logging import random +from enum import Enum from os import environ from typing import List, Tuple from urllib.parse import urlencode @@ -20,6 +21,29 @@ BASE_URL = "https://api.themoviedb.org/3/" logger = logging.getLogger(__name__) +# Genres with TMDB API IDs +class MovieGenres(Enum): + """Genre names and IDs.""" + + Action = 28 + Adventure = 12 + Animation = 16 + Comedy = 35 + Crime = 80 + Documentary = 99 + Drama = 18 + Family = 10751 + Fantasy = 14 + History = 36 + Horror = 27 + Music = 10402 + Mystery = 9648 + Romance = 10749 + Science = 878 + Thriller = 53 + Western = 37 + + async def get_random_movies(client: ClientSession, count: int, genre_id: int, @@ -181,66 +205,18 @@ class Movie(Cog): await ctx.send('You can\'t get less than 1 movies. Just logic.') return - # Make genre to lower characters due then users may use also like Genre - # or GENRE formats - genre = genre.lower() - - # Check genres, get pages and embed - if genre == 'action': - pages, embed = await get_random_movies(self.http_session, - amount, 28, "Action") - elif genre == 'adventure': - pages, embed = await get_random_movies(self.http_session, - amount, 12, "Adventure") - elif genre == 'animation': - pages, embed = await get_random_movies(self.http_session, - amount, 16, "Animation") - elif genre == 'comedy': - pages, embed = await get_random_movies(self.http_session, - amount, 35, "Comedy") - elif genre == 'crime': - pages, embed = await get_random_movies(self.http_session, - amount, 80, "Crime") - elif genre == 'documentary': - pages, embed = await get_random_movies(self.http_session, - amount, 99, "Documentary") - elif genre == 'drama': - pages, embed = await get_random_movies(self.http_session, - amount, 18, "Drama") - elif genre == 'family': - pages, embed = await get_random_movies(self.http_session, - amount, 10751, "Family") - elif genre == 'fantasy': - pages, embed = await get_random_movies(self.http_session, - amount, 14, "Fantasy") - elif genre == 'history': - pages, embed = await get_random_movies(self.http_session, - amount, 36, "History") - elif genre == 'horror': - pages, embed = await get_random_movies(self.http_session, - amount, 27, "Horror") - elif genre == 'music': - pages, embed = await get_random_movies(self.http_session, - amount, 10402, "Music") - elif genre == 'mystery': - pages, embed = await get_random_movies(self.http_session, - amount, 9648, "Mystery") - elif genre == 'romance': - pages, embed = await get_random_movies(self.http_session, - amount, 10749, "Romance") - elif genre == 'science': - pages, embed = await get_random_movies(self.http_session, - amount, 878, "Science Fiction") - elif genre == 'thriller': - pages, embed = await get_random_movies(self.http_session, - amount, 53, "Thriller") - elif genre == 'western': - pages, embed = await get_random_movies(self.http_session, - amount, 37, "Western") - else: + # Capitalize genre for getting data from Enum + genre = genre.capitalize() + + # If invalid genre, send help message + if genre not in MovieGenres.__members__: await ctx.send_help('movies') return + # Get pages and embed of movies + pages, embed = await get_random_movies(self.http_session, amount, MovieGenres[genre].value, genre) + + # Send movies, paginate await ImagePaginator.paginate(pages, ctx, embed) -- cgit v1.2.3 From f0d1cf5a25bfb435a19eca5fb16da490596cc429 Mon Sep 17 00:00:00 2001 From: ks123 Date: Fri, 14 Feb 2020 19:52:12 +0200 Subject: Replaced check from Enum members to try-except block. --- bot/seasons/evergreen/movie.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py index 8ae49cd2..e7c4c73c 100644 --- a/bot/seasons/evergreen/movie.py +++ b/bot/seasons/evergreen/movie.py @@ -208,14 +208,13 @@ class Movie(Cog): # Capitalize genre for getting data from Enum genre = genre.capitalize() - # If invalid genre, send help message - if genre not in MovieGenres.__members__: + # Try to fetch pages and embed, when invalid genre, show help + try: + pages, embed = await get_random_movies(self.http_session, amount, MovieGenres[genre].value, genre) + except KeyError: await ctx.send_help('movies') return - # Get pages and embed of movies - pages, embed = await get_random_movies(self.http_session, amount, MovieGenres[genre].value, genre) - # Send movies, paginate await ImagePaginator.paginate(pages, ctx, embed) -- cgit v1.2.3 From cce99c584364ea749a542d5c8fcbe2af8ea3c075 Mon Sep 17 00:00:00 2001 From: ks123 Date: Sat, 15 Feb 2020 10:27:12 +0200 Subject: Moved get_random_movies to Movie cog and made this to smaller functions. --- bot/seasons/evergreen/movie.py | 269 ++++++++++++++++++++--------------------- 1 file changed, 128 insertions(+), 141 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py index e7c4c73c..fc0053fd 100644 --- a/bot/seasons/evergreen/movie.py +++ b/bot/seasons/evergreen/movie.py @@ -2,7 +2,7 @@ import logging import random from enum import Enum from os import environ -from typing import List, Tuple +from typing import Dict, List, Tuple from urllib.parse import urlencode from aiohttp import ClientSession @@ -25,141 +25,23 @@ logger = logging.getLogger(__name__) class MovieGenres(Enum): """Genre names and IDs.""" - Action = 28 - Adventure = 12 - Animation = 16 - Comedy = 35 - Crime = 80 - Documentary = 99 - Drama = 18 - Family = 10751 - Fantasy = 14 - History = 36 - Horror = 27 - Music = 10402 - Mystery = 9648 - Romance = 10749 - Science = 878 - Thriller = 53 - Western = 37 - - -async def get_random_movies(client: ClientSession, - count: int, - genre_id: int, - genre_name: str,) \ - -> Tuple[List[Tuple[str, str]], Embed]: - """Get random movies by genre from TMDB.""" - pages = [] - - # Create embed - embed = Embed(title=f"Random {genre_name} Movies") - embed.set_footer(text='Powered by TMDB (themoviedb.org)') - - # Get random page between 1 and 200 - page = random.randint(1, 200) - - # Define TMDB request parameters - # (API key, exclusions, inclusions, sort) - params = { - "api_key": TMDB_API_KEY, - "language": "en-US", - "sort_by": "popularity.desc", - "include_adult": "false", - "include_video": "false", - "page": page, - "with_genres": str(genre_id) - } - - # Create request URL - url = BASE_URL + "discover/movie" + "?" + urlencode(params) - - # Do discover request to TMDB API and fetch information - async with client.get(url) as res: - try: - # Parse response data from JSON to dictionary - movie_list_data = await res.json() - - # Loop and fetch movies - for i in range(count): - # Get movie ID - movie_id = movie_list_data["results"][i]["id"] - - # Create movie params - movie_params = { - "api_key": TMDB_API_KEY, - "language": "en-US" - } - - # Generate URL - movie_url = BASE_URL + f"movie/{movie_id}?" + urlencode( - movie_params) - - # Fetch movie - async with client.get(movie_url) as m_res: - # Parse JSON to dict - movie_data = await m_res.json() - - # Create embed text - movie_text = "" - - # Add Title and tagline - movie_text += f"**{movie_data['title']}**\n" - if movie_data['tagline'] != "": - movie_text += movie_data['tagline'] + "\n\n" - else: - movie_text += "\n" - - # Add movie rating and release date - movie_text += f"**Rating:** {movie_data['vote_average']}/10 :star:\n" - movie_text += f"**Release Date:** {movie_data['release_date']}\n\n" - - # Add production title - movie_text += "__**Production Information**__\n" - - companies = movie_data['production_companies'] - countries = movie_data['production_countries'] - - # Add production information - movie_text += f"""**Made by:** {', '.join([comp['name'] - for comp in companies])}\n""" - movie_text += f"""**Made in:** {', '.join([country['name'] - for country in countries])}\n\n""" - - # Add Some Numbers title - movie_text += "__**Some Numbers**__\n" - - # Add Budget, Revenue and Duration - movie_text += f"**Budget:** ${movie_data['budget'] if movie_data['budget'] != 0 else '?'}\n" - movie_text += f"**Revenue:** ${movie_data['revenue'] if movie_data['revenue'] != 0 else '?'}\n" - movie_text += f"**Duration:** {movie_data['runtime']} minutes\n\n" - - # Add description - movie_text += movie_data['overview'] - - # Define Movie Image URL - movie_img_url = f"http://image.tmdb.org/t/p/w200{movie_data['poster_path']}" - - # Append this page to pages - pages.append((movie_text, movie_img_url)) - except KeyError as err: - # Create error message - msg = f"There was KeyError while executing HTTP request. API may " \ - f"down or API key may be incorrect, however, some movies " \ - f"have some missing fields, and this error will raise this " \ - f"too. Problematic Key: \n```{err}``` " - - # Create error embed - err_embed = Embed(title=":no_entry: Error :no_entry:") - - # Log error - logger.warning(msg) - - # Return error message + embed - return [(msg, "")], err_embed - - # Return all movies pages - return pages, embed + Action = "28" + Adventure = "12" + Animation = "16" + Comedy = "35" + Crime = "80" + Documentary = "99" + Drama = "18" + Family = "10751" + Fantasy = "14" + History = "36" + Horror = "27" + Music = "10402" + Mystery = "9648" + Romance = "10749" + Science = "878" + Thriller = "53" + Western = "37" class Movie(Cog): @@ -199,25 +81,130 @@ class Movie(Cog): # Check is there more than 20 movies specified, due TMDB return 20 movies # per page, so this is max. Also you can't get less movies than 1, just logic if amount > 20: - await ctx.send('You can\'t get more than 20 movies at once. (TMDB limits)') + await ctx.send("You can't get more than 20 movies at once. (TMDB limits)") return elif amount < 1: - await ctx.send('You can\'t get less than 1 movies. Just logic.') + await ctx.send("You can't get less than 1 movies. Just logic.") return - # Capitalize genre for getting data from Enum + # Capitalize genre for getting data from Enum, get random page genre = genre.capitalize() + page = random.randint(1, 200) - # Try to fetch pages and embed, when invalid genre, show help + # Get movies list from TMDB, check is results key in result. When not, raise error. When genre not exist, + # show help. try: - pages, embed = await get_random_movies(self.http_session, amount, MovieGenres[genre].value, genre) + movies = await self.get_movies_list(self.http_session, MovieGenres[genre].value, page) except KeyError: await ctx.send_help('movies') return + if 'results' not in movies.keys(): + err_text = f'There was problem while fetching movies list. Problematic response:\n```{movies}```' + err = Embed(title=':no_entry: Error :no_entry:', description=err_text) + + await ctx.send(embed=err) + logger.warning(err_text) + + return + + # Get all pages and embed + pages = await self.get_pages(self.http_session, movies, amount) + embed = await self.get_embed(genre) # Send movies, paginate await ImagePaginator.paginate(pages, ctx, embed) + async def get_movies_list(self, client: ClientSession, genre_id: str, page: int) -> Dict: + """Return JSON of TMDB discover request.""" + # Define params of request + params = { + "api_key": TMDB_API_KEY, + "language": "en-US", + "sort_by": "popularity.desc", + "include_adult": "false", + "include_video": "false", + "page": page, + "with_genres": genre_id + } + + # Create URL + url = BASE_URL + "discover/movie?" + urlencode(params) + + # Make discover request to TMDB + async with client.get(url) as resp: + data = await resp.json() + + # Return response result + return data + + async def get_pages(self, client: ClientSession, movies: Dict, amount: int) -> (List[Tuple[str, str]]): + """Fetch all movie pages from movies dictionary. Return list of pages.""" + pages = [] + + for i in range(amount): + # Get movie ID, fetch movie information + movie_id = movies['results'][i]['id'] + movie = await self.get_movie(client, movie_id) + + # Create page, append it to pages + page, img = await self.create_page(movie) + pages.append((page, img)) + + return pages + + async def get_movie(self, client: ClientSession, movie: int) -> Dict: + """Get Movie by movie ID from TMDB. Return result dictionary.""" + # Define URL params, generate URL + params = { + "api_key": TMDB_API_KEY, + "language": "en-US" + } + url = BASE_URL + f"movie/{movie}?" + urlencode(params) + + # Do request, return result + async with client.get(url) as resp: + return await resp.json() + + async def create_page(self, movie: Dict) -> (str, str): + """Create page from TMDB movie request result. Return formatted page + image.""" + text = "" + + # Add title + tagline (if not empty) + text += f"**{movie['title']}**\n" + if movie['tagline'] != "": + text += f"{movie['tagline']}\n\n" + else: + text += "\n" + + # Add other information + text += f"**Rating:** {movie['vote_average']}/10 :star:\n" + text += f"**Release Date:** {movie['release_date']}\n\n" + + text += "__**Production Information**__\n" + + companies = movie['production_companies'] + countries = movie['production_countries'] + + text += f"**Made by:** {', '.join(company['name'] for company in companies)}\n" + text += f"**Made in:** {', '.join(country['name'] for country in countries)}\n\n" + + text += "__**Some Numbers**__\n" + + text += f"**Budget:** ${movie['budget'] if movie['budget'] != 0 else '?'}\n" + text += f"**Revenue:** ${movie['revenue'] if movie['revenue'] != 0 else '?'}\n" + text += f"**Duration:** {movie['runtime']} minutes\n\n" + + text += movie['overview'] + + img = f"http://image.tmdb.org/t/p/w200{movie['poster_path']}" + + # Return page content and image + return text, img + + async def get_embed(self, name: str) -> Embed: + """Return embed of random movies. Uses name in title.""" + return Embed(title=f'Random {name} Movies').set_footer(text='Powered by TMDB (themoviedb.org)') + def setup(bot: Bot) -> None: """Load Movie Cog.""" -- cgit v1.2.3 From eaaeadc76dd859e5d462d648169559b434f76883 Mon Sep 17 00:00:00 2001 From: ks123 Date: Sun, 16 Feb 2020 08:02:36 +0200 Subject: Small style fixes: removed unnecessary comments, made ifs easier readable, fixed type hints. --- bot/seasons/evergreen/movie.py | 43 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py index fc0053fd..949da665 100644 --- a/bot/seasons/evergreen/movie.py +++ b/bot/seasons/evergreen/movie.py @@ -2,7 +2,7 @@ import logging import random from enum import Enum from os import environ -from typing import Dict, List, Tuple +from typing import Any, Dict, List, Tuple from urllib.parse import urlencode from aiohttp import ClientSession @@ -17,13 +17,17 @@ TMDB_API_KEY = environ.get('TMDB_API_KEY') # Define base URL of TMDB BASE_URL = "https://api.themoviedb.org/3/" -# Get logger logger = logging.getLogger(__name__) +# Define movie params, that will be used for every movie request +MOVIE_PARAMS = { + "api_key": TMDB_API_KEY, + "language": "en-US" +} + -# Genres with TMDB API IDs class MovieGenres(Enum): - """Genre names and IDs.""" + """Movies Genre names and IDs.""" Action = "28" Adventure = "12" @@ -111,10 +115,9 @@ class Movie(Cog): pages = await self.get_pages(self.http_session, movies, amount) embed = await self.get_embed(genre) - # Send movies, paginate await ImagePaginator.paginate(pages, ctx, embed) - async def get_movies_list(self, client: ClientSession, genre_id: str, page: int) -> Dict: + async def get_movies_list(self, client: ClientSession, genre_id: str, page: int) -> Dict[str, Any]: """Return JSON of TMDB discover request.""" # Define params of request params = { @@ -127,26 +130,20 @@ class Movie(Cog): "with_genres": genre_id } - # Create URL url = BASE_URL + "discover/movie?" + urlencode(params) - # Make discover request to TMDB + # Make discover request to TMDB, return result async with client.get(url) as resp: - data = await resp.json() - - # Return response result - return data + return await resp.json() - async def get_pages(self, client: ClientSession, movies: Dict, amount: int) -> (List[Tuple[str, str]]): + async def get_pages(self, client: ClientSession, movies: Dict[str, Any], amount: int) -> List[Tuple[str, str]]: """Fetch all movie pages from movies dictionary. Return list of pages.""" pages = [] for i in range(amount): - # Get movie ID, fetch movie information movie_id = movies['results'][i]['id'] movie = await self.get_movie(client, movie_id) - # Create page, append it to pages page, img = await self.create_page(movie) pages.append((page, img)) @@ -154,24 +151,18 @@ class Movie(Cog): async def get_movie(self, client: ClientSession, movie: int) -> Dict: """Get Movie by movie ID from TMDB. Return result dictionary.""" - # Define URL params, generate URL - params = { - "api_key": TMDB_API_KEY, - "language": "en-US" - } - url = BASE_URL + f"movie/{movie}?" + urlencode(params) + url = BASE_URL + f"movie/{movie}?" + urlencode(MOVIE_PARAMS) - # Do request, return result async with client.get(url) as resp: return await resp.json() - async def create_page(self, movie: Dict) -> (str, str): + async def create_page(self, movie: Dict[str, Any]) -> Tuple[str, str]: """Create page from TMDB movie request result. Return formatted page + image.""" text = "" # Add title + tagline (if not empty) text += f"**{movie['title']}**\n" - if movie['tagline'] != "": + if movie['tagline']: text += f"{movie['tagline']}\n\n" else: text += "\n" @@ -190,8 +181,8 @@ class Movie(Cog): text += "__**Some Numbers**__\n" - text += f"**Budget:** ${movie['budget'] if movie['budget'] != 0 else '?'}\n" - text += f"**Revenue:** ${movie['revenue'] if movie['revenue'] != 0 else '?'}\n" + text += f"**Budget:** ${movie['budget'] if movie['budget'] else '?'}\n" + text += f"**Revenue:** ${movie['revenue'] if movie['revenue'] else '?'}\n" text += f"**Duration:** {movie['runtime']} minutes\n\n" text += movie['overview'] -- cgit v1.2.3 From 87cd31e1af470d5ac52beb1edbb9e552eed9ece1 Mon Sep 17 00:00:00 2001 From: F4zii Date: Sun, 16 Feb 2020 18:22:40 +0200 Subject: Fix the Pagination cog When using pagination in the Reddit cog, clicking the LAST_EMOJI would raise an exception like this: TypeError: unsupported operand type(s) for -: 'list' and 'int' This was resolved by taking the subtraction out of the len() function. --- bot/pagination.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/pagination.py b/bot/pagination.py index f1233482..1858bd2d 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -389,7 +389,7 @@ class ImagePaginator(Paginator): log.debug("Got last page reaction, but we're on the last page - ignoring") continue - current_page = len(paginator.pages - 1) + current_page = len(paginator.pages) - 1 reaction_type = "last" # Previous reaction press - [:arrow_left: ] -- cgit v1.2.3 From 4ba52054c86e293eeec8730d4d338dbb6f375522 Mon Sep 17 00:00:00 2001 From: F4zii Date: Sun, 16 Feb 2020 21:38:09 +0200 Subject: Paginator Migration - Emoji and actions Switched the emoji used to clear the reactions of a paginator [":x:"] With [":trashcan:"], Clicking on this emoji deletes the message --- bot/pagination.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'bot') diff --git a/bot/pagination.py b/bot/pagination.py index 1858bd2d..841e33eb 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -10,7 +10,7 @@ FIRST_EMOJI = "\u23EE" # [:track_previous:] LEFT_EMOJI = "\u2B05" # [:arrow_left:] RIGHT_EMOJI = "\u27A1" # [:arrow_right:] LAST_EMOJI = "\u23ED" # [:track_next:] -DELETE_EMOJI = "\u274c" # [:x:] +DELETE_EMOJI = "<:trashcan:637136429717389331>" # [:trashcan:] PAGINATION_EMOJI = [FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMOJI] @@ -113,7 +113,7 @@ class LinePaginator(Paginator): # Reaction is on this message reaction_.message.id == message.id, # Reaction is one of the pagination emotes - reaction_.emoji in PAGINATION_EMOJI, + str(reaction_.emoji) in PAGINATION_EMOJI, # Note: DELETE_EMOJI is a string and not unicode # Reaction was not made by the Bot user_.id != ctx.bot.user.id, # There were no restrictions @@ -185,7 +185,7 @@ class LinePaginator(Paginator): log.debug("Timed out waiting for a reaction") break # We're done, no reactions for the last 5 minutes - if reaction.emoji == DELETE_EMOJI: + if str(reaction.emoji) == DELETE_EMOJI: # Note: DELETE_EMOJI is a string and not unicode log.debug("Got delete reaction") break @@ -261,8 +261,8 @@ class LinePaginator(Paginator): await message.edit(embed=embed) - log.debug("Ending pagination and removing all reactions...") - await message.clear_reactions() + log.debug("Ending pagination and deleting the message") + await message.delete() class ImagePaginator(Paginator): @@ -323,7 +323,7 @@ class ImagePaginator(Paginator): # Reaction is on the same message sent reaction_.message.id == message.id, # The reaction is part of the navigation menu - reaction_.emoji in PAGINATION_EMOJI, + str(reaction_.emoji) in PAGINATION_EMOJI, # Note: DELETE_EMOJI is a string and not unicode # The reactor is not a bot not member.bot )) @@ -369,8 +369,8 @@ class ImagePaginator(Paginator): # Deletes the users reaction await message.remove_reaction(reaction.emoji, user) - # Delete reaction press - [:x:] - if reaction.emoji == DELETE_EMOJI: + # Delete reaction press - [:trashcan:] + if str(reaction.emoji) == DELETE_EMOJI: # Note: DELETE_EMOJI is a string and not unicode log.debug("Got delete reaction") break @@ -424,5 +424,5 @@ class ImagePaginator(Paginator): await message.edit(embed=embed) - log.debug("Ending pagination and removing all reactions...") - await message.clear_reactions() + log.debug("Ending pagination and deleting the message") + await message.delete() -- cgit v1.2.3 From cd4841aa6407ab6bece89d12d9645dab56f18d89 Mon Sep 17 00:00:00 2001 From: F4zi <44242259+F4zi780@users.noreply.github.com> Date: Mon, 17 Feb 2020 11:35:14 +0200 Subject: Pagination migrations - Actions and emojis Clicking on [:trashcan:] broke the loop and deleted the message, instead, now we return after a message deletion and break when an `asyncio.TimeoutError` is raised (when a user fails to add reactions in time) --- bot/pagination.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/pagination.py b/bot/pagination.py index 841e33eb..b5bb1720 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -187,7 +187,7 @@ class LinePaginator(Paginator): if str(reaction.emoji) == DELETE_EMOJI: # Note: DELETE_EMOJI is a string and not unicode log.debug("Got delete reaction") - break + return await message.delete() if reaction.emoji == FIRST_EMOJI: await message.remove_reaction(reaction.emoji, user) @@ -261,8 +261,8 @@ class LinePaginator(Paginator): await message.edit(embed=embed) - log.debug("Ending pagination and deleting the message") - await message.delete() + log.debug("Ending pagination and clearing reactions...") + await message.clear_reactions() class ImagePaginator(Paginator): @@ -372,7 +372,7 @@ class ImagePaginator(Paginator): # Delete reaction press - [:trashcan:] if str(reaction.emoji) == DELETE_EMOJI: # Note: DELETE_EMOJI is a string and not unicode log.debug("Got delete reaction") - break + return await message.delete() # First reaction press - [:track_previous:] if reaction.emoji == FIRST_EMOJI: @@ -424,5 +424,5 @@ class ImagePaginator(Paginator): await message.edit(embed=embed) - log.debug("Ending pagination and deleting the message") - await message.delete() + log.debug("Ending pagination and clearing reactions...") + await message.clear_reactions() -- cgit v1.2.3 From c1fe1a989d1d9035bc32b1f6e789f2a82bbadab8 Mon Sep 17 00:00:00 2001 From: F4zi <44242259+F4zi780@users.noreply.github.com> Date: Mon, 17 Feb 2020 12:36:20 +0200 Subject: Pagination migrations - Data Structure Modified Changed the pagination emoji collection from list to tuple This change was suggested since this collection is constant --- bot/pagination.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/pagination.py b/bot/pagination.py index b5bb1720..a024e0d9 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -12,7 +12,7 @@ RIGHT_EMOJI = "\u27A1" # [:arrow_right:] LAST_EMOJI = "\u23ED" # [:track_next:] DELETE_EMOJI = "<:trashcan:637136429717389331>" # [:trashcan:] -PAGINATION_EMOJI = [FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMOJI] +PAGINATION_EMOJI = (FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMOJI) log = logging.getLogger(__name__) -- cgit v1.2.3 From 08c4d7f4883df94f6f63f27d1531d881cf33f1e5 Mon Sep 17 00:00:00 2001 From: F4zii Date: Mon, 17 Feb 2020 16:52:31 +0200 Subject: Paginator Migration - Added trashcan emoji to constants.py --- bot/constants.py | 1 + bot/pagination.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index eca4f67b..be92770d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -88,6 +88,7 @@ class Emojis: christmas_tree = "\U0001F384" check = "\u2611" envelope = "\U0001F4E8" + trashcan = "<:trashcan:678677706652647506>" terning1 = "<:terning1:431249668983488527>" terning2 = "<:terning2:462339216987127808>" diff --git a/bot/pagination.py b/bot/pagination.py index a024e0d9..c77ad571 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -5,12 +5,13 @@ from typing import Iterable, List, Optional, Tuple from discord import Embed, Member, Reaction from discord.abc import User from discord.ext.commands import Context, Paginator +from bot.constants import Emojis FIRST_EMOJI = "\u23EE" # [:track_previous:] LEFT_EMOJI = "\u2B05" # [:arrow_left:] RIGHT_EMOJI = "\u27A1" # [:arrow_right:] LAST_EMOJI = "\u23ED" # [:track_next:] -DELETE_EMOJI = "<:trashcan:637136429717389331>" # [:trashcan:] +DELETE_EMOJI = Emojis.trashcan # [:trashcan:] PAGINATION_EMOJI = (FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMOJI) -- cgit v1.2.3 From a43655831319ebeefc8038c2c4b1b981d6c5a759 Mon Sep 17 00:00:00 2001 From: F4zii Date: Mon, 17 Feb 2020 16:55:40 +0200 Subject: Paginator Migration - Added trashcan emoji to constants.py --- bot/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index be92770d..2c68f719 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -88,7 +88,7 @@ class Emojis: christmas_tree = "\U0001F384" check = "\u2611" envelope = "\U0001F4E8" - trashcan = "<:trashcan:678677706652647506>" + trashcan = "<:trashcan:637136429717389331>" terning1 = "<:terning1:431249668983488527>" terning2 = "<:terning2:462339216987127808>" -- cgit v1.2.3 From 7ec299251afd794d10e82e66fd9cb4c9c0f744ea Mon Sep 17 00:00:00 2001 From: F4zii Date: Mon, 17 Feb 2020 17:11:37 +0200 Subject: Paginator Migration - Added trashcan emoji to constants.py --- bot/constants.py | 1 + bot/pagination.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index eca4f67b..2c68f719 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -88,6 +88,7 @@ class Emojis: christmas_tree = "\U0001F384" check = "\u2611" envelope = "\U0001F4E8" + trashcan = "<:trashcan:637136429717389331>" terning1 = "<:terning1:431249668983488527>" terning2 = "<:terning2:462339216987127808>" diff --git a/bot/pagination.py b/bot/pagination.py index a024e0d9..9a7a0382 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -6,11 +6,13 @@ from discord import Embed, Member, Reaction from discord.abc import User from discord.ext.commands import Context, Paginator +from bot.constants import Emojis + FIRST_EMOJI = "\u23EE" # [:track_previous:] LEFT_EMOJI = "\u2B05" # [:arrow_left:] RIGHT_EMOJI = "\u27A1" # [:arrow_right:] LAST_EMOJI = "\u23ED" # [:track_next:] -DELETE_EMOJI = "<:trashcan:637136429717389331>" # [:trashcan:] +DELETE_EMOJI = Emojis.trashcan # [:trashcan:] PAGINATION_EMOJI = (FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMOJI) -- cgit v1.2.3 From 3e10585525ccf6fca5c5174f1077d0f6ecbf0622 Mon Sep 17 00:00:00 2001 From: F4zii Date: Mon, 17 Feb 2020 17:29:02 +0200 Subject: Lint error - missing line --- bot/pagination.py | 1 - 1 file changed, 1 deletion(-) (limited to 'bot') diff --git a/bot/pagination.py b/bot/pagination.py index f8fa538c..9a7a0382 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -5,7 +5,6 @@ from typing import Iterable, List, Optional, Tuple from discord import Embed, Member, Reaction from discord.abc import User from discord.ext.commands import Context, Paginator -from bot.constants import Emojis from bot.constants import Emojis -- cgit v1.2.3 From afd087fb949d892e644b304676ff81791be8909d Mon Sep 17 00:00:00 2001 From: ks123 Date: Mon, 17 Feb 2020 19:12:25 +0200 Subject: Added .movies genres|genre|g command. Made .movies command docstring smaller. Added warning loggings. Better Some Numbers section formatting. --- bot/constants.py | 1 + bot/seasons/evergreen/movie.py | 88 ++++++++++++++++++++---------------------- 2 files changed, 43 insertions(+), 46 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index eca4f67b..0a9af1dd 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -132,6 +132,7 @@ class Tokens(NamedTuple): aoc_session_cookie = environ.get("AOC_SESSION_COOKIE") omdb = environ.get("OMDB_API_KEY") youtube = environ.get("YOUTUBE_API_KEY") + tmdb = environ.get("TMDB_API_KEY") # Default role combinations diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py index 949da665..4bc59655 100644 --- a/bot/seasons/evergreen/movie.py +++ b/bot/seasons/evergreen/movie.py @@ -1,19 +1,16 @@ import logging import random from enum import Enum -from os import environ from typing import Any, Dict, List, Tuple from urllib.parse import urlencode from aiohttp import ClientSession from discord import Embed -from discord.ext.commands import Bot, Cog, Context, command +from discord.ext.commands import Bot, Cog, Context, group +from bot.constants import Tokens from bot.pagination import ImagePaginator -# Get TMDB API key from .env -TMDB_API_KEY = environ.get('TMDB_API_KEY') - # Define base URL of TMDB BASE_URL = "https://api.themoviedb.org/3/" @@ -21,7 +18,7 @@ logger = logging.getLogger(__name__) # Define movie params, that will be used for every movie request MOVIE_PARAMS = { - "api_key": TMDB_API_KEY, + "api_key": Tokens.tmdb, "language": "en-US" } @@ -55,32 +52,12 @@ class Movie(Cog): self.bot = bot self.http_session: ClientSession = bot.http_session - @command(name='movies', aliases=['movie']) + @group(name='movies', aliases=['movie'], invoke_without_command=True) async def movies(self, ctx: Context, genre: str = "", amount: int = 5) -> None: """ - Get random movies by specifing genre. - - Also support amount parameter, - that define how much movies will be shown. Default 5 - - Available genres: - - Action - - Adventure - - Animation - - Comedy - - Crime - - Documentary - - Drama - - Family - - Fantasy - - History - - Horror - - Music - - Mystery - - Romance - - Science - - Thriller - - Western + Get random movies by specifying genre. Also support amount parameter, that define how much movies will be shown. + + Default 5. Use .movies genres to get all available genres. """ # Check is there more than 20 movies specified, due TMDB return 20 movies # per page, so this is max. Also you can't get less movies than 1, just logic @@ -91,25 +68,31 @@ class Movie(Cog): await ctx.send("You can't get less than 1 movies. Just logic.") return - # Capitalize genre for getting data from Enum, get random page + # Capitalize genre for getting data from Enum, get random page, send help when genre don't exist. genre = genre.capitalize() - page = random.randint(1, 200) - - # Get movies list from TMDB, check is results key in result. When not, raise error. When genre not exist, - # show help. try: - movies = await self.get_movies_list(self.http_session, MovieGenres[genre].value, page) + result = await self.get_movies_list(self.http_session, MovieGenres[genre].value, 1) except KeyError: await ctx.send_help('movies') return - if 'results' not in movies.keys(): - err_text = f'There was problem while fetching movies list. Problematic response:\n```{movies}```' - err = Embed(title=':no_entry: Error :no_entry:', description=err_text) - await ctx.send(embed=err) - logger.warning(err_text) + # Check is results is result. If not, throw error. + if "results" not in result.keys(): + err_msg = f"There is problem while making TMDB API request. Response Code: {result['status_code']}, " \ + f"{result['status_message']}." + await ctx.send(err_msg) + logger.warning(err_msg) - return + # Get random page. Max page is last page where is movies with this genre. + page = random.randint(1, result["total_pages"]) + + # Get movies list from TMDB, check is results key in result. When not, raise error. + movies = await self.get_movies_list(self.http_session, MovieGenres[genre].value, page) + if 'results' not in movies.keys(): + err_msg = f"There is problem while making TMDB API request. Response Code: {result['status_code']}, " \ + f"{result['status_message']}." + await ctx.send(err_msg) + logger.warning(err_msg) # Get all pages and embed pages = await self.get_pages(self.http_session, movies, amount) @@ -117,11 +100,16 @@ class Movie(Cog): await ImagePaginator.paginate(pages, ctx, embed) + @movies.command(name='genres', aliases=['genre', 'g']) + async def genres(self, ctx: Context) -> None: + """Show all currently available genres for .movies command.""" + await ctx.send(f"Current available genres: {', '.join('`' + genre.name + '`' for genre in MovieGenres)}") + async def get_movies_list(self, client: ClientSession, genre_id: str, page: int) -> Dict[str, Any]: """Return JSON of TMDB discover request.""" # Define params of request params = { - "api_key": TMDB_API_KEY, + "api_key": Tokens.tmdb, "language": "en-US", "sort_by": "popularity.desc", "include_adult": "false", @@ -181,9 +169,17 @@ class Movie(Cog): text += "__**Some Numbers**__\n" - text += f"**Budget:** ${movie['budget'] if movie['budget'] else '?'}\n" - text += f"**Revenue:** ${movie['revenue'] if movie['revenue'] else '?'}\n" - text += f"**Duration:** {movie['runtime']} minutes\n\n" + budget = f"{movie['budget']:,d}" if movie['budget'] else "?" + revenue = f"{movie['revenue']:,d}" if movie['revenue'] else "?" + + if movie['runtime'] is not None: + duration = divmod(movie['runtime'], 60) + else: + duration = ("?", "?") + + text += f"**Budget:** ${budget}\n" + text += f"**Revenue:** ${revenue}\n" + text += f"**Duration:** {f'{duration[0]} hour(s) {duration[1]} minute(s)'}\n\n" text += movie['overview'] -- cgit v1.2.3 From f9fbed2e2f1828b0c91e3c8348b51ae9b0022de5 Mon Sep 17 00:00:00 2001 From: Karlis S <45097959+ks129@users.noreply.github.com> Date: Tue, 18 Feb 2020 06:45:26 +0200 Subject: Fixed error message for less than 1 movie check. --- bot/seasons/evergreen/movie.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py index 4bc59655..e7671c59 100644 --- a/bot/seasons/evergreen/movie.py +++ b/bot/seasons/evergreen/movie.py @@ -65,7 +65,7 @@ class Movie(Cog): await ctx.send("You can't get more than 20 movies at once. (TMDB limits)") return elif amount < 1: - await ctx.send("You can't get less than 1 movies. Just logic.") + await ctx.send("You can't get less than 1 movie.") return # Capitalize genre for getting data from Enum, get random page, send help when genre don't exist. -- cgit v1.2.3 From 007d93c5e63a8167f3aa5158b85aca8599f3bda3 Mon Sep 17 00:00:00 2001 From: Karlis S <45097959+ks129@users.noreply.github.com> Date: Tue, 18 Feb 2020 17:25:01 +0200 Subject: Fixed comments in Movie cog --- bot/seasons/evergreen/movie.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/seasons/evergreen/movie.py b/bot/seasons/evergreen/movie.py index e7671c59..3c5a312d 100644 --- a/bot/seasons/evergreen/movie.py +++ b/bot/seasons/evergreen/movie.py @@ -76,7 +76,7 @@ class Movie(Cog): await ctx.send_help('movies') return - # Check is results is result. If not, throw error. + # Check if "results" is in result. If not, throw error. if "results" not in result.keys(): err_msg = f"There is problem while making TMDB API request. Response Code: {result['status_code']}, " \ f"{result['status_message']}." @@ -86,7 +86,7 @@ class Movie(Cog): # Get random page. Max page is last page where is movies with this genre. page = random.randint(1, result["total_pages"]) - # Get movies list from TMDB, check is results key in result. When not, raise error. + # Get movies list from TMDB, check if results key in result. When not, raise error. movies = await self.get_movies_list(self.http_session, MovieGenres[genre].value, page) if 'results' not in movies.keys(): err_msg = f"There is problem while making TMDB API request. Response Code: {result['status_code']}, " \ -- cgit v1.2.3