diff options
| author | 2018-12-05 00:49:44 +0100 | |
|---|---|---|
| committer | 2018-12-05 00:49:44 +0100 | |
| commit | 1a40e4b17daa64179f14358b4f86f0602131d799 (patch) | |
| tree | abb41642938683c80588a4bb045634ccfc63d5a1 | |
| parent | Refactored - codeblocks now make use of the bot.utils.messages util. (#202) (diff) | |
Fixed the !user command so users can still use it if they target themselves. Also restricted it to #bot-commands for anyone except mods and up.
| -rw-r--r-- | bot/cogs/information.py | 32 | ||||
| -rw-r--r-- | bot/cogs/tags.py | 2 | ||||
| -rw-r--r-- | bot/decorators.py | 46 | ||||
| -rw-r--r-- | bot/utils/checks.py | 56 |
4 files changed, 105 insertions, 31 deletions
diff --git a/bot/cogs/information.py b/bot/cogs/information.py index 0f1aa75c5..fa6f56b3e 100644 --- a/bot/cogs/information.py +++ b/bot/cogs/information.py @@ -1,11 +1,13 @@ import logging +import random import textwrap from discord import CategoryChannel, Colour, Embed, Member, TextChannel, VoiceChannel -from discord.ext.commands import Bot, Context, command +from discord.ext.commands import BadArgument, Bot, CommandError, Context, MissingPermissions, command -from bot.constants import Emojis, Keys, Roles, URLs +from bot.constants import Channels, Emojis, Keys, NEGATIVE_REPLIES, Roles, URLs from bot.decorators import with_role +from bot.utils.checks import with_role_check from bot.utils.time import time_since log = logging.getLogger(__name__) @@ -121,13 +123,23 @@ class Information: await ctx.send(embed=embed) - @with_role(*MODERATION_ROLES) @command(name="user", aliases=["user_info", "member", "member_info"]) async def user_info(self, ctx: Context, user: Member = None, hidden: bool = False): """ Returns info about a user. """ + # Do a role check if this is being executed on + # someone other than the caller + if user and user != ctx.author: + if not with_role_check(ctx, *MODERATION_ROLES): + raise BadArgument("Only mods can do target other users.") + + # Non-moderators may only do this in #bot-commands + if not with_role_check(ctx, *MODERATION_ROLES): + if not ctx.channel == Channels.bot: + raise MissingPermissions("You can't do that here!") + # Validates hidden input hidden = str(hidden) @@ -192,6 +204,20 @@ class Information: await ctx.send(embed=embed) + @user_info.error + async def eval_command_error(self, ctx: Context, error: CommandError): + embed = Embed(colour=Colour.red()) + + if isinstance(error, BadArgument): + embed.title = random.choice(NEGATIVE_REPLIES) + embed.description = "You do not have permission to use this command on users other than yourself." + await ctx.send(embed=embed) + + elif isinstance(error, MissingPermissions): + embed.title = random.choice(NEGATIVE_REPLIES) + embed.description = f"Sorry, but you may only use this command within <#{Channels.bot}>." + await ctx.send(embed=embed) + def setup(bot): bot.add_cog(Information(bot)) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index a0ba7fdd1..ba4edeef7 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -149,7 +149,7 @@ class Tags: tags = [] - embed = Embed() + embed: Embed = Embed() embed.colour = Colour.red() tag_data = await self.get_tag_data(tag_name) diff --git a/bot/decorators.py b/bot/decorators.py index fe974cbd3..630c2267f 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -9,49 +9,41 @@ from discord.ext import commands from discord.ext.commands import Context from bot.constants import ERROR_REPLIES +from bot.utils.checks import in_channel_check, with_role_check, without_role_check log = logging.getLogger(__name__) def with_role(*role_ids: int): + """ + Returns True if the user has any one + of the roles in role_ids. + """ + async def predicate(ctx: Context): - if not ctx.guild: # Return False in a DM - log.debug(f"{ctx.author} tried to use the '{ctx.command.name}'command from a DM. " - "This command is restricted by the with_role decorator. Rejecting request.") - return False - - for role in ctx.author.roles: - if role.id in role_ids: - log.debug(f"{ctx.author} has the '{role.name}' role, and passes the check.") - return True - - log.debug(f"{ctx.author} does not have the required role to use " - f"the '{ctx.command.name}' command, so the request is rejected.") - return False + return with_role_check(ctx, *role_ids) return commands.check(predicate) def without_role(*role_ids: int): + """ + Returns True if the user does not have any + of the roles in role_ids. + """ + async def predicate(ctx: Context): - if not ctx.guild: # Return False in a DM - log.debug(f"{ctx.author} tried to use the '{ctx.command.name}' command from a DM. " - "This command is restricted by the without_role decorator. Rejecting request.") - return False - - author_roles = [role.id for role in ctx.author.roles] - check = all(role not in author_roles for role in role_ids) - log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " - f"The result of the without_role check was {check}.") - return check + return without_role_check(ctx, *role_ids) return commands.check(predicate) def in_channel(channel_id): + """ + Checks if the command was executed + inside of the specified channel. + """ + async def predicate(ctx: Context): - check = ctx.channel.id == channel_id - log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " - f"The result of the in_channel check was {check}.") - return check + return in_channel_check(ctx, channel_id) return commands.check(predicate) diff --git a/bot/utils/checks.py b/bot/utils/checks.py new file mode 100644 index 000000000..d07b09fc8 --- /dev/null +++ b/bot/utils/checks.py @@ -0,0 +1,56 @@ +import logging + +from discord.ext.commands import Context + +log = logging.getLogger(__name__) + + +def with_role_check(ctx: Context, *role_ids: int) -> bool: + """ + Returns True if the user has any one + of the roles in role_ids. + """ + + if not ctx.guild: # Return False in a DM + log.debug(f"{ctx.author} tried to use the '{ctx.command.name}'command from a DM. " + "This command is restricted by the with_role decorator. Rejecting request.") + return False + + for role in ctx.author.roles: + if role.id in role_ids: + log.debug(f"{ctx.author} has the '{role.name}' role, and passes the check.") + return True + + log.debug(f"{ctx.author} does not have the required role to use " + f"the '{ctx.command.name}' command, so the request is rejected.") + return False + + +def without_role_check(ctx: Context, *role_ids: int) -> bool: + """ + Returns True if the user does not have any + of the roles in role_ids. + """ + + if not ctx.guild: # Return False in a DM + log.debug(f"{ctx.author} tried to use the '{ctx.command.name}' command from a DM. " + "This command is restricted by the without_role decorator. Rejecting request.") + return False + + author_roles = [role.id for role in ctx.author.roles] + check = all(role not in author_roles for role in role_ids) + log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " + f"The result of the without_role check was {check}.") + return check + + +def in_channel_check(ctx: Context, channel_id: int) -> bool: + """ + Checks if the command was executed + inside of the specified channel. + """ + + check = ctx.channel.id == channel_id + log.debug(f"{ctx.author} tried to call the '{ctx.command.name}' command. " + f"The result of the in_channel check was {check}.") + return check |