Repository: Cog-Creators/Red-DiscordBot

Issue:
`[p]cleanup self` doesn't work in DMs if you're not a bot owner
# Command bugs

#### Command name

`[p]cleanup self`

#### What cog is this command from?

Cleanup

#### What were you expecting to happen?

The bot to clean one message.

#### What actually happened?

Nothing.

#### How can we reproduce this issue?

1. `[p]load cleanup` from bot owner account.
2. Use `[p]ping` and then `[p]cleanup self 1` from regular account in DMs with the bot



Discussion:

Resolving patch:
diff --git a/redbot/cogs/cleanup/checks.py b/redbot/cogs/cleanup/checks.py
new file mode 100644
--- /dev/null
+++ b/redbot/cogs/cleanup/checks.py
@@ -0,0 +1,15 @@
+from redbot.core.commands import Context, permissions_check
+from redbot.core.utils.mod import is_mod_or_superior, check_permissions
+
+
+def check_self_permissions():
+    async def predicate(ctx: Context):
+        if not ctx.guild:
+            return True
+        if await check_permissions(ctx, {"manage_messages": True}) or await is_mod_or_superior(
+            ctx.bot, ctx.author
+        ):
+            return True
+        return False
+
+    return permissions_check(predicate)
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
@@ -10,6 +10,7 @@
 from redbot.core.utils.chat_formatting import humanize_number
 from redbot.core.utils.mod import slow_deletion, mass_purge
 from redbot.core.utils.predicates import MessagePredicate
+from .checks import check_self_permissions
 from .converters import PositiveInt, RawMessageIds, positive_int
 
 _ = Translator("Cleanup", __file__)
@@ -115,13 +116,13 @@ def message_filter(message):
         return collected
 
     @commands.group()
-    @checks.mod_or_permissions(manage_messages=True)
     async def cleanup(self, ctx: commands.Context):
         """Delete messages."""
         pass
 
     @cleanup.command()
     @commands.guild_only()
+    @checks.mod_or_permissions(manage_messages=True)
     @commands.bot_has_permissions(manage_messages=True)
     async def text(
         self, ctx: commands.Context, text: str, number: positive_int, delete_pinned: bool = False
@@ -171,6 +172,7 @@ def check(m):
 
     @cleanup.command()
     @commands.guild_only()
+    @checks.mod_or_permissions(manage_messages=True)
     @commands.bot_has_permissions(manage_messages=True)
     async def user(
         self, ctx: commands.Context, user: str, number: positive_int, delete_pinned: bool = False
@@ -234,6 +236,7 @@ def check(m):
 
     @cleanup.command()
     @commands.guild_only()
+    @checks.mod_or_permissions(manage_messages=True)
     @commands.bot_has_permissions(manage_messages=True)
     async def after(
         self, ctx: commands.Context, message_id: RawMessageIds, delete_pinned: bool = False
@@ -269,6 +272,7 @@ async def after(
 
     @cleanup.command()
     @commands.guild_only()
+    @checks.mod_or_permissions(manage_messages=True)
     @commands.bot_has_permissions(manage_messages=True)
     async def before(
         self,
@@ -309,6 +313,7 @@ async def before(
 
     @cleanup.command()
     @commands.guild_only()
+    @checks.mod_or_permissions(manage_messages=True)
     @commands.bot_has_permissions(manage_messages=True)
     async def between(
         self,
@@ -354,6 +359,7 @@ async def between(
 
     @cleanup.command()
     @commands.guild_only()
+    @checks.mod_or_permissions(manage_messages=True)
     @commands.bot_has_permissions(manage_messages=True)
     async def messages(
         self, ctx: commands.Context, number: positive_int, delete_pinned: bool = False
@@ -386,6 +392,7 @@ async def messages(
 
     @cleanup.command(name="bot")
     @commands.guild_only()
+    @checks.mod_or_permissions(manage_messages=True)
     @commands.bot_has_permissions(manage_messages=True)
     async def cleanup_bot(
         self, ctx: commands.Context, number: positive_int, delete_pinned: bool = False
@@ -462,6 +469,7 @@ def check(m):
         await mass_purge(to_delete, channel)
 
     @cleanup.command(name="self")
+    @check_self_permissions()
     async def cleanup_self(
         self,
         ctx: commands.Context,
@@ -537,6 +545,7 @@ def check(m):
 
     @cleanup.command(name="spam")
     @commands.guild_only()
+    @checks.mod_or_permissions(manage_messages=True)
     @commands.bot_has_permissions(manage_messages=True)
     async def cleanup_spam(self, ctx: commands.Context, number: positive_int = PositiveInt(50)):
         """Deletes duplicate messages in the channel from the last X messages and keeps only one copy.


Test patch: