aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/exts/moderation/incidents.py23
-rw-r--r--tests/bot/exts/moderation/test_incidents.py23
2 files changed, 34 insertions, 12 deletions
diff --git a/bot/exts/moderation/incidents.py b/bot/exts/moderation/incidents.py
index 155b123ca..1ddbe9857 100644
--- a/bot/exts/moderation/incidents.py
+++ b/bot/exts/moderation/incidents.py
@@ -1,6 +1,6 @@
import asyncio
import re
-from datetime import datetime
+from datetime import datetime, timezone
from enum import Enum
from typing import Optional
@@ -13,6 +13,7 @@ from bot.bot import Bot
from bot.constants import Channels, Colours, Emojis, Guild, Roles, Webhooks
from bot.log import get_logger
from bot.utils.messages import format_user, sub_clyde
+from bot.utils.time import TimestampFormats, discord_timestamp
log = get_logger(__name__)
@@ -25,9 +26,9 @@ CRAWL_LIMIT = 50
CRAWL_SLEEP = 2
DISCORD_MESSAGE_LINK_RE = re.compile(
- r"(https?:\/\/(?:(ptb|canary|www)\.)?discord(?:app)?\.com\/channels\/"
+ r"(https?://(?:(ptb|canary|www)\.)?discord(?:app)?\.com/channels/"
r"[0-9]{15,20}"
- r"\/[0-9]{15,20}\/[0-9]{15,20})"
+ r"/[0-9]{15,20}/[0-9]{15,20})"
)
@@ -97,10 +98,20 @@ async def make_embed(incident: discord.Message, outcome: Signal, actioned_by: di
colour = Colours.soft_red
footer = f"Rejected by {actioned_by}"
+ reported_timestamp = discord_timestamp(incident.created_at)
+ relative_timestamp = discord_timestamp(incident.created_at, TimestampFormats.RELATIVE)
+ reported_on_msg = f"*Reported {reported_timestamp} ({relative_timestamp}).*"
+
+ # If the description will be too long (>4096 total characters), truncate the incident content
+ if len(incident.content) > (allowed_content_chars := 4096-len(reported_on_msg)-2): # -2 for the newlines
+ description = incident.content[:allowed_content_chars-3] + f"...\n\n{reported_on_msg}"
+ else:
+ description = incident.content + f"\n\n{reported_on_msg}"
+
embed = discord.Embed(
- description=incident.content,
- timestamp=datetime.utcnow(),
+ description=description,
colour=colour,
+ timestamp=datetime.now(timezone.utc)
)
embed.set_footer(text=footer, icon_url=actioned_by.display_avatar.url)
@@ -381,7 +392,7 @@ class Incidents(Cog):
webhook = await self.bot.fetch_webhook(Webhooks.incidents_archive)
await webhook.send(
embed=embed,
- username=sub_clyde(incident.author.name),
+ username=sub_clyde(incident.author.display_name),
avatar_url=incident.author.display_avatar.url,
file=attachment_file,
)
diff --git a/tests/bot/exts/moderation/test_incidents.py b/tests/bot/exts/moderation/test_incidents.py
index 97682163f..11fe565fc 100644
--- a/tests/bot/exts/moderation/test_incidents.py
+++ b/tests/bot/exts/moderation/test_incidents.py
@@ -1,4 +1,5 @@
import asyncio
+import datetime
import enum
import logging
import typing as t
@@ -12,6 +13,7 @@ import discord
from bot.constants import Colours
from bot.exts.moderation import incidents
from bot.utils.messages import format_user
+from bot.utils.time import TimestampFormats, discord_timestamp
from tests.base import RedisTestCase
from tests.helpers import (
MockAsyncWebhook, MockAttachment, MockBot, MockMember, MockMessage, MockReaction, MockRole, MockTextChannel,
@@ -114,10 +116,18 @@ class TestMakeEmbed(unittest.IsolatedAsyncioTestCase):
async def test_make_embed_content(self):
"""Incident content appears as embed description."""
- incident = MockMessage(content="this is an incident")
+ current_time = datetime.datetime(2022, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
+ incident = MockMessage(content="this is an incident", created_at=current_time)
+
+ reported_timestamp = discord_timestamp(current_time)
+ relative_timestamp = discord_timestamp(current_time, TimestampFormats.RELATIVE)
+
embed, file = await incidents.make_embed(incident, incidents.Signal.ACTIONED, MockMember())
- self.assertEqual(incident.content, embed.description)
+ self.assertEqual(
+ f"{incident.content}\n\n*Reported {reported_timestamp} ({relative_timestamp}).*",
+ embed.description
+ )
async def test_make_embed_with_attachment_succeeds(self):
"""Incident's attachment is downloaded and displayed in the embed's image field."""
@@ -375,7 +385,7 @@ class TestArchive(TestIncidents):
# Define our own `incident` to be archived
incident = MockMessage(
content="this is an incident",
- author=MockUser(name="author_name", display_avatar=Mock(url="author_avatar")),
+ author=MockUser(display_name="author_name", display_avatar=Mock(url="author_avatar")),
id=123,
)
built_embed = MagicMock(discord.Embed, id=123) # We patch `make_embed` to return this
@@ -406,7 +416,7 @@ class TestArchive(TestIncidents):
webhook = MockAsyncWebhook()
self.cog_instance.bot.fetch_webhook = AsyncMock(return_value=webhook)
- message_from_clyde = MockMessage(author=MockUser(name="clyde the great"))
+ message_from_clyde = MockMessage(author=MockUser(display_name="clyde the great"))
await self.cog_instance.archive(message_from_clyde, MagicMock(incidents.Signal), MockMember())
self.assertNotIn("clyde", webhook.send.call_args.kwargs["username"])
@@ -505,12 +515,13 @@ class TestProcessEvent(TestIncidents):
async def test_process_event_confirmation_task_is_awaited(self):
"""Task given by `Incidents.make_confirmation_task` is awaited before method exits."""
mock_task = AsyncMock()
+ mock_member = MockMember(display_name="Bobby Johnson", roles=[MockRole(id=1)])
with patch("bot.exts.moderation.incidents.Incidents.make_confirmation_task", mock_task):
await self.cog_instance.process_event(
reaction=incidents.Signal.ACTIONED.value,
- incident=MockMessage(id=123),
- member=MockMember(roles=[MockRole(id=1)])
+ incident=MockMessage(author=mock_member, id=123),
+ member=mock_member
)
mock_task.assert_awaited()