3x-ui: create VLESS/WireGuard clients and reload available inbounds
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+73
-33
@@ -4,12 +4,28 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models import XuiPanel
|
||||
from app.services.xui import XuiClient, XuiApiError, normalize_base_url
|
||||
from app.services.xui import (
|
||||
SUPPORTED_CLIENT_PROTOCOLS,
|
||||
XuiApiError,
|
||||
XuiClient,
|
||||
normalize_base_url,
|
||||
)
|
||||
|
||||
|
||||
def _client_for(panel: XuiPanel) -> XuiClient:
|
||||
return XuiClient(
|
||||
panel.base_url,
|
||||
username=panel.username,
|
||||
password=panel.password,
|
||||
api_token=panel.api_token,
|
||||
verify_ssl=panel.verify_ssl,
|
||||
)
|
||||
|
||||
|
||||
async def list_panels(session: AsyncSession) -> list[XuiPanel]:
|
||||
@@ -47,7 +63,6 @@ async def create_panel(
|
||||
await session.commit()
|
||||
await session.refresh(panel)
|
||||
|
||||
# Verify immediately
|
||||
await check_panel(session, panel.id)
|
||||
await session.refresh(panel)
|
||||
if not panel.is_reachable:
|
||||
@@ -62,13 +77,7 @@ async def check_panel(session: AsyncSession, panel_id: int) -> XuiPanel:
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
try:
|
||||
async with XuiClient(
|
||||
panel.base_url,
|
||||
username=panel.username,
|
||||
password=panel.password,
|
||||
api_token=panel.api_token,
|
||||
verify_ssl=panel.verify_ssl,
|
||||
) as client:
|
||||
async with _client_for(panel) as client:
|
||||
info = await client.test_connection()
|
||||
panel.is_reachable = True
|
||||
panel.last_error = None
|
||||
@@ -94,41 +103,72 @@ async def delete_panel(session: AsyncSession, panel_id: int) -> None:
|
||||
await session.commit()
|
||||
|
||||
|
||||
async def fetch_panel_data(panel: XuiPanel) -> dict:
|
||||
async with XuiClient(
|
||||
panel.base_url,
|
||||
username=panel.username,
|
||||
password=panel.password,
|
||||
api_token=panel.api_token,
|
||||
verify_ssl=panel.verify_ssl,
|
||||
) as client:
|
||||
async def fetch_panel_data(panel: XuiPanel) -> dict[str, Any]:
|
||||
async with _client_for(panel) as client:
|
||||
status = await client.get_status()
|
||||
inbounds = await client.list_inbounds()
|
||||
all_inbounds = await client.list_inbounds()
|
||||
available = await client.list_available_inbounds(
|
||||
protocols=SUPPORTED_CLIENT_PROTOCOLS, enabled_only=False
|
||||
)
|
||||
vless_inbounds = [i for i in available if str(i.get("protocol")).lower() == "vless"]
|
||||
wg_inbounds = [i for i in available if str(i.get("protocol")).lower() == "wireguard"]
|
||||
try:
|
||||
clients = await client.list_clients()
|
||||
except XuiApiError:
|
||||
clients = []
|
||||
return {"status": status, "inbounds": inbounds, "clients": clients}
|
||||
return {
|
||||
"status": status,
|
||||
"inbounds": all_inbounds,
|
||||
"available_inbounds": available,
|
||||
"vless_inbounds": vless_inbounds,
|
||||
"wireguard_inbounds": wg_inbounds,
|
||||
"clients": clients,
|
||||
}
|
||||
|
||||
|
||||
async def load_available_inbounds(
|
||||
panel: XuiPanel,
|
||||
*,
|
||||
protocol: str | None = None,
|
||||
) -> list[dict]:
|
||||
protocols: tuple[str, ...]
|
||||
if protocol:
|
||||
protocols = (protocol.lower(),)
|
||||
else:
|
||||
protocols = SUPPORTED_CLIENT_PROTOCOLS
|
||||
async with _client_for(panel) as client:
|
||||
return await client.list_available_inbounds(protocols=protocols, enabled_only=True)
|
||||
|
||||
|
||||
async def add_xui_client(
|
||||
panel: XuiPanel,
|
||||
*,
|
||||
protocol: str,
|
||||
email: str,
|
||||
inbound_ids: list[int],
|
||||
inbound_id: int,
|
||||
total_gb: int = 0,
|
||||
limit_ip: int = 0,
|
||||
flow: str = "",
|
||||
comment: str = "",
|
||||
) -> dict:
|
||||
async with XuiClient(
|
||||
panel.base_url,
|
||||
username=panel.username,
|
||||
password=panel.password,
|
||||
api_token=panel.api_token,
|
||||
verify_ssl=panel.verify_ssl,
|
||||
) as client:
|
||||
return await client.add_client(
|
||||
email=email,
|
||||
inbound_ids=inbound_ids,
|
||||
total_gb=total_gb * 1024 * 1024 * 1024 if total_gb > 0 else 0,
|
||||
limit_ip=limit_ip,
|
||||
)
|
||||
proto = protocol.strip().lower()
|
||||
bytes_limit = total_gb * 1024 * 1024 * 1024 if total_gb > 0 else 0
|
||||
async with _client_for(panel) as client:
|
||||
if proto == "vless":
|
||||
return await client.add_vless_client(
|
||||
email=email,
|
||||
inbound_id=inbound_id,
|
||||
total_gb=bytes_limit,
|
||||
limit_ip=limit_ip,
|
||||
flow=flow,
|
||||
comment=comment,
|
||||
)
|
||||
if proto == "wireguard":
|
||||
return await client.add_wireguard_client(
|
||||
email=email,
|
||||
inbound_id=inbound_id,
|
||||
total_gb=bytes_limit,
|
||||
limit_ip=limit_ip,
|
||||
comment=comment,
|
||||
)
|
||||
raise ValueError("Поддерживаются только vless и wireguard")
|
||||
|
||||
Reference in New Issue
Block a user