mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-09 12:48:54 -05:00
[Mod] Added [p]cleanup bot, [p]cleanup self (#466)
`[p]cleanup bot` deletes user's command messages and bot's messages `[p]cleanup self` deletes bot's messages
This commit is contained in:
commit
26ab7f2c45
162
cogs/mod.py
162
cogs/mod.py
@ -6,6 +6,7 @@ from __main__ import send_cmd_help, settings
|
|||||||
from collections import deque, defaultdict
|
from collections import deque, defaultdict
|
||||||
from cogs.utils.chat_formatting import escape_mass_mentions, box
|
from cogs.utils.chat_formatting import escape_mass_mentions, box
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
@ -398,14 +399,10 @@ class Mod:
|
|||||||
dataIO.save_json("data/mod/perms_cache.json", self._perms_cache)
|
dataIO.save_json("data/mod/perms_cache.json", self._perms_cache)
|
||||||
await self.bot.say("User has been unmuted in this server.")
|
await self.bot.say("User has been unmuted in this server.")
|
||||||
|
|
||||||
@commands.group(pass_context=True, no_pm=True)
|
@commands.group(pass_context=True)
|
||||||
@checks.mod_or_permissions(manage_messages=True)
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
async def cleanup(self, ctx):
|
async def cleanup(self, ctx):
|
||||||
"""Deletes messages.
|
"""Deletes messages."""
|
||||||
|
|
||||||
cleanup messages [number]
|
|
||||||
cleanup user [name/mention] [number]
|
|
||||||
cleanup text \"Text here\" [number]"""
|
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await send_cmd_help(ctx)
|
await send_cmd_help(ctx)
|
||||||
|
|
||||||
@ -492,7 +489,7 @@ class Mod:
|
|||||||
while tries_left and len(to_delete) - 1 < number:
|
while tries_left and len(to_delete) - 1 < number:
|
||||||
async for message in self.bot.logs_from(channel, limit=100,
|
async for message in self.bot.logs_from(channel, limit=100,
|
||||||
before=tmp):
|
before=tmp):
|
||||||
if len(to_delete) -1 < number and check(message):
|
if len(to_delete) - 1 < number and check(message):
|
||||||
to_delete.append(message)
|
to_delete.append(message)
|
||||||
tmp = message
|
tmp = message
|
||||||
tries_left -= 1
|
tries_left -= 1
|
||||||
@ -514,6 +511,8 @@ class Mod:
|
|||||||
To get a message id, enable developer mode in Discord's
|
To get a message id, enable developer mode in Discord's
|
||||||
settings, 'appearance' tab. Then right click a message
|
settings, 'appearance' tab. Then right click a message
|
||||||
and copy its id.
|
and copy its id.
|
||||||
|
|
||||||
|
This command only works on bots running as bot accounts.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
channel = ctx.message.channel
|
channel = ctx.message.channel
|
||||||
@ -522,6 +521,11 @@ class Mod:
|
|||||||
is_bot = self.bot.user.bot
|
is_bot = self.bot.user.bot
|
||||||
has_permissions = channel.permissions_for(server.me).manage_messages
|
has_permissions = channel.permissions_for(server.me).manage_messages
|
||||||
|
|
||||||
|
if not is_bot:
|
||||||
|
await self.bot.say("This command can only be used on bots with "
|
||||||
|
"bot accounts.")
|
||||||
|
return
|
||||||
|
|
||||||
to_delete = []
|
to_delete = []
|
||||||
|
|
||||||
after = await self.bot.get_message(channel, message_id)
|
after = await self.bot.get_message(channel, message_id)
|
||||||
@ -541,10 +545,7 @@ class Mod:
|
|||||||
"".format(author.name, author.id,
|
"".format(author.name, author.id,
|
||||||
len(to_delete), channel.name))
|
len(to_delete), channel.name))
|
||||||
|
|
||||||
if is_bot:
|
await self.mass_purge(to_delete)
|
||||||
await self.mass_purge(to_delete)
|
|
||||||
else:
|
|
||||||
await self.slow_deletion(to_delete)
|
|
||||||
|
|
||||||
@cleanup.command(pass_context=True, no_pm=True)
|
@cleanup.command(pass_context=True, no_pm=True)
|
||||||
async def messages(self, ctx, number: int):
|
async def messages(self, ctx, number: int):
|
||||||
@ -577,6 +578,139 @@ class Mod:
|
|||||||
else:
|
else:
|
||||||
await self.slow_deletion(to_delete)
|
await self.slow_deletion(to_delete)
|
||||||
|
|
||||||
|
@cleanup.command(pass_context=True, no_pm=True, name='bot')
|
||||||
|
async def cleanup_bot(self, ctx, number: int):
|
||||||
|
"""Cleans up command messages and messages from the bot"""
|
||||||
|
|
||||||
|
channel = ctx.message.channel
|
||||||
|
author = ctx.message.author
|
||||||
|
server = channel.server
|
||||||
|
is_bot = self.bot.user.bot
|
||||||
|
has_permissions = channel.permissions_for(server.me).manage_messages
|
||||||
|
|
||||||
|
prefixes = self.bot.command_prefix
|
||||||
|
if isinstance(prefixes, str):
|
||||||
|
prefixes = [prefixes]
|
||||||
|
elif callable(prefixes):
|
||||||
|
if asyncio.iscoroutine(prefixes):
|
||||||
|
await self.bot.say('Coroutine prefixes not yet implemented.')
|
||||||
|
return
|
||||||
|
prefixes = prefixes(self.bot, ctx.message)
|
||||||
|
|
||||||
|
# In case some idiot sets a null prefix
|
||||||
|
if '' in prefixes:
|
||||||
|
prefixes.pop('')
|
||||||
|
|
||||||
|
def check(m):
|
||||||
|
if m.author.id == self.bot.user.id:
|
||||||
|
return True
|
||||||
|
elif m == ctx.message:
|
||||||
|
return True
|
||||||
|
p = discord.utils.find(m.content.startswith, prefixes)
|
||||||
|
if p and len(p) > 0:
|
||||||
|
return m.content[len(p):].startswith(tuple(self.bot.commands))
|
||||||
|
return False
|
||||||
|
|
||||||
|
to_delete = [ctx.message]
|
||||||
|
|
||||||
|
if not has_permissions:
|
||||||
|
await self.bot.say("I'm not allowed to delete messages.")
|
||||||
|
return
|
||||||
|
|
||||||
|
tries_left = 5
|
||||||
|
tmp = ctx.message
|
||||||
|
|
||||||
|
while tries_left and len(to_delete) - 1 < number:
|
||||||
|
async for message in self.bot.logs_from(channel, limit=100,
|
||||||
|
before=tmp):
|
||||||
|
if len(to_delete) - 1 < number and check(message):
|
||||||
|
to_delete.append(message)
|
||||||
|
tmp = message
|
||||||
|
tries_left -= 1
|
||||||
|
|
||||||
|
logger.info("{}({}) deleted {} "
|
||||||
|
" command messages in channel {}"
|
||||||
|
"".format(author.name, author.id, len(to_delete),
|
||||||
|
channel.name))
|
||||||
|
|
||||||
|
if is_bot:
|
||||||
|
await self.mass_purge(to_delete)
|
||||||
|
else:
|
||||||
|
await self.slow_deletion(to_delete)
|
||||||
|
|
||||||
|
@cleanup.command(pass_context=True, name='self')
|
||||||
|
async def cleanup_self(self, ctx, number: int, match_pattern: str = None):
|
||||||
|
"""Cleans up messages owned by the bot.
|
||||||
|
|
||||||
|
By default, all messages are cleaned. If a third argument is specified,
|
||||||
|
it is used for pattern matching: If it begins with r( and ends with ),
|
||||||
|
then it is interpreted as a regex, and messages that match it are
|
||||||
|
deleted. Otherwise, it is used in a simple substring test.
|
||||||
|
|
||||||
|
Some helpful regex flags to include in your pattern:
|
||||||
|
Dots match newlines: (?s); Ignore case: (?i); Both: (?si)
|
||||||
|
"""
|
||||||
|
channel = ctx.message.channel
|
||||||
|
author = ctx.message.author
|
||||||
|
is_bot = self.bot.user.bot
|
||||||
|
|
||||||
|
# You can always delete your own messages, this is needed to purge
|
||||||
|
can_mass_purge = False
|
||||||
|
if type(author) is discord.Member:
|
||||||
|
me = channel.server.me
|
||||||
|
can_mass_purge = channel.permissions_for(me).manage_messages
|
||||||
|
|
||||||
|
use_re = (match_pattern and match_pattern.startswith('r(') and
|
||||||
|
match_pattern.endswith(')'))
|
||||||
|
|
||||||
|
if use_re:
|
||||||
|
match_pattern = match_pattern[1:] # strip 'r'
|
||||||
|
match_re = re.compile(match_pattern)
|
||||||
|
|
||||||
|
def content_match(c):
|
||||||
|
return bool(match_re.match(c))
|
||||||
|
elif match_pattern:
|
||||||
|
def content_match(c):
|
||||||
|
return match_pattern in c
|
||||||
|
else:
|
||||||
|
def content_match(_):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def check(m):
|
||||||
|
if m.author.id != self.bot.user.id:
|
||||||
|
return False
|
||||||
|
elif content_match(m.content):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
to_delete = []
|
||||||
|
|
||||||
|
tries_left = 5
|
||||||
|
tmp = ctx.message
|
||||||
|
|
||||||
|
while tries_left and len(to_delete) < number:
|
||||||
|
async for message in self.bot.logs_from(channel, limit=100,
|
||||||
|
before=tmp):
|
||||||
|
if len(to_delete) < number and check(message):
|
||||||
|
to_delete.append(message)
|
||||||
|
tmp = message
|
||||||
|
tries_left -= 1
|
||||||
|
|
||||||
|
if channel.name:
|
||||||
|
channel_name = 'channel ' + channel.name
|
||||||
|
else:
|
||||||
|
channel_name = str(channel)
|
||||||
|
|
||||||
|
logger.info("{}({}) deleted {} messages "
|
||||||
|
"sent by the bot in {}"
|
||||||
|
"".format(author.name, author.id, len(to_delete),
|
||||||
|
channel_name))
|
||||||
|
|
||||||
|
if is_bot and can_mass_purge:
|
||||||
|
await self.mass_purge(to_delete)
|
||||||
|
else:
|
||||||
|
await self.slow_deletion(to_delete)
|
||||||
|
|
||||||
@commands.command(pass_context=True)
|
@commands.command(pass_context=True)
|
||||||
@checks.mod_or_permissions(manage_messages=True)
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
async def reason(self, ctx, case, *, reason : str=""):
|
async def reason(self, ctx, case, *, reason : str=""):
|
||||||
@ -613,7 +747,6 @@ class Mod:
|
|||||||
else:
|
else:
|
||||||
await self.bot.say("Case #{} updated.".format(case))
|
await self.bot.say("Case #{} updated.".format(case))
|
||||||
|
|
||||||
|
|
||||||
@commands.group(pass_context=True)
|
@commands.group(pass_context=True)
|
||||||
@checks.is_owner()
|
@checks.is_owner()
|
||||||
async def blacklist(self, ctx):
|
async def blacklist(self, ctx):
|
||||||
@ -938,7 +1071,6 @@ class Mod:
|
|||||||
await self.bot.delete_message(message)
|
await self.bot.delete_message(message)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
await asyncio.sleep(1.5)
|
|
||||||
|
|
||||||
def is_mod_or_superior(self, message):
|
def is_mod_or_superior(self, message):
|
||||||
user = message.author
|
user = message.author
|
||||||
@ -1057,7 +1189,7 @@ class Mod:
|
|||||||
self.cache[author].append(message)
|
self.cache[author].append(message)
|
||||||
msgs = self.cache[author]
|
msgs = self.cache[author]
|
||||||
if len(msgs) == 3 and \
|
if len(msgs) == 3 and \
|
||||||
msgs[0].content == msgs[1].content == msgs[2].content:
|
msgs[0].content == msgs[1].content == msgs[2].content:
|
||||||
if any([m.attachments for m in msgs]):
|
if any([m.attachments for m in msgs]):
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
@ -1146,6 +1278,7 @@ class Mod:
|
|||||||
empty = [p for p in iter(discord.PermissionOverwrite())]
|
empty = [p for p in iter(discord.PermissionOverwrite())]
|
||||||
return original == empty
|
return original == empty
|
||||||
|
|
||||||
|
|
||||||
def check_folders():
|
def check_folders():
|
||||||
folders = ("data", "data/mod/")
|
folders = ("data", "data/mod/")
|
||||||
for folder in folders:
|
for folder in folders:
|
||||||
@ -1174,6 +1307,7 @@ def check_files():
|
|||||||
print("Creating empty {}".format(filename))
|
print("Creating empty {}".format(filename))
|
||||||
dataIO.save_json("data/mod/{}".format(filename), value)
|
dataIO.save_json("data/mod/{}".format(filename), value)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
global logger
|
global logger
|
||||||
check_folders()
|
check_folders()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user