mirror of
https://github.com/Lilac-Rose/Lacie.git
synced 2026-09-13 11:36:28 -05:00
Moderation & logging: - cleanban now collects all messages before banning and attaches them as a .txt audit log file via the member_ban log channel - purgememberall restricted to server owner only (nuke protection) - unban, lock, unlock, spam ban-button, and manual infraction deletes all now write to the DB infractions table and post to the mod log - new log types (channel_lock, infraction_modify, cleanban) added and seeded to route to the main mod log channel (982644273960873994) Bug fixes: - unban: mod log no longer fires on failure (missing return added) - mute: fixed DB connection leaks and silent unmute failures in schedule_unmute and check_mutes (try/finally + proper error logging) - suggest: fixed AttributeError crash when original_embed is None and IndexError risk on set_field_at calls without field count guards - ban/cleanban: removed isinstance(user, discord.User) guard that silently prevented DMs from ever being sent to in-server members - cleanban: wrapped collect_status.delete() in try/except - commands/infractions: fixed DB connection leak with try/finally - events/botban: silent ban failure now logs error instead of swallowing it Minesweeper: - track detonated_cell on mine hit; show 💥 on the clicked mine and 💣 on all others when the board is revealed on loss Emote credits: - new /emote_credits_pending command: shows the user their own unreviewed submissions; admins can pass all:True to see the full pending queue Code quality: - comprehensive docstrings and inline comments added across all cogs, events, commands, utils, and supporting modules
75 lines
2.3 KiB
Python
75 lines
2.3 KiB
Python
import sqlite3
|
|
from pathlib import Path
|
|
|
|
DB_DIR = Path(__file__).parent.parent / "data"
|
|
|
|
DB_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
def get_db(db_type="lifetime"):
|
|
"""Open (or create) an XP database for the given leaderboard type and return (conn, cursor).
|
|
|
|
Accepts a boolean for backwards-compatibility: True → "lifetime", False → "annual".
|
|
|
|
Each leaderboard type has its own SQLite file (e.g. lifetime.db, weekly.db).
|
|
The daily/weekly/monthly databases also include a reset_log table that
|
|
records the last time the leaderboard was wiped, so the UI can display
|
|
'last reset X ago'.
|
|
|
|
Parameters
|
|
----------
|
|
db_type:
|
|
One of "lifetime", "annual", "monthly", "weekly", "daily" (or a bool).
|
|
Defaults to "lifetime" for any unrecognised value.
|
|
"""
|
|
if isinstance(db_type, bool):
|
|
db_type = "lifetime" if db_type else "annual"
|
|
|
|
valid_types = ["lifetime", "annual", "monthly", "weekly", "daily"]
|
|
if db_type not in valid_types:
|
|
db_type = "lifetime"
|
|
|
|
db_name = f"{db_type}.db"
|
|
db_path = str(DB_DIR / db_name)
|
|
conn = sqlite3.connect(db_path)
|
|
cur = conn.cursor()
|
|
|
|
cur.execute("""
|
|
CREATE TABLE IF NOT EXISTS xp (
|
|
user_id TEXT PRIMARY KEY,
|
|
xp INTEGER DEFAULT 0,
|
|
level INTEGER DEFAULT 0,
|
|
last_message INTEGER DEFAULT 0
|
|
)
|
|
""")
|
|
|
|
if db_type in ["daily", "weekly", "monthly"]:
|
|
cur.execute("""
|
|
CREATE TABLE IF NOT EXISTS reset_log (
|
|
id INTEGER PRIMARY KEY,
|
|
last_reset INTEGER DEFAULT 0
|
|
)
|
|
""")
|
|
cur.execute("INSERT OR IGNORE INTO reset_log (id, last_reset) VALUES (1, 0)")
|
|
|
|
conn.commit()
|
|
return conn, cur
|
|
|
|
def reset_leaderboard(db_type):
|
|
"""Wipe all XP rows and record the reset timestamp in reset_log."""
|
|
import time
|
|
|
|
conn, cur = get_db(db_type)
|
|
cur.execute("DELETE FROM xp")
|
|
cur.execute("UPDATE reset_log SET last_reset = ? WHERE id = 1", (int(time.time()),))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
|
|
def get_last_reset(db_type):
|
|
"""Return the Unix timestamp of the last leaderboard reset, or 0 if never reset."""
|
|
conn, cur = get_db(db_type)
|
|
cur.execute("SELECT last_reset FROM reset_log WHERE id = 1")
|
|
row = cur.fetchone()
|
|
conn.close()
|
|
return row[0] if row else 0
|