diff options
| author | 2020-04-12 09:20:57 +0200 | |
|---|---|---|
| committer | 2020-04-12 09:20:57 +0200 | |
| commit | 42157c4b50163dcf7ba550b603ed4855e42816b4 (patch) | |
| tree | cbfc60ccd48c7c4110898f984b0b7145b658e757 | |
| parent | timer -> timing for statsd (diff) | |
| parent | Fix `help_channel_claimants` typehint. (diff) | |
Merge branch 'help-dormant-feedback' of https://github.com/Numerlor/bot into Numerlor-help-dormant-feedback
| -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. | 
