diff options
Diffstat (limited to '')
| -rw-r--r-- | bot/exts/moderation/infraction/_utils.py | 2 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/infractions.py | 87 | ||||
| -rw-r--r-- | bot/exts/moderation/voice_gate.py | 4 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/infraction/test_infractions.py | 86 | 
4 files changed, 104 insertions, 75 deletions
| diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py index e683c9db4..4df833ffb 100644 --- a/bot/exts/moderation/infraction/_utils.py +++ b/bot/exts/moderation/infraction/_utils.py @@ -21,7 +21,7 @@ INFRACTION_ICONS = {      "note": (Icons.user_warn, None),      "superstar": (Icons.superstarify, Icons.unsuperstarify),      "warning": (Icons.user_warn, None), -    "voice_ban": (Icons.voice_state_red, Icons.voice_state_green), +    "voice_mute": (Icons.voice_state_red, Icons.voice_state_green),  }  RULES_URL = "https://pythondiscord.com/pages/rules" diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index e495a94b3..7c0259b8e 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -27,7 +27,7 @@ class Infractions(InfractionScheduler, commands.Cog):      category_description = "Server moderation tools."      def __init__(self, bot: Bot): -        super().__init__(bot, supported_infractions={"ban", "kick", "mute", "note", "warning", "voice_ban"}) +        super().__init__(bot, supported_infractions={"ban", "kick", "mute", "note", "warning", "voice_mute"})          self.category = "Moderation"          self._muted_role = discord.Object(constants.Roles.muted) @@ -107,8 +107,19 @@ class Infractions(InfractionScheduler, commands.Cog):          """          await self.apply_ban(ctx, user, reason, 1, expires_at=duration) -    @command(aliases=('vban',)) -    async def voiceban( +    @command(aliases=("vban",)) +    async def voiceban(self, ctx: Context) -> None: +        """ +        NOT IMPLEMENTED. + +        Permanently ban a user from joining voice channels. + +        If duration is specified, it temporarily voice bans that user for the given duration. +        """ +        await ctx.send(":x: This command is not yet implemented. Maybe you meant to use `voicemute`?") + +    @command(aliases=("vmute",)) +    async def voicemute(          self,          ctx: Context,          user: UnambiguousMemberOrUser, @@ -117,11 +128,11 @@ class Infractions(InfractionScheduler, commands.Cog):          reason: t.Optional[str]      ) -> None:          """ -        Permanently ban user from using voice channels. +        Permanently mute user in voice channels. -        If duration is specified, it temporarily voice bans that user for the given duration. +        If duration is specified, it temporarily voice mutes that user for the given duration.          """ -        await self.apply_voice_ban(ctx, user, reason, expires_at=duration) +        await self.apply_voice_mute(ctx, user, reason, expires_at=duration)      # endregion      # region: Temporary infractions @@ -186,16 +197,25 @@ class Infractions(InfractionScheduler, commands.Cog):          await self.apply_ban(ctx, user, reason, expires_at=duration)      @command(aliases=("tempvban", "tvban")) -    async def tempvoiceban( -            self, -            ctx: Context, -            user: UnambiguousMemberOrUser, -            duration: Expiry, -            *, -            reason: t.Optional[str] +    async def tempvoiceban(self, ctx: Context) -> None: +        """ +        NOT IMPLEMENTED. + +        Temporarily voice bans that user for the given duration. +        """ +        await ctx.send(":x: This command is not yet implemented. Maybe you meant to use `tempvoicemute`?") + +    @command(aliases=("tempvmute", "tvmute")) +    async def tempvoicemute( +        self, +        ctx: Context, +        user: UnambiguousMemberOrUser, +        duration: Expiry, +        *, +        reason: t.Optional[str]      ) -> None:          """ -        Temporarily voice ban a user for the given reason and duration. +        Temporarily voice mute a user for the given reason and duration.          A unit of time should be appended to the duration.          Units (∗case-sensitive): @@ -209,7 +229,7 @@ class Infractions(InfractionScheduler, commands.Cog):          Alternatively, an ISO 8601 timestamp can be provided for the duration.          """ -        await self.apply_voice_ban(ctx, user, reason, expires_at=duration) +        await self.apply_voice_mute(ctx, user, reason, expires_at=duration)      # endregion      # region: Permanent shadow infractions @@ -271,9 +291,18 @@ class Infractions(InfractionScheduler, commands.Cog):          await self.pardon_infraction(ctx, "ban", user)      @command(aliases=("uvban",)) -    async def unvoiceban(self, ctx: Context, user: UnambiguousMemberOrUser) -> None: -        """Prematurely end the active voice ban infraction for the user.""" -        await self.pardon_infraction(ctx, "voice_ban", user) +    async def unvoiceban(self, ctx: Context) -> None: +        """ +        NOT IMPLEMENTED. + +        Temporarily voice bans that user for the given duration. +        """ +        await ctx.send(":x: This command is not yet implemented. Maybe you meant to use `unvoicemute`?") + +    @command(aliases=("uvmute",)) +    async def unvoicemute(self, ctx: Context, user: UnambiguousMemberOrUser) -> None: +        """Prematurely end the active voice mute infraction for the user.""" +        await self.pardon_infraction(ctx, "voice_mute", user)      # endregion      # region: Base apply functions @@ -395,12 +424,12 @@ class Infractions(InfractionScheduler, commands.Cog):          await bb_cog.apply_unwatch(ctx, user, bb_reason, send_message=False)      @respect_role_hierarchy(member_arg=2) -    async def apply_voice_ban(self, ctx: Context, user: MemberOrUser, reason: t.Optional[str], **kwargs) -> None: -        """Apply a voice ban infraction with kwargs passed to `post_infraction`.""" -        if await _utils.get_active_infraction(ctx, user, "voice_ban"): +    async def apply_voice_mute(self, ctx: Context, user: MemberOrUser, reason: t.Optional[str], **kwargs) -> None: +        """Apply a voice mute infraction with kwargs passed to `post_infraction`.""" +        if await _utils.get_active_infraction(ctx, user, "voice_mute"):              return -        infraction = await _utils.post_infraction(ctx, user, "voice_ban", reason, active=True, **kwargs) +        infraction = await _utils.post_infraction(ctx, user, "voice_mute", reason, active=True, **kwargs)          if infraction is None:              return @@ -414,7 +443,7 @@ class Infractions(InfractionScheduler, commands.Cog):              if not isinstance(user, Member):                  return -            await user.move_to(None, reason="Disconnected from voice to apply voiceban.") +            await user.move_to(None, reason="Disconnected from voice to apply voice mute.")              await user.remove_roles(self._voice_verified_role, reason=reason)          await self.apply_infraction(ctx, infraction, user, action()) @@ -471,7 +500,7 @@ class Infractions(InfractionScheduler, commands.Cog):          return log_text -    async def pardon_voice_ban( +    async def pardon_voice_mute(          self,          user_id: int,          guild: discord.Guild, @@ -487,9 +516,9 @@ class Infractions(InfractionScheduler, commands.Cog):                  # DM user about infraction expiration                  notified = await _utils.notify_pardon(                      user=user, -                    title="Voice ban ended", -                    content="You have been unbanned and can verify yourself again in the server.", -                    icon_url=_utils.INFRACTION_ICONS["voice_ban"][1] +                    title="Voice mute ended", +                    content="You have been unmuted and can verify yourself again in the server.", +                    icon_url=_utils.INFRACTION_ICONS["voice_mute"][1]                  )                  log_text["DM"] = "Sent" if notified else "**Failed**" @@ -514,8 +543,8 @@ class Infractions(InfractionScheduler, commands.Cog):              return await self.pardon_mute(user_id, guild, reason, notify=notify)          elif infraction["type"] == "ban":              return await self.pardon_ban(user_id, guild, reason) -        elif infraction["type"] == "voice_ban": -            return await self.pardon_voice_ban(user_id, guild, notify=notify) +        elif infraction["type"] == "voice_mute": +            return await self.pardon_voice_mute(user_id, guild, notify=notify)      # endregion diff --git a/bot/exts/moderation/voice_gate.py b/bot/exts/moderation/voice_gate.py index a382b13d1..42505b8e7 100644 --- a/bot/exts/moderation/voice_gate.py +++ b/bot/exts/moderation/voice_gate.py @@ -30,7 +30,7 @@ FAILED_MESSAGE = (  MESSAGE_FIELD_MAP = {      "joined_at": f"have been on the server for less than {GateConf.minimum_days_member} days", -    "voice_banned": "have an active voice ban infraction", +    "voice_muted": "have an active voice mute infraction",      "total_messages": f"have sent less than {GateConf.minimum_messages} messages",      "activity_blocks": f"have been active for fewer than {GateConf.minimum_activity_blocks} ten-minute blocks",  } @@ -170,7 +170,7 @@ class VoiceGate(Cog):                  ctx.author.joined_at > arrow.utcnow() - timedelta(days=GateConf.minimum_days_member)              ),              "total_messages": data["total_messages"] < GateConf.minimum_messages, -            "voice_banned": data["voice_banned"], +            "voice_muted": data["voice_muted"],              "activity_blocks": data["activity_blocks"] < GateConf.minimum_activity_blocks,          } diff --git a/tests/bot/exts/moderation/infraction/test_infractions.py b/tests/bot/exts/moderation/infraction/test_infractions.py index 4d01e18a5..f89465f84 100644 --- a/tests/bot/exts/moderation/infraction/test_infractions.py +++ b/tests/bot/exts/moderation/infraction/test_infractions.py @@ -62,8 +62,8 @@ class TruncationTests(unittest.IsolatedAsyncioTestCase):  @patch("bot.exts.moderation.infraction.infractions.constants.Roles.voice_verified", new=123456) -class VoiceBanTests(unittest.IsolatedAsyncioTestCase): -    """Tests for voice ban related functions and commands.""" +class VoiceMuteTests(unittest.IsolatedAsyncioTestCase): +    """Tests for voice mute related functions and commands."""      def setUp(self):          self.bot = MockBot() @@ -73,59 +73,59 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):          self.ctx = MockContext(bot=self.bot, author=self.mod)          self.cog = Infractions(self.bot) -    async def test_permanent_voice_ban(self): -        """Should call voice ban applying function without expiry.""" -        self.cog.apply_voice_ban = AsyncMock() -        self.assertIsNone(await self.cog.voiceban(self.cog, self.ctx, self.user, reason="foobar")) -        self.cog.apply_voice_ban.assert_awaited_once_with(self.ctx, self.user, "foobar", expires_at=None) +    async def test_permanent_voice_mute(self): +        """Should call voice mute applying function without expiry.""" +        self.cog.apply_voice_mute = AsyncMock() +        self.assertIsNone(await self.cog.voicemute(self.cog, self.ctx, self.user, reason="foobar")) +        self.cog.apply_voice_mute.assert_awaited_once_with(self.ctx, self.user, "foobar", expires_at=None) -    async def test_temporary_voice_ban(self): -        """Should call voice ban applying function with expiry.""" -        self.cog.apply_voice_ban = AsyncMock() -        self.assertIsNone(await self.cog.tempvoiceban(self.cog, self.ctx, self.user, "baz", reason="foobar")) -        self.cog.apply_voice_ban.assert_awaited_once_with(self.ctx, self.user, "foobar", expires_at="baz") +    async def test_temporary_voice_mute(self): +        """Should call voice mute applying function with expiry.""" +        self.cog.apply_voice_mute = AsyncMock() +        self.assertIsNone(await self.cog.tempvoicemute(self.cog, self.ctx, self.user, "baz", reason="foobar")) +        self.cog.apply_voice_mute.assert_awaited_once_with(self.ctx, self.user, "foobar", expires_at="baz") -    async def test_voice_unban(self): +    async def test_voice_unmute(self):          """Should call infraction pardoning function."""          self.cog.pardon_infraction = AsyncMock() -        self.assertIsNone(await self.cog.unvoiceban(self.cog, self.ctx, self.user)) -        self.cog.pardon_infraction.assert_awaited_once_with(self.ctx, "voice_ban", self.user) +        self.assertIsNone(await self.cog.unvoicemute(self.cog, self.ctx, self.user)) +        self.cog.pardon_infraction.assert_awaited_once_with(self.ctx, "voice_mute", self.user)      @patch("bot.exts.moderation.infraction.infractions._utils.post_infraction")      @patch("bot.exts.moderation.infraction.infractions._utils.get_active_infraction") -    async def test_voice_ban_user_have_active_infraction(self, get_active_infraction, post_infraction_mock): -        """Should return early when user already have Voice Ban infraction.""" +    async def test_voice_mute_user_have_active_infraction(self, get_active_infraction, post_infraction_mock): +        """Should return early when user already have Voice Mute infraction."""          get_active_infraction.return_value = {"foo": "bar"} -        self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, "foobar")) -        get_active_infraction.assert_awaited_once_with(self.ctx, self.user, "voice_ban") +        self.assertIsNone(await self.cog.apply_voice_mute(self.ctx, self.user, "foobar")) +        get_active_infraction.assert_awaited_once_with(self.ctx, self.user, "voice_mute")          post_infraction_mock.assert_not_awaited()      @patch("bot.exts.moderation.infraction.infractions._utils.post_infraction")      @patch("bot.exts.moderation.infraction.infractions._utils.get_active_infraction") -    async def test_voice_ban_infraction_post_failed(self, get_active_infraction, post_infraction_mock): +    async def test_voice_mute_infraction_post_failed(self, get_active_infraction, post_infraction_mock):          """Should return early when posting infraction fails."""          self.cog.mod_log.ignore = MagicMock()          get_active_infraction.return_value = None          post_infraction_mock.return_value = None -        self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, "foobar")) +        self.assertIsNone(await self.cog.apply_voice_mute(self.ctx, self.user, "foobar"))          post_infraction_mock.assert_awaited_once()          self.cog.mod_log.ignore.assert_not_called()      @patch("bot.exts.moderation.infraction.infractions._utils.post_infraction")      @patch("bot.exts.moderation.infraction.infractions._utils.get_active_infraction") -    async def test_voice_ban_infraction_post_add_kwargs(self, get_active_infraction, post_infraction_mock): -        """Should pass all kwargs passed to apply_voice_ban to post_infraction.""" +    async def test_voice_mute_infraction_post_add_kwargs(self, get_active_infraction, post_infraction_mock): +        """Should pass all kwargs passed to apply_voice_mute to post_infraction."""          get_active_infraction.return_value = None          # We don't want that this continue yet          post_infraction_mock.return_value = None -        self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, "foobar", my_kwarg=23)) +        self.assertIsNone(await self.cog.apply_voice_mute(self.ctx, self.user, "foobar", my_kwarg=23))          post_infraction_mock.assert_awaited_once_with( -            self.ctx, self.user, "voice_ban", "foobar", active=True, my_kwarg=23 +            self.ctx, self.user, "voice_mute", "foobar", active=True, my_kwarg=23          )      @patch("bot.exts.moderation.infraction.infractions._utils.post_infraction")      @patch("bot.exts.moderation.infraction.infractions._utils.get_active_infraction") -    async def test_voice_ban_mod_log_ignore(self, get_active_infraction, post_infraction_mock): +    async def test_voice_mute_mod_log_ignore(self, get_active_infraction, post_infraction_mock):          """Should ignore Voice Verified role removing."""          self.cog.mod_log.ignore = MagicMock()          self.cog.apply_infraction = AsyncMock() @@ -134,11 +134,11 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):          get_active_infraction.return_value = None          post_infraction_mock.return_value = {"foo": "bar"} -        self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, "foobar")) +        self.assertIsNone(await self.cog.apply_voice_mute(self.ctx, self.user, "foobar"))          self.cog.mod_log.ignore.assert_called_once_with(Event.member_update, self.user.id)      async def action_tester(self, action, reason: str) -> None: -        """Helper method to test voice ban action.""" +        """Helper method to test voice mute action."""          self.assertTrue(inspect.iscoroutine(action))          await action @@ -147,7 +147,7 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):      @patch("bot.exts.moderation.infraction.infractions._utils.post_infraction")      @patch("bot.exts.moderation.infraction.infractions._utils.get_active_infraction") -    async def test_voice_ban_apply_infraction(self, get_active_infraction, post_infraction_mock): +    async def test_voice_mute_apply_infraction(self, get_active_infraction, post_infraction_mock):          """Should ignore Voice Verified role removing."""          self.cog.mod_log.ignore = MagicMock()          self.cog.apply_infraction = AsyncMock() @@ -156,22 +156,22 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):          post_infraction_mock.return_value = {"foo": "bar"}          reason = "foobar" -        self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, reason)) +        self.assertIsNone(await self.cog.apply_voice_mute(self.ctx, self.user, reason))          self.cog.apply_infraction.assert_awaited_once_with(self.ctx, {"foo": "bar"}, self.user, ANY)          await self.action_tester(self.cog.apply_infraction.call_args[0][-1], reason)      @patch("bot.exts.moderation.infraction.infractions._utils.post_infraction")      @patch("bot.exts.moderation.infraction.infractions._utils.get_active_infraction") -    async def test_voice_ban_truncate_reason(self, get_active_infraction, post_infraction_mock): -        """Should truncate reason for voice ban.""" +    async def test_voice_mute_truncate_reason(self, get_active_infraction, post_infraction_mock): +        """Should truncate reason for voice mute."""          self.cog.mod_log.ignore = MagicMock()          self.cog.apply_infraction = AsyncMock()          get_active_infraction.return_value = None          post_infraction_mock.return_value = {"foo": "bar"} -        self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, "foobar" * 3000)) +        self.assertIsNone(await self.cog.apply_voice_mute(self.ctx, self.user, "foobar" * 3000))          self.cog.apply_infraction.assert_awaited_once_with(self.ctx, {"foo": "bar"}, self.user, ANY)          # Test action @@ -180,14 +180,14 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):      @autospec(_utils, "post_infraction", "get_active_infraction", return_value=None)      @autospec(Infractions, "apply_infraction") -    async def test_voice_ban_user_left_guild(self, apply_infraction_mock, post_infraction_mock, _): -        """Should voice ban user that left the guild without throwing an error.""" +    async def test_voice_mute_user_left_guild(self, apply_infraction_mock, post_infraction_mock, _): +        """Should voice mute user that left the guild without throwing an error."""          infraction = {"foo": "bar"}          post_infraction_mock.return_value = {"foo": "bar"}          user = MockUser() -        await self.cog.voiceban(self.cog, self.ctx, user, reason=None) -        post_infraction_mock.assert_called_once_with(self.ctx, user, "voice_ban", None, active=True, expires_at=None) +        await self.cog.voicemute(self.cog, self.ctx, user, reason=None) +        post_infraction_mock.assert_called_once_with(self.ctx, user, "voice_mute", None, active=True, expires_at=None)          apply_infraction_mock.assert_called_once_with(self.cog, self.ctx, infraction, user, ANY)          # Test action @@ -195,22 +195,22 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):          self.assertTrue(inspect.iscoroutine(action))          await action -    async def test_voice_unban_user_not_found(self): +    async def test_voice_unmute_user_not_found(self):          """Should include info to return dict when user was not found from guild."""          self.guild.get_member.return_value = None          self.guild.fetch_member.side_effect = NotFound(Mock(status=404), "Not found") -        result = await self.cog.pardon_voice_ban(self.user.id, self.guild) +        result = await self.cog.pardon_voice_mute(self.user.id, self.guild)          self.assertEqual(result, {"Info": "User was not found in the guild."})      @patch("bot.exts.moderation.infraction.infractions._utils.notify_pardon")      @patch("bot.exts.moderation.infraction.infractions.format_user") -    async def test_voice_unban_user_found(self, format_user_mock, notify_pardon_mock): +    async def test_voice_unmute_user_found(self, format_user_mock, notify_pardon_mock):          """Should add role back with ignoring, notify user and return log dictionary.."""          self.guild.get_member.return_value = self.user          notify_pardon_mock.return_value = True          format_user_mock.return_value = "my-user" -        result = await self.cog.pardon_voice_ban(self.user.id, self.guild) +        result = await self.cog.pardon_voice_mute(self.user.id, self.guild)          self.assertEqual(result, {              "Member": "my-user",              "DM": "Sent" @@ -219,13 +219,13 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):      @patch("bot.exts.moderation.infraction.infractions._utils.notify_pardon")      @patch("bot.exts.moderation.infraction.infractions.format_user") -    async def test_voice_unban_dm_fail(self, format_user_mock, notify_pardon_mock): +    async def test_voice_unmute_dm_fail(self, format_user_mock, notify_pardon_mock):          """Should add role back with ignoring, notify user and return log dictionary.."""          self.guild.get_member.return_value = self.user          notify_pardon_mock.return_value = False          format_user_mock.return_value = "my-user" -        result = await self.cog.pardon_voice_ban(self.user.id, self.guild) +        result = await self.cog.pardon_voice_mute(self.user.id, self.guild)          self.assertEqual(result, {              "Member": "my-user",              "DM": "**Failed**" | 
