convert Moderation to sqlite3 (and rename it to Aurora) #12

Merged
cswimr merged 16 commits from sqlite3 into main 2023-12-28 05:22:52 -05:00
16 changed files with 139 additions and 268 deletions

5
aurora/__init__.py Normal file
View file

@ -0,0 +1,5 @@
from .aurora import Aurora
async def setup(bot):
await bot.add_cog(Aurora(bot))

View file

@ -8,27 +8,27 @@
import json
import os
import time
import sqlite3
from datetime import datetime, timedelta, timezone
from math import ceil
import discord
import humanize
import mysql.connector
from discord.ext import tasks
from pytimeparse2 import disable_dateutil, parse
from redbot.core import app_commands, checks, commands, data_manager
from redbot.core.app_commands import Choice
from .importers.galacticbot import ImportGalacticBotView
from .importers.moderation import ImportModerationView
from .importers.aurora import ImportAuroraView
from .utilities.config import config, register_config
from .utilities.database import connect, create_guild_table, fetch_case, mysql_log
from .utilities.embed_factory import embed_factory
from .utilities.logger import logger
from .utilities.utils import check_conf, check_moddable, check_permissions, fetch_channel_dict, fetch_user_dict, generate_dict, log, send_evidenceformat
from .utilities.utils import check_moddable, check_permissions, fetch_channel_dict, fetch_user_dict, generate_dict, log, send_evidenceformat
class Moderation(commands.Cog):
class Aurora(commands.Cog):
"""Custom moderation cog.
Developed by SeaswimmerTheFsh."""
@ -36,7 +36,7 @@ class Moderation(commands.Cog):
if requester == "discord_deleted_user":
await config.user_from_id(user_id).clear()
database = await connect()
database = connect()
cursor = database.cursor()
cursor.execute("SHOW TABLES;")
@ -68,17 +68,6 @@ class Moderation(commands.Cog):
async def cog_load(self):
"""This method prepares the database schema for all of the guilds the bot is currently in."""
conf = await check_conf([
'mysql_address',
'mysql_database',
'mysql_username',
'mysql_password'
])
if conf:
logger.error("Failed to create tables, due to MySQL connection configuration being unset.")
return
guilds: list[discord.Guild] = self.bot.guilds
try:
@ -96,20 +85,8 @@ class Moderation(commands.Cog):
async def db_generate_guild_join(self, guild: discord.Guild):
"""This method prepares the database schema whenever the bot joins a guild."""
if not await self.bot.cog_disabled_in_guild(self, guild):
conf = await check_conf([
'mysql_address',
'mysql_database',
'mysql_username',
'mysql_password'
])
if conf:
logger.error("Failed to create a table for %s, due to MySQL connection configuration being unset.", guild.id)
return
try:
await create_guild_table(guild)
except ConnectionRefusedError:
return
@ -592,15 +569,16 @@ class Moderation(commands.Cog):
await interaction.followup.send(f"I do not have the `{permissions}` permission, required for this action.", ephemeral=True)
return
database = await connect()
database = connect()
if export:
cursor = database.cursor(dictionary=True)
database.row_factory = sqlite3.Row
cursor = database.cursor()
query = """SELECT *
FROM moderation_%s
query = f"""SELECT *
FROM moderation_{interaction.guild.id}
ORDER BY moderation_id DESC;"""
cursor.execute(query, (interaction.guild.id,))
cursor.execute(query)
results = cursor.fetchall()
@ -622,22 +600,22 @@ class Moderation(commands.Cog):
cursor = database.cursor()
if target:
query = """SELECT *
FROM moderation_%s
WHERE target_id = %s
query = f"""SELECT *
FROM moderation_{interaction.guild.id}
WHERE target_id = ?
ORDER BY moderation_id DESC;"""
cursor.execute(query, (interaction.guild.id, target.id))
cursor.execute(query, (target.id,))
elif moderator:
query = """SELECT *
FROM moderation_%s
WHERE moderator_id = %s
query = f"""SELECT *
FROM moderation_{interaction.guild.id}
WHERE moderator_id = ?
ORDER BY moderation_id DESC;"""
cursor.execute(query, (interaction.guild.id, moderator.id))
cursor.execute(query, (moderator.id,))
else:
query = """SELECT *
FROM moderation_%s
query = f"""SELECT *
FROM moderation_{interaction.guild.id}
ORDER BY moderation_id DESC;"""
cursor.execute(query, (interaction.guild.id,))
cursor.execute(query)
results = cursor.fetchall()
result_dict_list = []
@ -714,23 +692,18 @@ class Moderation(commands.Cog):
await interaction.response.send_message(f"I do not have the `{permissions}` permission, required for this action.", ephemeral=True)
return
conf = await check_conf(['mysql_database'])
if conf:
raise(LookupError)
database = await connect()
database = connect()
cursor = database.cursor()
db = await config.mysql_database()
query_1 = "SELECT * FROM moderation_%s WHERE moderation_id = %s;"
cursor.execute(query_1, (interaction.guild.id, case))
query_1 = f"SELECT * FROM moderation_{interaction.guild.id} WHERE moderation_id = ?;"
cursor.execute(query_1, (case,))
result_1 = cursor.fetchone()
if result_1 is None or case == 0:
await interaction.response.send_message(content=f"There is no moderation with a case number of {case}.", ephemeral=True)
return
query_2 = "SELECT * FROM moderation_%s WHERE moderation_id = %s AND resolved = 0;"
cursor.execute(query_2, (interaction.guild.id, case))
query_2 = f"SELECT * FROM moderation_{interaction.guild.id} WHERE moderation_id = ? AND resolved = 0;"
cursor.execute(query_2, (case,))
result_2 = cursor.fetchone()
if result_2 is None:
await interaction.response.send_message(content=f"This moderation has already been resolved!\nUse `/case {case}` for more information.", ephemeral=True)
@ -782,9 +755,9 @@ class Moderation(commands.Cog):
except discord.NotFound:
pass
resolve_query = f"UPDATE `{db}`.`moderation_{interaction.guild.id}` SET resolved = 1, changes = %s, resolved_by = %s, resolve_reason = %s WHERE moderation_id = %s"
resolve_query = f"UPDATE `moderation_{interaction.guild.id}` SET resolved = 1, changes = ?, resolved_by = ?, resolve_reason = ? WHERE moderation_id = ?"
else:
resolve_query = f"UPDATE `{db}`.`moderation_{interaction.guild.id}` SET resolved = 1, changes = %s, resolved_by = %s, resolve_reason = %s WHERE moderation_id = %s"
resolve_query = f"UPDATE `moderation_{interaction.guild.id}` SET resolved = 1, changes = ?, resolved_by = ?, resolve_reason = ? WHERE moderation_id = ?"
cursor.execute(resolve_query, (json.dumps(changes), interaction.user.id, reason, case_dict['moderation_id']))
database.commit()
@ -878,10 +851,6 @@ class Moderation(commands.Cog):
parsed_time = None
case_dict = await fetch_case(case, interaction.guild.id)
if case_dict:
conf = await check_conf(['mysql_database'])
if conf:
raise(LookupError)
if duration:
try:
parsed_time = parse(sval=duration, as_timedelta=True, raise_exception=True)
@ -941,15 +910,14 @@ class Moderation(commands.Cog):
}
)
database = await connect()
database = connect()
cursor = database.cursor()
db = await config.mysql_database()
if parsed_time:
update_query = f"UPDATE `{db}`.`moderation_{interaction.guild.id}` SET changes = %s, reason = %s, duration = %s, end_timestamp = %s WHERE moderation_id = %s"
update_query = f"UPDATE `moderation_{interaction.guild.id}` SET changes = %s, reason = %s, duration = %s, end_timestamp = %s WHERE moderation_id = %s"
cursor.execute(update_query, (json.dumps(changes), reason, parsed_time, end_timestamp, case))
else:
update_query = f"UPDATE `{db}`.`moderation_{interaction.guild.id}` SET changes = %s, reason = %s WHERE moderation_id = %s"
update_query = f"UPDATE `moderation_{interaction.guild.id}` SET changes = %s, reason = %s WHERE moderation_id = %s"
cursor.execute(update_query, (json.dumps(changes), reason, case))
database.commit()
@ -966,24 +934,19 @@ class Moderation(commands.Cog):
@tasks.loop(minutes=1)
async def handle_expiry(self):
conf = await check_conf(['mysql_database'])
if conf:
raise(LookupError)
database = await connect()
database = connect()
cursor = database.cursor()
db = await config.mysql_database()
guilds: list[discord.Guild] = self.bot.guilds
for guild in guilds:
if not await self.bot.cog_disabled_in_guild(self, guild):
tempban_query = f"SELECT target_id, moderation_id FROM moderation_{guild.id} WHERE end_timestamp != 0 AND end_timestamp <= %s AND moderation_type = 'TEMPBAN' AND expired = 0"
tempban_query = f"SELECT target_id, moderation_id FROM moderation_{guild.id} WHERE end_timestamp != 0 AND end_timestamp <= ? AND moderation_type = 'TEMPBAN' AND expired = 0"
try:
cursor.execute(tempban_query, (time.time(),))
result = cursor.fetchall()
except mysql.connector.errors.ProgrammingError:
except sqlite3.OperationalError:
continue
target_ids = [row[0] for row in result]
@ -1003,15 +966,14 @@ class Moderation(commands.Cog):
except [discord.errors.NotFound, discord.errors.Forbidden, discord.errors.HTTPException] as e:
print(f"Failed to unban {user.name}#{user.discriminator} ({user.id}) from {guild.name} ({guild.id})\n{e}")
expiry_query = f"UPDATE `{db}`.`moderation_{guild.id}` SET expired = 1 WHERE (end_timestamp != 0 AND end_timestamp <= %s AND expired = 0 AND moderation_type != 'BLACKLIST') OR (expired = 0 AND resolved = 1 AND moderation_type != 'BLACKLIST')"
expiry_query = f"UPDATE `moderation_{guild.id}` SET expired = 1 WHERE (end_timestamp != 0 AND end_timestamp <= ? AND expired = 0 AND moderation_type != 'BLACKLIST') OR (expired = 0 AND resolved = 1 AND moderation_type != 'BLACKLIST')"
cursor.execute(expiry_query, (time.time(),))
blacklist_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp != 0 AND end_timestamp <= %s AND moderation_type = 'BLACKLIST' AND expired = 0"
blacklist_query = f"SELECT target_id, moderation_id, role_id FROM moderation_{guild.id} WHERE end_timestamp != 0 AND end_timestamp <= ? AND moderation_type = 'BLACKLIST' AND expired = 0"
try:
cursor.execute(blacklist_query, (time.time(),))
result = cursor.fetchall()
except mysql.connector.errors.ProgrammingError:
except sqlite3.OperationalError:
continue
target_ids = [row[0] for row in result]
moderation_ids = [row[1] for row in result]
@ -1047,7 +1009,7 @@ class Moderation(commands.Cog):
guild_settings_string = ""
for setting in guild_settings:
if 'mysql' in setting or 'roles' in setting:
if 'roles' in setting:
continue
if setting == 'log_channel':
channel = ctx.guild.get_channel(guild_settings[setting])
@ -1323,96 +1285,20 @@ class Moderation(commands.Cog):
await config.guild(ctx.guild).log_channel.set(" ")
await ctx.send("Logging channel disabled.")
@moderationset.command(name="mysql")
@checks.is_owner()
async def moderationset_mysql(self, ctx: commands.Context):
"""Configure MySQL connection details."""
await ctx.message.add_reaction("")
await ctx.author.send(content="Click the button below to configure your MySQL connection details.", view=self.ConfigButtons(60))
class ConfigButtons(discord.ui.View):
def __init__(self, timeout):
super().__init__()
@discord.ui.button(label="Edit", style=discord.ButtonStyle.success)
async def config_button(self, interaction: discord.Interaction, button: discord.ui.Button): # pylint: disable=unused-argument
await interaction.response.send_modal(Moderation.MySQLConfigModal)
class MySQLConfigModal(discord.ui.Modal, title="MySQL Database Configuration"):
def __init__(self):
super().__init__()
address = discord.ui.TextInput(
label="Address",
placeholder="Input your MySQL address here.",
style=discord.TextStyle.short,
required=False,
max_length=300
)
database = discord.ui.TextInput(
label="Database",
placeholder="Input the name of your database here.",
style=discord.TextStyle.short,
required=False,
max_length=300
)
username = discord.ui.TextInput(
label="Username",
placeholder="Input your MySQL username here.",
style=discord.TextStyle.short,
required=False,
max_length=300
)
password = discord.ui.TextInput(
label="Password",
placeholder="Input your MySQL password here.",
style=discord.TextStyle.short,
required=False,
max_length=300
)
async def on_submit(self, interaction: discord.Interaction):
message = ""
if self.address.value != "":
await config.mysql_address.set(self.address.value)
message += f"- Address set to\n - `{self.address.value}`\n"
if self.database.value != "":
await config.mysql_database.set(self.database.value)
message += f"- Database set to\n - `{self.database.value}`\n"
if self.username.value != "":
await config.mysql_username.set(self.username.value)
message += f"- Username set to\n - `{self.username.value}`\n"
if self.password.value != "":
await config.mysql_password.set(self.password.value)
trimmed_password = self.password.value[:8]
message += f"- Password set to\n - `{trimmed_password}` - Trimmed for security\n"
if message == "":
trimmed_password = str(await config.mysql_password())[:8]
send = f"No changes were made.\nCurrent configuration:\n- Address:\n - `{await config.mysql_address()}`\n- Database:\n - `{await config.mysql_database()}`\n- Username:\n - `{await config.mysql_username()}`\n- Password:\n - `{trimmed_password}` - Trimmed for security"
else:
send = f"Configuration changed:\n{message}"
await interaction.response.send_message(send, ephemeral=True)
@moderationset.group(autohelp=True, name='import')
@checks.admin()
async def moderationset_import(self, ctx: commands.Context):
"""Import moderations from other bots."""
@moderationset_import.command(name="moderation")
@moderationset_import.command(name="aurora")
@checks.admin()
async def moderationset_import_moderation(self, ctx: commands.Context):
"""Import moderations from another bot using this cog."""
async def moderationset_import_aurora(self, ctx: commands.Context):
"""Import moderations from another bot using Aurora."""
if ctx.message.attachments and ctx.message.attachments[0].content_type == 'application/json; charset=utf-8':
message = await ctx.send("Are you sure you want to import moderations from another bot?\n**This will overwrite any moderations that already exist in this guild's moderation table.**\n*The import process will block the rest of your bot until it is complete.*")
await message.edit(view=ImportModerationView(60, ctx, message))
await message.edit(view=ImportAuroraView(60, ctx, message))
else:
await ctx.send("Please provide a valid moderation export file.")
await ctx.send("Please provide a valid Aurora export file.")
@moderationset_import.command(name="galacticbot")
@checks.admin()

