diff options
author | 2020-04-12 09:33:18 +0200 | |
---|---|---|
committer | 2020-04-12 09:33:18 +0200 | |
commit | d87097c99942b7b12016287e1a6bdb5924664436 (patch) | |
tree | cbfc60ccd48c7c4110898f984b0b7145b658e757 | |
parent | timer -> timing for statsd (diff) | |
parent | Merge branch 'help-dormant-feedback' of https://github.com/Numerlor/bot into ... (diff) |
Merge branch 'Numerlor-help-dormant-feedback' into `master`
After resolving the merge conflicts created by the recent stats addition, I'm merging this into master. No functional changes were made during conflict resolution (hopefully) and the merge has been tested.
-rw-r--r-- | bot/__init__.py | 2 | ||||
-rw-r--r-- | bot/cogs/help_channels.py | 61 |
2 files changed, 53 insertions, 10 deletions
diff --git a/bot/__init__.py b/bot/__init__.py index c9dbc3f40..2dd4af225 100644 --- a/bot/__init__.py +++ b/bot/__init__.py @@ -33,7 +33,7 @@ log_format = logging.Formatter(format_string) log_file = Path("logs", "bot.log") log_file.parent.mkdir(exist_ok=True) -file_handler = handlers.RotatingFileHandler(log_file, maxBytes=5242880, backupCount=7) +file_handler = handlers.RotatingFileHandler(log_file, maxBytes=5242880, backupCount=7, encoding="utf8") file_handler.setFormatter(log_format) root_log = logging.getLogger() diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 12bc4e279..4dd70d7bf 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -5,6 +5,7 @@ import logging import random import typing as t from collections import deque +from contextlib import suppress from datetime import datetime from pathlib import Path @@ -13,7 +14,7 @@ from discord.ext import commands from bot import constants from bot.bot import Bot -from bot.decorators import with_role +from bot.utils.checks import with_role_check from bot.utils.scheduling import Scheduler log = logging.getLogger(__name__) @@ -108,6 +109,9 @@ class HelpChannels(Scheduler, commands.Cog): super().__init__() self.bot = bot + self.help_channel_claimants: ( + t.Dict[discord.TextChannel, t.Union[discord.Member, discord.User]] + ) = {} # Categories self.available_category: discord.CategoryChannel = None @@ -190,15 +194,39 @@ class HelpChannels(Scheduler, commands.Cog): log.trace("Populating the name queue with names.") return deque(available_names) + async def dormant_check(self, ctx: commands.Context) -> bool: + """Return True if the user is the help channel claimant or passes the role check.""" + if self.help_channel_claimants.get(ctx.channel) == ctx.author: + log.trace(f"{ctx.author} is the help channel claimant, passing the check for dormant.") + return True + + log.trace(f"{ctx.author} is not the help channel claimant, checking roles.") + return with_role_check(ctx, *constants.HelpChannels.cmd_whitelist) + @commands.command(name="dormant", aliases=["close"], enabled=False) - @with_role(*constants.HelpChannels.cmd_whitelist) async def dormant_command(self, ctx: commands.Context) -> None: - """Make the current in-use help channel dormant.""" - log.trace("dormant command invoked; checking if the channel is in-use.") + """ + Make the current in-use help channel dormant. + Make the channel dormant if the user passes the `dormant_check`, + delete the message that invoked this, + and reset the send permissions cooldown for the user who started the session. + """ + log.trace("dormant command invoked; checking if the channel is in-use.") if ctx.channel.category == self.in_use_category: - self.cancel_task(ctx.channel.id) - await self.move_to_dormant(ctx.channel, "command") + if await self.dormant_check(ctx): + with suppress(KeyError): + del self.help_channel_claimants[ctx.channel] + + with suppress(discord.errors.NotFound): + log.trace("Deleting dormant invokation message.") + await ctx.message.delete() + + with suppress(discord.errors.HTTPException, discord.errors.NotFound): + await self.reset_claimant_send_permission(ctx.channel) + + await self.move_to_dormant(ctx.channel, "command") + self.cancel_task(ctx.channel.id) else: log.debug(f"{ctx.author} invoked command 'dormant' outside an in-use help channel") @@ -382,14 +410,13 @@ class HelpChannels(Scheduler, commands.Cog): self.bot.stats.gauge("help.total.available", total_available) self.bot.stats.gauge("help.total.dormant", total_dormant) - @staticmethod - def is_dormant_message(message: t.Optional[discord.Message]) -> bool: + def is_dormant_message(self, message: t.Optional[discord.Message]) -> bool: """Return True if the contents of the `message` match `DORMANT_MSG`.""" if not message or not message.embeds: return False embed = message.embeds[0] - return embed.description.strip() == DORMANT_MSG.strip() + return message.author == self.bot.user and embed.description.strip() == DORMANT_MSG.strip() async def move_idle_channel(self, channel: discord.TextChannel, has_task: bool = True) -> None: """ @@ -571,6 +598,8 @@ class HelpChannels(Scheduler, commands.Cog): await self.move_to_in_use(channel) await self.revoke_send_permissions(message.author) + # Add user with channel for dormant check. + self.help_channel_claimants[channel] = message.author self.bot.stats.incr("help.claimed") @@ -631,6 +660,20 @@ class HelpChannels(Scheduler, commands.Cog): log.trace(f"Ensuring channels in `Help: Available` are synchronized after permissions reset.") await self.ensure_permissions_synchronization(self.available_category) + async def reset_claimant_send_permission(self, channel: discord.TextChannel) -> None: + """Reset send permissions in the Available category for the help `channel` claimant.""" + log.trace(f"Attempting to find claimant for #{channel.name} ({channel.id}).") + try: + member = self.help_channel_claimants[channel] + except KeyError: + log.trace(f"Channel #{channel.name} ({channel.id}) not in claimant cache, permissions unchanged.") + return + + log.trace(f"Resetting send permissions for {member} ({member.id}).") + await self.update_category_permissions(self.available_category, member, overwrite=None) + # Ignore missing task when claim cooldown has passed but the channel still isn't dormant. + self.cancel_task(member.id, ignore_missing=True) + async def revoke_send_permissions(self, member: discord.Member) -> None: """ Disallow `member` to send messages in the Available category for a certain time. |