aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar mbaruh <[email protected]>2021-12-02 22:21:35 +0200
committerGravatar mbaruh <[email protected]>2021-12-02 22:21:35 +0200
commit0df94eac77703943221e39b9e9898515e266a9ef (patch)
tree72da0f979ed6a876f18d5f46f3a4c7d78f9e08fe
parentRemove cleaning based on number of messages (diff)
Simplify cache usage
Removes the cache usage argument from the clean commands. Cache usage is now an implementation detail. The cache will be used if the age of the oldest message requested for cleaning is younger than the oldest message in the cache. Additionally fixes the logger to the one used in the rest of the bot (caused by a faulty merge).
-rw-r--r--bot/exts/moderation/clean.py65
1 files changed, 26 insertions, 39 deletions
diff --git a/bot/exts/moderation/clean.py b/bot/exts/moderation/clean.py
index 8ad7a56d8..bb6e44d6f 100644
--- a/bot/exts/moderation/clean.py
+++ b/bot/exts/moderation/clean.py
@@ -1,11 +1,11 @@
import contextlib
-import logging
import re
import time
from collections import defaultdict
from contextlib import suppress
from datetime import datetime
-from typing import Any, Callable, Iterable, Literal, Optional, TYPE_CHECKING, Union
+from itertools import takewhile
+from typing import Callable, Iterable, Literal, Optional, TYPE_CHECKING, Union
from discord import Colour, Message, NotFound, TextChannel, User, errors
from discord.ext.commands import Cog, Context, Converter, Greedy, group, has_any_role
@@ -16,9 +16,10 @@ from bot.bot import Bot
from bot.constants import Channels, CleanMessages, Colours, Emojis, Event, Icons, MODERATION_ROLES
from bot.converters import Age, ISODateTime
from bot.exts.moderation.modlog import ModLog
+from bot.log import get_logger
from bot.utils.channel import is_mod_channel
-log = logging.getLogger(__name__)
+log = get_logger(__name__)
# Number of seconds before command invocations and responses are deleted in non-moderation channels.
MESSAGE_DELETE_DELAY = 5
@@ -191,11 +192,19 @@ class Clean(Cog):
# Invocation message has already been deleted
log.info("Tried to delete invocation message, but it was already deleted.")
- def _get_messages_from_cache(self, to_delete: Predicate) -> tuple[defaultdict[Any, list], list[int]]:
+ def _use_cache(self, limit: datetime) -> bool:
+ """Tell whether all messages to be cleaned can be found in the cache."""
+ return self.bot.cached_messages[0].created_at <= limit
+
+ def _get_messages_from_cache(
+ self,
+ to_delete: Predicate,
+ lower_limit: datetime
+ ) -> tuple[defaultdict[TextChannel, list], list[int]]:
"""Helper function for getting messages from the cache."""
message_mappings = defaultdict(list)
message_ids = []
- for message in self.bot.cached_messages:
+ for message in takewhile(lambda m: m.created_at > lower_limit, reversed(self.bot.cached_messages)):
if not self.cleaning:
# Cleaning was canceled
return message_mappings, message_ids
@@ -212,7 +221,7 @@ class Clean(Cog):
to_delete: Predicate,
before: datetime,
after: Optional[datetime] = None
- ) -> tuple[defaultdict[Any, list], list]:
+ ) -> tuple[defaultdict[TextChannel, list], list]:
message_mappings = defaultdict(list)
message_ids = []
@@ -344,7 +353,6 @@ class Clean(Cog):
regex: Optional[re.Pattern] = None,
first_limit: Optional[CleanLimit] = None,
second_limit: Optional[CleanLimit] = None,
- use_cache: Optional[bool] = True
) -> None:
"""A helper function that does the actual message cleaning."""
self._validate_input(channels, bots_only, users, first_limit, second_limit)
@@ -380,9 +388,11 @@ class Clean(Cog):
# Delete the invocation first
await self._delete_invocation(ctx)
- if channels == "*" and use_cache:
- message_mappings, message_ids = self._get_messages_from_cache(to_delete=predicate)
+ if self._use_cache(first_limit):
+ log.trace(f"Messages for cleaning by {ctx.author.id} will be searched in the cache.")
+ message_mappings, message_ids = self._get_messages_from_cache(to_delete=predicate, lower_limit=first_limit)
else:
+ log.trace(f"Messages for cleaning by {ctx.author.id} will be searched in channel histories.")
deletion_channels = channels
if channels == "*":
deletion_channels = [channel for channel in ctx.guild.channels if isinstance(channel, TextChannel)]
@@ -417,9 +427,8 @@ class Clean(Cog):
users: Greedy[User] = None,
first_limit: Optional[CleanLimit] = None,
second_limit: Optional[CleanLimit] = None,
- use_cache: Optional[bool] = None,
- bots_only: Optional[bool] = False,
regex: Optional[Regex] = None,
+ bots_only: Optional[bool] = False,
*,
channels: CleanChannels = None # "Optional" with discord.py silently ignores incorrect input.
) -> None:
@@ -433,24 +442,17 @@ class Clean(Cog):
At least one limit is required.
If a message is provided, cleaning will happen in that channel, and channels cannot be provided.
If only one of them is provided, acts as `clean until`. If both are provided, acts as `clean between`.
- \u2003• `use_cache`: Whether to use the message cache.
- If not provided, will default to False unless an asterisk is used for the channels.
- \u2003• `bots_only`: Whether to delete only bots. If specified, users cannot be specified.
\u2003• `regex`: A regex pattern the message must contain to be deleted.
The pattern must be provided enclosed in backticks.
If the pattern contains spaces, it still needs to be enclosed in double quotes on top of that.
+ \u2003• `bots_only`: Whether to delete only bots. If specified, users cannot be specified.
\u2003• `channels`: A series of channels to delete in, or an asterisk to delete from all channels.
"""
if not any([users, first_limit, second_limit, regex, channels]):
await ctx.send_help(ctx.command)
return
- if use_cache is None:
- use_cache = channels == "*"
-
- await self._clean_messages(
- ctx, channels, bots_only, users, regex, first_limit, second_limit, use_cache
- )
+ await self._clean_messages(ctx, channels, bots_only, users, regex, first_limit, second_limit)
@clean_group.command(name="user", aliases=["users"])
async def clean_user(
@@ -458,7 +460,6 @@ class Clean(Cog):
ctx: Context,
user: User,
message_or_time: CleanLimit,
- use_cache: Optional[bool] = True,
*,
channels: CleanChannels = None
) -> None:
@@ -470,19 +471,10 @@ class Clean(Cog):
If a message is specified, `channels` cannot be specified.
"""
- await self._clean_messages(
- ctx, users=[user], channels=channels, first_limit=message_or_time, use_cache=use_cache
- )
+ await self._clean_messages(ctx, users=[user], channels=channels, first_limit=message_or_time)
@clean_group.command(name="bots", aliases=["bot"])
- async def clean_bots(
- self,
- ctx: Context,
- message_or_time: CleanLimit,
- use_cache: Optional[bool] = True,
- *,
- channels: CleanChannels = None
- ) -> None:
+ async def clean_bots(self, ctx: Context, message_or_time: CleanLimit, *, channels: CleanChannels = None) -> None:
"""
Delete all messages posted by a bot, stop cleaning after traversing `traverse` messages.
@@ -491,9 +483,7 @@ class Clean(Cog):
If a message is specified, `channels` cannot be specified.
"""
- await self._clean_messages(
- ctx, bots_only=True, channels=channels, first_limit=message_or_time, use_cache=use_cache
- )
+ await self._clean_messages(ctx, bots_only=True, channels=channels, first_limit=message_or_time)
@clean_group.command(name="regex", aliases=["word", "expression", "pattern"])
async def clean_regex(
@@ -501,7 +491,6 @@ class Clean(Cog):
ctx: Context,
regex: Regex,
message_or_time: CleanLimit,
- use_cache: Optional[bool] = True,
*,
channels: CleanChannels = None
) -> None:
@@ -516,9 +505,7 @@ class Clean(Cog):
If the pattern contains spaces, it still needs to be enclosed in double quotes on top of that.
For example: `[0-9]`
"""
- await self._clean_messages(
- ctx, regex=regex, channels=channels, first_limit=message_or_time, use_cache=use_cache
- )
+ await self._clean_messages(ctx, regex=regex, channels=channels, first_limit=message_or_time)
@clean_group.command(name="until")
async def clean_until(