diff options
| author | 2018-07-23 23:48:54 -0400 | |
|---|---|---|
| committer | 2018-07-23 23:48:54 -0400 | |
| commit | d5bdc261acaba5d736ccecadd51d660fcc2e034c (patch) | |
| tree | 353d209677bffe78665e747fb632092d6929f74f | |
| parent | Unmute and unban commands (diff) | |
Add infraction search for user, converter for user-string-fallback
| -rw-r--r-- | bot/cogs/moderation.py | 69 | ||||
| -rw-r--r-- | bot/converters.py | 17 |
2 files changed, 84 insertions, 2 deletions
diff --git a/bot/cogs/moderation.py b/bot/cogs/moderation.py index 8829c595d..6eebd4f8d 100644 --- a/bot/cogs/moderation.py +++ b/bot/cogs/moderation.py @@ -3,12 +3,14 @@ import datetime import logging from typing import Dict -from discord import Guild, Member, User +from discord import Colour, Embed, Guild, Member, User from discord.ext.commands import Bot, Context, command from bot import constants from bot.constants import Keys, Roles, URLs +from bot.converters import InfractionSearchQuery from bot.decorators import with_role +from bot.pagination import LinePaginator log = logging.getLogger(__name__) @@ -36,6 +38,8 @@ class Moderation: if infraction_object["expires_at"] is not None: self.schedule_expiration(loop, infraction_object) + # Permanent infractions + @with_role(Roles.admin, Roles.owner, Roles.moderator) @command(name="moderation.warn") async def warn(self, ctx: Context, user: User, reason: str = None): @@ -153,6 +157,8 @@ class Moderation: await ctx.send(result_message) + # Temporary infractions + @with_role(Roles.admin, Roles.owner, Roles.moderator) @command(name="moderation.tempmute") async def tempmute(self, ctx: Context, user: Member, duration: str, reason: str = None): @@ -248,6 +254,8 @@ class Moderation: await ctx.send(result_message) + # Remove infractions (un- commands) + @with_role(Roles.admin, Roles.owner, Roles.moderator) @command(name="moderation.unmute") async def unmute(self, ctx, user: Member): @@ -324,6 +332,54 @@ class Moderation: await ctx.send(":x: There was an error removing the infraction.") return + @with_role(Roles.admin, Roles.owner, Roles.moderator) + @command(name="infraction.search") + async def search(self, ctx, arg: InfractionSearchQuery): + """ + Searches for infractions in the database. + :param arg: Either a user or a reason string. + """ + if isinstance(arg, User): + user: User = arg + # get infractions for this user + try: + response = await self.bot.http_session.get( + URLs.site_infractions_user.format( + user_id=user.id + ), + headers=self.headers + ) + infraction_list = await response.json() + except Exception: + log.exception("There was an error fetching infractions.") + await ctx.send(":x: There was an error fetching infraction.") + return + + if not infraction_list: + await ctx.send(f":warning: No infractions found for {user}.") + return + + embed = Embed( + title=f"Infractions for {user} ({len(infraction_list)} total)", + colour=Colour.orange() + ) + + await LinePaginator.paginate( + lines=(infraction_to_string(infraction_object) for infraction_object in infraction_list), + ctx=ctx, + embed=embed, + empty=True, + max_lines=5 + ) + + elif isinstance(arg, str): + # search by reason + return + else: + await ctx.send(":x: Invalid infraction search query.") + + # Utility functions + def schedule_expiration(self, loop: asyncio.AbstractEventLoop, infraction_object: dict): infraction_id = infraction_object["id"] if infraction_id in self.expiration_tasks: @@ -400,6 +456,17 @@ def _silent_exception(future): pass +def infraction_to_string(infraction_object): + return "\n".join(( + "===============", + "Type: **{0}**".format(infraction_object["type"]), + "Reason: {0}".format(infraction_object["reason"] or "*None*"), + "Created: {0}".format(infraction_object["inserted_at"]), + "Expires: {0}".format(infraction_object["expires_at"] or "*Permanent*"), + "===============", + )) + + def setup(bot): bot.add_cog(Moderation(bot)) # Here we'll need to call a command I haven't made yet diff --git a/bot/converters.py b/bot/converters.py index 5637ab8b2..f98e02015 100644 --- a/bot/converters.py +++ b/bot/converters.py @@ -4,7 +4,7 @@ from ssl import CertificateError import discord from aiohttp import AsyncResolver, ClientConnectorError, ClientSession, TCPConnector -from discord.ext.commands import BadArgument, Converter +from discord.ext.commands import BadArgument, Converter, UserConverter from fuzzywuzzy import fuzz from bot.constants import DEBUG_MODE, Keys, URLs @@ -157,3 +157,18 @@ class ValidURL(Converter): except ClientConnectorError: raise BadArgument(f"Cannot connect to host with URL `{url}`.") return url + + +class InfractionSearchQuery(Converter): + """ + A converter that checks if the argument is a Discord user, and if not, fall-backs to a string. + """ + + @staticmethod + async def convert(ctx, arg): + try: + user_converter = UserConverter() + user = await user_converter.convert(ctx, arg) + except Exception: + return arg + return user or arg |