aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/exts/moderation/infraction/_scheduler.py4
-rw-r--r--bot/exts/moderation/infraction/_utils.py19
-rw-r--r--bot/exts/moderation/infraction/management.py8
-rw-r--r--tests/bot/exts/moderation/infraction/test_utils.py26
4 files changed, 45 insertions, 12 deletions
diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py
index 762eb6afa..52dd79791 100644
--- a/bot/exts/moderation/infraction/_scheduler.py
+++ b/bot/exts/moderation/infraction/_scheduler.py
@@ -238,7 +238,9 @@ class InfractionScheduler:
dm_log_text = "\nDM: **Failed**"
# Accordingly update whether the user was successfully notified via DM.
- if await _utils.notify_infraction(user, infr_type.replace("_", " ").title(), expiry, user_reason, icon):
+ if await _utils.notify_infraction(
+ ctx.bot, user, infraction["id"], infr_type.replace("_", " ").title(), expiry, user_reason, icon
+ ):
dm_result = ":incoming_envelope: "
dm_log_text = "\nDM: Sent"
diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py
index bb3cc5380..e683c9db4 100644
--- a/bot/exts/moderation/infraction/_utils.py
+++ b/bot/exts/moderation/infraction/_utils.py
@@ -5,6 +5,7 @@ import discord
from discord.ext.commands import Context
from bot.api import ResponseCodeError
+from bot.bot import Bot
from bot.constants import Colours, Icons
from bot.converters import MemberOrUser
from bot.errors import InvalidInfractedUserError
@@ -78,7 +79,8 @@ async def post_infraction(
reason: str,
expires_at: datetime = None,
hidden: bool = False,
- active: bool = True
+ active: bool = True,
+ dm_sent: bool = False,
) -> t.Optional[dict]:
"""Posts an infraction to the API."""
if isinstance(user, (discord.Member, discord.User)) and user.bot:
@@ -93,7 +95,8 @@ async def post_infraction(
"reason": reason,
"type": infr_type,
"user": user.id,
- "active": active
+ "active": active,
+ "dm_sent": dm_sent
}
if expires_at:
payload['expires_at'] = expires_at.isoformat()
@@ -156,7 +159,9 @@ async def send_active_infraction_message(ctx: Context, infraction: Infraction) -
async def notify_infraction(
+ bot: Bot,
user: MemberOrUser,
+ infr_id: id,
infr_type: str,
expires_at: t.Optional[str] = None,
reason: t.Optional[str] = None,
@@ -186,7 +191,15 @@ async def notify_infraction(
embed.title = INFRACTION_TITLE
embed.url = RULES_URL
- return await send_private_embed(user, embed)
+ dm_sent = await send_private_embed(user, embed)
+ if dm_sent:
+ await bot.api_client.patch(
+ f"bot/infractions/{infr_id}",
+ json={"dm_sent": True}
+ )
+ log.debug(f"Update infraction #{infr_id} dm_sent field to true.")
+
+ return dm_sent
async def notify_pardon(
diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py
index a833eb227..b77c20434 100644
--- a/bot/exts/moderation/infraction/management.py
+++ b/bot/exts/moderation/infraction/management.py
@@ -352,6 +352,7 @@ class ModManagement(commands.Cog):
user = infraction["user"]
expires_at = infraction["expires_at"]
created = time.format_infraction(infraction["inserted_at"])
+ dm_sent = infraction["dm_sent"]
# Format the user string.
if user_obj := self.bot.get_user(user["id"]):
@@ -377,11 +378,18 @@ class ModManagement(commands.Cog):
date_to = dateutil.parser.isoparse(expires_at)
duration = humanize_delta(relativedelta(date_to, date_from))
+ # Format `dm_sent`
+ if dm_sent is None:
+ dm_sent_text = "N/A"
+ else:
+ dm_sent_text = "Yes" if dm_sent else "No"
+
lines = textwrap.dedent(f"""
{"**===============**" if active else "==============="}
Status: {"__**Active**__" if active else "Inactive"}
User: {user_str}
Type: **{infraction["type"]}**
+ DM Sent: {dm_sent_text}
Shadow: {infraction["hidden"]}
Created: {created}
Expires: {remaining}
diff --git a/tests/bot/exts/moderation/infraction/test_utils.py b/tests/bot/exts/moderation/infraction/test_utils.py
index 72eebb254..350274ecd 100644
--- a/tests/bot/exts/moderation/infraction/test_utils.py
+++ b/tests/bot/exts/moderation/infraction/test_utils.py
@@ -132,7 +132,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"""
test_cases = [
{
- "args": (self.user, "ban", "2020-02-26 09:20 (23 hours and 59 minutes)"),
+ "args": (self.bot, self.user, 0, "ban", "2020-02-26 09:20 (23 hours and 59 minutes)"),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
@@ -150,7 +150,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"send_result": True
},
{
- "args": (self.user, "warning", None, "Test reason."),
+ "args": (self.bot, self.user, 0, "warning", None, "Test reason."),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
@@ -170,7 +170,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
# Note that this test case asserts that the DM that *would* get sent to the user is formatted
# correctly, even though that message is deliberately never sent.
{
- "args": (self.user, "note", None, None, Icons.defcon_denied),
+ "args": (self.bot, self.user, 0, "note", None, None, Icons.defcon_denied),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
@@ -188,7 +188,15 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"send_result": False
},
{
- "args": (self.user, "mute", "2020-02-26 09:20 (23 hours and 59 minutes)", "Test", Icons.defcon_denied),
+ "args": (
+ self.bot,
+ self.user,
+ 0,
+ "mute",
+ "2020-02-26 09:20 (23 hours and 59 minutes)",
+ "Test",
+ Icons.defcon_denied
+ ),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
@@ -206,7 +214,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"send_result": False
},
{
- "args": (self.user, "mute", None, "foo bar" * 4000, Icons.defcon_denied),
+ "args": (self.bot, self.user, 0, "mute", None, "foo bar" * 4000, Icons.defcon_denied),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
@@ -238,7 +246,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
self.assertEqual(embed.to_dict(), case["expected_output"].to_dict())
- send_private_embed_mock.assert_awaited_once_with(case["args"][0], embed)
+ send_private_embed_mock.assert_awaited_once_with(case["args"][1], embed)
@patch("bot.exts.moderation.infraction._utils.send_private_embed")
async def test_notify_pardon(self, send_private_embed_mock):
@@ -313,7 +321,8 @@ class TestPostInfraction(unittest.IsolatedAsyncioTestCase):
"type": "ban",
"user": self.member.id,
"active": False,
- "expires_at": now.isoformat()
+ "expires_at": now.isoformat(),
+ "dm_sent": False
}
self.ctx.bot.api_client.post.return_value = "foo"
@@ -350,7 +359,8 @@ class TestPostInfraction(unittest.IsolatedAsyncioTestCase):
"reason": "Test reason",
"type": "mute",
"user": self.user.id,
- "active": True
+ "active": True,
+ "dm_sent": False
}
self.bot.api_client.post.side_effect = [ResponseCodeError(MagicMock(status=400), {"user": "foo"}), "foo"]