From 7caee34147ee041035c8d950c1e7e978263c4321 Mon Sep 17 00:00:00 2001 From: Capybara-z Date: Sat, 12 Jul 2025 02:24:29 +0300 Subject: [PATCH] Show all inbound nodes with country flags in Remnawave --- handlers/admin/clusters/clusters_handler.py | 66 +++++++++++++++------ panels/remnawave_time.py | 63 ++++++++++++++++++++ 2 files changed, 111 insertions(+), 18 deletions(-) diff --git a/handlers/admin/clusters/clusters_handler.py b/handlers/admin/clusters/clusters_handler.py index a64f92ef..ea3f6d86 100644 --- a/handlers/admin/clusters/clusters_handler.py +++ b/handlers/admin/clusters/clusters_handler.py @@ -29,6 +29,7 @@ from handlers.keys.key_utils import ( ) from logger import logger from panels.remnawave import RemnawaveAPI +from panels.remnawave_time import get_all_nodes_with_online from ..panel.keyboard import AdminPanelCallback, build_admin_back_kb from .keyboard import ( @@ -391,33 +392,62 @@ async def handle_cluster_availability( result_text += f"🌍 {prefix} {server_name} - {online_inbound_users} онлайн\n" elif panel_type == "remnawave": - remna = RemnawaveAPI(server["api_url"]) - if not await remna.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD): - raise Exception("Не удалось авторизоваться") + # remna = RemnawaveAPI(server["api_url"]) + # if not await remna.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD): + # raise Exception("Не удалось авторизоваться") server_inbound_id = server.get("inbound_id") if not server_inbound_id: raise Exception("Не указан inbound_id сервера") - all_nodes = await remna.get_all_nodes() - if not all_nodes: - raise Exception("Не удалось получить список нод") +# all_nodes = await remna.get_all_nodes() +# if not all_nodes: +# raise Exception("Не удалось получить список нод") - matching_node = None - for node in all_nodes: - excluded_inbounds = node.get("excludedInbounds", []) - if server_inbound_id not in excluded_inbounds: - matching_node = node - break +# matching_node = None +# for node in all_nodes: +# excluded_inbounds = node.get("excludedInbounds", []) +# if server_inbound_id not in excluded_inbounds: +# matching_node = node +# break - if not matching_node: - raise Exception("Нода, обслуживающая этот inbound_id, не найдена") +# if not matching_node: +# raise Exception("Нода, обслуживающая этот inbound_id, не найдена") - online_remna_users = matching_node.get("usersOnline", 0) - total_online_users += online_remna_users - result_text += ( - f"🌍 {prefix} {server_name} - {online_remna_users} онлайн\n" +# online_remna_users = matching_node.get("usersOnline", 0) +# total_online_users += online_remna_users +# result_text += ( +# f"🌍 {prefix} {server_name} - {online_remna_users} онлайн\n" +# ) + + nodes_data = await get_all_nodes_with_online( + server["api_url"], REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD, server_inbound_id ) + + if nodes_data.get("error"): + raise Exception(nodes_data["error"]) + + online_remna_users = nodes_data["total_online"] + total_online_users += online_remna_users + + nodes_info = nodes_data["nodes"] + if len(nodes_info) > 1: + result_text += f"🌍 {prefix} {server_name} - {online_remna_users} онлайн\n" + for node_info in nodes_info: + country_code = node_info.get('country_code', 'Unknown') + node_name = node_info.get('name', 'Unknown') + online_users = node_info.get('online_users', 0) + + if country_code != 'Unknown' and len(country_code) == 2: + flag = ''.join(chr(ord(c) + 127397) for c in country_code.upper()) + else: + flag = country_code + + result_text += f" ↳ {flag} ({node_name}): {online_users} онлайн\n" + else: + result_text += ( + f"🌍 {prefix} {server_name} - {online_remna_users} онлайн\n" + ) except Exception as e: error_text = str(e) or "Сервер недоступен" diff --git a/panels/remnawave_time.py b/panels/remnawave_time.py index 12218469..eeec3582 100644 --- a/panels/remnawave_time.py +++ b/panels/remnawave_time.py @@ -41,6 +41,69 @@ async def login_remnawave(api_url: str, username: str, password: str) -> str | N return None +async def get_all_nodes_with_online(api_url: str, username: str, password: str, inbound_id: str) -> Dict[str, Any]: + token = await login_remnawave(api_url, username, password) + if not token: + logger.error("[Remnawave API] Не удалось получить токен авторизации") + return {"total_online": 0, "nodes": [], "error": "Не удалось авторизоваться"} + + headers = {"Authorization": f"Bearer {token}"} + + async with aiohttp.ClientSession() as session: + try: + nodes_response = await session.get(f"{api_url}/nodes", headers=headers) + + if nodes_response.status != 200: + logger.error(f"[Remnawave API] Ошибка получения нод: {nodes_response.status}") + return {"total_online": 0, "nodes": [], "error": f"HTTP {nodes_response.status}"} + + nodes_result = await nodes_response.json() + + all_nodes = [] + if nodes_result.get("success") and "data" in nodes_result: + all_nodes = nodes_result["data"] + elif nodes_result.get("response"): + all_nodes = nodes_result["response"] + elif isinstance(nodes_result, list): + all_nodes = nodes_result + + if not all_nodes: + logger.warning("[Remnawave API] Список нод пуст") + return {"total_online": 0, "nodes": [], "error": "Список нод пуст"} + + matching_nodes = [] + total_online = 0 + + + + for node in all_nodes: + excluded_inbounds = node.get("excludedInbounds", []) + if inbound_id not in excluded_inbounds: + node_online = node.get("usersOnline", 0) + node_name = node.get("name", "Unknown Node") + node_id = node.get("id", "Unknown ID") + + matching_nodes.append({ + "name": node_name, + "online_users": node_online, + "country_code": node.get("countryCode", "Unknown") + }) + + total_online += node_online + + logger.info(f"[Remnawave API] Найдено {len(matching_nodes)} нод для inbound {inbound_id}, общий онлайн: {total_online}") + + return { + "total_online": total_online, + "nodes": matching_nodes, + "inbound_id": inbound_id + } + + except Exception as e: + logger.error(f"[Remnawave API] Ошибка при получении нод: {e}") + return {"total_online": 0, "nodes": [], "error": str(e)} + + async def get_all_users_time(api_url: str, username: str, password: str) -> List[Dict[str, Any]]: all_users = [] page_size = 250