View file

@ -8,7 +8,7 @@ from redbot.core import commands
from ..utilities.database import connect, create_guild_table, mysql_log
class ImportModerationView(ui.View):
class ImportAuroraView(ui.View):
def __init__(self, timeout, ctx, message):
super().__init__()
self.ctx: commands.Context = ctx
@ -23,7 +23,7 @@ class ImportModerationView(ui.View):
"Deleting original table...", ephemeral=True
)
database = await connect()
database = connect()
cursor = database.cursor()
query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};"
@ -66,10 +66,11 @@ class ImportModerationView(ui.View):
if "metadata" not in case:
metadata = {}
else:
metadata: Dict[str, any] = case["metadata"]
metadata.update({
'imported_from': 'SeaCogs/Moderation'
})
metadata: Dict[str, any] = json.loads(case["metadata"])
if not metadata['imported_from']:
metadata.update({
'imported_from': 'Aurora'
})
if case["duration"] != "NULL":
hours, minutes, seconds = map(int, case["duration"].split(":"))
@ -106,6 +107,6 @@ class ImportModerationView(ui.View):
async def import_button_n(
self, interaction: Interaction, button: ui.Button
): # pylint: disable=unused-argument
await self.message.edit("Import cancelled.", view=None)
await self.message.edit(content="Import cancelled.", view=None)
await self.message.delete(10)
await self.ctx.message.delete(10)

