aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Daniel Brown <[email protected]>2020-09-21 18:50:45 -0500
committerGravatar Daniel Brown <[email protected]>2020-09-21 18:50:45 -0500
commit282ef64ac931fc6919a740e97a97d7b976d7539d (patch)
tree61b337b5077fe96c84753193bd55e28b05278017
parentMerge pull request #1167 from Numerlor/eval-escape-paste (diff)
parentMerge branch 'master' into bug/1142/fix-everyone-ping (diff)
Merge branch 'bug/1142/fix-everyone-ping' into master
-rw-r--r--bot/constants.py2
-rw-r--r--bot/exts/filters/antispam.py3
-rw-r--r--bot/exts/filters/filtering.py38
-rw-r--r--bot/rules/__init__.py1
-rw-r--r--bot/rules/everyone_ping.py41
-rw-r--r--config-default.yml24
6 files changed, 47 insertions, 62 deletions
diff --git a/bot/constants.py b/bot/constants.py
index 17f14fec0..e4e0b1732 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -217,6 +217,7 @@ class Filter(metaclass=YAMLGetter):
filter_zalgo: bool
filter_invites: bool
filter_domains: bool
+ filter_everyone_ping: bool
watch_regex: bool
watch_rich_embeds: bool
@@ -224,6 +225,7 @@ class Filter(metaclass=YAMLGetter):
notify_user_zalgo: bool
notify_user_invites: bool
notify_user_domains: bool
+ notify_user_everyone_ping: bool
ping_everyone: bool
offensive_msg_delete_days: int
diff --git a/bot/exts/filters/antispam.py b/bot/exts/filters/antispam.py
index 2e7e32d9a..f2a2689e1 100644
--- a/bot/exts/filters/antispam.py
+++ b/bot/exts/filters/antispam.py
@@ -36,9 +36,6 @@ RULE_FUNCTION_MAPPING = {
'mentions': rules.apply_mentions,
'newlines': rules.apply_newlines,
'role_mentions': rules.apply_role_mentions,
- # the everyone filter is temporarily disabled until
- # it has been improved.
- # 'everyone_ping': rules.apply_everyone_ping,
}
diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py
index 2751ed7f6..3bf0d88a0 100644
--- a/bot/exts/filters/filtering.py
+++ b/bot/exts/filters/filtering.py
@@ -14,8 +14,8 @@ from discord.utils import escape_markdown
from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import (
- Channels, Colours,
- Filter, Icons, URLs
+ Channels, Colours, Filter,
+ Guild, Icons, URLs
)
from bot.exts.moderation.modlog import ModLog
from bot.utils.redis_cache import RedisCache
@@ -25,6 +25,12 @@ from bot.utils.scheduling import Scheduler
log = logging.getLogger(__name__)
# Regular expressions
+CODE_BLOCK_RE = re.compile(
+ r"(?P<delim>``?)[^`]+?(?P=delim)(?!`+)" # Inline codeblock
+ r"|```(.+?)```", # Multiline codeblock
+ re.DOTALL | re.MULTILINE
+)
+EVERYONE_PING_RE = re.compile(rf"@everyone|<@&{Guild.id}>|@here")
SPOILER_RE = re.compile(r"(\|\|.+?\|\|)", re.DOTALL)
URL_RE = re.compile(r"(https?://[^\s]+)", flags=re.IGNORECASE)
ZALGO_RE = re.compile(r"[\u0300-\u036F\u0489]")
@@ -82,6 +88,19 @@ class Filtering(Cog):
),
"schedule_deletion": False
},
+ "filter_everyone_ping": {
+ "enabled": Filter.filter_everyone_ping,
+ "function": self._has_everyone_ping,
+ "type": "filter",
+ "content_only": True,
+ "user_notification": Filter.notify_user_everyone_ping,
+ "notification_msg": (
+ "Please don't try to ping `@everyone` or `@here`. "
+ f"Your message has been removed. {staff_mistake_str}"
+ ),
+ "schedule_deletion": False,
+ "ping_everyone": False
+ },
"watch_regex": {
"enabled": Filter.watch_regex,
"function": self._has_watch_regex_match,
@@ -332,6 +351,9 @@ class Filtering(Cog):
log.debug(message)
+ # Allow specific filters to override ping_everyone
+ ping_everyone = Filter.ping_everyone and _filter.get("ping_everyone", True)
+
# Send pretty mod log embed to mod-alerts
await self.mod_log.send_log_message(
icon_url=Icons.filtering,
@@ -340,7 +362,7 @@ class Filtering(Cog):
text=message,
thumbnail=msg.author.avatar_url_as(static_format="png"),
channel_id=Channels.mod_alerts,
- ping_everyone=Filter.ping_everyone if not is_private else False,
+ ping_everyone=ping_everyone if not is_private else False,
additional_embeds=additional_embeds,
additional_embeds_msg=additional_embeds_msg
)
@@ -528,6 +550,16 @@ class Filtering(Cog):
return False
return False
+ @staticmethod
+ async def _has_everyone_ping(text: str) -> bool:
+ """Determines if `msg` contains an @everyone or @here ping outside of a codeblock."""
+ # First pass to avoid running re.sub on every message
+ if not EVERYONE_PING_RE.search(text):
+ return False
+
+ content_without_codeblocks = CODE_BLOCK_RE.sub("", text)
+ return bool(EVERYONE_PING_RE.search(content_without_codeblocks))
+
async def notify_member(self, filtered_member: Member, reason: str, channel: TextChannel) -> None:
"""
Notify filtered_member about a moderation action with the reason str.
diff --git a/bot/rules/__init__.py b/bot/rules/__init__.py
index 8a69cadee..a01ceae73 100644
--- a/bot/rules/__init__.py
+++ b/bot/rules/__init__.py
@@ -10,4 +10,3 @@ from .links import apply as apply_links
from .mentions import apply as apply_mentions
from .newlines import apply as apply_newlines
from .role_mentions import apply as apply_role_mentions
-from .everyone_ping import apply as apply_everyone_ping
diff --git a/bot/rules/everyone_ping.py b/bot/rules/everyone_ping.py
deleted file mode 100644
index 89d9fe570..000000000
--- a/bot/rules/everyone_ping.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import random
-import re
-from typing import Dict, Iterable, List, Optional, Tuple
-
-from discord import Embed, Member, Message
-
-from bot.constants import Colours, Guild, NEGATIVE_REPLIES
-
-# Generate regex for checking for pings:
-guild_id = Guild.id
-EVERYONE_RE_INLINE_CODE = re.compile(rf"^(?!`).*@everyone.*(?!`)$|^(?!`).*<@&{guild_id}>.*(?!`)$")
-EVERYONE_RE_MULTILINE_CODE = re.compile(rf"^(?!```).*@everyone.*(?!```)$|^(?!```).*<@&{guild_id}>.*(?!```)$")
-
-
-async def apply(
- last_message: Message,
- recent_messages: List[Message],
- config: Dict[str, int],
-) -> Optional[Tuple[str, Iterable[Member], Iterable[Message]]]:
- """Detects if a user has sent an '@everyone' ping."""
- relevant_messages = tuple(msg for msg in recent_messages if msg.author == last_message.author)
-
- everyone_messages_count = 0
- for msg in relevant_messages:
- num_everyone_pings_inline = len(re.findall(EVERYONE_RE_INLINE_CODE, msg.content))
- num_everyone_pings_multiline = len(re.findall(EVERYONE_RE_MULTILINE_CODE, msg.content))
- if num_everyone_pings_inline and num_everyone_pings_multiline:
- everyone_messages_count += 1
-
- if everyone_messages_count > config["max"]:
- # Send the channel an embed giving the user more info:
- embed_text = f"Please don't try to ping {last_message.guild.member_count:,} people."
- embed = Embed(title=random.choice(NEGATIVE_REPLIES), description=embed_text, colour=Colours.soft_red)
- await last_message.channel.send(embed=embed)
-
- return (
- "pinged the everyone role",
- (last_message.author,),
- relevant_messages,
- )
- return None
diff --git a/config-default.yml b/config-default.yml
index 58651f548..465f61b5f 100644
--- a/config-default.yml
+++ b/config-default.yml
@@ -275,17 +275,19 @@ guild:
filter:
# What do we filter?
- filter_zalgo: false
- filter_invites: true
- filter_domains: true
- watch_regex: true
- watch_rich_embeds: true
+ filter_zalgo: false
+ filter_invites: true
+ filter_domains: true
+ filter_everyone_ping: true
+ watch_regex: true
+ watch_rich_embeds: 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
+ notify_user_zalgo: false
+ notify_user_invites: true
+ notify_user_domains: false
+ notify_user_everyone_ping: true
# Filter configuration
ping_everyone: true
@@ -391,12 +393,6 @@ anti_spam:
interval: 10
max: 3
- # The everyone ping filter is temporarily disabled
- # until we've fixed a couple of bugs.
- # everyone_ping:
- # interval: 10
- # max: 0
-
reddit:
subreddits: