95 lines
3.6 KiB
Python
95 lines
3.6 KiB
Python
import asyncio
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from config import REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD, REMNAWAVE_TOKEN_LOGIN_ENABLED
|
|
from database import get_servers
|
|
from logger import (
|
|
CLOGGER as logger,
|
|
PANEL_REMNA,
|
|
PANEL_XUI,
|
|
)
|
|
from panels._3xui import delete_client, get_xui_instance
|
|
from panels.remnawave import RemnawaveAPI
|
|
|
|
from .utils import unique_by_api_url
|
|
|
|
|
|
async def delete_key_from_cluster(cluster_id: str, email: str, client_id: str, session: AsyncSession):
|
|
try:
|
|
servers = await get_servers(session)
|
|
cluster = servers.get(cluster_id)
|
|
|
|
if not cluster:
|
|
found_servers = []
|
|
for _, server_list in servers.items():
|
|
for server_info in server_list:
|
|
if server_info.get("server_name", "").lower() == cluster_id.lower():
|
|
found_servers.append(server_info)
|
|
if found_servers:
|
|
cluster = found_servers
|
|
else:
|
|
raise ValueError(f"Кластер или сервер с ID/именем {cluster_id} не найден.")
|
|
|
|
remna_servers = [s for s in cluster if s.get("panel_type", "3x-ui").lower() == "remnawave"]
|
|
xui_servers = [s for s in cluster if s.get("panel_type", "3x-ui").lower() == "3x-ui"]
|
|
|
|
await asyncio.gather(
|
|
delete_on_3xui(xui_servers, email, client_id),
|
|
delete_on_remnawave(remna_servers, client_id),
|
|
return_exceptions=True,
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Ошибка при удалении ключа {client_id} из кластера/сервера {cluster_id}: {e}")
|
|
raise
|
|
|
|
|
|
async def delete_on_3xui(servers: list, email: str, client_id: str):
|
|
tasks = []
|
|
for s in servers:
|
|
name = s.get("server_name", "unknown")
|
|
inbound_id = s.get("inbound_id")
|
|
if not inbound_id:
|
|
logger.warning(f"{PANEL_XUI} [{name}] INBOUND_ID отсутствует при удалении")
|
|
continue
|
|
try:
|
|
xui = await get_xui_instance(s["api_url"])
|
|
except Exception as e:
|
|
logger.warning(f"{PANEL_XUI} [{name}] недоступна панель 3x-ui при удалении: {e}")
|
|
continue
|
|
tasks.append(
|
|
delete_client(
|
|
xui=xui,
|
|
inbound_id=int(inbound_id),
|
|
email=email,
|
|
client_id=client_id,
|
|
)
|
|
)
|
|
if tasks:
|
|
await asyncio.gather(*tasks, return_exceptions=True)
|
|
|
|
|
|
async def delete_on_remnawave(servers: list, client_id: str) -> bool:
|
|
servers = unique_by_api_url(servers)
|
|
for s in servers:
|
|
name = s.get("server_name", "remna")
|
|
api = RemnawaveAPI(s.get("api_url"))
|
|
if not REMNAWAVE_TOKEN_LOGIN_ENABLED:
|
|
ok = await api.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD)
|
|
if not ok:
|
|
logger.warning(f"{PANEL_REMNA} [{name}] Авторизация не удалась")
|
|
continue
|
|
try:
|
|
done = await api.delete_user(client_id)
|
|
if done:
|
|
logger.info(f"{PANEL_REMNA} [{name}] Клиент {client_id} удалён")
|
|
return True
|
|
except Exception as e:
|
|
msg = str(e).lower()
|
|
if "not found" in msg or "не найден" in msg or "404" in msg:
|
|
logger.info(f"{PANEL_REMNA} [{name}] Клиент {client_id} не найден")
|
|
else:
|
|
logger.warning(f"{PANEL_REMNA} [{name}] Ошибка удаления клиента {client_id}: {e}")
|
|
return False
|