diff options
| -rw-r--r-- | bot/exts/help_channels/_caches.py | 16 | ||||
| -rw-r--r-- | bot/exts/help_channels/_channel.py | 33 | ||||
| -rw-r--r-- | bot/exts/help_channels/_cog.py | 21 | ||||
| -rw-r--r-- | bot/exts/help_channels/_message.py | 31 | ||||
| -rw-r--r-- | bot/exts/help_channels/_stats.py | 6 |
5 files changed, 48 insertions, 59 deletions
diff --git a/bot/exts/help_channels/_caches.py b/bot/exts/help_channels/_caches.py index d4676df87..834c5f4c2 100644 --- a/bot/exts/help_channels/_caches.py +++ b/bot/exts/help_channels/_caches.py @@ -8,20 +8,16 @@ claim_times = RedisCache(namespace="HelpChannels.claim_times") # RedisCache[discord.TextChannel.id, t.Union[discord.User.id, discord.Member.id]] claimants = RedisCache(namespace="HelpChannels.help_channel_claimants") -# Stores the timestamp of the last message in a help channel -# RedisCache[discord.TextChannel.id, UtcPosixTimestamp] -last_message_times = RedisCache(namespace="HelpChannels.last_message_times") - # Stores the timestamp of the last message from the claimant of a help channel # RedisCache[discord.TextChannel.id, UtcPosixTimestamp] claimant_last_message_times = RedisCache(namespace="HelpChannels.claimant_last_message_times") +# This cache maps a help channel to the timestamp of the last, non-claimant, +# message. This cache being empty for a given help channel indicates the +# question is unanswered. +# RedisCache[discord.TextChannel.id, UtcPosixTimestamp] +non_claimant_last_message_times = RedisCache(namespace="HelpChannels.non_claimant_last_message_times") + # This cache maps a help channel to original question message in same channel. # RedisCache[discord.TextChannel.id, discord.Message.id] question_messages = RedisCache(namespace="HelpChannels.question_messages") - -# This cache maps a help channel to whether it has had any -# activity other than the original claimant. True being no other -# activity and False being other activity. -# RedisCache[discord.TextChannel.id, bool] -unanswered = RedisCache(namespace="HelpChannels.unanswered") diff --git a/bot/exts/help_channels/_channel.py b/bot/exts/help_channels/_channel.py index 6c17a26e0..3e3749041 100644 --- a/bot/exts/help_channels/_channel.py +++ b/bot/exts/help_channels/_channel.py @@ -25,8 +25,13 @@ def get_category_channels(category: discord.CategoryChannel) -> t.Iterable[disco yield channel -async def get_closing_time(channel: discord.TextChannel) -> t.Optional[int]: - """Return the timestamp at which the given help `channel` should be closed.""" +async def get_closing_time(channel: discord.TextChannel) -> datetime: + """ + Return the timestamp at which the given help `channel` should be closed. + + If either cache is empty, use the last message in the channel to determine closign time. + If the last message connt be retreived, return datetime.min, I.E close right now. + """ log.trace(f"Getting the closing time for #{channel} ({channel.id}).") if await _message.is_empty(channel): @@ -34,32 +39,32 @@ async def get_closing_time(channel: discord.TextChannel) -> t.Optional[int]: else: idle_minutes = constants.HelpChannels.idle_minutes_others - last_message_time = await _caches.last_message_times.get(channel.id) + non_claimant_last_message_time = await _caches.non_claimant_last_message_times.get(channel.id) claimant_last_message_time = await _caches.claimant_last_message_times.get(channel.id) - if not (last_message_time or claimant_last_message_time): + if not (non_claimant_last_message_time or claimant_last_message_time): # Using the old method if we can't get cached info. msg = await _message.get_last_message(channel) if not msg: log.debug(f"No idle time available; #{channel} ({channel.id}) has no messages.") return datetime.min - # We want to get the time at which a channel should be closed. - closing_time = msg.created_at - closing_time += timedelta(minutes=idle_minutes) + # The time at which a channel should be closed. + return msg.created_at + timedelta(minutes=idle_minutes) - return closing_time - - # We want to get the time at which a channel should be closed. - last_message_time = datetime.fromtimestamp(last_message_time) + # Get the later time at which a channel should be closed + non_claimant_last_message_time = datetime.fromtimestamp(non_claimant_last_message_time) claimant_last_message_time = datetime.fromtimestamp(claimant_last_message_time) - last_message_time += timedelta(minutes=idle_minutes) + non_claimant_last_message_time += timedelta(minutes=idle_minutes) claimant_last_message_time += timedelta(minutes=constants.HelpChannels.idle_minutes_claimant) # The further away closing time is what we should use. - closing_time = max(claimant_last_message_time, last_message_time) - log.trace(f"claimant closing time: {claimant_last_message_time}, last_message closing time: {last_message_time}") + closing_time = max(claimant_last_message_time, non_claimant_last_message_time) + log.trace( + f"Claimant closing time: {claimant_last_message_time}, " + f"last_message closing time: {non_claimant_last_message_time}" + ) log.trace(f"#{channel} ({channel.id}) should be closed at {closing_time}.") return closing_time diff --git a/bot/exts/help_channels/_cog.py b/bot/exts/help_channels/_cog.py index bac9aa9dd..8c97ef2d0 100644 --- a/bot/exts/help_channels/_cog.py +++ b/bot/exts/help_channels/_cog.py @@ -117,8 +117,7 @@ class HelpChannels(commands.Cog): # Must use a timezone-aware datetime to ensure a correct POSIX timestamp. timestamp = datetime.now(timezone.utc).timestamp() await _caches.claim_times.set(message.channel.id, timestamp) - - await _caches.unanswered.set(message.channel.id, True) + await _caches.claimant_last_message_times.set(message.channel.id, timestamp) # Not awaited because it may indefinitely hold the lock while waiting for a channel. scheduling.create_task(self.move_to_available(), name=f"help_claim_{message.id}") @@ -378,6 +377,7 @@ class HelpChannels(commands.Cog): async def _unclaim_channel(self, channel: discord.TextChannel, claimant_id: int, is_auto: bool) -> None: """Actual implementation of `unclaim_channel`. See that for full documentation.""" await _caches.claimants.delete(channel.id) + await _caches.non_claimant_last_message_times.delete(channel.id) # Ignore missing tasks because a channel may still be dormant after the cooldown expires. if claimant_id in self.scheduler: @@ -419,7 +419,7 @@ class HelpChannels(commands.Cog): """ Move an available channel to the In Use category and replace it with a dormant one. - Also updates the `last_message_times` cache based on the current timestamp. If the message + Update the `last_message_times` cache based on the current timestamp. If the message author is the claimant of this channel, also update the `claimant_last_message_times` cache. """ if message.author.bot: @@ -430,21 +430,6 @@ class HelpChannels(commands.Cog): if channel_utils.is_in_category(message.channel, constants.Categories.help_available): if not _channel.is_excluded_channel(message.channel): await self.claim_channel(message) - # Initialise the cache for this channel - await _caches.claimant_last_message_times.set( - message.channel.id, - message.created_at.timestamp() - ) - await _caches.last_message_times.set( - message.channel.id, - message.created_at.timestamp() - ) - elif channel_utils.is_in_category(message.channel, constants.Categories.help_in_use): - # Overwrite the claimant message time, if its from the claimant. - if message.author == await _caches.claimants.get(message.channel.id): - await _caches.claimant_last_message_times(message.channel.id, message.created_at.timestamp()) - - await _caches.last_message_times.set(message.channel.id, message.created_at.timestamp()) else: await _message.check_for_answer(message) diff --git a/bot/exts/help_channels/_message.py b/bot/exts/help_channels/_message.py index ec2daab45..9ba019550 100644 --- a/bot/exts/help_channels/_message.py +++ b/bot/exts/help_channels/_message.py @@ -1,7 +1,7 @@ import logging import textwrap import typing as t -from datetime import datetime +from datetime import datetime, timezone import discord @@ -48,19 +48,22 @@ async def check_for_answer(message: discord.Message) -> None: # Confirm the channel is an in use help channel if is_in_category(channel, constants.Categories.help_in_use): - log.trace(f"Checking if #{channel} ({channel.id}) has been answered.") - - # Check if there is an entry in unanswered - if await _caches.unanswered.contains(channel.id): - claimant_id = await _caches.claimants.get(channel.id) - if not claimant_id: - # The mapping for this channel doesn't exist, we can't do anything. - return - - # Check the message did not come from the claimant - if claimant_id != message.author.id: - # Mark the channel as answered - await _caches.unanswered.set(channel.id, False) + log.trace(f"Checking if #{channel} ({channel.id}) has had a reply.") + # Must use a timezone-aware datetime to ensure a correct POSIX timestamp. + timestamp = datetime.now(timezone.utc).timestamp() + + # Overwrite the claimant message time, if its from the claimant. + if message.author == await _caches.claimants.get(channel.id): + await _caches.claimant_last_message_times.set(channel.id, timestamp) + return + + claimant_id = await _caches.claimants.get(channel.id) + if not claimant_id: + # The mapping for this channel doesn't exist, we can't do anything. + return + + # Cache the timestamp of the non-claimants message + await _caches.non_claimant_last_message_times.set(channel.id, timestamp) async def get_last_message(channel: discord.TextChannel) -> t.Optional[discord.Message]: diff --git a/bot/exts/help_channels/_stats.py b/bot/exts/help_channels/_stats.py index b8778e7d9..e212c495d 100644 --- a/bot/exts/help_channels/_stats.py +++ b/bot/exts/help_channels/_stats.py @@ -35,8 +35,8 @@ async def report_complete_session(channel_id: int, is_auto: bool) -> None: if in_use_time: bot.instance.stats.timing("help.in_use_time", in_use_time) - unanswered = await _caches.unanswered.get(channel_id) - if unanswered: + non_claimant_last_message_time = await _caches.non_claimant_last_message_times.get(channel_id) + if non_claimant_last_message_time is None: bot.instance.stats.incr("help.sessions.unanswered") - elif unanswered is not None: + else: bot.instance.stats.incr("help.sessions.answered") |