"""Admin routes for 3x-ui API panels.""" from __future__ import annotations import json from fastapi import APIRouter, Depends, Form, Request, status from fastapi.responses import HTMLResponse, RedirectResponse from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.models import XuiPanel from app.routers.admin import _is_redirect, require_admin from app.services import xui_panels as xui_service router = APIRouter(prefix="/admin/xui", tags=["xui"]) @router.get("", response_class=HTMLResponse) async def xui_list(request: Request, db: AsyncSession = Depends(get_db), admin=Depends(require_admin)): if _is_redirect(admin): return admin panels = await xui_service.list_panels(db) return request.app.state.templates.TemplateResponse( "admin/xui.html", { "request": request, "admin": admin, "panels": panels, "app_name": request.app.state.settings.app_name, "flash": request.query_params.get("flash"), }, ) @router.post("") async def xui_create( name: str = Form(""), base_url: str = Form(...), username: str = Form(""), password: str = Form(""), api_token: str = Form(""), verify_ssl: str = Form(""), db: AsyncSession = Depends(get_db), admin=Depends(require_admin), ): if _is_redirect(admin): return admin try: await xui_service.create_panel( db, name=name, base_url=base_url, username=username, password=password, api_token=api_token, verify_ssl=verify_ssl == "1", ) except Exception as exc: # noqa: BLE001 return RedirectResponse( f"/admin/xui?flash=error:{exc}", status_code=status.HTTP_303_SEE_OTHER, ) return RedirectResponse("/admin/xui?flash=created", status_code=status.HTTP_303_SEE_OTHER) @router.post("/{panel_id}/check") async def xui_check( panel_id: int, db: AsyncSession = Depends(get_db), admin=Depends(require_admin), ): if _is_redirect(admin): return admin try: await xui_service.check_panel(db, panel_id) except Exception as exc: # noqa: BLE001 return RedirectResponse( f"/admin/xui?flash=error:{exc}", status_code=status.HTTP_303_SEE_OTHER, ) return RedirectResponse("/admin/xui?flash=ok", status_code=status.HTTP_303_SEE_OTHER) @router.post("/{panel_id}/delete") async def xui_delete( panel_id: int, db: AsyncSession = Depends(get_db), admin=Depends(require_admin), ): if _is_redirect(admin): return admin await xui_service.delete_panel(db, panel_id) return RedirectResponse("/admin/xui?flash=deleted", status_code=status.HTTP_303_SEE_OTHER) @router.get("/{panel_id}", response_class=HTMLResponse) async def xui_detail( panel_id: int, request: Request, db: AsyncSession = Depends(get_db), admin=Depends(require_admin), ): if _is_redirect(admin): return admin panel = await db.get(XuiPanel, panel_id) if not panel: return RedirectResponse("/admin/xui", status_code=status.HTTP_303_SEE_OTHER) data = None error = None try: data = await xui_service.fetch_panel_data(panel) except Exception as exc: # noqa: BLE001 error = str(exc) info = None if panel.panel_info: try: info = json.loads(panel.panel_info) except json.JSONDecodeError: info = None return request.app.state.templates.TemplateResponse( "admin/xui_detail.html", { "request": request, "admin": admin, "panel": panel, "data": data, "info": info, "error": error, "app_name": request.app.state.settings.app_name, "flash": request.query_params.get("flash"), }, ) @router.post("/{panel_id}/clients") async def xui_add_client( panel_id: int, email: str = Form(...), inbound_id: int = Form(...), total_gb: int = Form(0), limit_ip: int = Form(0), db: AsyncSession = Depends(get_db), admin=Depends(require_admin), ): if _is_redirect(admin): return admin panel = await db.get(XuiPanel, panel_id) if not panel: return RedirectResponse("/admin/xui", status_code=status.HTTP_303_SEE_OTHER) try: await xui_service.add_xui_client( panel, email=email.strip(), inbound_ids=[inbound_id], total_gb=total_gb, limit_ip=limit_ip, ) except Exception as exc: # noqa: BLE001 return RedirectResponse( f"/admin/xui/{panel_id}?flash=error:{exc}", status_code=status.HTTP_303_SEE_OTHER, ) return RedirectResponse( f"/admin/xui/{panel_id}?flash=client_created", status_code=status.HTTP_303_SEE_OTHER, )