aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/cogs/moderation/incidents.py24
-rw-r--r--tests/bot/cogs/moderation/test_incidents.py29
2 files changed, 53 insertions, 0 deletions
diff --git a/bot/cogs/moderation/incidents.py b/bot/cogs/moderation/incidents.py
index 040f2c0c8..2cce9b6fe 100644
--- a/bot/cogs/moderation/incidents.py
+++ b/bot/cogs/moderation/incidents.py
@@ -41,6 +41,30 @@ ALLOWED_ROLES: t.Set[int] = {Roles.moderators, Roles.admins, Roles.owners}
ALL_SIGNALS: t.Set[str] = {signal.value for signal in Signal}
+def make_username(reported_by: discord.Member, actioned_by: discord.Member, max_length: int = 80) -> str:
+ """
+ Create a webhook-friendly username from the names of `reported_by` and `actioned_by`.
+
+ If the resulting username length exceeds `max_length`, it will be capped at `max_length - 3`
+ and have 3 dots appended to the end. The default value is 80, which corresponds to the limit
+ Discord imposes on webhook username length.
+
+ If the value of `max_length` is < 3, ValueError is raised.
+ """
+ if max_length < 3:
+ raise ValueError(f"Maximum length cannot be less than 3: {max_length=}")
+
+ username = f"{reported_by.name} | {actioned_by.name}"
+ log.trace(f"Generated webhook username: {username} (length: {len(username)})")
+
+ if len(username) > max_length:
+ stop = max_length - 3
+ username = f"{username[:stop]}..."
+ log.trace(f"Username capped at {max_length=}: {username}")
+
+ return username
+
+
def is_incident(message: discord.Message) -> bool:
"""True if `message` qualifies as an incident, False otherwise."""
conditions = (
diff --git a/tests/bot/cogs/moderation/test_incidents.py b/tests/bot/cogs/moderation/test_incidents.py
index 2fc9180cf..5700a5a35 100644
--- a/tests/bot/cogs/moderation/test_incidents.py
+++ b/tests/bot/cogs/moderation/test_incidents.py
@@ -68,6 +68,35 @@ mock_404 = discord.NotFound(
)
+class TestMakeUsername(unittest.TestCase):
+ """Collection of tests for the `make_username` helper function."""
+
+ def test_make_username_raises(self):
+ """Raises `ValueError` on `max_length` < 3."""
+ with self.assertRaises(ValueError):
+ incidents.make_username(MockMember(), MockMember(), max_length=2)
+
+ def test_make_username_never_exceed_limit(self):
+ """
+ The return string length is always less than or equal to `max_length`.
+
+ For this test we pass `max_length=10` for convenience. The name of the first
+ user (`reported_by`) is always 1 character in length, but we generate names
+ for the `actioned_by` user starting at length 1 and up to length 20.
+
+ Finally, we assert that the output length never exceeded 10 in total.
+ """
+ user_a = MockMember(name="A")
+
+ max_length = 10
+ test_cases = (MockMember(name="B" * n) for n in range(1, 20))
+
+ for user_b in test_cases:
+ with self.subTest(user_a=user_a, user_b=user_b, max_length=max_length):
+ generated_username = incidents.make_username(user_a, user_b, max_length)
+ self.assertLessEqual(len(generated_username), max_length)
+
+
@patch("bot.constants.Channels.incidents", 123)
class TestIsIncident(unittest.TestCase):
"""