async def test_message_with_illegal_attachment_logs(self): """Deleting a message with an illegal attachment should result in a log.""" attachment = MockAttachment(filename="python.disallowed") self.message.attachments = [attachment] with self.assertLogs(logger=antimalware.log, level="INFO"): await self.cog.on_message(self.message)
async def test_txt_file_redirect_embed_description(self): """A message containing a .txt/.json/.csv file should result in the correct embed.""" test_values = ( ("text", ".txt"), ("json", ".json"), ("csv", ".csv"), ) for file_name, disallowed_extension in test_values: with self.subTest(file_name=file_name, disallowed_extension=disallowed_extension): attachment = MockAttachment(filename=f"{file_name}{disallowed_extension}") self.message.attachments = [attachment] self.message.channel.send = AsyncMock() antimalware.TXT_EMBED_DESCRIPTION = Mock() antimalware.TXT_EMBED_DESCRIPTION.format.return_value = "test" await self.cog.on_message(self.message) self.message.channel.send.assert_called_once() args, kwargs = self.message.channel.send.call_args embed = kwargs.pop("embed") cmd_channel = self.bot.get_channel(Channels.bot_commands) self.assertEqual( embed.description, antimalware.TXT_EMBED_DESCRIPTION.format.return_value ) antimalware.TXT_EMBED_DESCRIPTION.format.assert_called_with( blocked_extension=disallowed_extension, cmd_channel_mention=cmd_channel.mention )
async def test_message_with_allowed_attachment(self): """Messages with allowed extensions should not be deleted""" attachment = MockAttachment(filename="python.first") self.message.attachments = [attachment] await self.cog.on_message(self.message) self.message.delete.assert_not_called()
async def test_download_file_success(self): """If `to_file` succeeds, function returns the acquired `discord.File`.""" file = MagicMock(discord.File, filename="bigbadlemon.jpg") attachment = MockAttachment(to_file=AsyncMock(return_value=file)) acquired_file = await incidents.download_file(attachment) self.assertIs(file, acquired_file)
async def test_message_with_allowed_attachment(self): """Messages with allowed extensions should not be deleted""" attachment = MockAttachment(filename=f"python{AntiMalwareConfig.whitelist[0]}") self.message.attachments = [attachment] await self.cog.on_message(self.message) self.message.delete.assert_not_called()
async def test_message_with_illegal_extension_gets_deleted(self): """A message containing an illegal extension should send an embed.""" attachment = MockAttachment(filename="python.disallowed") self.message.attachments = [attachment] await self.cog.on_message(self.message) self.message.delete.assert_called_once()
async def test_direct_message_with_attachment(self): """Direct messages should have no action taken.""" attachment = MockAttachment(filename="python.disallowed") self.message.attachments = [attachment] self.message.guild = None await self.cog.on_message(self.message) self.message.delete.assert_not_called()
async def test_bot_message_with_illegal_extension(self): """A bot message containing an illegal extension should be ignored.""" attachment = MockAttachment(filename="python.disallowed") self.message.author.bot = 409107086526644234 self.message.attachments = [attachment] await self.cog.on_message(self.message) self.message.delete.assert_not_called()
async def test_webhook_message_with_illegal_extension(self): """A webhook message containing an illegal extension should be ignored.""" attachment = MockAttachment(filename="python.disallowed") self.message.webhook_id = 697140105563078727 self.message.attachments = [attachment] await self.cog.on_message(self.message) self.message.delete.assert_not_called()
async def test_removing_deleted_message_logs(self): """Removing an already deleted message logs the correct message""" attachment = MockAttachment(filename="python.disallowed") self.message.attachments = [attachment] self.message.delete = AsyncMock(side_effect=NotFound(response=Mock(status=""), message="")) with self.assertLogs(logger=antimalware.log, level="INFO"): await self.cog.on_message(self.message) self.message.delete.assert_called_once()
async def test_message_send_by_staff(self): """A message send by a member of staff should be ignored.""" staff_role = MockRole(id=STAFF_ROLES[0]) self.message.author.roles.append(staff_role) attachment = MockAttachment(filename="python.disallowed") self.message.attachments = [attachment] await self.cog.on_message(self.message) self.message.delete.assert_not_called()
async def test_download_file_fail(self): """If `to_file` fails on a non-404 error, function logs the exception & returns None.""" arbitrary_error = discord.HTTPException( MagicMock(aiohttp.ClientResponse), "Arbitrary API error") attachment = MockAttachment(to_file=AsyncMock( side_effect=arbitrary_error)) with self.assertLogs(logger=incidents.log, level=logging.ERROR): acquired_file = await incidents.download_file(attachment) self.assertIsNone(acquired_file)
async def test_python_file_redirect_embed_description(self): """A message containing a .py file should result in an embed redirecting the user to our paste site""" attachment = MockAttachment(filename="python.py") self.message.attachments = [attachment] self.message.channel.send = AsyncMock() await self.cog.on_message(self.message) self.message.channel.send.assert_called_once() args, kwargs = self.message.channel.send.call_args embed = kwargs.pop("embed") self.assertEqual(embed.description, antimalware.PY_EMBED_DESCRIPTION)
async def test_make_embed_with_attachment_succeeds(self): """Incident's attachment is downloaded and displayed in the embed's image field.""" file = MagicMock(discord.File, filename="bigbadjoe.jpg") attachment = MockAttachment(filename="bigbadjoe.jpg") incident = MockMessage(content="this is an incident", attachments=[attachment]) # Patch `download_file` to return our `file` with patch("bot.exts.moderation.incidents.download_file", AsyncMock(return_value=file)): embed, returned_file = await incidents.make_embed( incident, incidents.Signal.ACTIONED, MockMember()) self.assertIs(file, returned_file) self.assertEqual("attachment://bigbadjoe.jpg", embed.image.url)
async def test_txt_file_redirect_embed_description(self): """A message containing a .txt file should result in the correct embed.""" attachment = MockAttachment(filename="python.txt") self.message.attachments = [attachment] self.message.channel.send = AsyncMock() antimalware.TXT_EMBED_DESCRIPTION = Mock() antimalware.TXT_EMBED_DESCRIPTION.format.return_value = "test" await self.cog.on_message(self.message) self.message.channel.send.assert_called_once() args, kwargs = self.message.channel.send.call_args embed = kwargs.pop("embed") cmd_channel = self.bot.get_channel(Channels.bot_commands) self.assertEqual(embed.description, antimalware.TXT_EMBED_DESCRIPTION.format.return_value) antimalware.TXT_EMBED_DESCRIPTION.format.assert_called_with(cmd_channel_mention=cmd_channel.mention)
async def test_get_disallowed_extensions(self): """The return value should include all non-whitelisted extensions.""" test_values = ( ([], []), (AntiMalwareConfig.whitelist, []), ([".first"], []), ([".first", ".disallowed"], [".disallowed"]), ([".disallowed"], [".disallowed"]), ([".disallowed", ".illegal"], [".disallowed", ".illegal"]), ) for extensions, expected_disallowed_extensions in test_values: with self.subTest(extensions=extensions, expected_disallowed_extensions=expected_disallowed_extensions): self.message.attachments = [MockAttachment(filename=f"filename{extension}") for extension in extensions] disallowed_extensions = self.cog.get_disallowed_extensions(self.message) self.assertCountEqual(disallowed_extensions, expected_disallowed_extensions)
async def test_make_embed_with_attachment_fails(self): """Incident's attachment fails to download, proxy url is linked instead.""" attachment = MockAttachment(proxy_url="discord.com/bigbadjoe.jpg") incident = MockMessage(content="this is an incident", attachments=[attachment]) # Patch `download_file` to return None as if the download failed with patch("bot.exts.moderation.incidents.download_file", AsyncMock(return_value=None)): embed, returned_file = await incidents.make_embed( incident, incidents.Signal.ACTIONED, MockMember()) self.assertIsNone(returned_file) # The author name field is simply expected to have something in it, we do not assert the message self.assertGreater(len(embed.author.name), 0) self.assertEqual(embed.author.url, "discord.com/bigbadjoe.jpg" ) # However, it should link the exact url
async def test_other_disallowed_extention_embed_description(self): """Test the description for a non .py/.txt disallowed extension.""" attachment = MockAttachment(filename="python.disallowed") self.message.attachments = [attachment] self.message.channel.send = AsyncMock() antimalware.DISALLOWED_EMBED_DESCRIPTION = Mock() antimalware.DISALLOWED_EMBED_DESCRIPTION.format.return_value = "test" await self.cog.on_message(self.message) self.message.channel.send.assert_called_once() args, kwargs = self.message.channel.send.call_args embed = kwargs.pop("embed") meta_channel = self.bot.get_channel(Channels.meta) self.assertEqual(embed.description, antimalware.DISALLOWED_EMBED_DESCRIPTION.format.return_value) antimalware.DISALLOWED_EMBED_DESCRIPTION.format.assert_called_with( blocked_extensions_str=".disallowed", meta_channel_mention=meta_channel.mention )
async def test_result_sending(self, create_leader_channel, create_team_channel): """Should call `ctx.send` when everything goes right.""" self.ctx.message.attachments = [MockAttachment()] self.ctx.message.attachments[0].read = AsyncMock() self.ctx.message.attachments[0].read.return_value = TEST_CSV team_leaders = MockRole() self.guild.get_member.return_value = MockMember() self.ctx.guild.create_role = AsyncMock() self.ctx.guild.create_role.return_value = team_leaders self.cog.add_roles = AsyncMock() await self.cog.create(self.cog, self.ctx, None) create_team_channel.assert_awaited() create_leader_channel.assert_awaited_once_with( self.ctx.guild, team_leaders ) self.ctx.send.assert_awaited_once()
async def test_download_file_404(self): """If `to_file` encounters a 404, function handles the exception & returns None.""" attachment = MockAttachment(to_file=AsyncMock(side_effect=mock_404)) acquired_file = await incidents.download_file(attachment) self.assertIsNone(acquired_file)