From df56e7d841a0c285cdcb2614e2dc577ca18f4dae Mon Sep 17 00:00:00 2001 From: nickpons666 Date: Fri, 20 Mar 2026 13:01:26 -0600 Subject: [PATCH] =?UTF-8?q?Fix:=20Recarga=20en=20caliente=20para=20canales?= =?UTF-8?q?=20y=20soluci=C3=B3n=20a=20cach=C3=A9=20estancado=20en=20MySQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- botdiscord/bot.py | 27 +++++++++++++---- botdiscord/bot_reload.py | 43 ++++++++++++++++++++++++++ botdiscord/database.py | 8 +++-- botdiscord/reload_marker.py | 60 +++++++++++++++++++++++++++++++++++++ panel/main.py | 6 ++++ 5 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 botdiscord/bot_reload.py create mode 100644 botdiscord/reload_marker.py diff --git a/botdiscord/bot.py b/botdiscord/bot.py index 9e6ebc2..ee6b9c3 100644 --- a/botdiscord/bot.py +++ b/botdiscord/bot.py @@ -5,9 +5,10 @@ import time sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import discord -from discord.ext import commands +from discord.ext import commands, tasks from discord import app_commands import re +from botdiscord.reload_marker import check_reload_marker import html from botdiscord.config import get_discord_token, load_config, get_languages @@ -22,6 +23,17 @@ intents.message_content = True intents.members = True bot = commands.Bot(command_prefix="!", intents=intents) +@tasks.loop(seconds=3) +async def restart_monitor(): + if check_reload_marker(): + print("[Bot] Cambios desde panel detectados. Recargando configuraciones sin reiniciar...") + from botdiscord.database import clear_channel_cache + from botdiscord.translate import load_lang_mappings + from botdiscord.config import load_config + clear_channel_cache() + load_config() + load_lang_mappings("discord") + @bot.event async def on_ready(): init_db() @@ -30,12 +42,15 @@ async def on_ready(): bot.add_view(PersistentTranslationView()) bot.add_view(WelcomeTranslationView()) + if not restart_monitor.is_running(): + restart_monitor.start() + print(f"Bot Discord conectado como {bot.user}") - try: - synced = await bot.tree.sync() - print(f"Sincronizados {len(synced)} comandos.") - except Exception as e: - print(f"Error sync: {e}") + # try: + # synced = await bot.tree.sync() + # print(f"Sincronizados {len(synced)} comandos.") + # except Exception as e: + # print(f"Error sync: {e}") @bot.event async def on_member_join(member): diff --git a/botdiscord/bot_reload.py b/botdiscord/bot_reload.py new file mode 100644 index 0000000..5198b2a --- /dev/null +++ b/botdiscord/bot_reload.py @@ -0,0 +1,43 @@ +import asyncio +import sys +import os + +# Agregar el path del proyecto para importar configuración +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from botdiscord.config import load_config, get_discord_token +from botdiscord.database import clear_channel_cache + +async def reload_bot_config(): + """ + Recarga la configuración del bot y limpia caches + """ + try: + print("[Bot Reload] Iniciando recarga de configuración...") + + # Limpiar cache de canales + clear_channel_cache() + print("[Bot Reload] Cache de canales limpiado") + + # Recargar configuración + load_config() + print("[Bot Reload] Configuración recargada") + + # Verificar token + token = get_discord_token() + if token: + print(f"[Bot Reload] Token encontrado: {bool(token)}") + else: + print("[Bot Reload] ADVERTENCIA: No se encontró token de Discord") + + print("[Bot Reload] ✅ Recarga completada") + return True + + except Exception as e: + print(f"[Bot Reload] Error en recarga: {e}") + import traceback + traceback.print_exc() + return False + +if __name__ == "__main__": + asyncio.run(reload_bot_config()) diff --git a/botdiscord/database.py b/botdiscord/database.py index 14b7f2f..aa35309 100644 --- a/botdiscord/database.py +++ b/botdiscord/database.py @@ -26,7 +26,8 @@ def get_connection(): password=db_config.get("password"), database=db_config.get("name"), consume_results=True, - connection_timeout=10 + connection_timeout=10, + autocommit=True ) print(f"[DB] MySQL conectado exitosamente") break @@ -52,7 +53,8 @@ def get_connection(): password=db_config.get("password"), database=db_config.get("name"), consume_results=True, - connection_timeout=10 + connection_timeout=10, + autocommit=True ) print(f"[DB] MySQL reconectado exitosamente") break @@ -72,7 +74,7 @@ def get_connection(): 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) + return sqlite3.connect(db_path, isolation_level=None) def close_connection(): global _connection diff --git a/botdiscord/reload_marker.py b/botdiscord/reload_marker.py new file mode 100644 index 0000000..1329423 --- /dev/null +++ b/botdiscord/reload_marker.py @@ -0,0 +1,60 @@ +import os +import time +import json +import threading + +MARKER_FILE = "/tmp/bot_reload_marker" +_last_marker_time = 0 +_marker_lock = threading.Lock() + +def set_reload_marker(): + """Crea un marcador para indicar que se necesita recarga""" + global _last_marker_time + + with _marker_lock: + current_time = time.time() + + # Evitar crear marcadores muy seguidos (mínimo 2 segundos) + if current_time - _last_marker_time < 2: + print(f"[Marker] Marcador omitido (demasiado pronto)") + return False + + try: + with open(MARKER_FILE, 'w') as f: + json.dump({ + 'timestamp': current_time, + 'reason': 'channel_toggle' + }, f) + _last_marker_time = current_time + print(f"[Marker] Marcador de recarga creado") + return True + except Exception as e: + print(f"[Marker] Error creando marcador: {e}") + return False + +def check_reload_marker(): + """Verifica si existe un marcador de recarga""" + try: + if os.path.exists(MARKER_FILE): + with open(MARKER_FILE, 'r') as f: + data = json.load(f) + # Eliminar el marcador + os.remove(MARKER_FILE) + print(f"[Marker] Marcador encontrado y eliminado: {data}") + return True + return False + except Exception as e: + print(f"[Marker] Error verificando marcador: {e}") + return False + +def clear_all_markers(): + """Limpia todos los marcadores existentes""" + try: + if os.path.exists(MARKER_FILE): + os.remove(MARKER_FILE) + print(f"[Marker] Todos los marcadores limpiados") + except Exception as e: + print(f"[Marker] Error limpiando marcadores: {e}") + +if __name__ == "__main__": + set_reload_marker() diff --git a/panel/main.py b/panel/main.py index 062e78c..7ae57f0 100644 --- a/panel/main.py +++ b/panel/main.py @@ -476,7 +476,9 @@ async def toggle_discord_channel(request: Request): try: from botdiscord.database import toggle_channel_status + from botdiscord.reload_marker import set_reload_marker toggle_channel_status(int(channel_id), is_active) + set_reload_marker() return RedirectResponse(url="/discord-channels?success=1", status_code=status.HTTP_303_SEE_OTHER) except Exception as e: print(f"Error toggling channel: {e}") @@ -495,7 +497,9 @@ async def delete_discord_server(request: Request): try: from botdiscord.database import delete_discord_server + from botdiscord.reload_marker import set_reload_marker delete_discord_server(int(server_id)) + set_reload_marker() return RedirectResponse(url="/discord-channels?success=1", status_code=status.HTTP_303_SEE_OTHER) except Exception as e: print(f"Error deleting server: {e}") @@ -550,6 +554,8 @@ async def bulk_toggle_discord_channels(request: Request): continue print(f"[Panel] Bulk toggle: {success_count} canales {'activados' if is_active else 'desactivados'}") + from botdiscord.reload_marker import set_reload_marker + set_reload_marker() return RedirectResponse(url="/discord-channels?success=1", status_code=status.HTTP_303_SEE_OTHER) except Exception as e: