diff options
| -rw-r--r-- | bot/cogs/utils.py | 37 | ||||
| -rw-r--r-- | bot/constants.py | 7 | ||||
| -rw-r--r-- | config-default.yml | 4 | ||||
| -rw-r--r-- | tests/cogs/test_information.py | 7 | 
4 files changed, 47 insertions, 8 deletions
| diff --git a/bot/cogs/utils.py b/bot/cogs/utils.py index b6cecdc7c..b1c289807 100644 --- a/bot/cogs/utils.py +++ b/bot/cogs/utils.py @@ -1,15 +1,16 @@  import logging  import re  import unicodedata +from asyncio import TimeoutError, sleep  from email.parser import HeaderParser  from io import StringIO  from typing import Tuple -from discord import Colour, Embed -from discord.ext.commands import Bot, Cog, Context, command +from discord import Colour, Embed, Message +from discord.ext.commands import Bot, Cog, Context, RoleConverter, command -from bot.constants import Channels, STAFF_ROLES -from bot.decorators import in_channel +from bot.constants import Channels, MODERATION_ROLES, Mention, STAFF_ROLES +from bot.decorators import in_channel, with_role  log = logging.getLogger(__name__) @@ -128,6 +129,34 @@ class Utils(Cog):          await ctx.send(embed=embed) +    @command() +    @with_role(*MODERATION_ROLES) +    async def mention(self, ctx: Context, *, role: RoleConverter) -> None: +        """Set a role to be mentionable for a limited time.""" +        if role.mentionable: +            await ctx.send(f'{role} (ID: {role.id}) is already mentionable!') +            return + +        await role.edit(mentionable=True, reason=f'!mention done by {ctx.author} ' +                                                 f'(ID: {ctx.author.id})') + +        await ctx.send(f'{role} (ID: {role.id}) has been made mentionable. ' +                       f'I will reset it in {Mention.message_timeout} seconds,' +                       f' or when you send a message mentioning this role.') + +        def check(m: Message) -> bool: +            return role in m.role_mentions + +        try: +            await self.bot.wait_for('message', check=check, timeout=Mention.message_timeout) +            await sleep(Mention.reset_delay) +        except TimeoutError: +            pass + +        await role.edit(mentionable=False) +        await ctx.send(f'{ctx.author.mention}, ' +                       f'I have reset {role} (ID: {role.id}) to be unmentionable.') +  def setup(bot: Bot) -> None:      """Utils cog load.""" diff --git a/bot/constants.py b/bot/constants.py index 1deeaa3b8..f4f45eb2c 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -475,6 +475,13 @@ class Free(metaclass=YAMLGetter):      cooldown_per: float +class Mention(metaclass=YAMLGetter): +    section = 'mention' + +    message_timeout: int +    reset_delay: int + +  class RedirectOutput(metaclass=YAMLGetter):      section = 'redirect_output' diff --git a/config-default.yml b/config-default.yml index 38b26f64f..827ae4619 100644 --- a/config-default.yml +++ b/config-default.yml @@ -347,6 +347,10 @@ free:      cooldown_rate: 1      cooldown_per: 60.0 +mention: +    message_timeout: 300 +    reset_delay: 5 +  redirect_output:      delete_invocation: true      delete_delay: 15 diff --git a/tests/cogs/test_information.py b/tests/cogs/test_information.py index 184bd2595..986e73a65 100644 --- a/tests/cogs/test_information.py +++ b/tests/cogs/test_information.py @@ -9,7 +9,6 @@ from discord import (      CategoryChannel,      Colour,      Permissions, -    Role,      TextChannel,      VoiceChannel,  ) @@ -69,7 +68,7 @@ def test_roles_info_command(cog, ctx):  def test_role_info_command(cog, ctx): -    dummy_role = MagicMock(spec=Role) +    dummy_role = MagicMock()      dummy_role.name = "Dummy"      dummy_role.colour = Colour.blurple()      dummy_role.id = 112233445566778899 @@ -77,7 +76,7 @@ def test_role_info_command(cog, ctx):      dummy_role.permissions = Permissions(0)      dummy_role.members = [ctx.author] -    admin_role = MagicMock(spec=Role) +    admin_role = MagicMock()      admin_role.name = "Admin"      admin_role.colour = Colour.red()      admin_role.id = 998877665544332211 @@ -90,7 +89,7 @@ def test_role_info_command(cog, ctx):      cog.role_info.can_run = AsyncMock()      cog.role_info.can_run.return_value = True -    coroutine = cog.role_info.callback(cog, ctx, dummy_role, admin_role) +    coroutine = cog.role_info.callback(cog, ctx, [dummy_role, admin_role])      assert asyncio.run(coroutine) is None | 
