aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Chris Lovering <[email protected]>2022-02-09 12:55:55 +0000
committerGravatar Chris Lovering <[email protected]>2022-02-20 20:28:23 +0000
commit6505ab00f0695148e0e52ed1dc6815b37d4b6cae (patch)
tree662fd1c638a34b43cfb68ab3f957e92c4c66c0fc
parentCancel help channel claim on 500 from Discord (diff)
Ensure each in-use channel has a cached claimant on init
This avoids issues when a user tries to close a channel, but the cache is empty, so the author check fails.
-rw-r--r--bot/exts/help_channels/_channel.py34
-rw-r--r--bot/exts/help_channels/_cog.py1
2 files changed, 35 insertions, 0 deletions
diff --git a/bot/exts/help_channels/_channel.py b/bot/exts/help_channels/_channel.py
index e43c1e789..ff9e6a347 100644
--- a/bot/exts/help_channels/_channel.py
+++ b/bot/exts/help_channels/_channel.py
@@ -1,3 +1,4 @@
+import re
import typing as t
from datetime import timedelta
from enum import Enum
@@ -16,6 +17,7 @@ log = get_logger(__name__)
MAX_CHANNELS_PER_CATEGORY = 50
EXCLUDED_CHANNELS = (constants.Channels.cooldown,)
+CLAIMED_BY_RE = re.compile(r"Channel claimed by <@!?(?P<user_id>\d{17,20})>\.$")
class ClosingReason(Enum):
@@ -157,3 +159,35 @@ async def move_to_bottom(channel: discord.TextChannel, category_id: int, **optio
# Now that the channel is moved, we can edit the other attributes
if options:
await channel.edit(**options)
+
+
+async def ensure_cached_claimant(channel: discord.TextChannel) -> None:
+ """
+ Ensure there is a claimant cached for each help channel.
+
+ Check the redis cache first, return early if there is already a claimant cached.
+ If there isn't an entry in redis, search for the "Claimed by X." embed in channel history.
+ Stopping early if we discover a dormant message first.
+
+ If a claimant could not be found, send a warning to #helpers and set the claimant to the bot.
+ """
+ if await _caches.claimants.get(channel.id):
+ return
+
+ async for message in channel.history(limit=1000):
+ if message.author.id != bot.instance.user.id:
+ # We only care about bot messages
+ continue
+ if message.embeds:
+ if _message._match_bot_embed(message, _message.DORMANT_MSG):
+ log.info("Hit the dormant message embed before finding a claimant in %s (%d).", channel, channel.id)
+ break
+ user_id = CLAIMED_BY_RE.match(message.embeds[0].description).group("user_id")
+ await _caches.claimants.set(channel.id, int(user_id))
+ return
+
+ await bot.instance.get_channel(constants.Channels.helpers).send(
+ f"I couldn't find a claimant for {channel.mention} in that last 1000 messages. "
+ "Please use your helper powers to close the channel if/when appropriate."
+ )
+ await _caches.claimants.set(channel.id, bot.instance.user.id)
diff --git a/bot/exts/help_channels/_cog.py b/bot/exts/help_channels/_cog.py
index 6d061c8ca..b0f1a1dce 100644
--- a/bot/exts/help_channels/_cog.py
+++ b/bot/exts/help_channels/_cog.py
@@ -326,6 +326,7 @@ class HelpChannels(commands.Cog):
log.trace("Moving or rescheduling in-use channels.")
for channel in _channel.get_category_channels(self.in_use_category):
+ await _channel.ensure_cached_claimant(channel)
await self.move_idle_channel(channel, has_task=False)
# Prevent the command from being used until ready.