From acc79870d55ca257a234a9dc49bfa4a7c85da2ca Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 19 Oct 2021 11:17:31 +0000 Subject: Filtering: add autoban on specific reasons Due to the increase in typo-squatting based phishing, we want to automatically ban users sending specific domain names. For that, this commit will automatically ban any user that trigger a filter which has `[autoban]` in its reason. That's it! --- bot/exts/filters/filtering.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 7faf063b9..ad67f3469 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -42,6 +42,10 @@ ZALGO_RE = regex.compile(rf"[\p{{NONSPACING MARK}}\p{{ENCLOSING MARK}}--[{VARIAT # Other constants. DAYS_BETWEEN_ALERTS = 3 OFFENSIVE_MSG_DELETE_TIME = timedelta(days=Filter.offensive_msg_delete_days) +AUTO_BAN_REASON = ( + "Your account seem to be compromised (%s). " + "Please appeal this ban once you have regained control of your account." +) FilterMatch = Union[re.Match, dict, bool, List[discord.Embed]] @@ -346,6 +350,26 @@ class Filtering(Cog): stats = self._add_stats(filter_name, match, msg.content) await self._send_log(filter_name, _filter, msg, stats, reason) + # If the filter reason contains `[autoban]`, we want to indeed ban + if "[autoban]" in reason.lower(): + # We create a new context from that message and make sure the staffer is the bot + # and the feeback message is sent in #mod-alert + context = await self.bot.get_context(msg) + context.author = self.bot.user + context.channel = self.bot.get_channel(Channels.mod_alerts) + + # We need to convert the user to a member if we are inside a DM channel + if msg.guild is None: + user = self.bot.get_guild(Guild.id).get_member(msg.author.id) + else: + user = msg.author + + await context.invoke( + self.bot.get_command("ban"), + user, + reason=AUTO_BAN_REASON % reason.lower().replace("[autoban]", "").strip() + ) + break # We don't want multiple filters to trigger async def _send_log( @@ -367,6 +391,10 @@ class Filtering(Cog): # Allow specific filters to override ping_everyone ping_everyone = Filter.ping_everyone and _filter.get("ping_everyone", True) + # If we are going to autoban, we don't want to ping + if "[autoban]" in reason: + ping_everyone = False + eval_msg = "using !eval " if is_eval else "" footer = f"Reason: {reason}" if reason else None message = ( -- cgit v1.2.3 From 8e4fe2e73198edb37eb1dcffb7f531a69cec34c2 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 19 Oct 2021 13:39:44 +0200 Subject: Filtering: update auto-ban message Co-authored-by: Boris Muratov <8bee278@gmail.com> --- bot/exts/filters/filtering.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index ad67f3469..82bbd880e 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -43,8 +43,8 @@ ZALGO_RE = regex.compile(rf"[\p{{NONSPACING MARK}}\p{{ENCLOSING MARK}}--[{VARIAT DAYS_BETWEEN_ALERTS = 3 OFFENSIVE_MSG_DELETE_TIME = timedelta(days=Filter.offensive_msg_delete_days) AUTO_BAN_REASON = ( - "Your account seem to be compromised (%s). " - "Please appeal this ban once you have regained control of your account." + "Your account seems to be compromised (%s). " + "You're welcome to appeal this ban once you have regained control of your account." ) FilterMatch = Union[re.Match, dict, bool, List[discord.Embed]] -- cgit v1.2.3 From cf6f11488523db9c25d396a6c70b4a60604e6306 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 19 Oct 2021 11:43:37 +0000 Subject: Filtering: do not try to convert to a member --- bot/exts/filters/filtering.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 82bbd880e..11d0f038b 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -358,9 +358,9 @@ class Filtering(Cog): context.author = self.bot.user context.channel = self.bot.get_channel(Channels.mod_alerts) - # We need to convert the user to a member if we are inside a DM channel + # We try to convert the user to a member if we are inside a DM channel if msg.guild is None: - user = self.bot.get_guild(Guild.id).get_member(msg.author.id) + user = self.bot.get_guild(Guild.id).get_member(msg.author.id) or msg.author else: user = msg.author -- cgit v1.2.3 From 9216e7e341e014528a4fdfaad3bd1a198b8fba02 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Tue, 19 Oct 2021 12:20:25 +0000 Subject: Filtering: make autoban temp --- bot/exts/filters/filtering.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 11d0f038b..15c12d27c 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -46,6 +46,7 @@ AUTO_BAN_REASON = ( "Your account seems to be compromised (%s). " "You're welcome to appeal this ban once you have regained control of your account." ) +AUTO_BAN_DURATION = timedelta(days=4) FilterMatch = Union[re.Match, dict, bool, List[discord.Embed]] @@ -358,15 +359,10 @@ class Filtering(Cog): context.author = self.bot.user context.channel = self.bot.get_channel(Channels.mod_alerts) - # We try to convert the user to a member if we are inside a DM channel - if msg.guild is None: - user = self.bot.get_guild(Guild.id).get_member(msg.author.id) or msg.author - else: - user = msg.author - await context.invoke( - self.bot.get_command("ban"), - user, + self.bot.get_command("tempban"), + msg.author, + datetime.now() + AUTO_BAN_DURATION, reason=AUTO_BAN_REASON % reason.lower().replace("[autoban]", "").strip() ) -- cgit v1.2.3 From 6885c6d79d86c5ce8ee93cf9d43d93521e80c3cd Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 25 Oct 2021 16:54:27 +0200 Subject: Infrac: prioritize mod over bot feedback msg --- bot/exts/filters/filtering.py | 2 +- bot/exts/moderation/infraction/_scheduler.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 15c12d27c..fa4b83438 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -354,7 +354,7 @@ class Filtering(Cog): # If the filter reason contains `[autoban]`, we want to indeed ban if "[autoban]" in reason.lower(): # We create a new context from that message and make sure the staffer is the bot - # and the feeback message is sent in #mod-alert + # and the feedback message is sent in #mod-alert context = await self.bot.get_context(msg) context.author = self.bot.user context.channel = self.bot.get_channel(Channels.mod_alerts) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index d4e96b10b..c07b043be 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -175,13 +175,7 @@ class InfractionScheduler: dm_log_text = "\nDM: Sent" end_msg = "" - if infraction["actor"] == self.bot.user.id: - log.trace( - f"Infraction #{id_} actor is bot; including the reason in the confirmation message." - ) - if reason: - end_msg = f" (reason: {textwrap.shorten(reason, width=1500, placeholder='...')})" - elif is_mod_channel(ctx.channel): + if is_mod_channel(ctx.channel): log.trace(f"Fetching total infraction count for {user}.") infractions = await self.bot.api_client.get( @@ -190,6 +184,12 @@ class InfractionScheduler: ) total = len(infractions) end_msg = f" (#{id_} ; {total} infraction{ngettext('', 's', total)} total)" + elif infraction["actor"] == self.bot.user.id: + log.trace( + f"Infraction #{id_} actor is bot; including the reason in the confirmation message." + ) + if reason: + end_msg = f" (reason: {textwrap.shorten(reason, width=1500, placeholder='...')})" purge = infraction.get("purge", "") -- cgit v1.2.3 From 4b44480a86ecde68e9f416c9ea8f2b49b1300273 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 25 Oct 2021 17:16:03 +0200 Subject: Filtering: update auto ban message --- bot/exts/filters/filtering.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index fa4b83438..8d55e7ee3 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -42,9 +42,21 @@ ZALGO_RE = regex.compile(rf"[\p{{NONSPACING MARK}}\p{{ENCLOSING MARK}}--[{VARIAT # Other constants. DAYS_BETWEEN_ALERTS = 3 OFFENSIVE_MSG_DELETE_TIME = timedelta(days=Filter.offensive_msg_delete_days) + +# Autoban +LINK_PASSWORD = "https://support.discord.com/hc/en-us/articles/218410947-I-forgot-my-Password-Where-can-I-set-a-new-one" +LINK_2FA = "https://support.discord.com/hc/en-us/articles/219576828-Setting-up-Two-Factor-Authentication" AUTO_BAN_REASON = ( - "Your account seems to be compromised (%s). " - "You're welcome to appeal this ban once you have regained control of your account." + "Your account has been used to send links to a phishing website. You have been automatically banned. " + "If you are not aware of sending them, that means your account has been compromised.\n\n" + + f"Here is a guide from Discord on [how to change your password]({LINK_PASSWORD}).\n\n" + + f"We also highly recommend that you [enable 2 factor authentication on your account]({LINK_2FA}), " + "for heightened security.\n\n" + + "Once you have changed your password, feel free to follow the instructions at the bottom of " + "this message to appeal your ban.""" ) AUTO_BAN_DURATION = timedelta(days=4) @@ -363,7 +375,7 @@ class Filtering(Cog): self.bot.get_command("tempban"), msg.author, datetime.now() + AUTO_BAN_DURATION, - reason=AUTO_BAN_REASON % reason.lower().replace("[autoban]", "").strip() + reason=AUTO_BAN_REASON.strip() ) break # We don't want multiple filters to trigger -- cgit v1.2.3 From 798150eca45e52350773e88d7845a1af913b462f Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 25 Oct 2021 17:25:19 +0200 Subject: Filter list: send warning when autoban trigger is added --- bot/constants.py | 1 + bot/exts/filters/filter_lists.py | 7 +++++++ bot/exts/filters/filtering.py | 4 ++-- config-default.yml | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/bot/constants.py b/bot/constants.py index f704c9e6a..a75a26a9b 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -444,6 +444,7 @@ class Channels(metaclass=YAMLGetter): incidents: int incidents_archive: int mod_alerts: int + mod_tools: int nominations: int nomination_voting: int organisation: int diff --git a/bot/exts/filters/filter_lists.py b/bot/exts/filters/filter_lists.py index 4b5200684..b1e07185a 100644 --- a/bot/exts/filters/filter_lists.py +++ b/bot/exts/filters/filter_lists.py @@ -6,6 +6,7 @@ from discord.ext.commands import BadArgument, Cog, Context, IDConverter, group, from bot import constants from bot.api import ResponseCodeError from bot.bot import Bot +from bot.constants import Channels from bot.converters import ValidDiscordServerInvite, ValidFilterListType from bot.log import get_logger from bot.pagination import LinePaginator @@ -100,6 +101,12 @@ class FilterLists(Cog): ) raise + # If it is an autoban trigger we send a warning in #mod-tools + if comment and "[autoban]" in comment: + await self.bot.get_channel(Channels.mod_tools).send( + f":warning: heads-up! The new filter `{content}` (`{comment}`) will automatically ban users." + ) + # Insert the item into the cache self.bot.insert_item_into_filter_list_cache(item) await ctx.message.add_reaction("✅") diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 8d55e7ee3..b20a9c2c9 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -364,7 +364,7 @@ class Filtering(Cog): await self._send_log(filter_name, _filter, msg, stats, reason) # If the filter reason contains `[autoban]`, we want to indeed ban - if "[autoban]" in reason.lower(): + if reason and "[autoban]" in reason.lower(): # We create a new context from that message and make sure the staffer is the bot # and the feedback message is sent in #mod-alert context = await self.bot.get_context(msg) @@ -400,7 +400,7 @@ class Filtering(Cog): ping_everyone = Filter.ping_everyone and _filter.get("ping_everyone", True) # If we are going to autoban, we don't want to ping - if "[autoban]" in reason: + if reason and "[autoban]" in reason: ping_everyone = False eval_msg = "using !eval " if is_eval else "" diff --git a/config-default.yml b/config-default.yml index b61d9c99c..c0e561cca 100644 --- a/config-default.yml +++ b/config-default.yml @@ -207,6 +207,7 @@ guild: incidents_archive: 720668923636351037 mod_alerts: 473092532147060736 mods: &MODS 305126844661760000 + mod_tools: 775413915391098921 nominations: 822920136150745168 nomination_voting: 822853512709931008 organisation: &ORGANISATION 551789653284356126 -- cgit v1.2.3 From 30612bc2f61361ac62a0615181f24366bab3f957 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 25 Oct 2021 19:20:54 +0200 Subject: Filter list: move warning to #mod-meta --- bot/constants.py | 2 +- bot/exts/filters/filter_lists.py | 4 ++-- config-default.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bot/constants.py b/bot/constants.py index a75a26a9b..e3846fb3d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -444,7 +444,7 @@ class Channels(metaclass=YAMLGetter): incidents: int incidents_archive: int mod_alerts: int - mod_tools: int + mod_meta: int nominations: int nomination_voting: int organisation: int diff --git a/bot/exts/filters/filter_lists.py b/bot/exts/filters/filter_lists.py index b1e07185a..4af76af76 100644 --- a/bot/exts/filters/filter_lists.py +++ b/bot/exts/filters/filter_lists.py @@ -101,9 +101,9 @@ class FilterLists(Cog): ) raise - # If it is an autoban trigger we send a warning in #mod-tools + # If it is an autoban trigger we send a warning in #mod-meta if comment and "[autoban]" in comment: - await self.bot.get_channel(Channels.mod_tools).send( + await self.bot.get_channel(Channels.mod_meta).send( f":warning: heads-up! The new filter `{content}` (`{comment}`) will automatically ban users." ) diff --git a/config-default.yml b/config-default.yml index c0e561cca..4a85ccc56 100644 --- a/config-default.yml +++ b/config-default.yml @@ -207,7 +207,7 @@ guild: incidents_archive: 720668923636351037 mod_alerts: 473092532147060736 mods: &MODS 305126844661760000 - mod_tools: 775413915391098921 + mod_meta: 775412552795947058 nominations: 822920136150745168 nomination_voting: 822853512709931008 organisation: &ORGANISATION 551789653284356126 -- cgit v1.2.3 From 874978e575ad6ef5c615f4736e47fd0f6b360af8 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 25 Oct 2021 21:49:34 +0200 Subject: Fltering: clean up autoban code --- bot/exts/filters/filter_lists.py | 2 +- bot/exts/filters/filtering.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bot/exts/filters/filter_lists.py b/bot/exts/filters/filter_lists.py index 4af76af76..ee5bd89f3 100644 --- a/bot/exts/filters/filter_lists.py +++ b/bot/exts/filters/filter_lists.py @@ -104,7 +104,7 @@ class FilterLists(Cog): # If it is an autoban trigger we send a warning in #mod-meta if comment and "[autoban]" in comment: await self.bot.get_channel(Channels.mod_meta).send( - f":warning: heads-up! The new filter `{content}` (`{comment}`) will automatically ban users." + f":warning: Heads-up! The new filter `{content}` (`{comment}`) will automatically ban users." ) # Insert the item into the cache diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index bda4e7ac2..5e91e7e3d 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -1,6 +1,6 @@ import asyncio import re -from datetime import datetime, timedelta +from datetime import timedelta from typing import Any, Dict, List, Mapping, NamedTuple, Optional, Tuple, Union import arrow @@ -375,8 +375,8 @@ class Filtering(Cog): await context.invoke( self.bot.get_command("tempban"), msg.author, - datetime.now() + AUTO_BAN_DURATION, - reason=AUTO_BAN_REASON.strip() + arrow.utcnow() + AUTO_BAN_DURATION, + reason=AUTO_BAN_REASON ) break # We don't want multiple filters to trigger -- cgit v1.2.3 From d957e2d9158e2fb0e43de33c8b174b759da4d905 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 25 Oct 2021 21:58:36 +0200 Subject: Filtering: fix ban flow --- bot/exts/filters/filtering.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 5e91e7e3d..30b447620 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -369,11 +369,12 @@ class Filtering(Cog): # We create a new context from that message and make sure the staffer is the bot # and the feedback message is sent in #mod-alert context = await self.bot.get_context(msg) - context.author = self.bot.user + context.author = self.bot.get_guild(Guild.id).get_member(self.bot.user.id) context.channel = self.bot.get_channel(Channels.mod_alerts) + context.command = self.bot.get_command("tempban") await context.invoke( - self.bot.get_command("tempban"), + context.command, msg.author, arrow.utcnow() + AUTO_BAN_DURATION, reason=AUTO_BAN_REASON -- cgit v1.2.3 From 4594b2b85d714a5e9a65c3ae6e2a2264b1c9b38d Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 25 Oct 2021 22:33:35 +0200 Subject: Filtering: update auto-ban comments Co-authored-by: ChrisJL --- bot/exts/filters/filtering.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 30b447620..804f60547 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -364,10 +364,11 @@ class Filtering(Cog): stats = self._add_stats(filter_name, match, msg.content) await self._send_log(filter_name, _filter, msg, stats, reason) - # If the filter reason contains `[autoban]`, we want to indeed ban + # If the filter reason contains `[autoban]`, we want to auto-ban the user if reason and "[autoban]" in reason.lower(): - # We create a new context from that message and make sure the staffer is the bot - # and the feedback message is sent in #mod-alert + # Create a new context, with the author as is the bot, and the channel as #mod-alerts. + # This sends the ban confirmation directly under watchlist trigger embed, to inform + # mods that the user was auto-banned for the message. context = await self.bot.get_context(msg) context.author = self.bot.get_guild(Guild.id).get_member(self.bot.user.id) context.channel = self.bot.get_channel(Channels.mod_alerts) -- cgit v1.2.3 From d55197b405d8fd71bf09ff32dc339215997368fa Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Mon, 25 Oct 2021 22:34:00 +0200 Subject: Filtering: remove dangling empty quote Co-authored-by: ChrisJL --- bot/exts/filters/filtering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 804f60547..b7a7e8093 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -57,7 +57,7 @@ AUTO_BAN_REASON = ( "for heightened security.\n\n" "Once you have changed your password, feel free to follow the instructions at the bottom of " - "this message to appeal your ban.""" + "this message to appeal your ban." ) AUTO_BAN_DURATION = timedelta(days=4) -- cgit v1.2.3 From e7959146d7949377d35a433ad83f0841070587d9 Mon Sep 17 00:00:00 2001 From: Boris Muratov <8bee278@gmail.com> Date: Tue, 26 Oct 2021 13:29:37 +0300 Subject: Handle autoban filtering in DMs (#1914) An autoban trigger being sent in DMs caused the ban to fail, but for it to still be registered in the database. That is becuase the ban command uses the `ctx.guild.ban` method, but in DMs `ctx.guild` is None. This commit solves it by overriding the `context.guild` field. --- bot/exts/filters/filtering.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index b7a7e8093..022b4ab02 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -370,7 +370,8 @@ class Filtering(Cog): # This sends the ban confirmation directly under watchlist trigger embed, to inform # mods that the user was auto-banned for the message. context = await self.bot.get_context(msg) - context.author = self.bot.get_guild(Guild.id).get_member(self.bot.user.id) + context.guild = self.bot.get_guild(Guild.id) + context.author = context.guild.get_member(self.bot.user.id) context.channel = self.bot.get_channel(Channels.mod_alerts) context.command = self.bot.get_command("tempban") -- cgit v1.2.3