Fix Discord channel activation system

- Fix MySQL boolean conversion in toggle_channel_status
- Improve cache management with 5-second timeout
- Add bulk channel selection and toggle functionality
- Fix Jinja2 template syntax errors
- Add comprehensive debugging for channel status queries
- Implement real-time channel activation without container restart
This commit is contained in:
2026-03-20 06:41:35 -06:00
parent 100fef5c90
commit 39f531a331
6 changed files with 743 additions and 9 deletions

View File

@@ -8,9 +8,14 @@ from fastapi.templating import Jinja2Templates
from fastapi import Request
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
from dotenv import load_dotenv
from passlib.hash import pbkdf2_sha256 as hasher
from botdiscord.config import load_config, get_web_config, get_libretranslate_url, get_db_type
# Asegurar que las variables de entorno se carguen correctamente
load_dotenv()
load_config() # Cargamos configuración inmediatamente
from botdiscord.database import (
@@ -397,6 +402,188 @@ async def delete_welcome(request: Request):
return RedirectResponse(url="/welcome", status_code=status.HTTP_303_SEE_OTHER)
@app.get("/discord-channels")
async def discord_channels_page(request: Request):
if request.cookies.get("auth") != "ok":
return RedirectResponse(url="/login")
from botdiscord.database import get_discord_servers, get_discord_channels
servers = get_discord_servers()
channels = get_discord_channels()
# Agrupar canales por servidor
servers_with_channels = {}
for server in servers:
server_id = server['server_id']
servers_with_channels[server_id] = {
'server_info': server,
'channels': [ch for ch in channels if ch['server_id'] == server_id]
}
success = request.query_params.get("success") == "1"
error = request.query_params.get("error") == "1"
synced = request.query_params.get("synced") == "1"
return templates.TemplateResponse("discord_channels.html", {
"request": request,
"servers_with_channels": servers_with_channels,
"success": success,
"error": error,
"synced": synced
})
@app.post("/discord-channels/sync")
async def sync_discord_servers(request: Request):
if request.cookies.get("auth") != "ok":
raise HTTPException(status_code=401)
try:
print("[Panel] Iniciando sincronización de Discord...")
# Diagnóstico de variables de entorno
print("[Panel] Variables de entorno disponibles:")
discord_env_vars = {k: v for k, v in os.environ.items() if 'DISCORD' in k or 'TOKEN' in k}
for key, value in discord_env_vars.items():
print(f" {key}: {'***' if 'TOKEN' in key else value}")
# Importar y usar el módulo de sincronización
from botdiscord.server_sync import sync_discord_servers_from_api
result = await sync_discord_servers_from_api()
print(f"[Panel] Resultado de sincronización: {result}")
if result:
return RedirectResponse(url="/discord-channels?synced=1", status_code=status.HTTP_303_SEE_OTHER)
else:
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
except Exception as e:
print(f"[Panel] Error en sincronización: {e}")
import traceback
traceback.print_exc()
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
@app.post("/discord-channels/toggle")
async def toggle_discord_channel(request: Request):
if request.cookies.get("auth") != "ok":
raise HTTPException(status_code=401)
form = await request.form()
channel_id = form.get("channel_id")
is_active = form.get("is_active") == "true"
if not channel_id:
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
try:
from botdiscord.database import toggle_channel_status
toggle_channel_status(int(channel_id), is_active)
return RedirectResponse(url="/discord-channels?success=1", status_code=status.HTTP_303_SEE_OTHER)
except Exception as e:
print(f"Error toggling channel: {e}")
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
@app.post("/discord-channels/delete-server")
async def delete_discord_server(request: Request):
if request.cookies.get("auth") != "ok":
raise HTTPException(status_code=401)
form = await request.form()
server_id = form.get("server_id")
if not server_id:
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
try:
from botdiscord.database import delete_discord_server
delete_discord_server(int(server_id))
return RedirectResponse(url="/discord-channels?success=1", status_code=status.HTTP_303_SEE_OTHER)
except Exception as e:
print(f"Error deleting server: {e}")
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
@app.post("/discord-channels/reload-bot")
async def reload_discord_bot(request: Request):
if request.cookies.get("auth") != "ok":
raise HTTPException(status_code=401)
try:
print("[Panel] Enviando señal de recarga al bot de Discord...")
# Importar y ejecutar la función de recarga
from botdiscord.bot_reload import reload_bot_config
result = await reload_bot_config()
if result:
return RedirectResponse(url="/discord-channels?success=1", status_code=status.HTTP_303_SEE_OTHER)
else:
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
except Exception as e:
print(f"[Panel] Error recargando bot: {e}")
import traceback
traceback.print_exc()
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
@app.post("/discord-channels/bulk-toggle")
async def bulk_toggle_discord_channels(request: Request):
if request.cookies.get("auth") != "ok":
raise HTTPException(status_code=401)
form = await request.form()
channel_ids = form.getlist("channel_ids")
bulk_action = form.get("bulk_action")
if not channel_ids or not bulk_action:
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
try:
from botdiscord.database import toggle_channel_status
is_active = (bulk_action == "activate")
success_count = 0
for channel_id_str in channel_ids:
try:
channel_id = int(channel_id_str)
toggle_channel_status(channel_id, is_active)
success_count += 1
except ValueError:
continue
print(f"[Panel] Bulk toggle: {success_count} canales {'activados' if is_active else 'desactivados'}")
return RedirectResponse(url="/discord-channels?success=1", status_code=status.HTTP_303_SEE_OTHER)
except Exception as e:
print(f"[Panel] Error en bulk toggle: {e}")
import traceback
traceback.print_exc()
return RedirectResponse(url="/discord-channels?error=1", status_code=status.HTTP_303_SEE_OTHER)
@app.get("/diagnosis")
async def diagnosis_page(request: Request):
if request.cookies.get("auth") != "ok":
return RedirectResponse(url="/login")
# Obtener variables de entorno relevantes
env_vars = {
'DISCORD_TOKEN': os.getenv('DISCORD_TOKEN'),
'TELEGRAM_TOKEN': os.getenv('TELEGRAM_TOKEN'),
'LIBRETRANSLATE_URL': os.getenv('LIBRETRANSLATE_URL'),
'DB_TYPE': os.getenv('DB_TYPE'),
'DB_HOST': os.getenv('DB_HOST'),
'DB_PORT': os.getenv('DB_PORT'),
'DB_NAME': os.getenv('DB_NAME'),
'DB_USER': os.getenv('DB_USER')
}
# Obtener configuración cargada
config = get_config()
return templates.TemplateResponse("diagnosis.html", {
"request": request,
"env_vars": env_vars,
"config": config
})
if __name__ == "__main__":
import uvicorn
web_config = get_web_config()