feat(aurora): bunch of changes
This commit is contained in:
parent
f6a42b97d9
commit
0bcbcd6c0c
6 changed files with 122 additions and 149 deletions
|
@ -19,7 +19,7 @@ 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 bold, box, error, humanize_list, humanize_timedelta, warning
|
||||||
|
|
||||||
from .importers.aurora import ImportAuroraView
|
from .importers.aurora import ImportAuroraView
|
||||||
from .importers.galacticbot import ImportGalacticBotView
|
from .importers.galacticbot import ImportGalacticBotView
|
||||||
|
@ -30,11 +30,10 @@ from .menus.overrides import Overrides
|
||||||
from .models.change import Change
|
from .models.change import Change
|
||||||
from .models.moderation import Moderation
|
from .models.moderation import Moderation
|
||||||
from .utilities.config import config, register_config
|
from .utilities.config import config, register_config
|
||||||
from .utilities.database import connect, create_guild_table
|
|
||||||
from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed
|
from .utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed
|
||||||
from .utilities.json import dump
|
from .utilities.json import dump
|
||||||
from .utilities.logger import logger
|
from .utilities.logger import logger
|
||||||
from .utilities.utils import check_moddable, check_permissions, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta
|
from .utilities.utils import check_moddable, check_permissions, create_guild_table, get_footer_image, log, send_evidenceformat, timedelta_from_relativedelta
|
||||||
|
|
||||||
|
|
||||||
class Aurora(commands.Cog):
|
class Aurora(commands.Cog):
|
||||||
|
@ -43,28 +42,22 @@ class Aurora(commands.Cog):
|
||||||
This cog stores all of its data in an SQLite database."""
|
This cog stores all of its data in an SQLite database."""
|
||||||
|
|
||||||
__author__ = ["SeaswimmerTheFsh"]
|
__author__ = ["SeaswimmerTheFsh"]
|
||||||
__version__ = "2.2.0"
|
__version__ = "2.3.0"
|
||||||
__documentation__ = "https://seacogs.coastalcommits.com/aurora/"
|
__documentation__ = "https://seacogs.coastalcommits.com/aurora/"
|
||||||
|
|
||||||
async def red_delete_data_for_user(self, *, requester, user_id: int):
|
async def red_delete_data_for_user(self, *, requester, user_id: int):
|
||||||
if requester == "discord_deleted_user":
|
if requester == "discord_deleted_user":
|
||||||
await config.user_from_id(user_id).clear()
|
await config.user_from_id(user_id).clear()
|
||||||
|
|
||||||
database = await connect()
|
results = await Moderation.execute(query="SHOW TABLES;", return_obj=False)
|
||||||
cursor = await database.cursor()
|
tables = [table[0] for table in results]
|
||||||
|
|
||||||
await cursor.execute("SHOW TABLES;")
|
|
||||||
tables = [table[0] for table in cursor.fetchall()]
|
|
||||||
|
|
||||||
condition = "target_id = %s OR moderator_id = %s;"
|
condition = "target_id = %s OR moderator_id = %s;"
|
||||||
|
|
||||||
for table in tables:
|
for table in tables:
|
||||||
delete_query = f"DELETE FROM {table[0]} WHERE {condition}"
|
delete_query = f"DELETE FROM {table[0]} WHERE {condition}"
|
||||||
await cursor.execute(delete_query, (user_id, user_id))
|
await Moderation.execute(query=delete_query, parameters=(user_id, user_id), return_obj=False)
|
||||||
|
|
||||||
await database.commit()
|
|
||||||
await cursor.close()
|
|
||||||
await database.close()
|
|
||||||
if requester == "owner":
|
if requester == "owner":
|
||||||
await config.user_from_id(user_id).clear()
|
await config.user_from_id(user_id).clear()
|
||||||
if requester == "user":
|
if requester == "user":
|
||||||
|
@ -86,16 +79,16 @@ class Aurora(commands.Cog):
|
||||||
# and the information that aiosqlite logs is not useful to the bot owner.
|
# and the information that aiosqlite logs is not useful to the bot owner.
|
||||||
# This is a bad solution though as it overrides it for any other cogs that are using aiosqlite too.
|
# This is a bad solution though as it overrides it for any other cogs that are using aiosqlite too.
|
||||||
# If there's a better solution that you're aware of, please let me know in Discord or in a CoastalCommits issue.
|
# If there's a better solution that you're aware of, please let me know in Discord or in a CoastalCommits issue.
|
||||||
py_logging.getLogger('aiosqlite').setLevel(py_logging.WARNING)
|
py_logging.getLogger('aiosqlite').setLevel(py_logging.INFO)
|
||||||
|
|
||||||
def format_help_for_context(self, ctx: commands.Context) -> str:
|
def format_help_for_context(self, ctx: commands.Context) -> str:
|
||||||
pre_processed = super().format_help_for_context(ctx) or ""
|
pre_processed = super().format_help_for_context(ctx) or ""
|
||||||
n = "\n" if "\n\n" not in pre_processed else ""
|
n = "\n" if "\n\n" not in pre_processed else ""
|
||||||
text = [
|
text = [
|
||||||
f"{pre_processed}{n}",
|
f"{pre_processed}{n}",
|
||||||
f"Cog Version: **{self.__version__}**",
|
f"{bold('Cog Version:')} {self.__version__}",
|
||||||
f"Author: {humanize_list(self.__author__)}",
|
f"{bold('Author:')} {humanize_list(self.__author__)}",
|
||||||
f"Documentation: {self.__documentation__}",
|
f"{bold('Documentation:')} {self.__documentation__}",
|
||||||
]
|
]
|
||||||
return "\n".join(text)
|
return "\n".join(text)
|
||||||
|
|
||||||
|
@ -127,13 +120,12 @@ class Aurora(commands.Cog):
|
||||||
async def addrole_on_member_join(self, member: discord.Member):
|
async def addrole_on_member_join(self, member: discord.Member):
|
||||||
"""This method automatically adds roles to users when they join the server."""
|
"""This method automatically adds roles to users when they join the server."""
|
||||||
if not await self.bot.cog_disabled_in_guild(self, member.guild):
|
if not await self.bot.cog_disabled_in_guild(self, member.guild):
|
||||||
database = await connect()
|
|
||||||
query = f"""SELECT moderation_id, role_id, reason FROM moderation_{member.guild.id} WHERE target_id = ? AND moderation_type = 'ADDROLE' AND expired = 0 AND resolved = 0;"""
|
query = f"""SELECT moderation_id, role_id, reason FROM moderation_{member.guild.id} WHERE target_id = ? AND moderation_type = 'ADDROLE' AND expired = 0 AND resolved = 0;"""
|
||||||
async with database.execute(query, (member.id,)) as cursor:
|
results = Moderation.execute(query, (member.id,))
|
||||||
async for row in cursor:
|
for row in results:
|
||||||
role = member.guild.get_role(row[1])
|
role = member.guild.get_role(row[1])
|
||||||
reason = row[2]
|
reason = row[2]
|
||||||
await member.add_roles(role, reason=f"Role automatically added on member rejoin for: {reason} (Case #{row[0]:,})")
|
await member.add_roles(role, reason=f"Role automatically added on member rejoin for: {reason} (Case #{row[0]:,})")
|
||||||
|
|
||||||
@commands.Cog.listener("on_audit_log_entry_create")
|
@commands.Cog.listener("on_audit_log_entry_create")
|
||||||
async def autologger(self, entry: discord.AuditLogEntry):
|
async def autologger(self, entry: discord.AuditLogEntry):
|
||||||
|
@ -1093,7 +1085,7 @@ class Aurora(commands.Cog):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
database = await connect()
|
database = await Moderation.connect()
|
||||||
|
|
||||||
if export:
|
if export:
|
||||||
try:
|
try:
|
||||||
|
@ -1268,7 +1260,7 @@ class Aurora(commands.Cog):
|
||||||
ephemeral: bool | None = None,
|
ephemeral: bool | None = None,
|
||||||
evidenceformat: bool = False,
|
evidenceformat: bool = False,
|
||||||
changes: bool = False,
|
changes: bool = False,
|
||||||
export: Choice[str] | None = None,
|
raw: Choice[str] | None = None,
|
||||||
):
|
):
|
||||||
"""Check the details of a specific case.
|
"""Check the details of a specific case.
|
||||||
|
|
||||||
|
@ -1278,9 +1270,11 @@ class Aurora(commands.Cog):
|
||||||
What case are you looking up?
|
What case are you looking up?
|
||||||
ephemeral: bool
|
ephemeral: bool
|
||||||
Hide the command response
|
Hide the command response
|
||||||
|
evidenceformat: bool
|
||||||
|
Display the evidence format of the case
|
||||||
changes: bool
|
changes: bool
|
||||||
List the changes made to the case
|
List the changes made to the case
|
||||||
export: bool
|
raw: bool
|
||||||
Export the case to a JSON file or codeblock"""
|
Export the case to a JSON file or codeblock"""
|
||||||
permissions = check_permissions(
|
permissions = check_permissions(
|
||||||
interaction.client.user, ["embed_links"], interaction
|
interaction.client.user, ["embed_links"], interaction
|
||||||
|
@ -1309,8 +1303,8 @@ class Aurora(commands.Cog):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
if export:
|
if raw:
|
||||||
if export.value == "file" or len(mod.to_json(2)) > 1800:
|
if raw.value == "file" or len(mod.to_json(2)) > 1800:
|
||||||
filename = (
|
filename = (
|
||||||
str(data_manager.cog_data_path(cog_instance=self))
|
str(data_manager.cog_data_path(cog_instance=self))
|
||||||
+ str(os.sep)
|
+ str(os.sep)
|
||||||
|
@ -1319,7 +1313,7 @@ class Aurora(commands.Cog):
|
||||||
|
|
||||||
with open(filename, "w", encoding="utf-8") as f:
|
with open(filename, "w", encoding="utf-8") as f:
|
||||||
mod.to_json(2, f)
|
mod.to_json(2, f)
|
||||||
if export.value == "codeblock":
|
if raw.value == "codeblock":
|
||||||
content = f"Case #{case:,} exported.\n" + warning(
|
content = f"Case #{case:,} exported.\n" + warning(
|
||||||
"Case was too large to export as codeblock, so it has been uploaded as a `.json` file."
|
"Case was too large to export as codeblock, so it has been uploaded as a `.json` file."
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,9 +9,8 @@ from redbot.core import commands, data_manager
|
||||||
from redbot.core.utils.chat_formatting import warning
|
from redbot.core.utils.chat_formatting import warning
|
||||||
|
|
||||||
from ..models.moderation import Moderation
|
from ..models.moderation import Moderation
|
||||||
from ..utilities.database import connect, create_guild_table
|
|
||||||
from ..utilities.json import dump
|
from ..utilities.json import dump
|
||||||
from ..utilities.utils import timedelta_from_string
|
from ..utilities.utils import create_guild_table, timedelta_from_string
|
||||||
|
|
||||||
|
|
||||||
class ImportAuroraView(ui.View):
|
class ImportAuroraView(ui.View):
|
||||||
|
@ -29,10 +28,8 @@ class ImportAuroraView(ui.View):
|
||||||
"Deleting original table...", ephemeral=True
|
"Deleting original table...", ephemeral=True
|
||||||
)
|
)
|
||||||
|
|
||||||
database = await connect()
|
|
||||||
query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};"
|
query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};"
|
||||||
await database.execute(query)
|
await Moderation.execute(query=query, return_obj=False)
|
||||||
await database.commit()
|
|
||||||
|
|
||||||
await interaction.edit_original_response(content="Creating new table...")
|
await interaction.edit_original_response(content="Creating new table...")
|
||||||
|
|
||||||
|
@ -111,15 +108,11 @@ class ImportAuroraView(ui.View):
|
||||||
expired=case["expired"],
|
expired=case["expired"],
|
||||||
changes=changes,
|
changes=changes,
|
||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
database=database,
|
|
||||||
return_obj=False
|
return_obj=False
|
||||||
)
|
)
|
||||||
except Exception as e: # pylint: disable=broad-exception-caught
|
except Exception as e: # pylint: disable=broad-exception-caught
|
||||||
failed_cases.append(str(case["moderation_id"]) + f": {e}")
|
failed_cases.append(str(case["moderation_id"]) + f": {e}")
|
||||||
|
|
||||||
await database.commit()
|
|
||||||
await database.close()
|
|
||||||
|
|
||||||
await interaction.edit_original_response(content="Import complete.")
|
await interaction.edit_original_response(content="Import complete.")
|
||||||
if failed_cases:
|
if failed_cases:
|
||||||
filename = (
|
filename = (
|
||||||
|
|
|
@ -8,13 +8,14 @@ from redbot.core import commands
|
||||||
from redbot.core.utils.chat_formatting import box, warning
|
from redbot.core.utils.chat_formatting import box, warning
|
||||||
|
|
||||||
from ..models.moderation import Change, Moderation
|
from ..models.moderation import Change, Moderation
|
||||||
from ..utilities.database import connect, create_guild_table
|
from ..utilities.database import create_guild_table
|
||||||
|
|
||||||
|
|
||||||
class ImportGalacticBotView(ui.View):
|
class ImportGalacticBotView(ui.View):
|
||||||
def __init__(self, timeout, ctx, message):
|
def __init__(self, timeout, ctx, message):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.ctx: commands.Context = ctx
|
self.ctx: commands.Context = ctx
|
||||||
|
self.timeout = timeout
|
||||||
self.message: Message = message
|
self.message: Message = message
|
||||||
|
|
||||||
@ui.button(label="Yes", style=ButtonStyle.success)
|
@ui.button(label="Yes", style=ButtonStyle.success)
|
||||||
|
@ -26,7 +27,7 @@ class ImportGalacticBotView(ui.View):
|
||||||
"Deleting original table...", ephemeral=True
|
"Deleting original table...", ephemeral=True
|
||||||
)
|
)
|
||||||
|
|
||||||
database = await connect()
|
database = await Moderation.connect()
|
||||||
cursor = await database.cursor()
|
cursor = await database.cursor()
|
||||||
|
|
||||||
query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};"
|
query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};"
|
||||||
|
|
|
@ -5,8 +5,10 @@ from time import time
|
||||||
from typing import Dict, Iterable, List, Optional, Tuple, Union
|
from typing import Dict, Iterable, List, Optional, Tuple, Union
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from aiosqlite import Cursor
|
from aiosqlite import Connection, Cursor, OperationalError, Row
|
||||||
|
from aiosqlite import connect as aiosqlite_connect
|
||||||
from discord import NotFound
|
from discord import NotFound
|
||||||
|
from redbot.core import data_manager
|
||||||
from redbot.core.bot import Red
|
from redbot.core.bot import Red
|
||||||
|
|
||||||
from ..utilities.logger import logger
|
from ..utilities.logger import logger
|
||||||
|
@ -211,34 +213,48 @@ class Moderation(AuroraGuildModel):
|
||||||
}
|
}
|
||||||
return cls.from_dict(bot=bot, data=case)
|
return cls.from_dict(bot=bot, data=case)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def connect() -> Connection:
|
||||||
|
"""Connects to the SQLite database, and returns a connection object."""
|
||||||
|
try:
|
||||||
|
connection = await aiosqlite_connect(
|
||||||
|
database=data_manager.cog_data_path(raw_name="Aurora") / "aurora.db"
|
||||||
|
)
|
||||||
|
return connection
|
||||||
|
|
||||||
|
except OperationalError as e:
|
||||||
|
logger.error("Unable to access the SQLite database!\nError:\n%s", e.msg)
|
||||||
|
raise ConnectionRefusedError(
|
||||||
|
f"Unable to access the SQLite Database!\n{e.msg}"
|
||||||
|
) from e
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def execute(cls, bot: Red, guild_id: int, query: str, parameters: tuple | None = None, cursor: Cursor | None = None, return_obj: bool = True) -> Tuple["Moderation"]:
|
async def execute(cls, query: str, parameters: tuple | None = None, bot: Red | None = None, guild_id: int | None = None, cursor: Cursor | None = None, return_obj: bool = True) -> Union[Tuple["Moderation"], Iterable[Row]]:
|
||||||
from ..utilities.database import connect
|
logger.trace("Executing query: \"%s\" with parameters \"%s\"", query, parameters)
|
||||||
logger.trace("Executing query: %s", query)
|
|
||||||
logger.trace("With parameters: %s", parameters)
|
|
||||||
if not parameters:
|
if not parameters:
|
||||||
parameters = ()
|
parameters = ()
|
||||||
if not cursor:
|
if not cursor:
|
||||||
no_cursor = True
|
no_cursor = True
|
||||||
database = await connect()
|
database = await cls.connect()
|
||||||
cursor = await database.cursor()
|
cursor = await database.cursor()
|
||||||
else:
|
else:
|
||||||
no_cursor = False
|
no_cursor = False
|
||||||
|
|
||||||
await cursor.execute(query, parameters)
|
await cursor.execute(query, parameters)
|
||||||
results = await cursor.fetchall()
|
results = await cursor.fetchall()
|
||||||
|
await database.commit()
|
||||||
if no_cursor:
|
if no_cursor:
|
||||||
await cursor.close()
|
await cursor.close()
|
||||||
await database.close()
|
await database.close()
|
||||||
|
|
||||||
if results and return_obj:
|
if results and return_obj and bot and guild_id:
|
||||||
cases = []
|
cases = []
|
||||||
for result in results:
|
for result in results:
|
||||||
case = cls.from_result(bot=bot, result=result, guild_id=guild_id)
|
case = cls.from_result(bot=bot, result=result, guild_id=guild_id)
|
||||||
if case.moderation_id != 0:
|
if case.moderation_id != 0:
|
||||||
cases.append(case)
|
cases.append(case)
|
||||||
return tuple(cases)
|
return tuple(cases)
|
||||||
return ()
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]:
|
async def get_latest(cls, bot: Red, guild_id: int, limit: int | None = None, offset: int = 0, types: Iterable | None = None, cursor: Cursor | None = None) -> Tuple["Moderation"]:
|
||||||
|
@ -306,7 +322,6 @@ class Moderation(AuroraGuildModel):
|
||||||
metadata: dict | None = None,
|
metadata: dict | None = None,
|
||||||
return_obj: bool = True,
|
return_obj: bool = True,
|
||||||
) -> Union["Moderation", int]:
|
) -> Union["Moderation", int]:
|
||||||
from ..utilities.database import connect
|
|
||||||
from ..utilities.json import dumps
|
from ..utilities.json import dumps
|
||||||
if not timestamp:
|
if not timestamp:
|
||||||
timestamp = datetime.fromtimestamp(time())
|
timestamp = datetime.fromtimestamp(time())
|
||||||
|
@ -341,7 +356,7 @@ class Moderation(AuroraGuildModel):
|
||||||
role_id = None
|
role_id = None
|
||||||
|
|
||||||
if not database:
|
if not database:
|
||||||
database = await connect()
|
database = await cls.connect()
|
||||||
close_db = True
|
close_db = True
|
||||||
else:
|
else:
|
||||||
close_db = False
|
close_db = False
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
import json
|
|
||||||
|
|
||||||
import aiosqlite
|
|
||||||
from discord import Guild
|
|
||||||
from redbot.core import data_manager
|
|
||||||
|
|
||||||
from .logger import logger
|
|
||||||
|
|
||||||
|
|
||||||
async def connect() -> aiosqlite.Connection:
|
|
||||||
"""Connects to the SQLite database, and returns a connection object."""
|
|
||||||
try:
|
|
||||||
connection = await aiosqlite.connect(
|
|
||||||
database=data_manager.cog_data_path(raw_name="Aurora") / "aurora.db"
|
|
||||||
)
|
|
||||||
return connection
|
|
||||||
|
|
||||||
except aiosqlite.OperationalError as e:
|
|
||||||
logger.error("Unable to access the SQLite database!\nError:\n%s", e.msg)
|
|
||||||
raise ConnectionRefusedError(
|
|
||||||
f"Unable to access the SQLite Database!\n{e.msg}"
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
async def create_guild_table(guild: Guild):
|
|
||||||
database = await connect()
|
|
||||||
|
|
||||||
try:
|
|
||||||
await database.execute(f"SELECT * FROM `moderation_{guild.id}`")
|
|
||||||
logger.verbose("SQLite Table exists for server %s (%s)", guild.name, guild.id)
|
|
||||||
|
|
||||||
except aiosqlite.OperationalError:
|
|
||||||
query = f"""
|
|
||||||
CREATE TABLE `moderation_{guild.id}` (
|
|
||||||
moderation_id INTEGER PRIMARY KEY,
|
|
||||||
timestamp INTEGER NOT NULL,
|
|
||||||
moderation_type TEXT NOT NULL,
|
|
||||||
target_type TEXT NOT NULL,
|
|
||||||
target_id INTEGER NOT NULL,
|
|
||||||
moderator_id INTEGER NOT NULL,
|
|
||||||
role_id INTEGER,
|
|
||||||
duration TEXT,
|
|
||||||
end_timestamp INTEGER,
|
|
||||||
reason TEXT,
|
|
||||||
resolved INTEGER NOT NULL,
|
|
||||||
resolved_by TEXT,
|
|
||||||
resolve_reason TEXT,
|
|
||||||
expired INTEGER NOT NULL,
|
|
||||||
changes JSON NOT NULL,
|
|
||||||
metadata JSON NOT NULL
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
await database.execute(query)
|
|
||||||
|
|
||||||
index_query_1 = f"CREATE INDEX IF NOT EXISTS idx_target_id ON moderation_{guild.id}(target_id);"
|
|
||||||
await database.execute(index_query_1)
|
|
||||||
|
|
||||||
index_query_2 = f"CREATE INDEX IF NOT EXISTS idx_moderator_id ON moderation_{guild.id}(moderator_id);"
|
|
||||||
await database.execute(index_query_2)
|
|
||||||
|
|
||||||
index_query_3 = f"CREATE INDEX IF NOT EXISTS idx_moderation_id ON moderation_{guild.id}(moderation_id);"
|
|
||||||
await database.execute(index_query_3)
|
|
||||||
|
|
||||||
insert_query = 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
||||||
"""
|
|
||||||
insert_values = (
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
"NULL",
|
|
||||||
"NULL",
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
0,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
0,
|
|
||||||
json.dumps([]),
|
|
||||||
json.dumps({}),
|
|
||||||
)
|
|
||||||
await database.execute(insert_query, insert_values)
|
|
||||||
|
|
||||||
await database.commit()
|
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
"SQLite Table (moderation_%s) created for %s (%s)",
|
|
||||||
guild.id,
|
|
||||||
guild.name,
|
|
||||||
guild.id,
|
|
||||||
)
|
|
||||||
|
|
||||||
await database.close()
|
|
|
@ -2,6 +2,7 @@
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Optional, Tuple, Union
|
from typing import Optional, Tuple, Union
|
||||||
|
|
||||||
|
import aiosqlite
|
||||||
from dateutil.relativedelta import relativedelta as rd
|
from dateutil.relativedelta import relativedelta as rd
|
||||||
from discord import File, Guild, Interaction, Member, SelectOption, TextChannel, User
|
from discord import File, Guild, Interaction, Member, SelectOption, TextChannel, User
|
||||||
from discord.errors import Forbidden
|
from discord.errors import Forbidden
|
||||||
|
@ -9,6 +10,8 @@ from redbot.core import commands, data_manager
|
||||||
from redbot.core.utils.chat_formatting import error
|
from redbot.core.utils.chat_formatting import error
|
||||||
|
|
||||||
from ..utilities.config import config
|
from ..utilities.config import config
|
||||||
|
from ..utilities.json import dumps
|
||||||
|
from ..utilities.logger import logger
|
||||||
|
|
||||||
|
|
||||||
def check_permissions(
|
def check_permissions(
|
||||||
|
@ -210,3 +213,69 @@ def get_footer_image(coginstance: commands.Cog) -> File:
|
||||||
"""Returns the footer image for the embeds."""
|
"""Returns the footer image for the embeds."""
|
||||||
image_path = data_manager.bundled_data_path(coginstance) / "arrow.png"
|
image_path = data_manager.bundled_data_path(coginstance) / "arrow.png"
|
||||||
return File(image_path, filename="arrow.png", description="arrow")
|
return File(image_path, filename="arrow.png", description="arrow")
|
||||||
|
|
||||||
|
async def create_guild_table(guild: Guild) -> None:
|
||||||
|
from ..models.moderation import Moderation
|
||||||
|
|
||||||
|
try:
|
||||||
|
await Moderation.execute(f"SELECT * FROM `moderation_{guild.id}`", return_obj=False)
|
||||||
|
logger.trace("SQLite Table exists for server %s (%s)", guild.name, guild.id)
|
||||||
|
|
||||||
|
except aiosqlite.OperationalError:
|
||||||
|
query = f"""
|
||||||
|
CREATE TABLE `moderation_{guild.id}` (
|
||||||
|
moderation_id INTEGER PRIMARY KEY,
|
||||||
|
timestamp INTEGER NOT NULL,
|
||||||
|
moderation_type TEXT NOT NULL,
|
||||||
|
target_type TEXT NOT NULL,
|
||||||
|
target_id INTEGER NOT NULL,
|
||||||
|
moderator_id INTEGER NOT NULL,
|
||||||
|
role_id INTEGER,
|
||||||
|
duration TEXT,
|
||||||
|
end_timestamp INTEGER,
|
||||||
|
reason TEXT,
|
||||||
|
resolved INTEGER NOT NULL,
|
||||||
|
resolved_by TEXT,
|
||||||
|
resolve_reason TEXT,
|
||||||
|
expired INTEGER NOT NULL,
|
||||||
|
changes JSON NOT NULL,
|
||||||
|
metadata JSON NOT NULL
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
await Moderation.execute(query=query, return_obj=False)
|
||||||
|
|
||||||
|
index_query_1 = f"CREATE INDEX IF NOT EXISTS idx_target_id ON moderation_{guild.id}(target_id);"
|
||||||
|
await Moderation.execute(query=index_query_1, return_obj=False)
|
||||||
|
|
||||||
|
index_query_2 = f"CREATE INDEX IF NOT EXISTS idx_moderator_id ON moderation_{guild.id}(moderator_id);"
|
||||||
|
await Moderation.execute(query=index_query_2, return_obj=False)
|
||||||
|
|
||||||
|
index_query_3 = f"CREATE INDEX IF NOT EXISTS idx_moderation_id ON moderation_{guild.id}(moderation_id);"
|
||||||
|
await Moderation.execute(query=index_query_3, return_obj=False)
|
||||||
|
|
||||||
|
insert_query = 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
"""
|
||||||
|
insert_values = (
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
"NULL",
|
||||||
|
"NULL",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
0,
|
||||||
|
dumps([]),
|
||||||
|
dumps({}),
|
||||||
|
)
|
||||||
|
await Moderation.execute(query=insert_query, parameters=insert_values, return_obj=False)
|
||||||
|
|
||||||
|
logger.trace("SQLite Table created for server %s (%s)", guild.name, guild.id)
|
||||||
|
|
Loading…
Reference in a new issue