Compare commits
3 commits
main
...
moderation
Author | SHA1 | Date | |
---|---|---|---|
9f86c20df4 | |||
9ec42f5d60 | |||
b8c3efdedc |
3 changed files with 107 additions and 82 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
galaxy/slashtag arguments.txt
|
galaxy/slashtag arguments.txt
|
||||||
.venv
|
.venv
|
||||||
|
*.db
|
||||||
|
|
|
@ -4,7 +4,7 @@ from datetime import datetime, timedelta, timezone
|
||||||
from typing import Union
|
from typing import Union
|
||||||
import discord
|
import discord
|
||||||
import humanize
|
import humanize
|
||||||
import mysql.connector
|
from prisma import Prisma
|
||||||
from discord.ext import tasks
|
from discord.ext import tasks
|
||||||
from pytimeparse2 import disable_dateutil, parse
|
from pytimeparse2 import disable_dateutil, parse
|
||||||
from redbot.core import app_commands, checks, Config, commands
|
from redbot.core import app_commands, checks, Config, commands
|
||||||
|
@ -19,10 +19,12 @@ class Moderation(commands.Cog):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.config = Config.get_conf(self, identifier=481923957134912)
|
self.config = Config.get_conf(self, identifier=481923957134912)
|
||||||
self.config.register_global(
|
self.config.register_global(
|
||||||
mysql_address= " ",
|
database_provider = "sqlite",
|
||||||
mysql_database = " ",
|
database_address= "file:moderation.db",
|
||||||
mysql_username = " ",
|
database_port = " ",
|
||||||
mysql_password = " "
|
database_name = " ",
|
||||||
|
database_username = " ",
|
||||||
|
database_password = " "
|
||||||
)
|
)
|
||||||
self.config.register_guild(
|
self.config.register_guild(
|
||||||
ignore_other_bots = True,
|
ignore_other_bots = True,
|
||||||
|
@ -108,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."""
|
||||||
|
@ -193,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 = {
|
||||||
|
|
30
moderation/prisma/schema.prisma
Normal file
30
moderation/prisma/schema.prisma
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
datasource db {
|
||||||
|
provider = "sqlite"
|
||||||
|
url = "file:moderation.db"
|
||||||
|
}
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-py"
|
||||||
|
interface = "asyncio"
|
||||||
|
recursive_type_depth = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
model Case {
|
||||||
|
globalId Int @id @unique
|
||||||
|
guildId BigInt
|
||||||
|
moderationId Int
|
||||||
|
timestamp DateTime
|
||||||
|
moderationType String
|
||||||
|
targetId BigInt
|
||||||
|
moderatorId BigInt
|
||||||
|
roleId BigInt?
|
||||||
|
duration String?
|
||||||
|
endTimestamp DateTime?
|
||||||
|
reason String?
|
||||||
|
resolved Boolean
|
||||||
|
resolvedBy BigInt?
|
||||||
|
resolveReason String?
|
||||||
|
expired Boolean
|
||||||
|
|
||||||
|
@@index([guildId, moderationId, targetId, moderatorId])
|
||||||
|
}
|
Loading…
Reference in a new issue