aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/cogs/filtering.py86
-rw-r--r--bot/constants.py1
-rw-r--r--config-default.yml3
3 files changed, 82 insertions, 8 deletions
diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py
index 74538542a..ca84e6240 100644
--- a/bot/cogs/filtering.py
+++ b/bot/cogs/filtering.py
@@ -1,11 +1,13 @@
+import asyncio
+import datetime
import logging
import re
-from typing import Optional, Union
+from typing import Mapping, Optional, Union
import discord.errors
from dateutil.relativedelta import relativedelta
-from discord import Colour, DMChannel, Member, Message, TextChannel
-from discord.ext.commands import Cog
+from discord import Colour, DMChannel, Member, Message, NotFound, TextChannel
+from discord.ext.commands import Bot, Cog
from bot.bot import Bot
from bot.cogs.moderation import ModLog
@@ -13,6 +15,8 @@ from bot.constants import (
Channels, Colours,
Filter, Icons, URLs
)
+from bot.utils.scheduling import Scheduler
+from bot.utils.time import wait_until
log = logging.getLogger(__name__)
@@ -37,12 +41,15 @@ TOKEN_WATCHLIST_PATTERNS = [
re.compile(fr'{expression}', flags=re.IGNORECASE) for expression in Filter.token_watchlist
]
+OFFENSIVE_MSG_DELETE_TIME = datetime.timedelta(days=Filter.offensive_msg_delete_time)
-class Filtering(Cog):
+
+class Filtering(Cog, Scheduler):
"""Filtering out invites, blacklisting domains, and warning us of certain regular expressions."""
def __init__(self, bot: Bot):
self.bot = bot
+ super().__init__()
staff_mistake_str = "If you believe this was a mistake, please let staff know!"
self.filters = {
@@ -55,7 +62,8 @@ class Filtering(Cog):
"notification_msg": (
"Your post has been removed for abusing Unicode character rendering (aka Zalgo text). "
f"{staff_mistake_str}"
- )
+ ),
+ "schedule_deletion": False
},
"filter_invites": {
"enabled": Filter.filter_invites,
@@ -66,7 +74,8 @@ class Filtering(Cog):
"notification_msg": (
f"Per Rule 6, your invite link has been removed. {staff_mistake_str}\n\n"
r"Our server rules can be found here: <https://pythondiscord.com/pages/rules>"
- )
+ ),
+ "schedule_deletion": False
},
"filter_domains": {
"enabled": Filter.filter_domains,
@@ -76,28 +85,35 @@ class Filtering(Cog):
"user_notification": Filter.notify_user_domains,
"notification_msg": (
f"Your URL has been removed because it matched a blacklisted domain. {staff_mistake_str}"
- )
+ ),
+ "schedule_deletion": False
},
"watch_rich_embeds": {
"enabled": Filter.watch_rich_embeds,
"function": self._has_rich_embed,
"type": "watchlist",
"content_only": False,
+ "schedule_deletion": False
},
"watch_words": {
"enabled": Filter.watch_words,
"function": self._has_watchlist_words,
"type": "watchlist",
"content_only": True,
+ "schedule_deletion": True
},
"watch_tokens": {
"enabled": Filter.watch_tokens,
"function": self._has_watchlist_tokens,
"type": "watchlist",
"content_only": True,
+ "schedule_deletion": True
},
}
+ self.deletion_task = None
+ self.bot.loop.create_task(self.reschedule_offensive_msg_deletion())
+
@property
def mod_log(self) -> ModLog:
"""Get currently loaded ModLog cog instance."""
@@ -176,6 +192,21 @@ class Filtering(Cog):
if _filter["user_notification"]:
await self.notify_member(msg.author, _filter["notification_msg"], msg.channel)
+ # If the message is classed as offensive, we store it in the site db and
+ # it will be deleted it after one week.
+ if _filter["schedule_deletion"]:
+ delete_date = msg.created_at + OFFENSIVE_MSG_DELETE_TIME
+ await self.bot.api_client.post(
+ 'bot/offensive-message',
+ json={
+ 'id': msg.id,
+ 'channel_id': msg.channel.id,
+ 'delete_date': delete_date.isoformat()[:-1]
+ }
+ )
+ log.trace(f"Offensive message will be deleted on "
+ f"{delete_date.isoformat()}")
+
if isinstance(msg.channel, DMChannel):
channel_str = "via DM"
else:
@@ -369,6 +400,47 @@ class Filtering(Cog):
except discord.errors.Forbidden:
await channel.send(f"{filtered_member.mention} {reason}")
+ async def _scheduled_task(self, msg: dict) -> None:
+ """A coroutine which delete the offensive message once the delete date is reached."""
+ delete_at = datetime.datetime.fromisoformat(msg['delete_date'][:-1])
+
+ await wait_until(delete_at)
+ await self.delete_offensive_msg(msg)
+
+ self.cancel_task(msg['id'])
+
+ async def reschedule_offensive_msg_deletion(self) -> None:
+ """Get all the pending message deletion from the API and reschedule them."""
+ await self.bot.wait_until_ready()
+ response = await self.bot.api_client.get(
+ 'bot/offensive-message',
+ )
+
+ now = datetime.datetime.utcnow()
+ loop = asyncio.get_event_loop()
+
+ for msg in response:
+ delete_at = datetime.datetime.fromisoformat(msg['delete_date'][:-1])
+
+ if delete_at < now:
+ await self.delete_offensive_msg(msg)
+ else:
+ self.schedule_task(loop, msg['id'], msg)
+
+ async def delete_offensive_msg(self, msg: Mapping[str, str]) -> None:
+ """Delete an offensive message, and then delete it from the db."""
+ try:
+ channel = self.bot.get_channel(msg['channel_id'])
+ if channel:
+ msg_obj = await channel.fetch_message(msg['id'])
+ await msg_obj.delete()
+ except NotFound:
+ log.info(f"Tried to delete message {msg['id']}, but the message can't be found "
+ f"(it has been probably already deleted).")
+
+ await self.bot.api_client.delete(f'bot/offensive-message/{msg["id"]}')
+ log.info(f"Deleted the offensive message with id {msg['id']}.")
+
def setup(bot: Bot) -> None:
"""Load the Filtering cog."""
diff --git a/bot/constants.py b/bot/constants.py
index 89504a2e0..075722a01 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -211,6 +211,7 @@ class Filter(metaclass=YAMLGetter):
notify_user_domains: bool
ping_everyone: bool
+ offensive_msg_delete_time: int
guild_invite_whitelist: List[int]
domain_blacklist: List[str]
word_watchlist: List[str]
diff --git a/config-default.yml b/config-default.yml
index 930a1a0e6..0765407af 100644
--- a/config-default.yml
+++ b/config-default.yml
@@ -179,7 +179,8 @@ filter:
notify_user_domains: false
# Filter configuration
- ping_everyone: true # Ping @everyone when we send a mod-alert?
+ ping_everyone: true # Ping @everyone when we send a mod-alert?
+ offensive_msg_delete_time: 7 # How many days before deleting an offensive message?
guild_invite_whitelist:
- 280033776820813825 # Functional Programming