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