From 5b9f265890bb7940fa91b4c1570ede3782f11222 Mon Sep 17 00:00:00 2001 From: sco1 Date: Wed, 2 Jan 2019 20:27:31 -0500 Subject: [PATCH 1/7] Add user notification on invite remove --- bot/cogs/filtering.py | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index f5811d9d2a..0c62be77eb 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -1,7 +1,8 @@ import logging import re -from discord import Colour, Member, Message +from discord import Colour, Member, Message, TextChannel +import discord.errors from discord.ext.commands import Bot from bot.cogs.modlog import ModLog @@ -42,27 +43,41 @@ def __init__(self, bot: Bot): "filter_zalgo": { "enabled": Filter.filter_zalgo, "function": self._has_zalgo, - "type": "filter" + "type": "filter", + "user_notification": False, + "notification_msg": "" }, "filter_invites": { "enabled": Filter.filter_invites, "function": self._has_invites, - "type": "filter" + "type": "filter", + "user_notification": True, + "notification_msg": ( + "Per Rule 10, your invite link has been removed. " + "If you believe this was a mistake, please the staff know!\n\n" + r"Our server rules can be found here: " + ) }, "filter_domains": { "enabled": Filter.filter_domains, "function": self._has_urls, - "type": "filter" + "type": "filter", + "user_notification": False, + "notification_msg": "" }, "watch_words": { "enabled": Filter.watch_words, "function": self._has_watchlist_words, - "type": "watchlist" + "type": "watchlist", + "user_notification": False, + "notification_msg": "" }, "watch_tokens": { "enabled": Filter.watch_tokens, "function": self._has_watchlist_tokens, - "type": "watchlist" + "type": "watchlist", + "user_notification": False, + "notification_msg": "" }, } @@ -136,6 +151,10 @@ async def _filter_message(self, msg: Message): if _filter["type"] == "filter": await msg.delete() + # Notify the user if the filter specifies + if _filter["user_notification"]: + await self.notify_member(msg.author, _filter["notification_msg"], msg.channel) + break # We don't want multiple filters to trigger @staticmethod @@ -247,6 +266,18 @@ async def _has_invites(self, text: str) -> bool: return True return False + async def notify_member(self, filtered_member: Member, reason: str, channel: TextChannel): + """ + Notify filtered_member about a moderation action with the reason str + + First attempts to DM the user, fall back to in-channel notification if user has DMs disabled + """ + + try: + await filtered_member.send(reason) + except discord.errors.Forbidden: + await channel.send(f"{filtered_member.mention} {reason}") + def setup(bot: Bot): bot.add_cog(Filtering(bot)) From 44f35ec35818c8355766a08d586691be5d76d860 Mon Sep 17 00:00:00 2001 From: sco1 Date: Wed, 2 Jan 2019 20:32:59 -0500 Subject: [PATCH 2/7] Add identification of invite via DM --- bot/cogs/filtering.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 0c62be77eb..8adde63127 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -1,7 +1,7 @@ import logging import re -from discord import Colour, Member, Message, TextChannel +from discord import Colour, DMChannel, Member, Message, TextChannel import discord.errors from discord.ext.commands import Bot @@ -126,10 +126,15 @@ async def _filter_message(self, msg: Message): triggered = await _filter["function"](msg.content) if triggered: + if isinstance(msg.channel, DMChannel): + channel_str = "via DM" + else: + channel_str = f"in <#{msg.channel.id}>" + message = ( f"The {filter_name} {_filter['type']} was triggered " f"by **{msg.author.name}#{msg.author.discriminator}** " - f"(`{msg.author.id}`) in <#{msg.channel.id}> with [the " + f"(`{msg.author.id}`) {channel_str} with [the " f"following message]({msg.jump_url}):\n\n" f"{msg.content}" ) From c6d6ffd261d711bdc29674b5dace0f16116cf87d Mon Sep 17 00:00:00 2001 From: sco1 Date: Thu, 3 Jan 2019 11:00:07 -0500 Subject: [PATCH 3/7] Move user notification bools to config Intentionally hardcode token notification, this is handled by the token remover cog Signed-off-by: sco1 --- bot/cogs/filtering.py | 10 +++++----- bot/constants.py | 6 ++++++ config-default.yml | 7 +++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 8adde63127..fe4009a326 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -44,14 +44,14 @@ def __init__(self, bot: Bot): "enabled": Filter.filter_zalgo, "function": self._has_zalgo, "type": "filter", - "user_notification": False, + "user_notification": Filter.notify_user_zalgo, "notification_msg": "" }, "filter_invites": { "enabled": Filter.filter_invites, "function": self._has_invites, "type": "filter", - "user_notification": True, + "user_notification": Filter.notify_user_invites, "notification_msg": ( "Per Rule 10, your invite link has been removed. " "If you believe this was a mistake, please the staff know!\n\n" @@ -62,21 +62,21 @@ def __init__(self, bot: Bot): "enabled": Filter.filter_domains, "function": self._has_urls, "type": "filter", - "user_notification": False, + "user_notification": Filter.notify_user_domains, "notification_msg": "" }, "watch_words": { "enabled": Filter.watch_words, "function": self._has_watchlist_words, "type": "watchlist", - "user_notification": False, + "user_notification": Filter.notify_user_words, "notification_msg": "" }, "watch_tokens": { "enabled": Filter.watch_tokens, "function": self._has_watchlist_tokens, "type": "watchlist", - "user_notification": False, + "user_notification": False, # Hardcode intentional, already in token remover cog "notification_msg": "" }, } diff --git a/bot/constants.py b/bot/constants.py index 99ef98da20..a3845f43a6 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -204,6 +204,12 @@ class Filter(metaclass=YAMLGetter): watch_words: bool watch_tokens: bool + notify_user_zalgo: bool + notify_user_invites: bool + notify_user_domains: bool + notify_user_words: bool + # Token notification intentionally ignored, notification is handled by the token remover cog + ping_everyone: bool guild_invite_whitelist: List[int] domain_blacklist: List[str] diff --git a/config-default.yml b/config-default.yml index 3a1ad8052b..f9f1a1d9e0 100644 --- a/config-default.yml +++ b/config-default.yml @@ -139,6 +139,13 @@ filter: watch_words: true watch_tokens: true + # Notify user on filter? + notify_user_zalgo: false + notify_user_invites: true + notify_user_domains: false + notify_user_words: false + # Token notification intentionally ignored, notification is handled by the token remover cog + # Filter configuration ping_everyone: true # Ping @everyone when we send a mod-alert? From 0453841a722bedd71392cc79132cfe4c87bee25d Mon Sep 17 00:00:00 2001 From: sco1 Date: Thu, 3 Jan 2019 16:54:03 -0500 Subject: [PATCH 4/7] Fix import order --- bot/cogs/filtering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index fe4009a326..27ec6aad92 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -1,8 +1,8 @@ import logging import re -from discord import Colour, DMChannel, Member, Message, TextChannel import discord.errors +from discord import Colour, DMChannel, Member, Message, TextChannel from discord.ext.commands import Bot from bot.cogs.modlog import ModLog From 069b7373b3b9283a4d7c59a82980e98578cb6120 Mon Sep 17 00:00:00 2001 From: sco1 Date: Sat, 5 Jan 2019 14:39:19 -0500 Subject: [PATCH 5/7] Add notification strings for remaining filters Hardcode watch words filter notification to False since it's a watchlist. This logic should be reworked eventually so we ignore user notifications for watchlist type filters. --- bot/cogs/filtering.py | 15 ++++++++++----- bot/constants.py | 2 +- config-default.yml | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 27ec6aad92..701798d185 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -39,13 +39,17 @@ class Filtering: def __init__(self, bot: Bot): self.bot = bot + _staff_mistake_str = "If you believe this was a mistake, please let staff know!" self.filters = { "filter_zalgo": { "enabled": Filter.filter_zalgo, "function": self._has_zalgo, "type": "filter", "user_notification": Filter.notify_user_zalgo, - "notification_msg": "" + "notification_msg": ( + "Your post has been removed for abusing Unicode character rendering (aka Zalgo text). " + f"{_staff_mistake_str}" + ) }, "filter_invites": { "enabled": Filter.filter_invites, @@ -53,8 +57,7 @@ def __init__(self, bot: Bot): "type": "filter", "user_notification": Filter.notify_user_invites, "notification_msg": ( - "Per Rule 10, your invite link has been removed. " - "If you believe this was a mistake, please the staff know!\n\n" + f"Per Rule 10, your invite link has been removed. {_staff_mistake_str}\n\n" r"Our server rules can be found here: " ) }, @@ -63,13 +66,15 @@ def __init__(self, bot: Bot): "function": self._has_urls, "type": "filter", "user_notification": Filter.notify_user_domains, - "notification_msg": "" + "notification_msg": ( + f"Your URL has been removed because it matched a blacklisted domain. {_staff_mistake_str}" + ) }, "watch_words": { "enabled": Filter.watch_words, "function": self._has_watchlist_words, "type": "watchlist", - "user_notification": Filter.notify_user_words, + "user_notification": False, # Hardcode intentional for watchlist filter type "notification_msg": "" }, "watch_tokens": { diff --git a/bot/constants.py b/bot/constants.py index f67b7f45f2..7014a73b3d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -207,7 +207,7 @@ class Filter(metaclass=YAMLGetter): notify_user_zalgo: bool notify_user_invites: bool notify_user_domains: bool - notify_user_words: bool + # Words watch intentionally ignored since it's a watchlist # Token notification intentionally ignored, notification is handled by the token remover cog ping_everyone: bool diff --git a/config-default.yml b/config-default.yml index 5ea9fc6025..f8d8f0c262 100644 --- a/config-default.yml +++ b/config-default.yml @@ -144,7 +144,7 @@ filter: notify_user_zalgo: false notify_user_invites: true notify_user_domains: false - notify_user_words: false + # Words watch intentionally ignored since it's a watchlist # Token notification intentionally ignored, notification is handled by the token remover cog # Filter configuration From 30fcdb91efe9b55448b91a323672ec68b07361cf Mon Sep 17 00:00:00 2001 From: sco1 Date: Sat, 5 Jan 2019 14:44:45 -0500 Subject: [PATCH 6/7] Marginally smarter filter notification logic Only check for a user notification for "filter" type filters --- bot/cogs/filtering.py | 10 +++------- bot/constants.py | 3 +-- config-default.yml | 3 +-- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 701798d185..d5f19a7cc6 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -74,15 +74,11 @@ def __init__(self, bot: Bot): "enabled": Filter.watch_words, "function": self._has_watchlist_words, "type": "watchlist", - "user_notification": False, # Hardcode intentional for watchlist filter type - "notification_msg": "" }, "watch_tokens": { "enabled": Filter.watch_tokens, "function": self._has_watchlist_tokens, "type": "watchlist", - "user_notification": False, # Hardcode intentional, already in token remover cog - "notification_msg": "" }, } @@ -161,9 +157,9 @@ async def _filter_message(self, msg: Message): if _filter["type"] == "filter": await msg.delete() - # Notify the user if the filter specifies - if _filter["user_notification"]: - await self.notify_member(msg.author, _filter["notification_msg"], msg.channel) + # Notify the user if the filter specifies + if _filter["user_notification"]: + await self.notify_member(msg.author, _filter["notification_msg"], msg.channel) break # We don't want multiple filters to trigger diff --git a/bot/constants.py b/bot/constants.py index 7014a73b3d..bbe6c16041 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -204,11 +204,10 @@ class Filter(metaclass=YAMLGetter): watch_words: bool watch_tokens: bool + # Notifications are not expected for "watchlist" type filters notify_user_zalgo: bool notify_user_invites: bool notify_user_domains: bool - # Words watch intentionally ignored since it's a watchlist - # Token notification intentionally ignored, notification is handled by the token remover cog ping_everyone: bool guild_invite_whitelist: List[int] diff --git a/config-default.yml b/config-default.yml index f8d8f0c262..ad87e44ac0 100644 --- a/config-default.yml +++ b/config-default.yml @@ -141,11 +141,10 @@ filter: watch_tokens: true # Notify user on filter? + # Notifications are not expected for "watchlist" type filters notify_user_zalgo: false notify_user_invites: true notify_user_domains: false - # Words watch intentionally ignored since it's a watchlist - # Token notification intentionally ignored, notification is handled by the token remover cog # Filter configuration ping_everyone: true # Ping @everyone when we send a mod-alert? From 1c965ac25bceab3d1d9a57aa0be515c02334ff94 Mon Sep 17 00:00:00 2001 From: sco1 Date: Sat, 5 Jan 2019 16:41:29 -0500 Subject: [PATCH 7/7] Use explicit channel mention --- bot/cogs/filtering.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index d5f19a7cc6..247ee26b85 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -130,7 +130,7 @@ async def _filter_message(self, msg: Message): if isinstance(msg.channel, DMChannel): channel_str = "via DM" else: - channel_str = f"in <#{msg.channel.id}>" + channel_str = f"in {msg.channel.mention}" message = ( f"The {filter_name} {_filter['type']} was triggered "