aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/exts/help_channels/_caches.py16
-rw-r--r--bot/exts/help_channels/_channel.py33
-rw-r--r--bot/exts/help_channels/_cog.py21
-rw-r--r--bot/exts/help_channels/_message.py31
-rw-r--r--bot/exts/help_channels/_stats.py6
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")