WIP: Moderation type registry #26

Closed
cswimr wants to merge 146 commits from aurora-3rd-party into main
2 changed files with 86 additions and 93 deletions
Showing only changes of commit dc44e8c6de - Show all commits

View file

@ -27,13 +27,13 @@ from aurora.menus.addrole import Addrole
from aurora.menus.guild import Guild from aurora.menus.guild import Guild
from aurora.menus.immune import Immune from aurora.menus.immune import Immune
from aurora.menus.overrides import Overrides from aurora.menus.overrides import Overrides
from aurora.models import 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, fetch_case, mysql_log
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, dumps from aurora.utilities.json import dump, dumps
from aurora.utilities.logger import logger from aurora.utilities.logger import logger
from aurora.utilities.utils import check_moddable, check_permissions, convert_timedelta_to_str, fetch_channel_dict, fetch_user_dict, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta from aurora.utilities.utils import check_moddable, check_permissions, fetch_channel_dict, fetch_user_dict, generate_dict, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta
class Aurora(commands.Cog): class Aurora(commands.Cog):
@ -1490,107 +1490,77 @@ class Aurora(commands.Cog):
return return
if case != 0: if case != 0:
parsed_time = None moderation = Moderation.from_sql(interaction.client, case, interaction.guild.id)
case_dict = await fetch_case(case, interaction.guild.id) old_moderation = moderation
if case_dict: if moderation:
if duration: if len(moderation.changes) > 25:
parsed_time = parse_timedelta(duration) return await interaction.response.send_message(
if parsed_time is None:
await interaction.response.send_message(
error("Please provide a valid duration!"), ephemeral=True
)
return
end_timestamp = case_dict["timestamp"] + parsed_time.total_seconds()
if case_dict["moderation_type"] == "MUTE":
if (
time.time() - case_dict["timestamp"]
) + parsed_time.total_seconds() > 2419200:
await interaction.response.send_message(
error(
"Please provide a duration that is less than 28 days from the initial moderation."
)
)
return
try:
member = await interaction.guild.fetch_member(
case_dict["target_id"]
)
await member.timeout(
parsed_time,
reason=f"Case #{case:,} edited by {interaction.user.id}",
)
except discord.NotFound:
pass
changes: list = case_dict["changes"]
if len(changes) > 25:
await interaction.response.send_message(
content=error( content=error(
"Due to limitations with Discord's embed system, you cannot edit a case more than 25 times." "Due to limitations with Discord's embed system, you cannot edit a case more than 25 times."
), ),
ephemeral=True, ephemeral=True,
) )
return if duration:
if not changes: moderation.duration = parse_timedelta(duration)
changes.append( if moderation.duration is None:
{ return await interaction.response.send_message(
error("Please provide a valid duration!"), ephemeral=True
)
moderation.end_timestamp = moderation.timestamp + moderation.duration.total_seconds()
if moderation.type == "MUTE":
if (
time.time() - moderation.unix_timestamp
) + moderation.duration.total_seconds() > 2419200:
return await interaction.response.send_message(
error(
"Please provide a duration that is less than 28 days from the initial moderation."
)
)
try:
member = await interaction.guild.fetch_member(
moderation.target_id
)
await member.timeout(
moderation.duration,
reason=f"Case #{case:,} edited by {interaction.user.id}",
)
except discord.NotFound:
pass
if not moderation.changes:
moderation.changes.append(Change.from_dict(interaction.client, {
"type": "ORIGINAL", "type": "ORIGINAL",
"timestamp": case_dict["timestamp"], "timestamp": old_moderation.timestamp,
"reason": case_dict["reason"], "reason": old_moderation.reason,
"user_id": case_dict["moderator_id"], "user_id": old_moderation.moderator_id,
"duration": case_dict["duration"], "duration": old_moderation.duration,
"end_timestamp": case_dict["end_timestamp"], "end_timestamp": old_moderation.end_timestamp,
} }))
) if duration:
if parsed_time: moderation.changes.append(Change.from_dict(interaction.client, {
changes.append(
{
"type": "EDIT", "type": "EDIT",
"timestamp": int(time.time()), "timestamp": int(time.time()),
"reason": reason, "reason": reason,
"user_id": interaction.user.id, "user_id": interaction.user.id,
"duration": convert_timedelta_to_str(parsed_time), "duration": moderation.duration,
"end_timestamp": end_timestamp, "end_timestamp": moderation.end_timestamp,
} }))
)
else: else:
changes.append( moderation.changes.append(Change.from_dict(interaction.client, {
{
"type": "EDIT", "type": "EDIT",
"timestamp": int(time.time()), "timestamp": int(time.time()),
"reason": reason, "reason": reason,
"user_id": interaction.user.id, "user_id": interaction.user.id,
"duration": case_dict["duration"], "duration": moderation.duration,
"end_timestamp": case_dict["end_timestamp"], "end_timestamp": moderation.end_timestamp,
} }))
)
database = connect() moderation.update()
cursor = database.cursor() embed = await case_factory(interaction=interaction, moderation=moderation)
if parsed_time:
update_query = f"UPDATE `moderation_{interaction.guild.id}` SET changes = ?, reason = ?, duration = ?, end_timestamp = ? WHERE moderation_id = ?"
cursor.execute(
update_query,
(
dumps(changes),
reason,
convert_timedelta_to_str(parsed_time),
end_timestamp,
case,
),
)
else:
update_query = f"UPDATE `moderation_{interaction.guild.id}` SET changes = ?, reason = ? WHERE moderation_id = ?"
cursor.execute(update_query, (dumps(changes), reason, case))
database.commit()
new_case = await fetch_case(case, interaction.guild.id)
embed = await case_factory(interaction=interaction, case_dict=new_case)
await interaction.response.send_message( await interaction.response.send_message(
content=f"✅ Moderation #{case:,} edited!", content=f"✅ Moderation #{case:,} edited!",
@ -1599,8 +1569,6 @@ class Aurora(commands.Cog):
) )
await log(interaction, case) await log(interaction, case)
cursor.close()
database.close()
return return
await interaction.response.send_message( await interaction.response.send_message(
content=error(f"No case with case number `{case}` found."), ephemeral=True content=error(f"No case with case number `{case}` found."), ephemeral=True

View file

@ -77,6 +77,16 @@ class Moderation(AuroraGuildModel):
def __str__(self): def __str__(self):
return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}" return f"{self.moderation_type} {self.target_type} {self.target_id} {self.reason}"
def update(self):
from aurora.utilities.database import connect
query = f"UPDATE moderation_{self.guild_id} SET timestamp = ?, moderation_type = ?, target_type = ?, moderator_id = ?, role_id = ?, duration = ?, end_timestamp = ?, reason = ?, resolved = ?, resolved_by = ?, resolve_reason = ?, expired = ?, changes = ?, metadata = ? WHERE moderation_id = ?;"
changes = [change.to_json() for change in self.changes]
with connect() as database:
cursor = database.cursor()
cursor.execute(query, (self.timestamp, self.moderation_type, self.target_type, self.moderator_id, self.role_id, self.duration, self.end_timestamp, self.reason, self.resolved, self.resolved_by, self.resolve_reason, self.expired, changes, self.metadata, self.moderation_id))
cursor.close()
@classmethod @classmethod
def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> Optional["Moderation"]: def from_sql(cls, bot: Red, moderation_id: int, guild_id: int) -> Optional["Moderation"]:
from aurora.utilities.database import connect from aurora.utilities.database import connect
@ -118,14 +128,29 @@ class Change(AuroraBaseModel):
@classmethod @classmethod
def from_dict(cls, bot: Red, data: dict) -> "Change": def from_dict(cls, bot: Red, data: dict) -> "Change":
if "duration" in data and data["duration"] is not None: if "duration" in data and data["duration"] and not isinstance(data["duration"], timedelta):
hours, minutes, seconds = map(int, data["duration"].split(':')) hours, minutes, seconds = map(int, data["duration"].split(':'))
duration = timedelta(hours=hours, minutes=minutes, seconds=seconds) duration = timedelta(hours=hours, minutes=minutes, seconds=seconds)
elif duration in data and isinstance(data["duration"], timedelta):
duration = data["duration"]
else: else:
duration = None duration = None
if "end_timestamp" in data and data["end_timestamp"] and not isinstance(data["end_timestamp"], datetime):
end_timestamp = datetime.fromtimestamp(data["end_timestamp"])
elif "end_timestamp" in data and isinstance(data["end_timestamp"], datetime):
end_timestamp = data["end_timestamp"]
else:
end_timestamp = None
if not isinstance(data["timestamp"], datetime):
timestamp = datetime.fromtimestamp(data["timestamp"])
else:
timestamp = data["timestamp"]
data.update({ data.update({
"timestamp": datetime.fromtimestamp(data["timestamp"]), "timestamp": timestamp,
"end_timestamp": datetime.fromtimestamp(data["end_timestamp"]) if "end_timestamp" in data and data["end_timestamp"] else None, "end_timestamp": end_timestamp,
"duration": duration "duration": duration
}) })
return cls(bot=bot, **data) return cls(bot=bot, **data)