- Nueva tabla 'welcome_messages' en la base de datos - Panel web con página de configuración de bienvenida (/welcome) - Listar, crear, editar y eliminar mensajes por servidor - Vista previa del mensaje - Plantillas predefinidas - Bot Discord: - Nuevo intent 'members' para detectar nuevos usuarios - Evento on_member_join que envía mensaje de bienvenida - Botones de traducción en mensajes de bienvenida - Actualizada configuración de MySQL en docker-compose.yml - Añadido logging de debug para traducciones
702 lines
28 KiB
Python
702 lines
28 KiB
Python
import sqlite3
|
|
import mysql.connector
|
|
import json
|
|
from mysql.connector import Error as MySQLError
|
|
from botdiscord.config import get_db_config, get_db_type
|
|
|
|
_connection = None
|
|
|
|
def get_connection():
|
|
global _connection
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
db_config = get_db_config()
|
|
|
|
# Si no hay conexión o no está activa, intentamos conectar/reconectar
|
|
if _connection is None:
|
|
try:
|
|
_connection = mysql.connector.connect(
|
|
host=db_config.get("host"),
|
|
port=db_config.get("port"),
|
|
user=db_config.get("user"),
|
|
password=db_config.get("password"),
|
|
database=db_config.get("name"),
|
|
consume_results=True,
|
|
connection_timeout=5
|
|
)
|
|
except MySQLError as e:
|
|
print(f"CRITICAL: Could not establish initial MySQL connection: {e}")
|
|
raise
|
|
|
|
# Verificar salud de la conexión existente
|
|
try:
|
|
_connection.ping(reconnect=True, attempts=3, delay=1)
|
|
except MySQLError:
|
|
try:
|
|
_connection = mysql.connector.connect(
|
|
host=db_config.get("host"),
|
|
port=db_config.get("port"),
|
|
user=db_config.get("user"),
|
|
password=db_config.get("password"),
|
|
database=db_config.get("name"),
|
|
consume_results=True,
|
|
connection_timeout=5
|
|
)
|
|
except MySQLError as e:
|
|
print(f"CRITICAL: MySQL reconnection failed: {e}")
|
|
raise
|
|
|
|
return _connection
|
|
else:
|
|
import os
|
|
from botdiscord.config import get_db_path
|
|
db_path = get_db_path()
|
|
db_dir = os.path.dirname(db_path)
|
|
if db_dir and not os.path.exists(db_dir):
|
|
os.makedirs(db_dir, exist_ok=True)
|
|
return sqlite3.connect(db_path)
|
|
|
|
def close_connection():
|
|
global _connection
|
|
if _connection and _connection.is_connected():
|
|
_connection.close()
|
|
_connection = None
|
|
|
|
def _execute_query(query, params=None, fetch=False):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
try:
|
|
cursor.execute(query, params or ())
|
|
if fetch:
|
|
result = cursor.fetchall()
|
|
else:
|
|
conn.commit()
|
|
result = cursor.lastrowid
|
|
return result
|
|
finally:
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
try:
|
|
cursor.execute(query, params or ())
|
|
if fetch:
|
|
result = cursor.fetchall()
|
|
else:
|
|
conn.commit()
|
|
result = cursor.lastrowid
|
|
return result
|
|
finally:
|
|
cursor.close()
|
|
|
|
def init_db():
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS guild_languages
|
|
(guild_id BIGINT NOT NULL, lang_code VARCHAR(10) NOT NULL,
|
|
PRIMARY KEY (guild_id, lang_code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS bot_config
|
|
(`key` VARCHAR(255) NOT NULL, value TEXT,
|
|
PRIMARY KEY (`key`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS available_languages
|
|
(code VARCHAR(10) NOT NULL, name VARCHAR(100) NOT NULL, flag VARCHAR(20),
|
|
PRIMARY KEY (code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS bot_languages
|
|
(bot_type VARCHAR(50) NOT NULL, lang_code VARCHAR(10) NOT NULL,
|
|
PRIMARY KEY (bot_type, lang_code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
|
|
# Nuevas tablas para caché y persistencia
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS messages
|
|
(message_id BIGINT PRIMARY KEY,
|
|
guild_id BIGINT,
|
|
author_id BIGINT,
|
|
content TEXT NOT NULL,
|
|
mentions_map JSON,
|
|
bot_type ENUM('discord', 'telegram') NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS translations
|
|
(id INT AUTO_INCREMENT PRIMARY KEY,
|
|
message_id BIGINT NOT NULL,
|
|
target_lang VARCHAR(10) NOT NULL,
|
|
translated_text TEXT NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (message_id) REFERENCES messages(message_id) ON DELETE CASCADE,
|
|
UNIQUE KEY idx_msg_lang (message_id, target_lang)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
# Tabla para traducciones de la interfaz web
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS ui_translations
|
|
(id INT AUTO_INCREMENT PRIMARY KEY,
|
|
text_hash VARCHAR(64) NOT NULL,
|
|
original_text TEXT NOT NULL,
|
|
target_lang VARCHAR(10) NOT NULL,
|
|
translated_text TEXT NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE KEY idx_ui_hash_lang (text_hash, target_lang)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
|
|
# Migración automática: Añadir text_hash si no existe
|
|
try:
|
|
cursor.execute("SHOW COLUMNS FROM ui_translations LIKE 'text_hash'")
|
|
if not cursor.fetchone():
|
|
print("Migrating ui_translations: Adding text_hash column...")
|
|
# Primero borramos el índice viejo si existe (basado en el código anterior)
|
|
try:
|
|
cursor.execute("ALTER TABLE ui_translations DROP INDEX idx_ui_lang")
|
|
except: pass
|
|
# Añadimos la columna y el nuevo índice
|
|
cursor.execute("ALTER TABLE ui_translations ADD COLUMN text_hash VARCHAR(64) NOT NULL AFTER id")
|
|
cursor.execute("ALTER TABLE ui_translations ADD UNIQUE KEY idx_ui_hash_lang (text_hash, target_lang)")
|
|
# Limpiamos la tabla para evitar conflictos de hash con datos viejos
|
|
cursor.execute("DELETE FROM ui_translations")
|
|
except Exception as e:
|
|
print(f"Migration warning: {e}")
|
|
|
|
conn.commit()
|
|
# Tabla para administradores del panel web
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS admins
|
|
(id INT AUTO_INCREMENT PRIMARY KEY,
|
|
username VARCHAR(50) NOT NULL UNIQUE,
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
|
|
cursor.execute('''CREATE TABLE IF NOT EXISTS welcome_messages
|
|
(guild_id BIGINT PRIMARY KEY,
|
|
channel_id BIGINT NOT NULL,
|
|
message_content TEXT NOT NULL,
|
|
enabled BOOLEAN DEFAULT TRUE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
|
|
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute('''CREATE TABLE IF NOT EXISTS guild_languages
|
|
(guild_id INTEGER, lang_code TEXT, PRIMARY KEY (guild_id, lang_code))''')
|
|
c.execute('''CREATE TABLE IF NOT EXISTS bot_config
|
|
(key TEXT PRIMARY KEY, value TEXT)''')
|
|
c.execute('''CREATE TABLE IF NOT EXISTS available_languages
|
|
(code TEXT PRIMARY KEY, name TEXT, flag TEXT)''')
|
|
c.execute('''CREATE TABLE IF NOT EXISTS bot_languages
|
|
(bot_type TEXT, lang_code TEXT, PRIMARY KEY (bot_type, lang_code))''')
|
|
|
|
# SQLite equivalents
|
|
c.execute('''CREATE TABLE IF NOT EXISTS messages
|
|
(message_id INTEGER PRIMARY KEY,
|
|
guild_id INTEGER,
|
|
author_id INTEGER,
|
|
content TEXT NOT NULL,
|
|
mentions_map TEXT,
|
|
bot_type TEXT NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
|
|
|
|
c.execute('''CREATE TABLE IF NOT EXISTS translations
|
|
(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
message_id INTEGER NOT NULL,
|
|
target_lang TEXT NOT NULL,
|
|
translated_text TEXT NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(message_id, target_lang))''')
|
|
|
|
# SQLite equivalent for UI translations
|
|
c.execute('''CREATE TABLE IF NOT EXISTS ui_translations
|
|
(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
original_text TEXT NOT NULL,
|
|
target_lang TEXT NOT NULL,
|
|
translated_text TEXT NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(original_text, target_lang))''')
|
|
|
|
# SQLite equivalent for admins
|
|
c.execute('''CREATE TABLE IF NOT EXISTS admins
|
|
(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username TEXT NOT NULL UNIQUE,
|
|
password_hash TEXT NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
|
|
|
|
c.execute('''CREATE TABLE IF NOT EXISTS welcome_messages
|
|
(guild_id INTEGER PRIMARY KEY,
|
|
channel_id INTEGER NOT NULL,
|
|
message_content TEXT NOT NULL,
|
|
enabled INTEGER DEFAULT 1)''')
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def set_available_languages(languages: list):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("DELETE FROM available_languages")
|
|
for lang in languages:
|
|
cursor.execute("INSERT INTO available_languages (code, name, flag) VALUES (%s, %s, %s)",
|
|
(lang.get("code"), lang.get("name"), lang.get("flag", "")))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("DELETE FROM available_languages")
|
|
for lang in languages:
|
|
c.execute("INSERT OR REPLACE INTO available_languages (code, name, flag) VALUES (?, ?, ?)",
|
|
(lang.get("code"), lang.get("name"), lang.get("flag", "")))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def get_available_languages() -> list:
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT code, name, flag FROM available_languages ORDER BY name")
|
|
rows = cursor.fetchall()
|
|
cursor.close()
|
|
return [{"code": row[0], "name": row[1], "flag": row[2] or ""} for row in rows]
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT code, name, flag FROM available_languages ORDER BY name")
|
|
langs = [{"code": row[0], "name": row[1], "flag": row[2] or ""} for row in c.fetchall()]
|
|
conn.close()
|
|
return langs
|
|
|
|
def set_bot_languages(bot_type: str, lang_codes: list):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("DELETE FROM bot_languages WHERE bot_type = %s", (bot_type,))
|
|
for code in lang_codes:
|
|
cursor.execute("INSERT INTO bot_languages (bot_type, lang_code) VALUES (%s, %s)",
|
|
(bot_type, code))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("DELETE FROM bot_languages WHERE bot_type = ?", (bot_type,))
|
|
for code in lang_codes:
|
|
c.execute("INSERT INTO bot_languages (bot_type, lang_code) VALUES (?, ?)",
|
|
(bot_type, code))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def get_bot_languages(bot_type: str) -> list:
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT lang_code FROM bot_languages WHERE bot_type = %s", (bot_type,))
|
|
rows = cursor.fetchall()
|
|
cursor.close()
|
|
return [row[0] for row in rows]
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT lang_code FROM bot_languages WHERE bot_type = ?", (bot_type,))
|
|
langs = [row[0] for row in c.fetchall()]
|
|
conn.close()
|
|
return langs
|
|
|
|
def get_active_languages(guild_id: int) -> list:
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT lang_code FROM guild_languages WHERE guild_id = %s", (guild_id,))
|
|
rows = cursor.fetchall()
|
|
cursor.close()
|
|
return [row[0] for row in rows]
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT lang_code FROM guild_languages WHERE guild_id = ?", (guild_id,))
|
|
langs = [row[0] for row in c.fetchall()]
|
|
conn.close()
|
|
return langs
|
|
|
|
def set_active_languages(guild_id: int, lang_codes: list):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("DELETE FROM guild_languages WHERE guild_id = %s", (guild_id,))
|
|
for code in lang_codes:
|
|
cursor.execute("INSERT INTO guild_languages (guild_id, lang_code) VALUES (%s, %s)",
|
|
(guild_id, code))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("DELETE FROM guild_languages WHERE guild_id = ?", (guild_id,))
|
|
for code in lang_codes:
|
|
c.execute("INSERT INTO guild_languages (guild_id, lang_code) VALUES (?, ?)", (guild_id, code))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def get_config_value(key: str) -> str:
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT value FROM bot_config WHERE `key` = %s", (key,))
|
|
row = cursor.fetchone()
|
|
cursor.close()
|
|
return row[0] if row else None
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT value FROM bot_config WHERE key = ?", (key,))
|
|
row = c.fetchone()
|
|
conn.close()
|
|
return row[0] if row else None
|
|
|
|
def set_config_value(key: str, value: str):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("INSERT INTO bot_config (`key`, value) VALUES (%s, %s) ON DUPLICATE KEY UPDATE value = %s",
|
|
(key, value, value))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("INSERT OR REPLACE INTO bot_config (key, value) VALUES (?, ?)", (key, value))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def save_message(message_id: int, guild_id: int, author_id: int, content: str, mentions_map: dict, bot_type: str):
|
|
db_type = get_db_type()
|
|
mentions_json = json.dumps(mentions_map)
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
query = """INSERT INTO messages (message_id, guild_id, author_id, content, mentions_map, bot_type)
|
|
VALUES (%s, %s, %s, %s, %s, %s)
|
|
ON DUPLICATE KEY UPDATE content = %s, mentions_map = %s"""
|
|
cursor.execute(query, (message_id, guild_id, author_id, content, mentions_json, bot_type, content, mentions_json))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("INSERT OR REPLACE INTO messages (message_id, guild_id, author_id, content, mentions_map, bot_type) VALUES (?, ?, ?, ?, ?, ?)",
|
|
(message_id, guild_id, author_id, content, mentions_json, bot_type))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def get_message(message_id: int):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor(dictionary=True)
|
|
cursor.execute("SELECT content, mentions_map, bot_type FROM messages WHERE message_id = %s", (message_id,))
|
|
row = cursor.fetchone()
|
|
cursor.close()
|
|
if row:
|
|
if row['mentions_map']:
|
|
row['mentions_map'] = json.loads(row['mentions_map'])
|
|
return row
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT content, mentions_map, bot_type FROM messages WHERE message_id = ?", (message_id,))
|
|
row = c.fetchone()
|
|
conn.close()
|
|
if row:
|
|
return {
|
|
'content': row[0],
|
|
'mentions_map': json.loads(row[1]) if row[1] else {},
|
|
'bot_type': row[2]
|
|
}
|
|
return None
|
|
|
|
def save_translation(message_id: int, target_lang: str, translated_text: str):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
query = "INSERT INTO translations (message_id, target_lang, translated_text) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE translated_text = %s"
|
|
cursor.execute(query, (message_id, target_lang, translated_text, translated_text))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("INSERT OR REPLACE INTO translations (message_id, target_lang, translated_text) VALUES (?, ?, ?)",
|
|
(message_id, target_lang, translated_text))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def get_cached_translation(message_id: int, target_lang: str) -> str:
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT translated_text FROM translations WHERE message_id = %s AND target_lang = %s", (message_id, target_lang))
|
|
row = cursor.fetchone()
|
|
cursor.close()
|
|
return row[0] if row else None
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT translated_text FROM translations WHERE message_id = ? AND target_lang = ?", (message_id, target_lang))
|
|
row = c.fetchone()
|
|
conn.close()
|
|
return row[0] if row else None
|
|
|
|
import hashlib
|
|
|
|
def _normalize_text(text: str) -> str:
|
|
"""Normaliza el texto para que el caché sea consistente."""
|
|
if not text: return ""
|
|
# Quitar espacios en extremos, normalizar saltos de línea y quitar espacios dobles
|
|
text = text.strip().replace('\r\n', '\n')
|
|
return " ".join(text.split())
|
|
|
|
def _get_text_hash(text: str) -> str:
|
|
"""Genera un hash único para el texto normalizado."""
|
|
norm = _normalize_text(text)
|
|
return hashlib.sha256(norm.encode('utf-8')).hexdigest()
|
|
|
|
def get_ui_translation(text: str, target_lang: str) -> str:
|
|
db_type = get_db_type()
|
|
text_hash = _get_text_hash(text)
|
|
try:
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT translated_text FROM ui_translations WHERE text_hash = %s AND target_lang = %s", (text_hash, target_lang))
|
|
row = cursor.fetchone()
|
|
cursor.close()
|
|
return row[0] if row else None
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT translated_text FROM ui_translations WHERE text_hash = ? AND target_lang = ?", (text_hash, target_lang))
|
|
row = c.fetchone()
|
|
conn.close()
|
|
return row[0] if row else None
|
|
except Exception as e:
|
|
print(f"Database error in get_ui_translation: {e}")
|
|
return None
|
|
|
|
def save_ui_translation(text: str, target_lang: str, translated_text: str):
|
|
db_type = get_db_type()
|
|
text_hash = _get_text_hash(text)
|
|
try:
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
query = """INSERT INTO ui_translations (text_hash, original_text, target_lang, translated_text)
|
|
VALUES (%s, %s, %s, %s)
|
|
ON DUPLICATE KEY UPDATE translated_text = %s"""
|
|
cursor.execute(query, (text_hash, text, target_lang, translated_text, translated_text))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("INSERT OR REPLACE INTO ui_translations (text_hash, original_text, target_lang, translated_text) VALUES (?, ?, ?, ?)",
|
|
(text_hash, text, target_lang, translated_text))
|
|
conn.commit()
|
|
conn.close()
|
|
except Exception as e:
|
|
print(f"Database error in save_ui_translation: {e}")
|
|
|
|
# Funciones para administradores
|
|
def get_admins():
|
|
db_type = get_db_type()
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor(dictionary=True)
|
|
cursor.execute("SELECT id, username, created_at FROM admins ORDER BY username")
|
|
rows = cursor.fetchall()
|
|
cursor.close()
|
|
return rows
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT id, username, created_at FROM admins ORDER BY username")
|
|
rows = [{"id": r[0], "username": r[1], "created_at": r[2]} for r in c.fetchall()]
|
|
conn.close()
|
|
return rows
|
|
|
|
def get_admin_by_username(username: str):
|
|
db_type = get_db_type()
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor(dictionary=True)
|
|
cursor.execute("SELECT * FROM admins WHERE username = %s", (username,))
|
|
row = cursor.fetchone()
|
|
cursor.close()
|
|
return row
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT id, username, password_hash, created_at FROM admins WHERE username = ?", (username,))
|
|
row = c.fetchone()
|
|
conn.close()
|
|
if row:
|
|
return {"id": row[0], "username": row[1], "password_hash": row[2], "created_at": row[3]}
|
|
return None
|
|
|
|
def add_admin(username: str, password_hash: str):
|
|
db_type = get_db_type()
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("INSERT INTO admins (username, password_hash) VALUES (%s, %s)", (username, password_hash))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("INSERT INTO admins (username, password_hash) VALUES (?, ?)", (username, password_hash))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def delete_admin(admin_id: int):
|
|
db_type = get_db_type()
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("DELETE FROM admins WHERE id = %s", (admin_id,))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("DELETE FROM admins WHERE id = ?", (admin_id,))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def update_admin_password(admin_id: int, password_hash: str):
|
|
db_type = get_db_type()
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("UPDATE admins SET password_hash = %s WHERE id = %s", (password_hash, admin_id))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("UPDATE admins SET password_hash = ? WHERE id = ?", (password_hash, admin_id))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def save_welcome_message(guild_id: int, channel_id: int, message_content: str, enabled: bool = True):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
query = """INSERT INTO welcome_messages (guild_id, channel_id, message_content, enabled)
|
|
VALUES (%s, %s, %s, %s)
|
|
ON DUPLICATE KEY UPDATE channel_id = %s, message_content = %s, enabled = %s"""
|
|
cursor.execute(query, (guild_id, channel_id, message_content, enabled, channel_id, message_content, enabled))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("""INSERT OR REPLACE INTO welcome_messages (guild_id, channel_id, message_content, enabled)
|
|
VALUES (?, ?, ?, ?)""", (guild_id, channel_id, message_content, 1 if enabled else 0))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def get_welcome_message(guild_id: int):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor(dictionary=True)
|
|
cursor.execute("SELECT channel_id, message_content, enabled FROM welcome_messages WHERE guild_id = %s", (guild_id,))
|
|
row = cursor.fetchone()
|
|
cursor.close()
|
|
if row:
|
|
return {
|
|
'channel_id': int(row['channel_id']) if row['channel_id'] else 0,
|
|
'message_content': row['message_content'] or '',
|
|
'enabled': bool(row['enabled'])
|
|
}
|
|
return None
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT channel_id, message_content, enabled FROM welcome_messages WHERE guild_id = ?", (guild_id,))
|
|
row = c.fetchone()
|
|
conn.close()
|
|
if row:
|
|
return {
|
|
"channel_id": int(row[0]) if row[0] else 0,
|
|
"message_content": row[1] or '',
|
|
"enabled": bool(row[2])
|
|
}
|
|
return None
|
|
|
|
def get_all_welcome_configs():
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor(dictionary=True)
|
|
cursor.execute("SELECT guild_id, channel_id, message_content, enabled FROM welcome_messages")
|
|
rows = cursor.fetchall()
|
|
cursor.close()
|
|
result = []
|
|
for row in rows:
|
|
result.append({
|
|
'guild_id': int(row['guild_id']) if row['guild_id'] else 0,
|
|
'channel_id': int(row['channel_id']) if row['channel_id'] else 0,
|
|
'message_content': row['message_content'] or '',
|
|
'enabled': bool(row['enabled'])
|
|
})
|
|
return result
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("SELECT guild_id, channel_id, message_content, enabled FROM welcome_messages")
|
|
rows = [{"guild_id": r[0], "channel_id": r[1], "message_content": r[2], "enabled": bool(r[3])} for r in c.fetchall()]
|
|
conn.close()
|
|
return rows
|
|
|
|
def delete_welcome_message(guild_id: int):
|
|
db_type = get_db_type()
|
|
|
|
if db_type == "mysql":
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("DELETE FROM welcome_messages WHERE guild_id = %s", (guild_id,))
|
|
conn.commit()
|
|
cursor.close()
|
|
else:
|
|
conn = get_connection()
|
|
c = conn.cursor()
|
|
c.execute("DELETE FROM welcome_messages WHERE guild_id = ?", (guild_id,))
|
|
conn.commit()
|
|
conn.close()
|