Show all inbound nodes with country flags in Remnawave

This commit is contained in:
Capybara-z
2025-07-12 02:24:29 +03:00
parent cafe576478
commit 52d5f784a2
2 changed files with 111 additions and 18 deletions
+48 -18
View File
@@ -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"🌍 <b>{prefix} {server_name}</b> - {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"🌍 <b>{prefix} {server_name}</b> - {online_remna_users} онлайн\n"
# online_remna_users = matching_node.get("usersOnline", 0)
# total_online_users += online_remna_users
# result_text += (
# f"🌍 <b>{prefix} {server_name}</b> - {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"🌍 <b>{prefix} {server_name}</b> - {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"🌍 <b>{prefix} {server_name}</b> - {online_remna_users} онлайн\n"
)
except Exception as e:
error_text = str(e) or "Сервер недоступен"
+63
View File
@@ -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