perefouras/database.py
2026-08-06 16:20:08 +02:00

186 lines
5.5 KiB
Python

# database.py
import sqlite3
import random
from datetime import datetime, timedelta
from pathlib import Path
from typing import Any, Dict, Tuple
DB_FILE = "data/database.db"
CREATE_GUILD_STATE_QUERY = """
INSERT INTO guild_state (guild_id, cooldown_until, cooldown_ratio, self_control, last_updated)
VALUES (?, datetime('now'), 1.0, 1.0, datetime('now'))
"""
GET_GUILD_STATE_QUERY = """
SELECT cooldown_until, cooldown_ratio, self_control, last_updated
FROM guild_state
WHERE guild_id = ?
"""
CONFIGURE_COOLDOWN_RATIO_QUERY = """
UPDATE guild_state
SET cooldown_ratio = ?
WHERE guild_id = ?
"""
DAMAGE_SELF_CONTROL_QUERY = """
UPDATE guild_state
SET self_control = self_control * 0.9
WHERE guild_id = ?
"""
RESET_COOLDOWN_QUERY = """
UPDATE guild_state
SET cooldown_until = ?,
self_control = self_control + 1.0,
last_updated = datetime('now')
WHERE guild_id = ?
"""
SAVE_RIDDLE_QUERY = """
INSERT OR REPLACE INTO active_riddles
(channel_id, riddle_index, nb_clues, message_id, solver_id, updated_at)
VALUES (?, ?, ?, ?, ?, datetime('now'))
"""
INCREMENT_CLUE_QUERY = """
UPDATE active_riddles
SET nb_clues = nb_clues + 1
WHERE channel_id = ?
"""
DELETE_RIDDLE_QUERY = "DELETE FROM active_riddles WHERE channel_id = ?"
def ensure_db() -> None:
"""Initialize SQLite database and create tables if needed."""
Path(DB_FILE).parent.mkdir(parents=True, exist_ok=True)
with sqlite3.connect(DB_FILE) as conn:
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS guild_state (
guild_id TEXT PRIMARY KEY,
cooldown_until TEXT NOT NULL DEFAULT '1970-01-01T00:00:00',
cooldown_ratio REAL NOT NULL DEFAULT 1.0,
self_control REAL NOT NULL DEFAULT 1.0,
last_updated TEXT NOT NULL DEFAULT (datetime('now'))
)
""")
cursor.execute("""
CREATE TABLE IF NOT EXISTS active_riddles (
channel_id TEXT PRIMARY KEY,
riddle_index INTEGER NOT NULL,
nb_clues INTEGER NOT NULL DEFAULT -1,
message_id INTEGER NOT NULL,
solver_id TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
)
""")
conn.commit()
def get_connection() -> sqlite3.Connection:
conn = sqlite3.connect(DB_FILE)
conn.row_factory = sqlite3.Row
return conn
def get_guild_state(guild_id: str) -> Dict[str, Any]:
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute(GET_GUILD_STATE_QUERY,(guild_id,))
row = cursor.fetchone()
if not row:
cursor.execute(CREATE_GUILD_STATE_QUERY, (guild_id,))
conn.commit()
cursor.execute(GET_GUILD_STATE_QUERY,(guild_id,))
row = cursor.fetchone()
if row:
return {
"cooldown_until": row["cooldown_until"],
"cooldown_ratio": row["cooldown_ratio"],
"self_control": row["self_control"],
"last_updated": row["last_updated"],
}
return {}
def rhyme_configure_cooldown_ratio(guild_id: str, cooldown_ratio: float) -> bool:
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute(CONFIGURE_COOLDOWN_RATIO_QUERY, (cooldown_ratio, guild_id,))
conn.commit()
def rhyme_damage_self_control(guild_id: str) -> None:
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute(DAMAGE_SELF_CONTROL_QUERY, (guild_id,))
conn.commit()
def rhyme_reset_cooldown(
guild_id: str,
ratio: float
) -> None:
with get_connection() as conn:
# Calculate new cooldown duration
wait_time = random.randint(900, 10800) if bool(random.getrandbits(1)) else random.randint(0, 900)
wait_time = 0 if ratio < 0 else int(wait_time * ratio)
cooldown_until = datetime.now().replace(second=0, microsecond=0) + timedelta(seconds=wait_time)
cursor = conn.cursor()
cursor.execute(RESET_COOLDOWN_QUERY, (cooldown_until.isoformat(), guild_id,))
conn.commit()
def get_active_riddle(channel_id: str) -> Any:
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM active_riddles WHERE channel_id = ?", (str(channel_id),))
row = cursor.fetchone()
if row:
return {
"channel_id": row["channel_id"],
"riddle_index": row["riddle_index"],
"nb_clues": row["nb_clues"],
"message_id": row["message_id"],
"solver_id": row["solver_id"],
"created_at": row["created_at"],
"updated_at": row["updated_at"],
}
return None
def save_active_riddle(
channel_id: str,
riddle_index: int,
nb_clues: int,
message_id: int,
solver_id: str = "",
) -> None:
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute(SAVE_RIDDLE_QUERY, (channel_id, riddle_index, nb_clues, message_id, solver_id))
conn.commit()
def increment_clue(channel_id: str) -> None:
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute(INCREMENT_CLUE_QUERY, (channel_id,),)
conn.commit()
def remove_active_riddle(channel_id: str) -> None:
with get_connection() as conn:
cursor = conn.cursor()
cursor.execute(DELETE_RIDDLE_QUERY, (str(channel_id),))
conn.commit()