aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/cogs/moderation.py69
-rw-r--r--bot/converters.py17
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