From fcf0a82296ddf1c46623b14ca0bfca6d50514242 Mon Sep 17 00:00:00 2001 From: asleep-cult Date: Mon, 1 Mar 2021 09:51:49 -0500 Subject: Unescape html escape characters in reddit text and titles --- bot/exts/info/reddit.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bot/exts/info/reddit.py b/bot/exts/info/reddit.py index 6790be762..3630a02ee 100644 --- a/bot/exts/info/reddit.py +++ b/bot/exts/info/reddit.py @@ -2,6 +2,7 @@ import asyncio import logging import random import textwrap +import html from collections import namedtuple from datetime import datetime, timedelta from typing import List @@ -179,7 +180,7 @@ class Reddit(Cog): for post in posts: data = post["data"] - text = data["selftext"] + text = html.unescape(data["selftext"]) if text: text = textwrap.shorten(text, width=128, placeholder="...") text += "\n" # Add newline to separate embed info @@ -188,7 +189,8 @@ class Reddit(Cog): comments = data["num_comments"] author = data["author"] - title = textwrap.shorten(data["title"], width=64, placeholder="...") + title = html.unescape(data["title"]) + title = textwrap.shorten(title, width=64, placeholder="...") # Normal brackets interfere with Markdown. title = escape_markdown(title).replace("[", "⦋").replace("]", "⦌") link = self.URL + data["permalink"] -- cgit v1.2.3 From c04d83721baf68f6beb6bd0d830f7602916f21ed Mon Sep 17 00:00:00 2001 From: asleep-cult Date: Mon, 1 Mar 2021 10:09:03 -0500 Subject: Make flake8 happy --- bot/exts/info/reddit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/info/reddit.py b/bot/exts/info/reddit.py index 3630a02ee..2a74de1d4 100644 --- a/bot/exts/info/reddit.py +++ b/bot/exts/info/reddit.py @@ -1,8 +1,8 @@ import asyncio import logging import random -import textwrap import html +import textwrap from collections import namedtuple from datetime import datetime, timedelta from typing import List -- cgit v1.2.3 From 6e3ff04da525b0987464b6012b9bb6747bf6fce3 Mon Sep 17 00:00:00 2001 From: asleep-cult Date: Mon, 1 Mar 2021 10:55:46 -0500 Subject: Fix pre-commit issues --- bot/exts/info/reddit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/info/reddit.py b/bot/exts/info/reddit.py index 2a74de1d4..2711fd43d 100644 --- a/bot/exts/info/reddit.py +++ b/bot/exts/info/reddit.py @@ -1,7 +1,7 @@ import asyncio import logging -import random import html +import random import textwrap from collections import namedtuple from datetime import datetime, timedelta -- cgit v1.2.3 From e48ff8e25afcf22e7476fc92e074cc0f00f48695 Mon Sep 17 00:00:00 2001 From: asleep-cult Date: Mon, 1 Mar 2021 11:43:37 -0500 Subject: Fix import order --- bot/exts/info/reddit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/info/reddit.py b/bot/exts/info/reddit.py index 2711fd43d..534917c07 100644 --- a/bot/exts/info/reddit.py +++ b/bot/exts/info/reddit.py @@ -1,6 +1,6 @@ import asyncio -import logging import html +import logging import random import textwrap from collections import namedtuple -- cgit v1.2.3 From 2b6d58db377a22b049a67738a6cfba50e771b628 Mon Sep 17 00:00:00 2001 From: asleep-cult Date: Mon, 1 Mar 2021 12:00:07 -0500 Subject: Import unescape directly --- bot/exts/info/reddit.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot/exts/info/reddit.py b/bot/exts/info/reddit.py index 534917c07..9c026caca 100644 --- a/bot/exts/info/reddit.py +++ b/bot/exts/info/reddit.py @@ -1,10 +1,10 @@ import asyncio -import html import logging import random import textwrap from collections import namedtuple from datetime import datetime, timedelta +from html import unescape from typing import List from aiohttp import BasicAuth, ClientError @@ -180,7 +180,7 @@ class Reddit(Cog): for post in posts: data = post["data"] - text = html.unescape(data["selftext"]) + text = unescape(data["selftext"]) if text: text = textwrap.shorten(text, width=128, placeholder="...") text += "\n" # Add newline to separate embed info @@ -189,7 +189,7 @@ class Reddit(Cog): comments = data["num_comments"] author = data["author"] - title = html.unescape(data["title"]) + title = unescape(data["title"]) title = textwrap.shorten(title, width=64, placeholder="...") # Normal brackets interfere with Markdown. title = escape_markdown(title).replace("[", "⦋").replace("]", "⦌") -- cgit v1.2.3 From 7a07fa89746e70f1539ae57912ed19e5690a561a Mon Sep 17 00:00:00 2001 From: SavagePastaMan <69145546+SavagePastaMan@users.noreply.github.com> Date: Mon, 12 Apr 2021 10:09:43 -0400 Subject: Create identity.md Tag to demonstrate the difference between `is` and `==`. --- bot/resources/tags/identity.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 bot/resources/tags/identity.md diff --git a/bot/resources/tags/identity.md b/bot/resources/tags/identity.md new file mode 100644 index 000000000..32995aef6 --- /dev/null +++ b/bot/resources/tags/identity.md @@ -0,0 +1,25 @@ +**Identity vs. Equality** + +Should I be using `is` or `==`? + +To check if two things are equal, use the equality operator (`==`). +```py +x = 5 +if x == 5: + print("x equals 5") +if x == 3: + print("x equals 3") +# Prints 'x equals 5' +``` + +To check if two things are actually the same thing in memory, use the identity comparison operator (`is`). +```py +x = [1, 2, 3] +y = [1, 2, 3] +if x is [1, 2, 3]: + print("x is y") +z = x +if x is z: + print("x is z") +# Prints 'x is z' +``` -- cgit v1.2.3 From 1f2a04870c509b5667d903c187fe05e0796be041 Mon Sep 17 00:00:00 2001 From: asleep-cult Date: Thu, 15 Apr 2021 11:19:43 -0400 Subject: Resolved issues --- bot/exts/info/reddit.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bot/exts/info/reddit.py b/bot/exts/info/reddit.py index 9c026caca..e1f0c5f9f 100644 --- a/bot/exts/info/reddit.py +++ b/bot/exts/info/reddit.py @@ -180,8 +180,7 @@ class Reddit(Cog): for post in posts: data = post["data"] - text = unescape(data["selftext"]) - if text: + if text := unescape(data["selftext"]): text = textwrap.shorten(text, width=128, placeholder="...") text += "\n" # Add newline to separate embed info @@ -189,8 +188,7 @@ class Reddit(Cog): comments = data["num_comments"] author = data["author"] - title = unescape(data["title"]) - title = textwrap.shorten(title, width=64, placeholder="...") + title = textwrap.shorten(unescape(data["title"]), width=64, placeholder="...") # Normal brackets interfere with Markdown. title = escape_markdown(title).replace("[", "⦋").replace("]", "⦌") link = self.URL + data["permalink"] -- cgit v1.2.3 From a2059decb86138f367618dcd5ef5b42fe5de7eae Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Sat, 17 Apr 2021 12:28:36 -0400 Subject: chore: Redirect output to bot-commands channel for the eval command --- bot/decorators.py | 20 +++++++++++++++++--- bot/exts/utils/snekbox.py | 9 +++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/bot/decorators.py b/bot/decorators.py index e971a5bd3..5d9d74bd7 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -107,11 +107,16 @@ def has_no_roles(*roles: t.Union[str, int]) -> t.Callable: return commands.check(predicate) -def redirect_output(destination_channel: int, bypass_roles: t.Container[int] = None) -> t.Callable: +def redirect_output( + destination_channel: int, + bypass_roles: t.Optional[t.Container[int]] = None, + channels: t.Optional[t.Container[int]] = None, + categories: t.Optional[t.Container[int]] = None +) -> t.Callable: """ Changes the channel in the context of the command to redirect the output to a certain channel. - Redirect is bypassed if the author has a role to bypass redirection. + Redirect is bypassed if the author has a bypass role or if it is in a channel that can bypass redirection. This decorator must go before (below) the `command` decorator. """ @@ -119,7 +124,7 @@ def redirect_output(destination_channel: int, bypass_roles: t.Container[int] = N @command_wraps(func) async def inner(self: Cog, ctx: Context, *args, **kwargs) -> None: if ctx.channel.id == destination_channel: - log.trace(f"Command {ctx.command.name} was invoked in destination_channel, not redirecting") + log.trace(f"Command {ctx.command} was invoked in destination_channel, not redirecting") await func(self, ctx, *args, **kwargs) return @@ -128,6 +133,15 @@ def redirect_output(destination_channel: int, bypass_roles: t.Container[int] = N await func(self, ctx, *args, **kwargs) return + elif channels and ctx.channel.id not in channels: + log.trace(f"{ctx.author} used {ctx.command} in a channel that can bypass output redirection") + await func(self, ctx, *args, **kwargs) + return + + elif categories and ctx.channel.category.id not in categories: + log.trace(f"{ctx.author} used {ctx.command} in a category that can bypass output redirection") + await func(self, ctx, *args, **kwargs) + redirect_channel = ctx.guild.get_channel(destination_channel) old_channel = ctx.channel diff --git a/bot/exts/utils/snekbox.py b/bot/exts/utils/snekbox.py index da95240bb..4cc7291e8 100644 --- a/bot/exts/utils/snekbox.py +++ b/bot/exts/utils/snekbox.py @@ -13,7 +13,7 @@ from discord.ext.commands import Cog, Context, command, guild_only from bot.bot import Bot from bot.constants import Categories, Channels, Roles, URLs -from bot.decorators import not_in_blacklist +from bot.decorators import redirect_output from bot.utils import send_to_paste_service from bot.utils.messages import wait_for_deletion @@ -280,7 +280,12 @@ class Snekbox(Cog): @command(name="eval", aliases=("e",)) @guild_only() - @not_in_blacklist(channels=NO_EVAL_CHANNELS, categories=NO_EVAL_CATEGORIES, override_roles=EVAL_ROLES) + @redirect_output( + destination_channel=Channels.bot_commands, + bypass_roles=EVAL_ROLES, + categories=NO_EVAL_CATEGORIES, + channels=NO_EVAL_CHANNELS + ) async def eval_command(self, ctx: Context, *, code: str = None) -> None: """ Run Python code and get the results. -- cgit v1.2.3 From ded578e6b81ca2a39e383472a5a0a4071586f94c Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Thu, 22 Apr 2021 20:14:15 -0400 Subject: fix: Add a missing return statement --- bot/decorators.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot/decorators.py b/bot/decorators.py index 5d9d74bd7..2d0f8bf0d 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -141,6 +141,7 @@ def redirect_output( elif categories and ctx.channel.category.id not in categories: log.trace(f"{ctx.author} used {ctx.command} in a category that can bypass output redirection") await func(self, ctx, *args, **kwargs) + return redirect_channel = ctx.guild.get_channel(destination_channel) old_channel = ctx.channel -- cgit v1.2.3 From 3c6fa7a24a003ea67e10146ea49dd94b6bd022ad Mon Sep 17 00:00:00 2001 From: DawnOfMidnight <78233879+dawnofmidnight@users.noreply.github.com> Date: Tue, 4 May 2021 10:12:10 -0400 Subject: Update stars.json --- bot/resources/stars.json | 1 + 1 file changed, 1 insertion(+) diff --git a/bot/resources/stars.json b/bot/resources/stars.json index 5ecad0213..2021c09df 100644 --- a/bot/resources/stars.json +++ b/bot/resources/stars.json @@ -61,6 +61,7 @@ "Pink", "Prince", "Reba McEntire", + "Rick Astley", "Rihanna", "Robbie Williams", "Rod Stewart", -- cgit v1.2.3 From 2a8ce937c0c71e3e0808b435070dcbfc005f027b Mon Sep 17 00:00:00 2001 From: DawnOfMidnight <78233879+dawnofmidnight@users.noreply.github.com> Date: Tue, 4 May 2021 11:12:38 -0400 Subject: Add more celebrities to stars.json Celebrities: - The Weeknd - Ringo Starr - John Lennon - Guido Van Rossum - George Harrison - Darude --- bot/resources/stars.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bot/resources/stars.json b/bot/resources/stars.json index 2021c09df..3eb0a9d0d 100644 --- a/bot/resources/stars.json +++ b/bot/resources/stars.json @@ -20,6 +20,7 @@ "Céline Dion", "Cher", "Christina Aguilera", + "Darude", "David Bowie", "Donna Summer", "Drake", @@ -31,11 +32,14 @@ "Flo Rida", "Frank Sinatra", "Garth Brooks", + "George Harrison", "George Michael", "George Strait", + "Guido Van Rossum", "James Taylor", "Janet Jackson", "Jay-Z", + "John Lennon", "Johnny Cash", "Johnny Hallyday", "Julio Iglesias", @@ -63,12 +67,14 @@ "Reba McEntire", "Rick Astley", "Rihanna", + "Ringo Starr", "Robbie Williams", "Rod Stewart", "Santana", "Shania Twain", "Stevie Wonder", "Taylor Swift", + "The Weeknd", "Tim McGraw", "Tina Turner", "Tom Petty", -- cgit v1.2.3 From 70bfc1086c6e6213801c315fe3afbe89feedc793 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Wed, 5 May 2021 09:54:06 +0100 Subject: fix: remove the newline --- bot/resources/tags/identity.md | 1 - 1 file changed, 1 deletion(-) diff --git a/bot/resources/tags/identity.md b/bot/resources/tags/identity.md index 32995aef6..033fc0cec 100644 --- a/bot/resources/tags/identity.md +++ b/bot/resources/tags/identity.md @@ -11,7 +11,6 @@ if x == 3: print("x equals 3") # Prints 'x equals 5' ``` - To check if two things are actually the same thing in memory, use the identity comparison operator (`is`). ```py x = [1, 2, 3] -- cgit v1.2.3 From e13018dc92fb2b9fa98696cbca4697464bf9ff67 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Wed, 5 May 2021 10:10:16 +0100 Subject: fix: make requested changes --- bot/resources/tags/identity.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bot/resources/tags/identity.md b/bot/resources/tags/identity.md index 033fc0cec..fb2010759 100644 --- a/bot/resources/tags/identity.md +++ b/bot/resources/tags/identity.md @@ -2,7 +2,7 @@ Should I be using `is` or `==`? -To check if two things are equal, use the equality operator (`==`). +To check if two objects are equal, use the equality operator (`==`). ```py x = 5 if x == 5: @@ -11,14 +11,14 @@ if x == 3: print("x equals 3") # Prints 'x equals 5' ``` -To check if two things are actually the same thing in memory, use the identity comparison operator (`is`). +To check if two objects are actually the same thing in memory, use the identity comparison operator (`is`). ```py -x = [1, 2, 3] -y = [1, 2, 3] -if x is [1, 2, 3]: - print("x is y") -z = x -if x is z: - print("x is z") -# Prints 'x is z' +list_1 = [1, 2, 3] +list_2 = [1, 2, 3] +if list_1 is [1, 2, 3]: + print("list_1 is list_2") +reference_to_list_1 = list_1 +if list_1 is reference_to_list_1: + print("list_1 is reference_to_list_1") +# Prints 'list_1 is reference_to_list_1' ``` -- cgit v1.2.3 From 0fa28ac392c9ae12c3b800a4e9acb32724ddb783 Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Wed, 5 May 2021 09:43:32 -0400 Subject: chore: Don't send a message when redirecting eval output which would ping users twice --- bot/decorators.py | 9 +++++++-- bot/exts/utils/snekbox.py | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bot/decorators.py b/bot/decorators.py index 5d9d74bd7..e4e640748 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -111,13 +111,16 @@ def redirect_output( destination_channel: int, bypass_roles: t.Optional[t.Container[int]] = None, channels: t.Optional[t.Container[int]] = None, - categories: t.Optional[t.Container[int]] = None + categories: t.Optional[t.Container[int]] = None, + ping_user: bool = True ) -> t.Callable: """ Changes the channel in the context of the command to redirect the output to a certain channel. Redirect is bypassed if the author has a bypass role or if it is in a channel that can bypass redirection. + If ping_user is False, it will not send a message in the destination channel. + This decorator must go before (below) the `command` decorator. """ def wrap(func: types.FunctionType) -> types.FunctionType: @@ -147,7 +150,9 @@ def redirect_output( log.trace(f"Redirecting output of {ctx.author}'s command '{ctx.command.name}' to {redirect_channel.name}") ctx.channel = redirect_channel - await ctx.channel.send(f"Here's the output of your command, {ctx.author.mention}") + + if ping_user: + await ctx.send(f"Here's the output of your command, {ctx.author.mention}") asyncio.create_task(func(self, ctx, *args, **kwargs)) message = await old_channel.send( diff --git a/bot/exts/utils/snekbox.py b/bot/exts/utils/snekbox.py index 4cc7291e8..b1f1ba6a8 100644 --- a/bot/exts/utils/snekbox.py +++ b/bot/exts/utils/snekbox.py @@ -284,7 +284,8 @@ class Snekbox(Cog): destination_channel=Channels.bot_commands, bypass_roles=EVAL_ROLES, categories=NO_EVAL_CATEGORIES, - channels=NO_EVAL_CHANNELS + channels=NO_EVAL_CHANNELS, + ping_user=False ) async def eval_command(self, ctx: Context, *, code: str = None) -> None: """ -- cgit v1.2.3 From 425b4f1d2f71b42f197dbaacd7926a5431a74a45 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff Date: Thu, 6 May 2021 19:28:18 +0200 Subject: Prevent accidental addition of users to talentpool Bug: When asking for a review for a user that isn't currently nominated using the `!talentpool get_review ` command, the user is added to the talentpool `watched_users` cache, causing their messages to be relayed to the talentpool watch channel. Steps to reproduce: Use `!talentpool get_review `, where `` is the ID of a user not currently nominated. The command will correctly reply that the user isn't nominated, but their ID will be added as a key to the defaultdict nonetheless. Solution: replace all regular getitem usages with `.get()`, as the Reviewer should never insert IDs using the regular defaultdict path. Additional note: I've replaced all occurrences of regular getitem access into the defaultdict, even those that are normally not reachable with the id of a user that's currently not nominated, to prevent a future refactor from accidentally introducing this bug again. --- bot/exts/recruitment/talentpool/_review.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bot/exts/recruitment/talentpool/_review.py b/bot/exts/recruitment/talentpool/_review.py index 11aa3b62b..4ae1c5ad6 100644 --- a/bot/exts/recruitment/talentpool/_review.py +++ b/bot/exts/recruitment/talentpool/_review.py @@ -57,7 +57,7 @@ class Reviewer: """Schedules a single user for review.""" log.trace(f"Scheduling review of user with ID {user_id}") - user_data = self._pool.watched_users[user_id] + user_data = self._pool.watched_users.get(user_id) inserted_at = isoparse(user_data['inserted_at']).replace(tzinfo=None) review_at = inserted_at + timedelta(days=MAX_DAYS_IN_POOL) @@ -81,14 +81,18 @@ class Reviewer: await message.add_reaction(reaction) if update_database: - nomination = self._pool.watched_users[user_id] + nomination = self._pool.watched_users.get(user_id) await self.bot.api_client.patch(f"{self._pool.api_endpoint}/{nomination['id']}", json={"reviewed": True}) async def make_review(self, user_id: int) -> typing.Tuple[str, Optional[Emoji]]: """Format a generic review of a user and return it with the seen emoji.""" log.trace(f"Formatting the review of {user_id}") - nomination = self._pool.watched_users[user_id] + # Since `watched_users` is a defaultdict, we should take care + # not to accidentally insert the IDs of users that have no + # active nominated by using the `watched_users.get(user_id)` + # instead of `watched_users[user_id]`. + nomination = self._pool.watched_users.get(user_id) if not nomination: log.trace(f"There doesn't appear to be an active nomination for {user_id}") return "", None @@ -303,7 +307,7 @@ class Reviewer: await ctx.send(f":x: Can't find a currently nominated user with id `{user_id}`") return False - nomination = self._pool.watched_users[user_id] + nomination = self._pool.watched_users.get(user_id) if nomination["reviewed"]: await ctx.send(":x: This nomination was already reviewed, but here's a cookie :cookie:") return False -- cgit v1.2.3