diff --git a/aurora/importers/aurora.py b/aurora/importers/aurora.py index fce790e..0885ee9 100644 --- a/aurora/importers/aurora.py +++ b/aurora/importers/aurora.py @@ -8,7 +8,8 @@ from discord import ButtonStyle, Interaction, Message, ui from redbot.core import commands from redbot.core.utils.chat_formatting import box, warning -from ..utilities.database import connect, create_guild_table, mysql_log +from aurora.models import Moderation +from aurora.utilities.database import connect, create_guild_table class ImportAuroraView(ui.View): @@ -91,7 +92,8 @@ class ImportAuroraView(ui.View): else: duration = None - await mysql_log( + Moderation.log( + interaction.client, self.ctx.guild.id, case["moderator_id"], case["moderation_type"], diff --git a/aurora/models.py b/aurora/models.py index 66ed68a..9d70330 100644 --- a/aurora/models.py +++ b/aurora/models.py @@ -1,4 +1,6 @@ +import sqlite3 from datetime import datetime, timedelta +from time import time from typing import Any, Dict, List, Literal, Optional, Union from discord import Forbidden, HTTPException, InvalidData, NotFound @@ -6,7 +8,7 @@ from pydantic import BaseModel, ConfigDict from redbot.core.bot import Red from aurora.utilities.logger import logger -from aurora.utilities.utils import generate_dict +from aurora.utilities.utils import generate_dict, get_next_case_number class AuroraBaseModel(BaseModel): @@ -80,7 +82,6 @@ class Moderation(AuroraGuildModel): def update(self): from aurora.utilities.database import connect - from aurora.utilities.json import dumps 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 = ?;" with connect() as database: @@ -98,8 +99,8 @@ class Moderation(AuroraGuildModel): self.resolved_by, self.resolve_reason, self.expired, - dumps(self.changes).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), - dumps(self.metadata).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), + self.changes, + self.metadata, self.moderation_id )) cursor.close() @@ -119,8 +120,8 @@ class Moderation(AuroraGuildModel): self.resolved_by, self.resolve_reason, self.expired, - dumps(self.changes).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), - dumps(self.metadata).replace('\\"', '"').replace('["{', '[{').replace('}"]', '}]'), + self.changes, + self.metadata, ) @classmethod @@ -144,6 +145,107 @@ class Moderation(AuroraGuildModel): def from_dict(cls, bot: Red, data: dict) -> "Moderation": return cls(bot=bot, **data) + @classmethod + def log( + cls, + bot: Red, + guild_id: int, + author_id: int, + moderation_type: str, + target_type: str, + target_id: int, + role_id: int, + duration: timedelta = None, + reason: str = None, + database: sqlite3.Connection = None, + timestamp: datetime = None, + resolved: bool = False, + resolved_by: int = None, + resolved_reason: str = None, + expired: bool = None, + changes: list = None, + metadata: dict = None, + ) -> "Moderation": + from aurora.utilities.database import connect + if not timestamp: + timestamp = datetime.fromtimestamp(time()) + elif not isinstance(timestamp, datetime): + timestamp = datetime.fromtimestamp(timestamp) + + if duration != "NULL" and duration is not None: + end_timedelta = timestamp + duration + end_timestamp = int(end_timedelta.timestamp()) + else: + duration = None + end_timestamp = None + + if not expired: + if timestamp.timestamp() > end_timestamp: + expired = True + else: + expired = False + + 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) + + case = { + "guild_id": guild_id, + "moderation_id": moderation_id, + "timestamp": timestamp, + "moderation_type": moderation_type, + "target_type": target_type, + "target_id": target_id, + "moderator_id": author_id, + "role_id": role_id, + "duration": duration, + "end_timestamp": end_timestamp, + "reason": reason, + "resolved": resolved, + "resolved_by": resolved_by, + "resolve_reason": resolved_reason, + "expired": expired, + "changes": changes, + "metadata": metadata + } + + case_safe = case.copy() + case_safe.pop("guild_id") + case_safe["timestamp"] = case_safe["timestamp"].timestamp() + case_safe["end_timestamp"] = case_safe["end_timestamp"].timestamp() if case_safe["end_timestamp"] else None + + 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + cursor.execute(sql, case_safe.values()) + + 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, case_safe.values() + ) + + return cls.from_dict(bot=bot, **case) + class Change(AuroraBaseModel): type: Literal["ORIGINAL", "RESOLVE", "EDIT"] timestamp: datetime diff --git a/aurora/utilities/database.py b/aurora/utilities/database.py index 95ad7c8..88cec8b 100644 --- a/aurora/utilities/database.py +++ b/aurora/utilities/database.py @@ -8,7 +8,8 @@ from discord import Guild from redbot.core import data_manager from .logger import logger -from .utils import convert_timedelta_to_str, generate_dict, get_next_case_number +from .utils import (convert_timedelta_to_str, generate_dict, + get_next_case_number) def connect() -> sqlite3.Connection: @@ -103,7 +104,7 @@ async def create_guild_table(guild: Guild): database.close() -async def mysql_log( +def mysql_log( guild_id: str, author_id: str, moderation_type: str, @@ -158,7 +159,7 @@ async def mysql_log( close_db = False cursor = database.cursor() - moderation_id = await get_next_case_number(guild_id=guild_id, cursor=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 = ( diff --git a/aurora/utilities/utils.py b/aurora/utilities/utils.py index 63a894a..fcc8d61 100644 --- a/aurora/utilities/utils.py +++ b/aurora/utilities/utils.py @@ -111,9 +111,9 @@ async def check_moddable( return True -async def get_next_case_number(guild_id: str, cursor=None) -> int: +def get_next_case_number(guild_id: str, cursor=None) -> int: """This function returns the next case number from the MySQL table for a specific guild.""" - from .database import connect + from aurora.utilities.database import connect if not cursor: database = connect()