from ._base import * from .pages import check_server_status, get_online_characters_count from .auth import _set_game_account_session from .account import get_account_characters, get_account_status, formatear_fecha # Endpoints JSON que alimentan las islas React/TSX del frontend (Vite). # Se montan bajo /api/ (fuera de i18n_patterns). De momento con JsonResponse; # si crece la superficie de la API se puede introducir DRF. def home_news_api(request): """Últimas noticias para la isla de la portada.""" noticias = Noticia.objects.order_by('-fecha_publicacion')[:50] data = [ { "id": n.id, "titulo": n.titulo, "fecha": n.fecha_publicacion.isoformat() if n.fecha_publicacion else None, "contenido": n.contenido, "enlace": n.enlace or None, } for n in noticias ] return JsonResponse({"noticias": data}) def home_status_api(request): """Estado del servidor para la isla de la portada (nombre, online, login, dirección).""" server = ServerSelection.objects.first() online = get_online_characters_count() status = "Online" if (server and check_server_status(server.address, server.port)) else "Offline" expansion = server.expansion if server else "Unknown" return JsonResponse( { "server_name": server.name if server else None, "address": server.address if server else None, "expansion": expansion, "online_characters": online, "status": status, } ) def account_select_api(request): """Selecciona la cuenta de juego de la bnet en sesión (isla del selector). Vía GET (sin POST): es idempotente y solo permite elegir cuentas ligadas a la propia cuenta Battle.net de la sesión, así que no expone nada de otros usuarios. """ bnet_id = request.session.get('bnet_id') if not bnet_id: return JsonResponse({"success": False, "error": "No autenticado"}, status=401) try: selected_id = int(request.GET.get("account_id", "")) except (TypeError, ValueError): return JsonResponse({"success": False, "error": "Cuenta no válida"}) with connections['acore_auth'].cursor() as cursor: accounts = bnet.get_game_accounts_for_bnet(cursor, bnet_id) chosen = next((g for g in accounts if g["id"] == selected_id), None) if not chosen: return JsonResponse({"success": False, "error": "Cuenta de juego no válida."}) _set_game_account_session(request, chosen) return JsonResponse({"success": True, "redirect": reverse("my-account")}) def account_me_api(request): """Datos del panel «Mi cuenta» (isla): info de cuenta, estado, puntos, créditos Battlepay, token de seguridad y personajes. Requiere sesión.""" username = request.session.get('username') if not username: return JsonResponse({"authenticated": False}, status=401) try: with connections['acore_auth'].cursor() as cursor: cursor.execute( "SELECT id, username, reg_mail, email, last_ip, last_attempt_ip, joindate " "FROM account WHERE username = %s", [username]) row = cursor.fetchone() if not row: return JsonResponse({"authenticated": False}, status=404) account_id = row[0] characters = get_account_characters(account_id) status = get_account_status(account_id) points = HomeApiPoints.objects.filter(accountID=account_id).first() sectoken = SecurityToken.objects.filter(user_id=account_id).first() with connections['acore_auth'].cursor() as cursor: credits = bnet.get_battlepay_credits(cursor, request.session.get('bnet_id')) except Exception as e: logger.error("account_me_api: %s", e) return JsonResponse({"authenticated": True, "error": "No se pudieron cargar los datos de la cuenta."}, status=200) return JsonResponse({ "authenticated": True, "user_info": { "bnet_email": request.session.get('bnet_email') or row[3], "username": row[1], "reg_mail": row[2], "email": row[3], "last_ip": row[4], "last_attempt_ip": row[5], "joindate": formatear_fecha(row[6]), }, "account_status": status, "dp": points.dp if points else 0, "vp": points.vp if points else 0, "battlepay_credits": credits, "token_status": "Solicitado" if sectoken else "Sin solicitar", "token_date": sectoken.created_at.strftime('%H:%M:%S %d-%m-%Y') if sectoken else None, "characters": characters, })