33import itertools
44import re
55import time
6- from collections import defaultdict
76from collections .abc import Callable , Collection
87from datetime import datetime
98from itertools import takewhile
4039
4140BULK_DELETE_LIMIT = 100
4241
42+ PRIORITY_CHANNELS = [Channels .python_general ]
43+
4344
4445class CleanChannels (Converter ):
4546 """A converter to turn the string into a list of channels to clean, or the literal `*` for all public channels."""
@@ -125,31 +126,37 @@ async def _send_expiring_message(ctx: Context, content: str) -> None:
125126 await ctx .send (content , delete_after = delete_after )
126127
127128 @staticmethod
128- def _channels_set (
129- channels : CleanChannels , ctx : Context , first_limit : CleanLimit , second_limit : CleanLimit
130- ) -> set [TextChannel ]:
131- """Standardize the input `channels` argument to a usable set of text channels."""
129+ def _get_channels (
130+ channels : CleanChannels , ctx : Context , first_limit : CleanLimit , second_limit : CleanLimit
131+ ) -> list [TextChannel ]:
132+ """Standardize the input `channels` argument to a usable list of text channels, arranged by priority."""
133+ def channel_rank (channel : TextChannel ) -> int :
134+ if channel == ctx .channel : # Clean the invocation channel first if it's listed.
135+ return - 1
136+ try :
137+ return PRIORITY_CHANNELS .index (channel .id )
138+ except ValueError :
139+ return len (PRIORITY_CHANNELS )
140+
132141 # Default to using the invoking context's channel or the channel of the message limit(s).
133142 if not channels :
134143 # Input was validated - if first_limit is a message, second_limit won't point at a different channel.
135144 if isinstance (first_limit , Message ):
136- channels = { first_limit .channel }
145+ channels = [ first_limit .channel ]
137146 elif isinstance (second_limit , Message ):
138- channels = { second_limit .channel }
147+ channels = [ second_limit .channel ]
139148 else :
140- channels = {ctx .channel }
141- else :
142- if channels == "*" :
143- channels = {
144- channel for channel in itertools .chain (ctx .guild .channels , ctx .guild .threads )
145- if isinstance (channel , TextChannel | Thread )
146- # Ignore non-public channels or ones that can't be written in to optimize for speed.
147- and channel .permissions_for (ctx .guild .default_role ).view_channel
148- and channel .permissions_for (ctx .guild .default_role ).send_messages
149- }
150- else :
151- channels = set (channels )
152-
149+ channels = [ctx .channel ]
150+ elif channels == "*" :
151+ channels = [
152+ channel for channel in itertools .chain (ctx .guild .channels , ctx .guild .threads )
153+ if isinstance (channel , TextChannel | Thread )
154+ # Ignore non-public channels or ones that can't be written in to optimize for speed.
155+ and channel .permissions_for (ctx .guild .default_role ).view_channel
156+ and channel .permissions_for (ctx .guild .default_role ).send_messages
157+ ]
158+
159+ channels .sort (key = channel_rank )
153160 return channels
154161
155162 @staticmethod
@@ -239,18 +246,19 @@ def _use_api(self, oldest_limit: datetime) -> bool:
239246
240247 def _get_messages_from_cache (
241248 self ,
242- channels : set [TextChannel ],
249+ channels : list [TextChannel ],
243250 to_delete : Predicate ,
244251 lower_limit : datetime
245- ) -> defaultdict [TextChannel , list ]:
252+ ) -> dict [TextChannel , list [ Message ] ]:
246253 """Helper function for getting messages from the cache."""
247- message_mappings = defaultdict (list )
254+ message_mappings = {channel : [] for channel in channels }
255+ channels_set = set (channels )
248256 for message in takewhile (lambda m : m .created_at > lower_limit , reversed (self .bot .cached_messages )):
249257 if not self .cleaning :
250258 # Cleaning was canceled
251259 return message_mappings
252260
253- if message .channel in channels and to_delete (message ):
261+ if message .channel in channels_set and to_delete (message ):
254262 message_mappings [message .channel ].append (message )
255263
256264 return message_mappings
@@ -344,7 +352,7 @@ async def _delete_bulk(
344352 If cleaning was cancelled in the middle, return messages already deleted.
345353 """
346354 deleted = []
347- old_messages = {channel : [] for channel in messages_per_channel }
355+ old_messages = {}
348356
349357 for channel , messages in messages_per_channel .items ():
350358 to_delete = []
@@ -442,7 +450,7 @@ async def _clean_messages(
442450 return None
443451 self .cleaning = True
444452
445- deletion_channels = self ._channels_set (channels , ctx , first_limit , second_limit )
453+ deletion_channels = self ._get_channels (channels , ctx , first_limit , second_limit )
446454
447455 if isinstance (first_limit , Message ):
448456 first_limit = first_limit .created_at
@@ -468,7 +476,9 @@ async def _clean_messages(
468476 messages_per_channel = self ._get_messages_from_cache (
469477 channels = deletion_channels , to_delete = predicate , lower_limit = first_limit
470478 )
471- deleted_messages , old_messages = await self ._delete_bulk (messages_per_channel , executor )
479+ deleted_messages , cache_old_messages = await self ._delete_bulk (messages_per_channel , executor )
480+ for channel , messages in cache_old_messages .items ():
481+ old_messages [channel ].extend (messages )
472482 second_limit = self ._earliest_cache_datetime ()
473483
474484 if self ._use_api (first_limit ):
0 commit comments