Repository: python-discord/bot

Issue:
!clean command returns malformed API request
Since we added attachments to the deleted message logs the clean command was not updated to store this.

When running a clean command the following error is returned:
```
web_1       | Bad Request: /bot/deleted-messages
web_1       | "POST /bot/deleted-messages HTTP/1.1" 400 792
bot_1       | 2020-02-25 19:32:41,081 | bot.cogs.error_handler | DEBUG | API responded with 400 for command clean all: {'deletedmessage_set': [{'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}, {'attachments': ['This field may not be null.']}]}.
```

This is not critical since the clean command still operates, it just does not store deleted messages like intended.


Discussion:
The issue is caused by a small oversight in how `ModLog.upload_log` handles empty attachment lists. Normally, `attachments` is a list of lists, with each sublist containing the attachments for that particular message

However, if the attachments kwarg isn't used (i.e., gets the default `None` value), we initialize `attachments` with an empty outer list. That results in us adding `None` from the default value of `zip_longests` in the request part instead of an empty list indicating that a message had no attachments:

```py
        # here it attaches an empty list
        if attachments is None:
            # Empty list
            attachments = []

        response = await self.bot.api_client.post(
            'bot/deleted-messages',
            json={
                'actor': actor_id,
                'creation': datetime.utcnow().isoformat(),
                'deletedmessage_set': [
                    {
                        'id': message.id,
                        'author': message.author.id,
                        'channel_id': message.channel.id,
                        'content': message.content,
                        'embeds': [embed.to_dict() for embed in message.embeds],
                        'attachments': attachment,
                    }
                    # attachment here will get `None` from `zip_longest` if attachments is an empty list
                    for message, attachment in zip_longest(messages, attachments)
                ]
            }
        )

        return f"{URLs.site_logs_view}/{response['id']}"
```

Resolving patch:
diff --git a/bot/cogs/moderation/modlog.py b/bot/cogs/moderation/modlog.py
--- a/bot/cogs/moderation/modlog.py
+++ b/bot/cogs/moderation/modlog.py
@@ -67,7 +67,7 @@ async def upload_log(
                         'embeds': [embed.to_dict() for embed in message.embeds],
                         'attachments': attachment,
                     }
-                    for message, attachment in zip_longest(messages, attachments)
+                    for message, attachment in zip_longest(messages, attachments, fillvalue=[])
                 ]
             }
         )


Test patch: