Repository: python-discord/bot

Issue:
Auto-respond to non-mod everyone pings.
# The issue:
Currently, if someone puts down an `@everyone` ping, a mod has to come and respond to it to tell the person not to ping 95k+ people. Now, this usually works fine, but accidents happen, and things can end up happening like lemon accidentally pinging everyone, because android doesn't have a check for that (we're not upset lemon!).

# Proposed solution:
We add a auto-respond to the bot, sort of like in the attachment auto-respond, that contacts the user to explain why they shouldn't ping 95k people, and maybe even temp-mutes them and/or deletes the message. Here is an example message:
```
Sorry @user, but please don't try to ping 95k people. It will not have good results.
If you want to see what can happen, take a look at this pin: 
https://discordapp.com/channels/267624335836053506/267624335836053506/748352909904969740
```
It should only respond to non-staff too.


Discussion:
- This should be implemented as a filter.
- Automatically deletes the message with the fake everyone ping in it, because we don't want any idiot owners quoting those messages by accident :grin: 
- Mutes the user for 10 minutes, similar to what we do for spam detectors.
- Posts a message to the channel with a ping of the user and a message similar to what's in OPs description.
- Maybe we don't need to link the pinned message, lol.
I just thought linking the pinned message would help people realize what happens when more 95k+ people get pinged :lemon_pleased:.
I think this link is not good idea, but yes, this should have filter and I can create it, when someone else don't do this.
The link was more of a joke, but I could also implement this to the bot.
I think since you created the issue, @MrAwesomeRocks, you can handle it if you want it.
@lemonsaurus How does the current spam filter work? Could you send one of the current filter files?
See this cog: https://github.com/python-discord/bot/blob/master/bot/cogs/antispam.py

And these rules: https://github.com/python-discord/bot/tree/master/bot/rules

So I have to:
1. Add my rule to the [config file](https://github.com/MrAwesomeRocks/bot/blob/master/config-default.yml).
2. Write my rule in [this folder](https://github.com/python-discord/bot/tree/master/bot/rules).
3. Add my rule to [this dict](https://github.com/python-discord/bot/blob/04cafc66d2e8067f9c94b111f5dac6e7dd915e1e/bot/cogs/antispam.py#L27).

@lemonsaurus 

Resolving patch:
diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py
--- a/bot/cogs/antispam.py
+++ b/bot/cogs/antispam.py
@@ -34,7 +34,8 @@
     'links': rules.apply_links,
     'mentions': rules.apply_mentions,
     'newlines': rules.apply_newlines,
-    'role_mentions': rules.apply_role_mentions
+    'role_mentions': rules.apply_role_mentions,
+    'everyone_ping': rules.apply_everyone_ping,
 }
 
 
diff --git a/bot/rules/__init__.py b/bot/rules/__init__.py
--- a/bot/rules/__init__.py
+++ b/bot/rules/__init__.py
@@ -10,3 +10,4 @@
 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
new file mode 100644
--- /dev/null
+++ b/bot/rules/everyone_ping.py
@@ -0,0 +1,41 @@
+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


Test patch: