prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Antimalware cog file filter triggers on bot and webhook messages
  Currently the antimalware cog file filter triggers on messages from the bot, and also on webhook messages. So for the example somebody tries to send an attachment from python using `!int eval`, it will be caught by the filter
  ![image](https://user-images.githubusercontent.com/22353562/91752774-be76ed00-ebbe-11ea-99ac-e1147ca1d2df.png)
  Also, if somebody sends a non-whitelisted attachment to the bot, (and it isn't ignored because of #1139), it will be relayed to dm-log but then caught by the filter, which will delete it and then reply to the webhook in the channel.
  
  I think the best thing to do here would just be to ignore all webhook messages and bot messages, I can't think of any problems with this. 
  
  I would be happy to make this change
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `bot/cogs/antimalware.py`
  Content:
  ```
  1 import logging
  2 import typing as t
  3 from os.path import splitext
  4 
  5 from discord import Embed, Message, NotFound
  6 from discord.ext.commands import Cog
  7 
  8 from bot.bot import Bot
  9 from bot.constants import Channels, STAFF_ROLES, URLs
  10 
  11 log = logging.getLogger(__name__)
  12 
  13 PY_EMBED_DESCRIPTION = (
  14     "It looks like you tried to attach a Python file - "
  15     f"please use a code-pasting service such as {URLs.site_schema}{URLs.site_paste}"
  16 )
  17 
  18 TXT_EMBED_DESCRIPTION = (
  19     "**Uh-oh!** It looks like your message got zapped by our spam filter. "
  20     "We currently don't allow `.txt` attachments, so here are some tips to help you travel safely: \n\n"
  21     "• If you attempted to send a message longer than 2000 characters, try shortening your message "
  22     "to fit within the character limit or use a pasting service (see below) \n\n"
  23     "• If you tried to show someone your code, you can use codeblocks \n(run `!code-blocks` in "
  24     "{cmd_channel_mention} for more information) or use a pasting service like: "
  25     f"\n\n{URLs.site_schema}{URLs.site_paste}"
  26 )
  27 
  28 DISALLOWED_EMBED_DESCRIPTION = (
  29     "It looks like you tried to attach file type(s) that we do not allow ({blocked_extensions_str}). "
  30     "We currently allow the following file types: **{joined_whitelist}**.\n\n"
  31     "Feel free to ask in {meta_channel_mention} if you think this is a mistake."
  32 )
  33 
  34 
  35 class AntiMalware(Cog):
  36     """Delete messages which contain attachments with non-whitelisted file extensions."""
  37 
  38     def __init__(self, bot: Bot):
  39         self.bot = bot
  40 
  41     def _get_whitelisted_file_formats(self) -> list:
  42         """Get the file formats currently on the whitelist."""
  43         return self.bot.filter_list_cache['FILE_FORMAT.True'].keys()
  44 
  45     def _get_disallowed_extensions(self, message: Message) -> t.Iterable[str]:
  46         """Get an iterable containing all the disallowed extensions of attachments."""
  47         file_extensions = {splitext(attachment.filename.lower())[1] for attachment in message.attachments}
  48         extensions_blocked = file_extensions - set(self._get_whitelisted_file_formats())
  49         return extensions_blocked
  50 
  51     @Cog.listener()
  52     async def on_message(self, message: Message) -> None:
  53         """Identify messages with prohibited attachments."""
  54         # Return when message don't have attachment and don't moderate DMs
  55         if not message.attachments or not message.guild:
  56             return
  57 
  58         # Check if user is staff, if is, return
  59         # Since we only care that roles exist to iterate over, check for the attr rather than a User/Member instance
  60         if hasattr(message.author, "roles") and any(role.id in STAFF_ROLES for role in message.author.roles):
  61             return
  62 
  63         embed = Embed()
  64         extensions_blocked = self._get_disallowed_extensions(message)
  65         blocked_extensions_str = ', '.join(extensions_blocked)
  66         if ".py" in extensions_blocked:
  67             # Short-circuit on *.py files to provide a pastebin link
  68             embed.description = PY_EMBED_DESCRIPTION
  69         elif ".txt" in extensions_blocked:
  70             # Work around Discord AutoConversion of messages longer than 2000 chars to .txt
  71             cmd_channel = self.bot.get_channel(Channels.bot_commands)
  72             embed.description = TXT_EMBED_DESCRIPTION.format(cmd_channel_mention=cmd_channel.mention)
  73         elif extensions_blocked:
  74             meta_channel = self.bot.get_channel(Channels.meta)
  75             embed.description = DISALLOWED_EMBED_DESCRIPTION.format(
  76                 joined_whitelist=', '.join(self._get_whitelisted_file_formats()),
  77                 blocked_extensions_str=blocked_extensions_str,
  78                 meta_channel_mention=meta_channel.mention,
  79             )
  80 
  81         if embed.description:
  82             log.info(
  83                 f"User '{message.author}' ({message.author.id}) uploaded blacklisted file(s): {blocked_extensions_str}",
  84                 extra={"attachment_list": [attachment.filename for attachment in message.attachments]}
  85             )
  86 
  87             await message.channel.send(f"Hey {message.author.mention}!", embed=embed)
  88 
  89             # Delete the offending message:
  90             try:
  91                 await message.delete()
  92             except NotFound:
  93                 log.info(f"Tried to delete message `{message.id}`, but message could not be found.")
  94 
  95 
  96 def setup(bot: Bot) -> None:
  97     """Load the AntiMalware cog."""
  98     bot.add_cog(AntiMalware(bot))
  99
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/bot/cogs/antimalware.py b/bot/cogs/antimalware.py
  --- a/bot/cogs/antimalware.py
  +++ b/bot/cogs/antimalware.py
  @@ -55,6 +55,10 @@
           if not message.attachments or not message.guild:
               return
   
  +        # Ignore webhook and bot messages
  +        if message.webhook_id or message.author.bot:
  +            return
  +
           # Check if user is staff, if is, return
           # Since we only care that roles exist to iterate over, check for the attr rather than a User/Member instance
           if hasattr(message.author, "roles") and any(role.id in STAFF_ROLES for role in message.author.roles):
  
verification_info: {"golden_diff": "diff --git a/bot/cogs/antimalware.py b/bot/cogs/antimalware.py\n--- a/bot/cogs/antimalware.py\n+++ b/bot/cogs/antimalware.py\n@@ -55,6 +55,10 @@\n         if not message.attachments or not message.guild:\n             return\n \n+        # Ignore webhook and bot messages\n+        if message.webhook_id or message.author.bot:\n+            return\n+\n         # Check if user is staff, if is, return\n         # Since we only care that roles exist to iterate over, check for the attr rather than a User/Member instance\n         if hasattr(message.author, \"roles\") and any(role.id in STAFF_ROLES for role in message.author.roles):\n", "issue": "Antimalware cog file filter triggers on bot and webhook messages\nCurrently the antimalware cog file filter triggers on messages from the bot, and also on webhook messages. So for the example somebody tries to send an attachment from python using `!int eval`, it will be caught by the filter\r\n![image](https://user-images.githubusercontent.com/22353562/91752774-be76ed00-ebbe-11ea-99ac-e1147ca1d2df.png)\r\nAlso, if somebody sends a non-whitelisted attachment to the bot, (and it isn't ignored because of #1139), it will be relayed to dm-log but then caught by the filter, which will delete it and then reply to the webhook in the channel.\r\n\r\nI think the best thing to do here would just be to ignore all webhook messages and bot messages, I can't think of any problems with this. \r\n\r\nI would be happy to make this change\n", "before_files": [{"content": "import logging\nimport typing as t\nfrom os.path import splitext\n\nfrom discord import Embed, Message, NotFound\nfrom discord.ext.commands import Cog\n\nfrom bot.bot import Bot\nfrom bot.constants import Channels, STAFF_ROLES, URLs\n\nlog = logging.getLogger(__name__)\n\nPY_EMBED_DESCRIPTION = (\n    \"It looks like you tried to attach a Python file - \"\n    f\"please use a code-pasting service such as {URLs.site_schema}{URLs.site_paste}\"\n)\n\nTXT_EMBED_DESCRIPTION = (\n    \"**Uh-oh!** It looks like your message got zapped by our spam filter. \"\n    \"We currently don't allow `.txt` attachments, so here are some tips to help you travel safely: \\n\\n\"\n    \"\u2022 If you attempted to send a message longer than 2000 characters, try shortening your message \"\n    \"to fit within the character limit or use a pasting service (see below) \\n\\n\"\n    \"\u2022 If you tried to show someone your code, you can use codeblocks \\n(run `!code-blocks` in \"\n    \"{cmd_channel_mention} for more information) or use a pasting service like: \"\n    f\"\\n\\n{URLs.site_schema}{URLs.site_paste}\"\n)\n\nDISALLOWED_EMBED_DESCRIPTION = (\n    \"It looks like you tried to attach file type(s) that we do not allow ({blocked_extensions_str}). \"\n    \"We currently allow the following file types: **{joined_whitelist}**.\\n\\n\"\n    \"Feel free to ask in {meta_channel_mention} if you think this is a mistake.\"\n)\n\n\nclass AntiMalware(Cog):\n    \"\"\"Delete messages which contain attachments with non-whitelisted file extensions.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n    def _get_whitelisted_file_formats(self) -> list:\n        \"\"\"Get the file formats currently on the whitelist.\"\"\"\n        return self.bot.filter_list_cache['FILE_FORMAT.True'].keys()\n\n    def _get_disallowed_extensions(self, message: Message) -> t.Iterable[str]:\n        \"\"\"Get an iterable containing all the disallowed extensions of attachments.\"\"\"\n        file_extensions = {splitext(attachment.filename.lower())[1] for attachment in message.attachments}\n        extensions_blocked = file_extensions - set(self._get_whitelisted_file_formats())\n        return extensions_blocked\n\n    @Cog.listener()\n    async def on_message(self, message: Message) -> None:\n        \"\"\"Identify messages with prohibited attachments.\"\"\"\n        # Return when message don't have attachment and don't moderate DMs\n        if not message.attachments or not message.guild:\n            return\n\n        # Check if user is staff, if is, return\n        # Since we only care that roles exist to iterate over, check for the attr rather than a User/Member instance\n        if hasattr(message.author, \"roles\") and any(role.id in STAFF_ROLES for role in message.author.roles):\n            return\n\n        embed = Embed()\n        extensions_blocked = self._get_disallowed_extensions(message)\n        blocked_extensions_str = ', '.join(extensions_blocked)\n        if \".py\" in extensions_blocked:\n            # Short-circuit on *.py files to provide a pastebin link\n            embed.description = PY_EMBED_DESCRIPTION\n        elif \".txt\" in extensions_blocked:\n            # Work around Discord AutoConversion of messages longer than 2000 chars to .txt\n            cmd_channel = self.bot.get_channel(Channels.bot_commands)\n            embed.description = TXT_EMBED_DESCRIPTION.format(cmd_channel_mention=cmd_channel.mention)\n        elif extensions_blocked:\n            meta_channel = self.bot.get_channel(Channels.meta)\n            embed.description = DISALLOWED_EMBED_DESCRIPTION.format(\n                joined_whitelist=', '.join(self._get_whitelisted_file_formats()),\n                blocked_extensions_str=blocked_extensions_str,\n                meta_channel_mention=meta_channel.mention,\n            )\n\n        if embed.description:\n            log.info(\n                f\"User '{message.author}' ({message.author.id}) uploaded blacklisted file(s): {blocked_extensions_str}\",\n                extra={\"attachment_list\": [attachment.filename for attachment in message.attachments]}\n            )\n\n            await message.channel.send(f\"Hey {message.author.mention}!\", embed=embed)\n\n            # Delete the offending message:\n            try:\n                await message.delete()\n            except NotFound:\n                log.info(f\"Tried to delete message `{message.id}`, but message could not be found.\")\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Load the AntiMalware cog.\"\"\"\n    bot.add_cog(AntiMalware(bot))\n", "path": "bot/cogs/antimalware.py"}], "after_files": [{"content": "import logging\nimport typing as t\nfrom os.path import splitext\n\nfrom discord import Embed, Message, NotFound\nfrom discord.ext.commands import Cog\n\nfrom bot.bot import Bot\nfrom bot.constants import Channels, STAFF_ROLES, URLs\n\nlog = logging.getLogger(__name__)\n\nPY_EMBED_DESCRIPTION = (\n    \"It looks like you tried to attach a Python file - \"\n    f\"please use a code-pasting service such as {URLs.site_schema}{URLs.site_paste}\"\n)\n\nTXT_EMBED_DESCRIPTION = (\n    \"**Uh-oh!** It looks like your message got zapped by our spam filter. \"\n    \"We currently don't allow `.txt` attachments, so here are some tips to help you travel safely: \\n\\n\"\n    \"\u2022 If you attempted to send a message longer than 2000 characters, try shortening your message \"\n    \"to fit within the character limit or use a pasting service (see below) \\n\\n\"\n    \"\u2022 If you tried to show someone your code, you can use codeblocks \\n(run `!code-blocks` in \"\n    \"{cmd_channel_mention} for more information) or use a pasting service like: \"\n    f\"\\n\\n{URLs.site_schema}{URLs.site_paste}\"\n)\n\nDISALLOWED_EMBED_DESCRIPTION = (\n    \"It looks like you tried to attach file type(s) that we do not allow ({blocked_extensions_str}). \"\n    \"We currently allow the following file types: **{joined_whitelist}**.\\n\\n\"\n    \"Feel free to ask in {meta_channel_mention} if you think this is a mistake.\"\n)\n\n\nclass AntiMalware(Cog):\n    \"\"\"Delete messages which contain attachments with non-whitelisted file extensions.\"\"\"\n\n    def __init__(self, bot: Bot):\n        self.bot = bot\n\n    def _get_whitelisted_file_formats(self) -> list:\n        \"\"\"Get the file formats currently on the whitelist.\"\"\"\n        return self.bot.filter_list_cache['FILE_FORMAT.True'].keys()\n\n    def _get_disallowed_extensions(self, message: Message) -> t.Iterable[str]:\n        \"\"\"Get an iterable containing all the disallowed extensions of attachments.\"\"\"\n        file_extensions = {splitext(attachment.filename.lower())[1] for attachment in message.attachments}\n        extensions_blocked = file_extensions - set(self._get_whitelisted_file_formats())\n        return extensions_blocked\n\n    @Cog.listener()\n    async def on_message(self, message: Message) -> None:\n        \"\"\"Identify messages with prohibited attachments.\"\"\"\n        # Return when message don't have attachment and don't moderate DMs\n        if not message.attachments or not message.guild:\n            return\n\n        # Ignore webhook and bot messages\n        if message.webhook_id or message.author.bot:\n            return\n\n        # Check if user is staff, if is, return\n        # Since we only care that roles exist to iterate over, check for the attr rather than a User/Member instance\n        if hasattr(message.author, \"roles\") and any(role.id in STAFF_ROLES for role in message.author.roles):\n            return\n\n        embed = Embed()\n        extensions_blocked = self._get_disallowed_extensions(message)\n        blocked_extensions_str = ', '.join(extensions_blocked)\n        if \".py\" in extensions_blocked:\n            # Short-circuit on *.py files to provide a pastebin link\n            embed.description = PY_EMBED_DESCRIPTION\n        elif \".txt\" in extensions_blocked:\n            # Work around Discord AutoConversion of messages longer than 2000 chars to .txt\n            cmd_channel = self.bot.get_channel(Channels.bot_commands)\n            embed.description = TXT_EMBED_DESCRIPTION.format(cmd_channel_mention=cmd_channel.mention)\n        elif extensions_blocked:\n            meta_channel = self.bot.get_channel(Channels.meta)\n            embed.description = DISALLOWED_EMBED_DESCRIPTION.format(\n                joined_whitelist=', '.join(self._get_whitelisted_file_formats()),\n                blocked_extensions_str=blocked_extensions_str,\n                meta_channel_mention=meta_channel.mention,\n            )\n\n        if embed.description:\n            log.info(\n                f\"User '{message.author}' ({message.author.id}) uploaded blacklisted file(s): {blocked_extensions_str}\",\n                extra={\"attachment_list\": [attachment.filename for attachment in message.attachments]}\n            )\n\n            await message.channel.send(f\"Hey {message.author.mention}!\", embed=embed)\n\n            # Delete the offending message:\n            try:\n                await message.delete()\n            except NotFound:\n                log.info(f\"Tried to delete message `{message.id}`, but message could not be found.\")\n\n\ndef setup(bot: Bot) -> None:\n    \"\"\"Load the AntiMalware cog.\"\"\"\n    bot.add_cog(AntiMalware(bot))\n", "path": "bot/cogs/antimalware.py"}]}