View file

@ -18,7 +18,7 @@ class ImportGalacticBotView(ui.View):
await self.message.delete()
await interaction.response.send_message("Deleting original table...", ephemeral=True)
database = await connect()
database = connect()
cursor = database.cursor()
query = f"DROP TABLE IF EXISTS moderation_{self.ctx.guild.id};"
@ -140,6 +140,6 @@ class ImportGalacticBotView(ui.View):
@ui.button(label="No", style=ButtonStyle.danger)
async def import_button_n(self, interaction: Interaction, button: ui.Button): # pylint: disable=unused-argument
await self.message.edit("Import cancelled.", view=None)
await self.message.edit(content="Import cancelled.", view=None)
await self.message.delete(10)
await self.ctx.message.delete(10)

11
aurora/info.json Normal file
View file

@ -0,0 +1,11 @@
{
"author" : ["SeaswimmerTheFsh"],
"install_msg" : "Thank you for installing Aurora!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).",
"name" : "Aurora",
"short" : "A full replacement for Red's core Mod cogs.",
"description" : "Aurora is designed to be a full replacement for Red's core Mod cogs. It is heavily inspired by GalacticBot, and is designed to be a more user-friendly alternative to Red's core Mod cogs. This cog stores all of its data in an SQLite database.",
"end_user_data_statement" : "This cog stores the following information:\n- User IDs of accounts who moderate users or are moderated\n- Guild IDs of guilds with the cog enabled\n- Timestamps of moderations\n- Other information relating to moderations",
"requirements": ["humanize", "pytimeparse2"],
"hidden": false,
"disabled": false
}

