From f48d32ff836bbfc239aa82f013cfb0687aa3defd Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Mon, 20 Apr 2020 18:58:57 +0100 Subject: Add statistics on whether a help session was closed with no input from anyone but the claimant --- bot/cogs/help_channels.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index e73bbdae5..060a010cc 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -133,6 +133,7 @@ class HelpChannels(Scheduler, commands.Cog): # Stats self.claim_times = {} + self.unanswered = {} def cog_unload(self) -> None: """Cancel the init task and scheduled tasks when the cog unloads.""" @@ -506,6 +507,12 @@ class HelpChannels(Scheduler, commands.Cog): in_use_time = datetime.now() - claimed self.bot.stats.timing("help.in_use_time", in_use_time) + if channel.id in self.unanswered: + if self.unanswered[channel.id]: + self.bot.stats.incr("help.sessions.unanswered") + else: + self.bot.stats.incr("help.sessions.answered") + log.trace(f"Position of #{channel} ({channel.id}) is actually {channel.position}.") log.trace(f"Sending dormant message for #{channel} ({channel.id}).") @@ -587,6 +594,13 @@ class HelpChannels(Scheduler, commands.Cog): return # Ignore messages sent by bots. channel = message.channel + if not self.is_in_category(channel, constants.Categories.help_in_use): + if channel.id in self.unanswered: + claimant_id = self.help_channel_claimants[channel].id + + if claimant_id != message.author.id: + self.unanswered[channel.id] = False + if not self.is_in_category(channel, constants.Categories.help_available): return # Ignore messages outside the Available category. @@ -612,6 +626,7 @@ class HelpChannels(Scheduler, commands.Cog): self.bot.stats.incr("help.claimed") self.claim_times[channel.id] = datetime.now() + self.unanswered[channel.id] = True log.trace(f"Releasing on_message lock for {message.id}.") -- cgit v1.2.3 From 96ef7f76ba24134b4688ca69a2287eb52a33a1e4 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Mon, 20 Apr 2020 19:01:24 +0100 Subject: Incorrect comparison, we need to check if we are in help_in_use, not out of it --- bot/cogs/help_channels.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 060a010cc..c640c4d6f 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -594,7 +594,7 @@ class HelpChannels(Scheduler, commands.Cog): return # Ignore messages sent by bots. channel = message.channel - if not self.is_in_category(channel, constants.Categories.help_in_use): + if self.is_in_category(channel, constants.Categories.help_in_use): if channel.id in self.unanswered: claimant_id = self.help_channel_claimants[channel].id -- cgit v1.2.3 From d5aef24b212814ad63f3f01069d3c375625af858 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Mon, 20 Apr 2020 21:12:38 +0100 Subject: Add different emoji for different channel statuses (in use answered/unanswered) --- bot/cogs/help_channels.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index c640c4d6f..815a5997a 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -62,7 +62,8 @@ through our guide for [asking a good question]({ASKING_GUIDE_URL}). """ AVAILABLE_EMOJI = "✅" -IN_USE_EMOJI = "⌛" +IN_USE_ANSWERED_EMOJI = "⌛" +IN_USE_UNANSWERED_EMOJI = "⏳" NAME_SEPARATOR = "|" @@ -528,7 +529,7 @@ class HelpChannels(Scheduler, commands.Cog): log.info(f"Moving #{channel} ({channel.id}) to the In Use category.") await channel.edit( - name=f"{IN_USE_EMOJI}{NAME_SEPARATOR}{self.get_clean_channel_name(channel)}", + name=f"{IN_USE_UNANSWERED_EMOJI}{NAME_SEPARATOR}{self.get_clean_channel_name(channel)}", category=self.in_use_category, sync_permissions=True, topic=IN_USE_TOPIC, @@ -601,6 +602,10 @@ class HelpChannels(Scheduler, commands.Cog): if claimant_id != message.author.id: self.unanswered[channel.id] = False + await channel.edit( + name=f"{IN_USE_ANSWERED_EMOJI}{NAME_SEPARATOR}{self.get_clean_channel_name(channel)}" + ) + if not self.is_in_category(channel, constants.Categories.help_available): return # Ignore messages outside the Available category. -- cgit v1.2.3 From 2b8bc72dacab82edc82111ab0cd8dbc6d3e724d6 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Mon, 20 Apr 2020 21:28:27 +0100 Subject: Extra documentation + split out to separate function --- bot/cogs/help_channels.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 815a5997a..3c41673b4 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -133,8 +133,14 @@ class HelpChannels(Scheduler, commands.Cog): self.init_task = self.bot.loop.create_task(self.init_cog()) # Stats - self.claim_times = {} - self.unanswered = {} + + # This dictionary maps a help channel to the time it was claimed + self.claim_times: t.Dict[int, datetime] = {} + + # This dictionary 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. + self.unanswered: t.Dict[int, bool] = {} def cog_unload(self) -> None: """Cancel the init task and scheduled tasks when the cog unloads.""" @@ -588,24 +594,36 @@ class HelpChannels(Scheduler, commands.Cog): # Handle it here cause this feature isn't critical for the functionality of the system. log.exception("Failed to send notification about lack of dormant channels!") - @commands.Cog.listener() - async def on_message(self, message: discord.Message) -> None: - """Move an available channel to the In Use category and replace it with a dormant one.""" - if message.author.bot: - return # Ignore messages sent by bots. - + async def check_for_answer(self, message: discord.Message) -> None: + """Checks for whether new content in a help channel comes from non-claimants.""" channel = message.channel + + # Confirm the channel is an in use help channel if self.is_in_category(channel, constants.Categories.help_in_use): + # Check if there is an entry in unanswered (does not persist across restarts) if channel.id in self.unanswered: claimant_id = self.help_channel_claimants[channel].id + # Check the message did not come from the claimant if claimant_id != message.author.id: + # Mark the channel as answered self.unanswered[channel.id] = False + # Change the emoji in the channel name to signify activity await channel.edit( name=f"{IN_USE_ANSWERED_EMOJI}{NAME_SEPARATOR}{self.get_clean_channel_name(channel)}" ) + @commands.Cog.listener() + async def on_message(self, message: discord.Message) -> None: + """Move an available channel to the In Use category and replace it with a dormant one.""" + if message.author.bot: + return # Ignore messages sent by bots. + + channel = message.channel + + await self.check_for_answer(message) + if not self.is_in_category(channel, constants.Categories.help_available): return # Ignore messages outside the Available category. -- cgit v1.2.3 From b842bfe9a1f5b811bc9cbfa0e354a01bbb02152e Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 20 Apr 2020 14:09:31 -0700 Subject: HelpChannels: add logging to answered check --- bot/cogs/help_channels.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 3c41673b4..9d7328739 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -597,6 +597,7 @@ class HelpChannels(Scheduler, commands.Cog): async def check_for_answer(self, message: discord.Message) -> None: """Checks for whether new content in a help channel comes from non-claimants.""" channel = message.channel + log.trace(f"Checking if #{channel} ({channel.id}) has been answered.") # Confirm the channel is an in use help channel if self.is_in_category(channel, constants.Categories.help_in_use): @@ -610,9 +611,9 @@ class HelpChannels(Scheduler, commands.Cog): self.unanswered[channel.id] = False # Change the emoji in the channel name to signify activity - await channel.edit( - name=f"{IN_USE_ANSWERED_EMOJI}{NAME_SEPARATOR}{self.get_clean_channel_name(channel)}" - ) + log.trace(f"#{channel} ({channel.id}) has been answered; changing its emoji") + name = self.get_clean_channel_name(channel) + await channel.edit(name=f"{IN_USE_ANSWERED_EMOJI}{NAME_SEPARATOR}{name}") @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: -- cgit v1.2.3 From ed80b91c36bfa397634a64f7881655454fc9557f Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Tue, 21 Apr 2020 14:12:48 +0100 Subject: Fix category cache issue --- bot/cogs/help_channels.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 9d7328739..a61f30deb 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -276,13 +276,12 @@ class HelpChannels(Scheduler, commands.Cog): return name - @staticmethod - def get_category_channels(category: discord.CategoryChannel) -> t.Iterable[discord.TextChannel]: + def get_category_channels(self, category: discord.CategoryChannel) -> t.Iterable[discord.TextChannel]: """Yield the text channels of the `category` in an unsorted manner.""" log.trace(f"Getting text channels in the category '{category}' ({category.id}).") # This is faster than using category.channels because the latter sorts them. - for channel in category.guild.channels: + for channel in self.bot.get_guild(constants.Guild.id).channels: if channel.category_id == category.id and isinstance(channel, discord.TextChannel): yield channel -- cgit v1.2.3