feat(moderation): updated prisma_log (mysql_log) and get_next_case_number to use prisma, added get_next_global_case_number
Some checks failed
Pylint / Pylint (3.10) (push) Failing after 1m0s

BREAKING: changed database schema
This commit is contained in:
Seaswimmer 2023-10-27 10:40:18 -04:00
parent 9ec42f5d60
commit 9f86c20df4
Signed by: cswimr
GPG key ID: 1EBC234EEDA901AE
2 changed files with 77 additions and 83 deletions

View file

@ -22,9 +22,9 @@ class Moderation(commands.Cog):
database_provider = "sqlite", database_provider = "sqlite",
database_address= "file:moderation.db", database_address= "file:moderation.db",
database_port = " ", database_port = " ",
database_name = "moderation", database_name = " ",
database_username = "red", database_username = " ",
database_password = "red" database_password = " "
) )
self.config.register_guild( self.config.register_guild(
ignore_other_bots = True, ignore_other_bots = True,
@ -110,67 +110,20 @@ class Moderation(commands.Cog):
await self.mysql_log(entry.guild.id, entry.user.id, moderation_type, entry.target.id, duration, reason) await self.mysql_log(entry.guild.id, entry.user.id, moderation_type, entry.target.id, duration, reason)
async def connect(self): async def connect(self):
"""Connects to the MySQL database, and returns a connection object.""" """Connects to the database, and returns a connection object."""
conf = await self.check_conf([ provider = await self.config.database_provider()
'mysql_address', address = await self.config.database_address()
'mysql_database', if provider == "sqlite" and address == "file:moderation.db":
'mysql_username', return await Prisma().connect()
'mysql_password' else:
]) return await Prisma(
if conf: provider=provider,
raise LookupError("MySQL connection details not set properly!") address=address,
try: port=await self.config.database_port(),
connection = mysql.connector.connect( database=await self.config.database_name(),
host=await self.config.mysql_address(), username=await self.config.database_username(),
user=await self.config.mysql_username(), password=await self.config.database_password()
password=await self.config.mysql_password(), ).connect()
database=await self.config.mysql_database()
)
return connection
except mysql.connector.ProgrammingError as e:
self.logger.fatal("Unable to access the MySQL database!\nError:\n%s", e.msg)
raise ConnectionRefusedError(f"Unable to access the MySQL Database!\n{e.msg}") from e
async def create_guild_table(self, guild: discord.Guild):
database = await self.connect()
cursor = database.cursor()
try:
cursor.execute(f"SELECT * FROM `moderation_{guild.id}`")
self.logger.info("MySQL Table exists for server %s (%s)", guild.name, guild.id)
except mysql.connector.errors.ProgrammingError:
query = f"""
CREATE TABLE `moderation_{guild.id}` (
moderation_id INT UNIQUE PRIMARY KEY NOT NULL,
timestamp INT NOT NULL,
moderation_type LONGTEXT NOT NULL,
target_id LONGTEXT NOT NULL,
moderator_id LONGTEXT NOT NULL,
duration LONGTEXT,
end_timestamp INT,
reason LONGTEXT,
resolved BOOL NOT NULL,
resolved_by LONGTEXT,
resolve_reason LONGTEXT,
expired BOOL NOT NULL
)
"""
cursor.execute(query)
index_query_1 = "CREATE INDEX idx_target_id ON moderation_%s(target_id(25));"
cursor.execute(index_query_1, (guild.id,))
index_query_2 = "CREATE INDEX idx_moderator_id ON moderation_%s(moderator_id(25));"
cursor.execute(index_query_2, (guild.id,))
index_query_3 = "CREATE INDEX idx_moderation_id ON moderation_%s(moderation_id);"
cursor.execute(index_query_3, (guild.id,))
insert_query = f"""
INSERT INTO `moderation_{guild.id}`
(moderation_id, timestamp, moderation_type, target_id, moderator_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
insert_values = (0, 0, "NULL", 0, 0, "NULL", 0, "NULL", 0, "NULL", "NULL", 0)
cursor.execute(insert_query, insert_values)
database.commit()
self.logger.info("MySQL Table (moderation_%s) created for %s (%s)", guild.id, guild.name, guild.id)
database.close()
async def check_conf(self, config: list): async def check_conf(self, config: list):
"""Checks if any required config options are not set.""" """Checks if any required config options are not set."""
@ -195,31 +148,70 @@ class Moderation(commands.Cog):
return permission return permission
return False return False
async def mysql_log(self, guild_id: str, author_id: str, moderation_type: str, target_id: int, duration, reason: str): async def prisma_log(self, guild_id: str, author_id: str, moderation_type: str, target_id: int, duration, reason: str, role_id = None):
timestamp = int(time.time()) timestamp = int(time.time())
if duration != "NULL": if duration != "NULL":
end_timedelta = datetime.fromtimestamp(timestamp) + duration end_timedelta = datetime.fromtimestamp(timestamp) + duration
end_timestamp = int(end_timedelta.timestamp()) end_timestamp = int(end_timedelta.timestamp())
else: else:
end_timestamp = 0 end_timestamp = 0
database = await self.connect() if not role_id:
cursor = database.cursor() role_id = "NULL"
moderation_id = await self.get_next_case_number(guild_id=guild_id, cursor=cursor) db = await self.connect()
sql = f"INSERT INTO `moderation_{guild_id}` (moderation_id, timestamp, moderation_type, target_id, moderator_id, duration, end_timestamp, reason, resolved, resolved_by, resolve_reason, expired) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" global_id = await self.get_next_global_case_number(database=db)
val = (moderation_id, timestamp, moderation_type, target_id, author_id, duration, end_timestamp, f"{reason}", 0, "NULL", "NULL", 0) moderation_id = await self.get_next_case_number(guild_id=guild_id, database=db)
cursor.execute(sql, val) await db.Case.create(
database.commit() data={
database.close() 'globalId': global_id,
self.logger.debug("MySQL row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, 0, NULL, NULL, 0", guild_id, moderation_id, timestamp, moderation_type, target_id, author_id, duration, end_timestamp, reason) 'guildId': guild_id,
'moderationId': moderation_id,
'timestamp': timestamp,
'moderationType': moderation_type,
'targetId': target_id,
'moderatorId': author_id,
'roleId': role_id,
'duration': duration,
'endTimestamp': end_timestamp,
'reason': reason,
'resolved': False,
'resolvedBy': None,
'resolveReason': None,
'expired': False
}
)
await db.disconnect()
return moderation_id return moderation_id
async def get_next_case_number(self, guild_id: str, cursor = None): async def get_next_case_number(self, guild_id: str, database = None):
"""This method returns the next case number from the MySQL table for a specific guild.""" """This method returns the next case number from the database table for a specific guild."""
if not cursor: if not database:
database = await self.connect() database = await self.connect()
cursor = database.cursor() db_not_provided = True
cursor.execute(f"SELECT moderation_id FROM `moderation_{guild_id}` ORDER BY moderation_id DESC LIMIT 1") else:
return cursor.fetchone()[0] + 1 db_not_provided = False
result = await database.Case.find_first(
select={"moderationId": True},
where={"guildId": guild_id},
order=[{"moderationId": "desc"}],
)
if db_not_provided:
await database.disconnect()
return result.moderationId + 1 if result else 1
async def get_next_global_case_number(self, database = None):
"""This method returns the next case number from the database table."""
if not database:
database = await self.connect()
db_not_provided = True
else:
db_not_provided = False
result = await database.Case.find_first(
select={"globalId": True},
order=[{"globalId": "desc"}],
)
if db_not_provided:
await database.disconnect()
return result.globalId + 1 if result else 1
def generate_dict(self, result): def generate_dict(self, result):
case: dict = { case: dict = {

View file

@ -9,8 +9,10 @@ generator client {
recursive_type_depth = 5 recursive_type_depth = 5
} }
model Moderation { model Case {
moderationId Int @id @unique globalId Int @id @unique
guildId BigInt
moderationId Int
timestamp DateTime timestamp DateTime
moderationType String moderationType String
targetId BigInt targetId BigInt
@ -24,5 +26,5 @@ model Moderation {
resolveReason String? resolveReason String?
expired Boolean expired Boolean
@@index([moderationId, targetId, moderatorId]) @@index([guildId, moderationId, targetId, moderatorId])
} }