diff options
author | 2019-10-11 21:37:32 +0200 | |
---|---|---|
committer | 2019-10-11 21:37:32 +0200 | |
commit | d5f20ca11eb7873a79ff70efbc7db4f4c9fdab23 (patch) | |
tree | f3d453eed5c81bdd0ae773493dbac6774bdbfd2c | |
parent | Merge pull request #512 from python-discord/user-left-log (diff) | |
parent | Merge branch 'master' into moderation-tweaks (diff) |
Merge pull request #509 from python-discord/moderation-tweaks
Moderation tweaks
-rw-r--r-- | bot/cogs/moderation/infractions.py | 56 | ||||
-rw-r--r-- | bot/cogs/moderation/management.py | 17 | ||||
-rw-r--r-- | bot/cogs/moderation/superstarify.py | 22 | ||||
-rw-r--r-- | bot/cogs/moderation/utils.py | 2 |
4 files changed, 71 insertions, 26 deletions
diff --git a/bot/cogs/moderation/infractions.py b/bot/cogs/moderation/infractions.py index 76f39d13c..592ead60f 100644 --- a/bot/cogs/moderation/infractions.py +++ b/bot/cogs/moderation/infractions.py @@ -12,7 +12,6 @@ from discord.ext.commands import Context, command from bot import constants from bot.api import ResponseCodeError from bot.constants import Colours, Event -from bot.converters import Duration from bot.decorators import respect_role_hierarchy from bot.utils import time from bot.utils.checks import with_role_check @@ -113,7 +112,7 @@ class Infractions(Scheduler, commands.Cog): # region: Temporary infractions @command(aliases=["mute"]) - async def tempmute(self, ctx: Context, user: Member, duration: Duration, *, reason: str = None) -> None: + async def tempmute(self, ctx: Context, user: Member, duration: utils.Expiry, *, reason: str = None) -> None: """ Temporarily mute a user for the given reason and duration. @@ -126,11 +125,13 @@ class Infractions(Scheduler, commands.Cog): \u2003`h` - hours \u2003`M` - minutes∗ \u2003`s` - seconds + + Alternatively, an ISO 8601 timestamp can be provided for the duration. """ await self.apply_mute(ctx, user, reason, expires_at=duration) @command() - async def tempban(self, ctx: Context, user: MemberConverter, duration: Duration, *, reason: str = None) -> None: + async def tempban(self, ctx: Context, user: MemberConverter, duration: utils.Expiry, *, reason: str = None) -> None: """ Temporarily ban a user for the given reason and duration. @@ -143,6 +144,8 @@ class Infractions(Scheduler, commands.Cog): \u2003`h` - hours \u2003`M` - minutes∗ \u2003`s` - seconds + + Alternatively, an ISO 8601 timestamp can be provided for the duration. """ await self.apply_ban(ctx, user, reason, expires_at=duration) @@ -172,9 +175,7 @@ class Infractions(Scheduler, commands.Cog): # region: Temporary shadow infractions @command(hidden=True, aliases=["shadowtempmute, stempmute", "shadowmute", "smute"]) - async def shadow_tempmute( - self, ctx: Context, user: Member, duration: Duration, *, reason: str = None - ) -> None: + async def shadow_tempmute(self, ctx: Context, user: Member, duration: utils.Expiry, *, reason: str = None) -> None: """ Temporarily mute a user for the given reason and duration without notifying the user. @@ -187,12 +188,19 @@ class Infractions(Scheduler, commands.Cog): \u2003`h` - hours \u2003`M` - minutes∗ \u2003`s` - seconds + + Alternatively, an ISO 8601 timestamp can be provided for the duration. """ await self.apply_mute(ctx, user, reason, expires_at=duration, hidden=True) @command(hidden=True, aliases=["shadowtempban, stempban"]) async def shadow_tempban( - self, ctx: Context, user: MemberConverter, duration: Duration, *, reason: str = None + self, + ctx: Context, + user: MemberConverter, + duration: utils.Expiry, + *, + reason: str = None ) -> None: """ Temporarily ban a user for the given reason and duration without notifying the user. @@ -206,6 +214,8 @@ class Infractions(Scheduler, commands.Cog): \u2003`h` - hours \u2003`M` - minutes∗ \u2003`s` - seconds + + Alternatively, an ISO 8601 timestamp can be provided for the duration. """ await self.apply_ban(ctx, user, reason, expires_at=duration, hidden=True) @@ -310,7 +320,8 @@ class Infractions(Scheduler, commands.Cog): log_content = None log_text = { "Member": str(user_id), - "Actor": str(self.bot.user) + "Actor": str(self.bot.user), + "Reason": infraction["reason"] } try: @@ -355,6 +366,22 @@ class Infractions(Scheduler, commands.Cog): log_text["Failure"] = f"HTTPException with code {e.code}." log_content = mod_role.mention + # Check if the user is currently being watched by Big Brother. + try: + active_watch = await self.bot.api_client.get( + "bot/infractions", + params={ + "active": "true", + "type": "watch", + "user__id": user_id + } + ) + + log_text["Watching"] = "Yes" if active_watch else "No" + except ResponseCodeError: + log.exception(f"Failed to fetch watch status for user {user_id}") + log_text["Watching"] = "Unknown - failed to fetch watch status." + try: # Mark infraction as inactive in the database. await self.bot.api_client.patch( @@ -415,7 +442,6 @@ class Infractions(Scheduler, commands.Cog): expiry_log_text = f"Expires: {expiry}" if expiry else "" log_title = "applied" log_content = None - reason_msg = "" # DM the user about the infraction if it's not a shadow/hidden infraction. if not infraction["hidden"]: @@ -431,7 +457,13 @@ class Infractions(Scheduler, commands.Cog): log_content = ctx.author.mention if infraction["actor"] == self.bot.user.id: - reason_msg = f" (reason: {infraction['reason']})" + end_msg = f" (reason: {infraction['reason']})" + else: + infractions = await self.bot.api_client.get( + "bot/infractions", + params={"user__id": str(user.id)} + ) + end_msg = f" ({len(infractions)} infractions total)" # Execute the necessary actions to apply the infraction on Discord. if action_coro: @@ -448,7 +480,9 @@ class Infractions(Scheduler, commands.Cog): log_title = "failed to apply" # Send a confirmation message to the invoking context. - await ctx.send(f"{dm_result}{confirm_msg} **{infr_type}** to {user.mention}{expiry_msg}{reason_msg}.") + await ctx.send( + f"{dm_result}{confirm_msg} **{infr_type}** to {user.mention}{expiry_msg}{end_msg}." + ) # Send a log message to the mod log. await self.mod_log.send_log_message( diff --git a/bot/cogs/moderation/management.py b/bot/cogs/moderation/management.py index cb266b608..491f6d400 100644 --- a/bot/cogs/moderation/management.py +++ b/bot/cogs/moderation/management.py @@ -8,7 +8,7 @@ from discord.ext import commands from discord.ext.commands import Context from bot import constants -from bot.converters import Duration, InfractionSearchQuery +from bot.converters import InfractionSearchQuery from bot.pagination import LinePaginator from bot.utils import time from bot.utils.checks import with_role_check @@ -60,7 +60,7 @@ class ModManagement(commands.Cog): self, ctx: Context, infraction_id: int, - expires_at: t.Union[Duration, permanent_duration, None], + duration: t.Union[utils.Expiry, permanent_duration, None], *, reason: str = None ) -> None: @@ -77,9 +77,10 @@ class ModManagement(commands.Cog): \u2003`M` - minutes∗ \u2003`s` - seconds - Use "permanent" to mark the infraction as permanent. + Use "permanent" to mark the infraction as permanent. Alternatively, an ISO 8601 timestamp + can be provided for the duration. """ - if expires_at is None and reason is None: + if duration is None and reason is None: # Unlike UserInputError, the error handler will show a specified message for BadArgument raise commands.BadArgument("Neither a new expiry nor a new reason was specified.") @@ -90,12 +91,12 @@ class ModManagement(commands.Cog): confirm_messages = [] log_text = "" - if expires_at == "permanent": + if duration == "permanent": request_data['expires_at'] = None confirm_messages.append("marked as permanent") - elif expires_at is not None: - request_data['expires_at'] = expires_at.isoformat() - expiry = expires_at.strftime(time.INFRACTION_FORMAT) + elif duration is not None: + request_data['expires_at'] = duration.isoformat() + expiry = duration.strftime(time.INFRACTION_FORMAT) confirm_messages.append(f"set to expire on {expiry}") else: confirm_messages.append("expiry unchanged") diff --git a/bot/cogs/moderation/superstarify.py b/bot/cogs/moderation/superstarify.py index f3fcf236b..ccc6395d9 100644 --- a/bot/cogs/moderation/superstarify.py +++ b/bot/cogs/moderation/superstarify.py @@ -8,7 +8,6 @@ from discord.errors import Forbidden from discord.ext.commands import Bot, Cog, Context, command from bot import constants -from bot.converters import Duration from bot.utils.checks import with_role_check from bot.utils.time import format_infraction from . import utils @@ -144,21 +143,30 @@ class Superstarify(Cog): ) @command(name='superstarify', aliases=('force_nick', 'star')) - async def superstarify( - self, ctx: Context, member: Member, expiration: Duration, reason: str = None - ) -> None: + async def superstarify(self, ctx: Context, member: Member, duration: utils.Expiry, reason: str = None) -> None: """ Force a random superstar name (like Taylor Swift) to be the user's nickname for a specified duration. - An optional reason can be provided. + A unit of time should be appended to the duration. + Units (∗case-sensitive): + \u2003`y` - years + \u2003`m` - months∗ + \u2003`w` - weeks + \u2003`d` - days + \u2003`h` - hours + \u2003`M` - minutes∗ + \u2003`s` - seconds - If no reason is given, the original name will be shown in a generated reason. + Alternatively, an ISO 8601 timestamp can be provided for the duration. + + An optional reason can be provided. If no reason is given, the original name will be shown + in a generated reason. """ if await utils.has_active_infraction(ctx, member, "superstar"): return reason = reason or ('old nick: ' + member.display_name) - infraction = await utils.post_infraction(ctx, member, 'superstar', reason, expires_at=expiration) + infraction = await utils.post_infraction(ctx, member, 'superstar', reason, expires_at=duration) forced_nick = self.get_nick(infraction['id'], member.id) expiry_str = format_infraction(infraction["expires_at"]) diff --git a/bot/cogs/moderation/utils.py b/bot/cogs/moderation/utils.py index e9c879b46..788a40d40 100644 --- a/bot/cogs/moderation/utils.py +++ b/bot/cogs/moderation/utils.py @@ -9,6 +9,7 @@ from discord.ext.commands import Context from bot.api import ResponseCodeError from bot.constants import Colours, Icons +from bot.converters import Duration, ISODateTime log = logging.getLogger(__name__) @@ -26,6 +27,7 @@ APPEALABLE_INFRACTIONS = ("ban", "mute") UserTypes = t.Union[discord.Member, discord.User] MemberObject = t.Union[UserTypes, discord.Object] Infraction = t.Dict[str, t.Union[str, int, bool]] +Expiry = t.Union[Duration, ISODateTime] def proxy_user(user_id: str) -> discord.Object: |