View file

@ -3,12 +3,6 @@ from redbot.core import Config
config: Config = Config.get_conf(None, identifier=481923957134912, cog_name="Moderation")
def register_config(config_obj: Config):
config_obj.register_global(
mysql_address= " ",
mysql_database = " ",
mysql_username = " ",
mysql_password = " "
)
config_obj.register_guild(
use_discord_permissions = True,
ignore_other_bots = True,

View file

@ -2,88 +2,73 @@
import json
import time
from datetime import datetime
import sqlite3
from datetime import datetime, timedelta
import mysql.connector
from discord import Guild
from redbot.core import data_manager
from .config import config
from .logger import logger
from .utils import check_conf, generate_dict, get_next_case_number
from .utils import generate_dict, get_next_case_number
async def connect():
"""Connects to the MySQL database, and returns a connection object."""
conf = await check_conf(
["mysql_address", "mysql_database", "mysql_username", "mysql_password"]
)
if conf:
raise LookupError("MySQL connection details not set properly!")
def connect() -> sqlite3.Connection:
"""Connects to the SQLite database, and returns a connection object."""
try:
connection = mysql.connector.connect(
host=await config.mysql_address(),
user=await config.mysql_username(),
password=await config.mysql_password(),
database=await config.mysql_database(),
)
connection = sqlite3.connect(database=data_manager.cog_data_path(raw_name='Aurora') / 'aurora.db')
return connection
except mysql.connector.ProgrammingError as e:
logger.error("Unable to access the MySQL database!\nError:\n%s", e.msg)
except sqlite3.OperationalError as e:
logger.error("Unable to access the SQLite database!\nError:\n%s", e.msg)
raise ConnectionRefusedError(
f"Unable to access the MySQL Database!\n{e.msg}"
f"Unable to access the SQLite Database!\n{e.msg}"
) from e
async def create_guild_table(guild: Guild):
database = await connect()
database = connect()
cursor = database.cursor()
try:
cursor.execute(f"SELECT * FROM `moderation_{guild.id}`")
logger.debug("MySQL Table exists for server %s (%s)", guild.name, guild.id)
logger.debug("SQLite Table exists for server %s (%s)", guild.name, guild.id)
except mysql.connector.errors.ProgrammingError:
except sqlite3.OperationalError:
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_type LONGTEXT NOT NULL,
target_id LONGTEXT NOT NULL,
moderator_id LONGTEXT NOT NULL,
role_id LONGTEXT,
duration LONGTEXT,
end_timestamp INT,
reason LONGTEXT,
resolved BOOL NOT NULL,
resolved_by LONGTEXT,
resolve_reason LONGTEXT,
expired BOOL NOT NULL,
changes JSON NOT NULL,
metadata JSON NOT NULL
moderation_id INTEGER PRIMARY KEY,
timestamp INTEGER NOT NULL,
moderation_type TEXT NOT NULL,
target_type TEXT NOT NULL,
target_id TEXT NOT NULL,
moderator_id TEXT NOT NULL,
role_id TEXT,
duration TEXT,
end_timestamp INTEGER,
reason TEXT,
resolved INTEGER NOT NULL,
resolved_by TEXT,
resolve_reason TEXT,
expired INTEGER NOT NULL,
changes TEXT NOT NULL,
metadata TEXT 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,))
index_query_1 = "CREATE INDEX idx_target_id ON moderation_{}(target_id);"
cursor.execute(index_query_1.format(guild.id))
index_query_2 = "CREATE INDEX idx_moderator_id ON moderation_{}(moderator_id);"
cursor.execute(index_query_2.format(guild.id))
index_query_3 = "CREATE INDEX idx_moderation_id ON moderation_{}(moderation_id);"
cursor.execute(index_query_3.format(guild.id))
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 (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"""
insert_values = (
0,
@ -108,7 +93,7 @@ async def create_guild_table(guild: Guild):
database.commit()
logger.debug(
"MySQL Table (moderation_%s) created for %s (%s)",
"SQLite Table (moderation_%s) created for %s (%s)",
guild.id,
guild.name,
guild.id,
@ -117,6 +102,7 @@ async def create_guild_table(guild: Guild):
database.close()
# pylint: disable=dangerous-default-value
async def mysql_log(
guild_id: str,
author_id: str,
@ -124,9 +110,9 @@ async def mysql_log(
target_type: str,
target_id: int,
role_id: int,
duration,
duration: timedelta,
reason: str,
database: mysql.connector.MySQLConnection = None,
database: sqlite3.Connection = None,
timestamp: int = None,
resolved: bool = False,
resolved_by: str = None,
@ -134,13 +120,19 @@ async def mysql_log(
expired: bool = None,
changes: list = [],
metadata: dict = {},
): # pylint: disable=dangerous-default-value
) -> int:
if not timestamp:
timestamp = int(time.time())
if duration != "NULL":
end_timedelta = datetime.fromtimestamp(timestamp) + duration
end_timestamp = int(end_timedelta.timestamp())
total_seconds = int(duration.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
seconds = total_seconds % 60
duration = f"{hours}:{minutes}:{seconds}"
else:
end_timestamp = 0
@ -157,7 +149,7 @@ async def mysql_log(
resolved_reason = "NULL"
if not database:
database = await connect()
database = connect()
close_db = True
else:
close_db = False
@ -165,7 +157,7 @@ async def mysql_log(
moderation_id = await 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 (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
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 = (
moderation_id,
timestamp,
@ -192,7 +184,7 @@ async def mysql_log(
database.close()
logger.debug(
"MySQL row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s",
"Row inserted into moderation_%s!\n%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s",
guild_id,
moderation_id,
timestamp,
@ -215,13 +207,13 @@ async def mysql_log(
return moderation_id
async def fetch_case(moderation_id: int, guild_id: str):
async def fetch_case(moderation_id: int, guild_id: str) -> dict:
"""This method fetches a case from the database and returns the case's dictionary."""
database = await connect()
database = connect()
cursor = database.cursor()
query = "SELECT * FROM moderation_%s WHERE moderation_id = %s;"
cursor.execute(query, (guild_id, moderation_id))
query = f"SELECT * FROM moderation_{guild_id} WHERE moderation_id = ?;"
cursor.execute(query, (moderation_id,))
result = cursor.fetchone()
cursor.close()

View file

@ -0,0 +1,3 @@
import logging
logger = logging.getLogger("red.sea.aurora")

View file

@ -10,17 +10,6 @@ from redbot.core import commands
from .config import config
async def check_conf(config_list: list):
"""Checks if any required config options are not set."""
not_found_list = []
for item in config_list:
if await config.item() == " ":
not_found_list.append(item)
return not_found_list
def check_permissions(
user: User,
permissions: list,
@ -116,7 +105,7 @@ async def get_next_case_number(guild_id: str, cursor=None):
from .database import connect
if not cursor:
database = await connect()
database = connect()
cursor = database.cursor()
cursor.execute(
f"SELECT moderation_id FROM `moderation_{guild_id}` ORDER BY moderation_id DESC LIMIT 1"

9
info.json Normal file
View file

@ -0,0 +1,9 @@
{
"author": [
"SeaswimmerTheFsh (seasw.)"
],
"install_msg": "Thanks for installing my repo!\n\nIf you have any issues with any of the cogs, please create an issue [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs/issues) or join my [Discord Server](https://discord.gg/eMUMe77Yb8 ).",
"name": "SeaCogs",
"short": "Various cogs for Red, by SeaswimmerTheFsh (seasw.)",
"description": "Various cogs for Red, by SeaswimmerTheFsh (seasw.)"
}

View file

@ -1,5 +0,0 @@
from .moderation import Moderation
async def setup(bot):
await bot.add_cog(Moderation(bot))

View file

@ -1,11 +0,0 @@
{
"author" : ["SeaswimmerTheFsh"],
"install_msg" : "Thank you for installing Moderation!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).\nThis cog currently requires a MySQL database to function, instructions on how to set this up can be found [here]()",
"name" : "Moderation",
"short" : "Implements a variety of moderation commands",
"description" : "Implements a variety of moderation commands, including a warning system, a mute system, and a ban system.",
"end_user_data_statement" : "This cog stores the following information:\n- User IDs of accounts who moderate users or are moderated\n- Guild IDs of guilds with the cog enabled\n- Timestamps of moderations\n- Other information relating to moderations",
"requirements": ["mysql-connector-python", "humanize", "pytimeparse2"],
"hidden": false,
"disabled": false
}

View file

@ -1,3 +0,0 @@
import logging
logger = logging.getLogger("red.sea.moderation")