diff --git a/handlers/admin/users/users_keys.py b/handlers/admin/users/users_keys.py index d8b4e480..3bacbe84 100644 --- a/handlers/admin/users/users_keys.py +++ b/handlers/admin/users/users_keys.py @@ -14,7 +14,8 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder from sqlalchemy import select, update from sqlalchemy.ext.asyncio import AsyncSession -from config import USE_COUNTRY_SELECTION +from config import USE_COUNTRY_SELECTION, REMNAWAVE_TOKEN_LOGIN_ENABLED, REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD +from panels.remnawave import RemnawaveAPI from core.bootstrap import MODES_CONFIG from database import ( delete_key, @@ -737,7 +738,9 @@ async def handle_recreate_key_confirm( ) return - remnawave_servers = [s for s in cluster if s.get("panel_type", "3x-ui").lower() == "remnawave"] + remnawave_servers = [ + s for s in cluster if s.get("panel_type", "3x-ui").lower() == "remnawave" + ] if not remnawave_servers: await callback_query.message.edit_text( @@ -747,10 +750,21 @@ async def handle_recreate_key_confirm( return api_url = remnawave_servers[0].get("api_url") + if not api_url: + await callback_query.message.edit_text( + text="❗ У Remnawave сервера не задан api_url.", + reply_markup=build_editor_kb(tg_id), + ) + return - from panels.remnawave_ext import revoke_user_subscription + api = RemnawaveAPI(api_url) + try: + if not REMNAWAVE_TOKEN_LOGIN_ENABLED: + await api.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD) - user_data = await revoke_user_subscription(api_url, client_id) + user_data = await api.revoke_user_subscription(client_id) + finally: + await api.aclose() if not user_data: await callback_query.message.edit_text( @@ -785,8 +799,18 @@ async def handle_recreate_key_confirm( "Старая ссылка больше не работает." ) user_kb = InlineKeyboardBuilder() - user_kb.row(InlineKeyboardButton(text="📱 Мои подписки", callback_data="view_keys")) - user_kb.row(InlineKeyboardButton(text="👤 Личный кабинет", callback_data="profile")) + user_kb.row( + InlineKeyboardButton( + text="📱 Мои подписки", + callback_data="view_keys", + ) + ) + user_kb.row( + InlineKeyboardButton( + text="👤 Личный кабинет", + callback_data="profile", + ) + ) await callback_query.bot.send_message( chat_id=tg_id, @@ -812,7 +836,11 @@ async def handle_recreate_key_confirm( builder.row( InlineKeyboardButton( text="🔙 Назад", - callback_data=AdminUserEditorCallback(action="users_key_edit", tg_id=tg_id, data=old_email).pack(), + callback_data=AdminUserEditorCallback( + action="users_key_edit", + tg_id=tg_id, + data=old_email, + ).pack(), ) ) diff --git a/handlers/keys/operations/traffic.py b/handlers/keys/operations/traffic.py index cb348f0c..cbfc1e66 100644 --- a/handlers/keys/operations/traffic.py +++ b/handlers/keys/operations/traffic.py @@ -107,7 +107,8 @@ async def get_user_traffic(session: AsyncSession, tg_id: int, email: str) -> dic if not user_data: user_traffic_data["Remnawave (общий)"] = "Клиент не найден" else: - used_bytes = user_data.get("usedTrafficBytes", 0) + user_traffic = user_data.get("userTraffic", {}) + used_bytes = user_traffic.get("usedTrafficBytes", 0) used_gb = round(used_bytes / 1073741824, 2) user_traffic_data["Remnawave (общий)"] = used_gb except Exception as e: diff --git a/panels/remnawave.cpython-312-x86_64-linux-gnu.so b/panels/remnawave.cpython-312-x86_64-linux-gnu.so index f54c8d0f..4a11a5d8 100644 Binary files a/panels/remnawave.cpython-312-x86_64-linux-gnu.so and b/panels/remnawave.cpython-312-x86_64-linux-gnu.so differ diff --git a/panels/remnawave_ext.py b/panels/remnawave_ext.py deleted file mode 100644 index 852a9d96..00000000 --- a/panels/remnawave_ext.py +++ /dev/null @@ -1,68 +0,0 @@ -import aiohttp - -from config import ( - REMNAWAVE_ACCESS_TOKEN, - REMNAWAVE_LOGIN, - REMNAWAVE_PASSWORD, - REMNAWAVE_TOKEN_LOGIN_ENABLED, -) -from logger import logger - -PANEL_REMNA = "[Remnawave]" - - -async def revoke_user_subscription( - api_url: str, - user_uuid: str, - short_uuid: str | None = None, -) -> dict | None: - base_url = api_url.rstrip("/") - - async with aiohttp.ClientSession() as session: - if REMNAWAVE_TOKEN_LOGIN_ENABLED and REMNAWAVE_ACCESS_TOKEN: - token = REMNAWAVE_ACCESS_TOKEN - else: - login_url = f"{base_url}/auth/login" - login_data = {"username": REMNAWAVE_LOGIN, "password": REMNAWAVE_PASSWORD} - - try: - async with session.post(login_url, json=login_data) as resp: - if resp.status != 200 and resp.status != 201: - logger.error(f"{PANEL_REMNA} Авторизация не удалась: {resp.status}") - return None - - auth_response = await resp.json() - token = auth_response.get("response", {}).get("accessToken") - if not token: - logger.error(f"{PANEL_REMNA} Не получен accessToken") - return None - except Exception as e: - logger.error(f"{PANEL_REMNA} Ошибка авторизации: {e}") - return None - - revoke_url = f"{base_url}/users/{user_uuid}/actions/revoke" - headers = { - "Authorization": f"Bearer {token}", - "Content-Type": "application/json", - } - - revoke_data = {} - if short_uuid: - revoke_data["shortUuid"] = short_uuid - - try: - async with session.post(revoke_url, json=revoke_data, headers=headers) as resp: - if resp.status != 200 and resp.status != 201: - error_text = await resp.text() - logger.error(f"{PANEL_REMNA} Revoke не удался: {resp.status} - {error_text}") - return None - - result = await resp.json() - user_data = result.get("response", {}) - - logger.info(f"{PANEL_REMNA} Подписка {user_uuid} успешно отозвана") - return user_data - - except Exception as e: - logger.error(f"{PANEL_REMNA} Ошибка revoke: {e}") - return None diff --git a/utils/versioning.py b/utils/versioning.py index 994b2bd6..9baaa38f 100644 --- a/utils/versioning.py +++ b/utils/versioning.py @@ -92,4 +92,4 @@ def get_git_commit_number() -> str: def get_version() -> str: - return f"v.5.1-a111227 {get_git_commit_number()}" + return f"v.5.1-a141229 {get_git_commit_number()}"