WIP: Moderation type registry #26

Closed
cswimr wants to merge 146 commits from aurora-3rd-party into main
5 changed files with 148 additions and 343 deletions
Showing only changes of commit d7ca5cab46 - Show all commits

View file

@ -20,7 +20,8 @@ from redbot.core import app_commands, commands, data_manager
from redbot.core.app_commands import Choice from redbot.core.app_commands import Choice
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.commands.converter import parse_relativedelta, parse_timedelta from redbot.core.commands.converter import parse_relativedelta, parse_timedelta
from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning from redbot.core.utils.chat_formatting import (box, error, humanize_list,
humanize_timedelta, warning)
from aurora.importers.aurora import ImportAuroraView from aurora.importers.aurora import ImportAuroraView
from aurora.importers.galacticbot import ImportGalacticBotView from aurora.importers.galacticbot import ImportGalacticBotView
@ -30,11 +31,17 @@ from aurora.menus.immune import Immune
from aurora.menus.overrides import Overrides from aurora.menus.overrides import Overrides
from aurora.models import Change, Moderation from aurora.models import Change, Moderation
from aurora.utilities.config import config, register_config from aurora.utilities.config import config, register_config
from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log from aurora.utilities.database import connect, create_guild_table
from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed from aurora.utilities.factory import (addrole_embed, case_factory,
changes_factory, evidenceformat_factory,
guild_embed, immune_embed,
message_factory, overrides_embed)
from aurora.utilities.json import dump from aurora.utilities.json import dump
from aurora.utilities.logger import logger from aurora.utilities.logger import logger
from aurora.utilities.utils import check_moddable, check_permissions, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta from aurora.utilities.utils import (check_moddable, check_permissions,
get_footer_image, log, send_evidenceformat,
timedelta_from_relativedelta)
class Aurora(commands.Cog): class Aurora(commands.Cog):
@ -142,7 +149,7 @@ class Aurora(commands.Cog):
if entry.user.id == self.bot.user.id: if entry.user.id == self.bot.user.id:
return return
duration = "NULL" duration = None
if entry.reason: if entry.reason:
reason = entry.reason + " (This action was performed without the bot.)" reason = entry.reason + " (This action was performed without the bot.)"
@ -175,13 +182,14 @@ class Aurora(commands.Cog):
else: else:
return return
await mysql_log( Moderation.log(
self.bot,
entry.guild.id, entry.guild.id,
entry.user.id, entry.user.id,
moderation_type, moderation_type,
"USER", "USER",
entry.target.id, entry.target.id,
0, None,
duration, duration,
reason, reason,
) )
@ -231,23 +239,22 @@ class Aurora(commands.Cog):
except discord.errors.HTTPException: except discord.errors.HTTPException:
pass pass
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"NOTE", "NOTE",
"USER", "USER",
target.id, target.id,
0, None,
"NULL", None,
reason, reason,
) )
await interaction.edit_original_response( await interaction.edit_original_response(
content=f"{target.mention} has received a note! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" content=f"{target.mention} has received a note! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`"
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="warn") @app_commands.command(name="warn")
async def warn( async def warn(
@ -290,23 +297,22 @@ class Aurora(commands.Cog):
except discord.errors.HTTPException: except discord.errors.HTTPException:
pass pass
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"WARN", "WARN",
"USER", "USER",
target.id, target.id,
0, None,
"NULL", None,
reason, reason,
) )
await interaction.edit_original_response( await interaction.edit_original_response(
content=f"{target.mention} has been warned! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" content=f"{target.mention} has been warned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`"
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="addrole") @app_commands.command(name="addrole")
async def addrole( async def addrole(
@ -349,7 +355,7 @@ class Aurora(commands.Cog):
) )
return return
else: else:
parsed_time = "NULL" parsed_time = None
if role.id not in addrole_whitelist: if role.id not in addrole_whitelist:
await interaction.response.send_message( await interaction.response.send_message(
@ -396,7 +402,8 @@ class Aurora(commands.Cog):
content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`"
) )
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"ADDROLE", "ADDROLE",
@ -407,12 +414,10 @@ class Aurora(commands.Cog):
reason, reason,
) )
await response.edit( await response.edit(
content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`", content=f"{target.mention} has been given the {role.mention} role{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`",
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="removerole") @app_commands.command(name="removerole")
async def removerole( async def removerole(
@ -455,7 +460,7 @@ class Aurora(commands.Cog):
) )
return return
else: else:
parsed_time = "NULL" parsed_time = None
if role.id not in addrole_whitelist: if role.id not in addrole_whitelist:
await interaction.response.send_message( await interaction.response.send_message(
@ -502,7 +507,8 @@ class Aurora(commands.Cog):
content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`" content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}!\n**Reason** - `{reason}`"
) )
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"REMOVEROLE", "REMOVEROLE",
@ -513,12 +519,10 @@ class Aurora(commands.Cog):
reason, reason,
) )
await response.edit( await response.edit(
content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`", content=f"{target.mention} has had the {role.mention} role removed{' for ' + humanize_timedelta(timedelta=parsed_time) if parsed_time != 'NULL' else ''}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`",
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="mute") @app_commands.command(name="mute")
async def mute( async def mute(
@ -590,23 +594,22 @@ class Aurora(commands.Cog):
except discord.errors.HTTPException: except discord.errors.HTTPException:
pass pass
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"MUTE", "MUTE",
"USER", "USER",
target.id, target.id,
0, None,
parsed_time, parsed_time,
reason, reason,
) )
await interaction.edit_original_response( await interaction.edit_original_response(
content=f"{target.mention} has been muted for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" content=f"{target.mention} has been muted for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`"
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="unmute") @app_commands.command(name="unmute")
async def unmute( async def unmute(
@ -665,23 +668,22 @@ class Aurora(commands.Cog):
except discord.errors.HTTPException: except discord.errors.HTTPException:
pass pass
moderation_id = await mysql_log( moderation = await Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"UNMUTE", "UNMUTE",
"USER", "USER",
target.id, target.id,
0, None,
"NULL", None,
reason, reason,
) )
await interaction.edit_original_response( await interaction.edit_original_response(
content=f"{target.mention} has been unmuted! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" content=f"{target.mention} has been unmuted! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`"
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="kick") @app_commands.command(name="kick")
async def kick( async def kick(
@ -726,23 +728,22 @@ class Aurora(commands.Cog):
await target.kick(reason=f"Kicked by {interaction.user.id} for: {reason}") await target.kick(reason=f"Kicked by {interaction.user.id} for: {reason}")
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"KICK", "KICK",
"USER", "USER",
target.id, target.id,
0, None,
"NULL", None,
reason, reason,
) )
await interaction.edit_original_response( await interaction.edit_original_response(
content=f"{target.mention} has been kicked! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" content=f"{target.mention} has been kicked! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`"
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="ban") @app_commands.command(name="ban")
@app_commands.choices( @app_commands.choices(
@ -834,23 +835,22 @@ class Aurora(commands.Cog):
delete_message_seconds=delete_messages_seconds, delete_message_seconds=delete_messages_seconds,
) )
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"TEMPBAN", "TEMPBAN",
"USER", "USER",
target.id, target.id,
0, None,
parsed_time, parsed_time,
reason, reason,
) )
await interaction.edit_original_response( await interaction.edit_original_response(
content=f"{target.mention} has been banned for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation_id}`)\n**Reason** - `{reason}`" content=f"{target.mention} has been banned for {humanize_timedelta(timedelta=parsed_time)}! (Case `#{moderation.id}`)\n**Reason** - `{reason}`"
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
else: else:
await interaction.response.send_message( await interaction.response.send_message(
content=f"{target.mention} has been banned!\n**Reason** - `{reason}`" content=f"{target.mention} has been banned!\n**Reason** - `{reason}`"
@ -878,7 +878,8 @@ class Aurora(commands.Cog):
delete_message_seconds=delete_messages_seconds, delete_message_seconds=delete_messages_seconds,
) )
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"BAN", "BAN",
@ -889,12 +890,10 @@ class Aurora(commands.Cog):
reason, reason,
) )
await interaction.edit_original_response( await interaction.edit_original_response(
content=f"{target.mention} has been banned! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" content=f"{target.mention} has been banned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`"
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="unban") @app_commands.command(name="unban")
async def unban( async def unban(
@ -955,23 +954,22 @@ class Aurora(commands.Cog):
except discord.errors.HTTPException: except discord.errors.HTTPException:
pass pass
moderation_id = await mysql_log( moderation = Moderation.log(
interaction.client,
interaction.guild.id, interaction.guild.id,
interaction.user.id, interaction.user.id,
"UNBAN", "UNBAN",
"USER", "USER",
target.id, target.id,
0, None,
"NULL", None,
reason, reason,
) )
await interaction.edit_original_response( await interaction.edit_original_response(
content=f"{target.mention} has been unbanned! (Case `#{moderation_id:,}`)\n**Reason** - `{reason}`" content=f"{target.mention} has been unbanned! (Case `#{moderation.id:,}`)\n**Reason** - `{reason}`"
) )
await log(interaction, moderation_id) await log(interaction, moderation.id)
await send_evidenceformat(interaction, moderation.id)
case = await fetch_case(moderation_id, interaction.guild.id)
await send_evidenceformat(interaction, case)
@app_commands.command(name="history") @app_commands.command(name="history")
async def history( async def history(
@ -1118,8 +1116,7 @@ class Aurora(commands.Cog):
moderation_list: List[Moderation] = [] moderation_list: List[Moderation] = []
for result in results: for result in results:
result_dictionary = generate_dict(result) moderation = Moderation.from_result(interaction.client, result, interaction.guild.id)
moderation = Moderation.from_dict(interaction.client, result_dictionary)
moderation_list.append(moderation) moderation_list.append(moderation)
case_quantity = len(moderation_list) case_quantity = len(moderation_list)
@ -1235,7 +1232,7 @@ class Aurora(commands.Cog):
embed = await case_factory( embed = await case_factory(
interaction=interaction, interaction=interaction,
case_dict=await fetch_case(case, interaction.guild.id), moderation=moderation,
) )
await interaction.response.send_message( await interaction.response.send_message(
content=f"✅ Moderation #{case:,} resolved!", embed=embed content=f"✅ Moderation #{case:,} resolved!", embed=embed

View file

@ -7,7 +7,8 @@ from discord import ButtonStyle, Interaction, Message, ui
from redbot.core import commands from redbot.core import commands
from redbot.core.utils.chat_formatting import box, warning from redbot.core.utils.chat_formatting import box, warning
from ..utilities.database import connect, create_guild_table, mysql_log from aurora.models import Change, Moderation
from aurora.utilities.database import connect, create_guild_table
class ImportGalacticBotView(ui.View): class ImportGalacticBotView(ui.View):
@ -99,37 +100,37 @@ class ImportGalacticBotView(ui.View):
if resolved_timestamp is None: if resolved_timestamp is None:
resolved_timestamp = timestamp resolved_timestamp = timestamp
changes = [ changes = [
{ Change.from_dict({
"type": "ORIGINAL", "type": "ORIGINAL",
"reason": case["reason"], "reason": case["reason"],
"user_id": case["executor"], "user_id": case["executor"],
"timestamp": timestamp, "timestamp": timestamp,
}, }),
{ Change.from_dict({
"type": "RESOLVE", "type": "RESOLVE",
"reason": resolved_reason, "reason": resolved_reason,
"user_id": resolved_by, "user_id": resolved_by,
"timestamp": resolved_timestamp, "timestamp": resolved_timestamp,
}, }),
] ]
else: else:
resolved = 0 resolved = None
resolved_by = None resolved_by = None
resolved_reason = None resolved_reason = None
changes = [] changes = None
if case["reason"] and case["reason"] != "N/A": if case["reason"] and case["reason"] != "N/A":
reason = case["reason"] reason = case["reason"]
else: else:
reason = None reason = None
await mysql_log( Moderation.log(
self.ctx.guild.id, self.ctx.guild.id,
case["executor"], case["executor"],
case["type"], case["type"],
case["targetType"], case["targetType"],
case["target"], case["target"],
0, None,
duration, duration,
reason, reason,
timestamp=timestamp, timestamp=timestamp,

View file

@ -2,7 +2,7 @@ import json
import sqlite3 import sqlite3
from datetime import datetime, timedelta from datetime import datetime, timedelta
from time import time from time import time
from typing import Any, Dict, List, Literal, Optional, Union from typing import Any, Dict, Iterable, List, Literal, Optional, Union
import discord import discord
from discord import Forbidden, HTTPException, InvalidData, NotFound from discord import Forbidden, HTTPException, InvalidData, NotFound
@ -10,7 +10,7 @@ from pydantic import BaseModel, ConfigDict
from redbot.core.bot import Red from redbot.core.bot import Red
from aurora.utilities.logger import logger from aurora.utilities.logger import logger
from aurora.utilities.utils import generate_dict, get_next_case_number from aurora.utilities.utils import get_next_case_number
class AuroraBaseModel(BaseModel): class AuroraBaseModel(BaseModel):
@ -178,6 +178,41 @@ class Moderation(AuroraGuildModel):
def from_dict(cls, bot: Red, data: dict) -> "Moderation": def from_dict(cls, bot: Red, data: dict) -> "Moderation":
return cls(bot=bot, **data) return cls(bot=bot, **data)
@classmethod
def from_result(bot: Red, result: Iterable, guild_id: int) -> dict:
if result[7] is not None:
hours, minutes, seconds = map(int, result[7].split(':'))
duration = timedelta(hours=hours, minutes=minutes, seconds=seconds)
else:
duration = None
if result[14] is not None:
changes = json.loads(result[14])
change_obj_list = []
for change in changes:
change_obj_list.append(Change.from_dict(bot=bot, data=change))
case = {
"moderation_id": int(result[0]),
"guild_id": int(guild_id),
"timestamp": datetime.fromtimestamp(result[1]),
"moderation_type": str(result[2]),
"target_type": str(result[3]),
"target_id": int(result[4]),
"moderator_id": int(result[5]),
"role_id": int(result[6]) if result[6] is not None else None,
"duration": duration,
"end_timestamp": datetime.fromtimestamp(result[8]) if result[8] is not None else None,
"reason": result[9],
"resolved": bool(result[10]),
"resolved_by": result[11],
"resolve_reason": result[12],
"expired": bool(result[13]),
"changes": change_obj_list if result[14] else [],
"metadata": json.loads(result[15].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) if result[15] else {},
}
return case
@classmethod @classmethod
def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation": def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> "Moderation":
from aurora.utilities.database import connect from aurora.utilities.database import connect
@ -190,8 +225,7 @@ class Moderation(AuroraGuildModel):
cursor.close() cursor.close()
if result and not moderation_id == 0: if result and not moderation_id == 0:
case = generate_dict(bot, result, guild_id) return cls.from_result(bot, result, guild_id)
return cls.from_dict(bot, case)
raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!") raise ValueError(f"Case {moderation_id} not found in moderation_{guild_id}!")

View file

@ -1,15 +1,11 @@
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
import json import json
import sqlite3 import sqlite3
import time
from datetime import datetime, timedelta
from discord import Guild from discord import Guild
from redbot.core import data_manager from redbot.core import data_manager
from .logger import logger from .logger import logger
from .utils import (convert_timedelta_to_str, generate_dict,
get_next_case_number)
def connect() -> sqlite3.Connection: def connect() -> sqlite3.Connection:
@ -79,13 +75,13 @@ async def create_guild_table(guild: Guild):
"NULL", "NULL",
0, 0,
0, 0,
None,
None,
None,
None,
0, 0,
"NULL", None,
0, None,
"NULL",
0,
"NULL",
"NULL",
0, 0,
json.dumps([]), json.dumps([]),
json.dumps({}), json.dumps({}),
@ -102,125 +98,3 @@ async def create_guild_table(guild: Guild):
) )
database.close() database.close()
def mysql_log(
guild_id: str,
author_id: str,
moderation_type: str,
target_type: str,
target_id: int,
role_id: int,
duration: timedelta = None,
reason: str = None,
database: sqlite3.Connection = None,
timestamp: int = None,
resolved: bool = False,
resolved_by: str = None,
resolved_reason: str = None,
expired: bool = None,
changes: list = None,
metadata: dict = None,
) -> int:
if not timestamp:
timestamp = int(time.time())
if duration != "NULL" and duration is not None:
end_timedelta = datetime.fromtimestamp(timestamp) + duration
end_timestamp = int(end_timedelta.timestamp())
duration = convert_timedelta_to_str(duration)
else:
duration = None
end_timestamp = None
if not expired:
if int(time.time()) > end_timestamp:
expired = 1
else:
expired = 0
if reason == "NULL":
reason = None
if resolved_by == "NULL":
resolved_by = None
if resolved_reason == "NULL":
resolved_reason = None
if role_id == 0:
role_id = None
if not database:
database = connect()
close_db = True
else:
close_db = False
cursor = database.cursor()
moderation_id = get_next_case_number(guild_id=guild_id, cursor=cursor)
sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_type, target_id, moderator_id, role_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired, changes, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
val = (
moderation_id,
timestamp,
moderation_type,
target_type,
target_id,
author_id,
role_id,
duration,
end_timestamp,
reason,
int(resolved),
resolved_by,
resolved_reason,
expired,
json.dumps(changes if changes else []),
json.dumps(metadata if metadata else {}),
)
cursor.execute(sql, val)
cursor.close()
database.commit()
if close_db:
database.close()
logger.debug(
"Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s",
guild_id,
moderation_id,
timestamp,
moderation_type,
target_type,
target_id,
author_id,
role_id,
duration,
end_timestamp,
reason,
int(resolved),
resolved_by,
resolved_reason,
expired,
changes,
metadata,
)
return moderation_id
async def fetch_case(moderation_id: int, guild_id: str) -> dict:
"""This method fetches a case from the database and returns the case's dictionary."""
database = connect()
cursor = database.cursor()
query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;"
cursor.execute(query, (moderation_id,))
result = cursor.fetchone()
cursor.close()
database.close()
return generate_dict(result)

View file

@ -1,13 +1,11 @@
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
import json
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Optional, Union from typing import Optional, Union
from dateutil.relativedelta import relativedelta as rd from dateutil.relativedelta import relativedelta as rd
from discord import File, Guild, Interaction, Member, SelectOption, User from discord import File, Guild, Interaction, Member, SelectOption, User
from discord.errors import Forbidden, NotFound from discord.errors import Forbidden
from redbot.core import commands, data_manager from redbot.core import commands, data_manager
from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import error from redbot.core.utils.chat_formatting import error
from aurora.utilities.config import config from aurora.utilities.config import config
@ -125,123 +123,32 @@ def get_next_case_number(guild_id: str, cursor=None) -> int:
return (result[0] + 1) if result else 1 return (result[0] + 1) if result else 1
def generate_dict(bot: Red, result: dict, guild_id: int) -> dict:
from aurora.models import Change
if result[7] is not None:
hours, minutes, seconds = map(int, result[7].split(':'))
duration = timedelta(hours=hours, minutes=minutes, seconds=seconds)
else:
duration = None
if result[14] is not None:
changes = json.loads(result[14])
change_obj_list = []
for change in changes:
change_obj_list.append(Change.from_dict(bot=bot, data=change))
case = {
"moderation_id": int(result[0]),
"guild_id": int(guild_id),
"timestamp": datetime.fromtimestamp(result[1]),
"moderation_type": str(result[2]),
"target_type": str(result[3]),
"target_id": int(result[4]),
"moderator_id": int(result[5]),
"role_id": int(result[6]) if result[6] is not None else None,
"duration": duration,
"end_timestamp": datetime.fromtimestamp(result[8]) if result[8] is not None else None,
"reason": result[9],
"resolved": bool(result[10]),
"resolved_by": result[11],
"resolve_reason": result[12],
"expired": bool(result[13]),
"changes": change_obj_list if result[14] else [],
"metadata": json.loads(result[15].replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]')) if result[15] else {},
}
return case
async def fetch_user_dict(client: commands.Bot, user_id: str) -> dict:
"""This function returns a dictionary containing either user information or a standard deleted user template."""
if user_id == "?":
user_dict = {"id": "?", "name": "Unknown User", "discriminator": "0"}
else:
try:
user = client.get_user(int(user_id))
if user is None:
user = await client.fetch_user(int(user_id))
user_dict = {
"id": user.id,
"name": user.name,
"discriminator": user.discriminator,
}
except NotFound:
user_dict = {
"id": user_id,
"name": "Deleted User",
"discriminator": "0",
}
return user_dict
async def fetch_channel_dict(guild: Guild, channel_id: int) -> dict:
"""This function returns a dictionary containing either channel information or a standard deleted channel template."""
try:
channel = guild.get_channel(int(channel_id))
if not channel:
channel = await guild.fetch_channel(channel_id)
channel_dict = {
"id": channel.id,
"name": channel.name,
"mention": channel.mention,
}
except NotFound:
channel_dict = {"id": channel_id, "name": "Deleted Channel", "mention": None}
return channel_dict
async def fetch_role_dict(guild: Guild, role_id: int) -> dict:
"""This function returns a dictionary containing either role information or a standard deleted role template."""
role = guild.get_role(int(role_id))
if not role:
role_dict = {"id": role_id, "name": "Deleted Role"}
role_dict = {"id": role.id, "name": role.name}
return role_dict
async def log(interaction: Interaction, moderation_id: int, resolved: bool = False) -> None: async def log(interaction: Interaction, moderation_id: int, resolved: bool = False) -> None:
"""This function sends a message to the guild's configured logging channel when an infraction takes place.""" """This function sends a message to the guild's configured logging channel when an infraction takes place."""
from .database import fetch_case from aurora.models import Moderation
from .factory import log_factory from aurora.utilities.factory import log_factory
logging_channel_id = await config.guild(interaction.guild).log_channel() logging_channel_id = await config.guild(interaction.guild).log_channel()
if logging_channel_id != " ": if logging_channel_id != " ":
logging_channel = interaction.guild.get_channel(logging_channel_id) logging_channel = interaction.guild.get_channel(logging_channel_id)
case = await fetch_case(moderation_id, interaction.guild.id) try:
if case: moderation = Moderation.from_sql(interaction.client, moderation_id)
embed = await log_factory( embed = await log_factory(
interaction=interaction, case_dict=case, resolved=resolved interaction=interaction, moderation=moderation, resolved=resolved
) )
try: try:
await logging_channel.send(embed=embed) await logging_channel.send(embed=embed)
except Forbidden: except Forbidden:
return return
except ValueError:
return
async def send_evidenceformat(interaction: Interaction, case_dict: dict) -> None: async def send_evidenceformat(interaction: Interaction, moderation_id: int) -> None:
"""This function sends an ephemeral message to the moderator who took the moderation action, with a pre-made codeblock for use in the mod-evidence channel.""" """This function sends an ephemeral message to the moderator who took the moderation action, with a pre-made codeblock for use in the mod-evidence channel."""
from .factory import evidenceformat_factory from aurora.models import Moderation
from aurora.utilities.factory import evidenceformat_factory
send_evidence_bool = ( send_evidence_bool = (
await config.user(interaction.user).auto_evidenceformat() await config.user(interaction.user).auto_evidenceformat()
@ -251,19 +158,11 @@ async def send_evidenceformat(interaction: Interaction, case_dict: dict) -> None
if send_evidence_bool is False: if send_evidence_bool is False:
return return
content = await evidenceformat_factory(interaction=interaction, case_dict=case_dict) moderation = Moderation.from_sql(interaction.client, moderation_id)
content = await evidenceformat_factory(interaction=interaction, moderation=moderation)
await interaction.followup.send(content=content, ephemeral=True) await interaction.followup.send(content=content, ephemeral=True)
def convert_timedelta_to_str(td: timedelta) -> str:
"""This function converts a timedelta object to a string."""
total_seconds = int(td.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
seconds = total_seconds % 60
return f"{hours}:{minutes}:{seconds}"
def get_bool_emoji(value: Optional[bool]) -> str: def get_bool_emoji(value: Optional[bool]) -> str:
"""Returns a unicode emoji based on a boolean value.""" """Returns a unicode emoji based on a boolean value."""
if value is True: if value is True: