diff options
| -rw-r--r-- | bot/cogs/moderation/incidents.py | 24 | ||||
| -rw-r--r-- | tests/bot/cogs/moderation/test_incidents.py | 29 | 
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):      """ | 
