Repository: Cog-Creators/Red-DiscordBot

Issue:
Specify audit log reason in cleanup cog
### What component of Red (cog, command, API) would you like to see improvements on?

Cleanup

### Describe the enhancement you're suggesting.

Delete messages endpoint supports specifying audit log reason and discord.py 2.0 added a `reason` kwarg to `Messageable.delete_messages(...)` in order to support it. I think that the cleanup cog should be specifying the audit log reason in all places where it deletes messages.

This change will require an addition of a `reason` kwarg to `redbot.core.utils.mod.mass_purge(...)` and usage of that new kwarg in all calls to this function in the Cleanup cog.

### Anything else?

What should the contents of the audit log reason be? Just whatever `get_audit_reason(...)` utility function returns?


Discussion:

Resolving patch:
diff --git a/redbot/cogs/cleanup/cleanup.py b/redbot/cogs/cleanup/cleanup.py
--- a/redbot/cogs/cleanup/cleanup.py
+++ b/redbot/cogs/cleanup/cleanup.py
@@ -227,7 +227,7 @@ def check(m):
         )
         log.info(reason)
 
-        await mass_purge(to_delete, channel)
+        await mass_purge(to_delete, channel, reason=reason)
         await self.send_optional_notification(len(to_delete), channel, subtract_invoking=True)
 
     @cleanup.command()
@@ -298,7 +298,7 @@ def check(m):
         )
         log.info(reason)
 
-        await mass_purge(to_delete, channel)
+        await mass_purge(to_delete, channel, reason=reason)
         await self.send_optional_notification(len(to_delete), channel, subtract_invoking=True)
 
     @cleanup.command()
@@ -351,7 +351,7 @@ async def after(
         )
         log.info(reason)
 
-        await mass_purge(to_delete, channel)
+        await mass_purge(to_delete, channel, reason=reason)
         await self.send_optional_notification(len(to_delete), channel)
 
     @cleanup.command()
@@ -407,7 +407,7 @@ async def before(
         )
         log.info(reason)
 
-        await mass_purge(to_delete, channel)
+        await mass_purge(to_delete, channel, reason=reason)
         await self.send_optional_notification(len(to_delete), channel, subtract_invoking=True)
 
     @cleanup.command()
@@ -460,7 +460,7 @@ async def between(
         )
         log.info(reason)
 
-        await mass_purge(to_delete, channel)
+        await mass_purge(to_delete, channel, reason=reason)
         await self.send_optional_notification(len(to_delete), channel, subtract_invoking=True)
 
     @cleanup.command()
@@ -499,7 +499,7 @@ async def messages(
         )
         log.info(reason)
 
-        await mass_purge(to_delete, channel)
+        await mass_purge(to_delete, channel, reason=reason)
         await self.send_optional_notification(len(to_delete), channel, subtract_invoking=True)
 
     @cleanup.command(name="bot")
@@ -586,7 +586,7 @@ def check(m):
         )
         log.info(reason)
 
-        await mass_purge(to_delete, channel)
+        await mass_purge(to_delete, channel, reason=reason)
         await self.send_optional_notification(len(to_delete), channel, subtract_invoking=True)
 
     @cleanup.command(name="self")
@@ -673,7 +673,7 @@ def check(m):
         log.info(reason)
 
         if can_mass_purge:
-            await mass_purge(to_delete, channel)
+            await mass_purge(to_delete, channel, reason=reason)
         else:
             await slow_deletion(to_delete)
         await self.send_optional_notification(
@@ -733,7 +733,7 @@ def check(m):
         )
 
         to_delete.append(ctx.message)
-        await mass_purge(to_delete, ctx.channel)
+        await mass_purge(to_delete, ctx.channel, "Duplicate message cleanup")
         await self.send_optional_notification(len(to_delete), ctx.channel, subtract_invoking=True)
 
     @commands.group()
diff --git a/redbot/core/utils/mod.py b/redbot/core/utils/mod.py
--- a/redbot/core/utils/mod.py
+++ b/redbot/core/utils/mod.py
@@ -1,6 +1,6 @@
 import asyncio
 from datetime import timedelta
-from typing import List, Iterable, Union, TYPE_CHECKING, Dict
+from typing import List, Iterable, Union, TYPE_CHECKING, Dict, Optional
 
 import discord
 
@@ -12,6 +12,8 @@
 async def mass_purge(
     messages: List[discord.Message],
     channel: Union[discord.TextChannel, discord.VoiceChannel, discord.Thread],
+    *,
+    reason: Optional[str] = None,
 ):
     """Bulk delete messages from a channel.
 
@@ -29,6 +31,8 @@ async def mass_purge(
         The messages to bulk delete.
     channel : `discord.TextChannel`, `discord.VoiceChannel`, or `discord.Thread`
         The channel to delete messages from.
+    reason : `str`, optional
+        The reason for bulk deletion, which will appear in the audit log.
 
     Raises
     ------
@@ -43,7 +47,7 @@ async def mass_purge(
         # discord.NotFound can be raised when `len(messages) == 1` and the message does not exist.
         # As a result of this obscure behavior, this error needs to be caught just in case.
         try:
-            await channel.delete_messages(messages[:100])
+            await channel.delete_messages(messages[:100], reason=reason)
         except discord.errors.HTTPException:
             pass
         messages = messages[100:]


Test patch: