aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Shivansh-007 <[email protected]>2021-03-03 18:03:44 +0530
committerGravatar Shivansh-007 <[email protected]>2021-10-11 12:05:26 +0530
commite9c2bcce3e00e88ccff35885e50c4ed3ecbd9e0f (patch)
tree22cc03e37d35c7153adfd981e6f335dcd9c36d5e
parentMerge pull request #1865 from python-discord/fix-bot-1858 (diff)
Send webhook embed containing information about the message if there is a message link in the incident report
-rw-r--r--bot/constants.py1
-rw-r--r--bot/exts/moderation/incidents.py73
2 files changed, 70 insertions, 4 deletions
diff --git a/bot/constants.py b/bot/constants.py
index f99913b17..33c911874 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -481,6 +481,7 @@ class Webhooks(metaclass=YAMLGetter):
big_brother: int
dev_log: int
duck_pond: int
+ incidents: int
incidents_archive: int
diff --git a/bot/exts/moderation/incidents.py b/bot/exts/moderation/incidents.py
index a3d90e3fe..0d63ef34f 100644
--- a/bot/exts/moderation/incidents.py
+++ b/bot/exts/moderation/incidents.py
@@ -1,16 +1,18 @@
import asyncio
import logging
+import re
import typing as t
from datetime import datetime
from enum import Enum
import discord
+from async_rediscache import RedisCache
from discord.ext.commands import Cog
from bot.bot import Bot
from bot.constants import Channels, Colours, Emojis, Guild, Webhooks
from bot.utils import scheduling
-from bot.utils.messages import sub_clyde
+from bot.utils.messages import format_user, sub_clyde
log = logging.getLogger(__name__)
@@ -22,6 +24,10 @@ CRAWL_LIMIT = 50
# Seconds for `crawl_task` to sleep after adding reactions to a message
CRAWL_SLEEP = 2
+DISCORD_MESSAGE_LINK_RE = re.compile(
+ r"discord(?:[\.,]|dot)com(?:\/|slash)channels(?:\/|slash)[0-9]{18}(?:\/|slash)[0-9]{18}(?:\/|slash)[0-9]{18}"
+)
+
class Signal(Enum):
"""
@@ -114,9 +120,9 @@ def is_incident(message: discord.Message) -> bool:
"""True if `message` qualifies as an incident, False otherwise."""
conditions = (
message.channel.id == Channels.incidents, # Message sent in #incidents
- not message.author.bot, # Not by a bot
- not message.content.startswith("#"), # Doesn't start with a hash
- not message.pinned, # And isn't header
+ not message.author.bot, # Not by a bot
+ not message.content.startswith("#"), # Doesn't start with a hash
+ not message.pinned, # And isn't header
)
return all(conditions)
@@ -131,6 +137,32 @@ def has_signals(message: discord.Message) -> bool:
return ALL_SIGNALS.issubset(own_reactions(message))
+async def make_message_link_embed(incident: discord.Message, message_link: str) -> discord.Embed:
+ """
+ Create an embed representation of discord message link contained in the incident report.
+
+ The Embed would contain the following information -->
+ Author: @Jason Terror ♦ (736234578745884682)
+ Channel: Special/#bot-commands (814190307980607493)
+ Content: This is a very important message!
+ """
+ channel_id = int(message_link.split("/")[3])
+ msg_id = int(message_link.split("/")[4])
+
+ channel = incident.guild.get_channel(channel_id)
+ message = await channel.fetch_message(msg_id)
+
+ text = message.content
+ channel = message.channel
+ description = (
+ f"**Author:** {format_user(message.author)}\n"
+ f"**Channel:** {channel.category}/#{channel.name} (`{channel.id}`)\n"
+ f"**Content:** {text[:2045] + '...' if len(text) > 2048 else text}\n"
+ "\n"
+ )
+ return discord.Embed(description=description)
+
+
async def add_signals(incident: discord.Message) -> None:
"""
Add `Signal` member emoji to `incident` as reactions.
@@ -186,6 +218,10 @@ class Incidents(Cog):
Please refer to function docstrings for implementation details.
"""
+ # This dictionary maps a incident message to the message link embeds(s) sent by it
+ # RedisCache[discord.Message.id, List[discord.Message.id]]
+ message_link_embeds_cache = RedisCache()
+
def __init__(self, bot: Bot) -> None:
"""Prepare `event_lock` and schedule `crawl_task` on start-up."""
self.bot = bot
@@ -340,6 +376,12 @@ class Incidents(Cog):
else:
log.trace("Deletion was confirmed")
+ log.trace("Deleting discord links webhook message.")
+ webhook_msg_id = await self.message_link_embeds_cache.get(incident.id)
+ webhook = await self.bot.fetch_webhook(Webhooks.incidents)
+ await webhook.delete_message(webhook_msg_id)
+ log.trace("Successfully deleted discord links webhook message.")
+
async def resolve_message(self, message_id: int) -> t.Optional[discord.Message]:
"""
Get `discord.Message` for `message_id` from cache, or API.
@@ -421,6 +463,29 @@ class Incidents(Cog):
async def on_message(self, message: discord.Message) -> None:
"""Pass `message` to `add_signals` if and only if it satisfies `is_incident`."""
if is_incident(message):
+ message_links = DISCORD_MESSAGE_LINK_RE.findall(message.content)
+ if message_links:
+
+ embeds = []
+ for message_link in message_links:
+ embeds.append(
+ await make_message_link_embed(message, message_link)
+ )
+
+ try:
+ webhook = await self.bot.fetch_webhook(Webhooks.incidents)
+ webhook_msg = await webhook.send(
+ embeds=embeds,
+ username=sub_clyde(message.author.name),
+ avatar_url=message.author.avatar_url,
+ wait=True
+ )
+ except Exception:
+ log.exception(f"Failed to send message link embeds {message.id} to #incidents")
+ else:
+ log.trace("Message Link Embeds Sent successfully!")
+ await self.message_link_embeds_cache.set(message.id, webhook_msg.id)
+
await add_signals(message)