diff --git a/handlers/admin/clusters/clusters_handler.py b/handlers/admin/clusters/clusters_handler.py index f9dbad14..20f0cecf 100644 --- a/handlers/admin/clusters/clusters_handler.py +++ b/handlers/admin/clusters/clusters_handler.py @@ -1,5 +1,5 @@ import asyncio -from datetime import datetime +from datetime import datetime, timezone from typing import Any from aiogram import F, Router, types @@ -582,38 +582,83 @@ async def handle_sync_cluster( ) return + servers = await get_servers(session) + cluster_servers = servers.get(cluster_name, []) + only_remnawave = all(s.get("panel_type") == "remnawave" for s in cluster_servers) + await callback_query.message.edit_text( text=f"πŸ”„ Бинхронизация кластСра {cluster_name}\n\nπŸ”‘ ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΠΊΠ»ΡŽΡ‡Π΅ΠΉ: {len(keys_to_sync)}" ) for key in keys_to_sync: try: - await delete_key_from_cluster( - cluster_name, key["email"], key["client_id"], session - ) - - await session.execute( - delete(Key).where( - Key.tg_id == key["tg_id"], Key.client_id == key["client_id"] + if only_remnawave: + expire_iso = ( + datetime.utcfromtimestamp(key["expiry_time"] / 1000) + .replace(tzinfo=timezone.utc) + .isoformat() ) - ) - await create_key_on_cluster( - cluster_name, - key["tg_id"], - key["client_id"], - key["email"], - key["expiry_time"], - plan=key["tariff_id"], - session=session, - remnawave_link=key["remnawave_link"], - ) + remna = RemnawaveAPI(cluster_servers[0]["api_url"]) + if not await remna.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD): + raise Exception("НС ΡƒΠ΄Π°Π»ΠΎΡΡŒ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² Remnawave") + + traffic_limit_bytes = 0 + hwid_limit = None + if key["tariff_id"]: + tariff = await session.get(Tariff, key["tariff_id"]) + if tariff: + traffic_limit_bytes = int(tariff.traffic_limit * 1024**3) + hwid_limit = tariff.device_limit + else: + logger.warning(f"[Sync] ΠšΠ»ΡŽΡ‡ {key['client_id']} с Π½Π΅ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ Ρ‚Π°Ρ€ΠΈΡ„ΠΎΠΌ ID={key['tariff_id']} β€” ΠΎΠ±Π½ΠΎΠ²ΠΈΠΌ Π±Π΅Π· Π»ΠΈΠΌΠΈΡ‚ΠΎΠ²") + + valid_email = f"{key['email']}@fake.local" + + inbound_ids = [ + s["inbound_id"] + for s in cluster_servers + if s.get("inbound_id") + ] + + await remna.update_user( + uuid=key["client_id"], + expire_at=expire_iso, + telegram_id=key["tg_id"], + email=valid_email, + active_user_inbounds=inbound_ids, + traffic_limit_bytes=traffic_limit_bytes, + hwid_device_limit=hwid_limit, + ) + + else: + await delete_key_from_cluster( + cluster_name, key["email"], key["client_id"], session + ) + + await session.execute( + delete(Key).where( + Key.tg_id == key["tg_id"], + Key.client_id == key["client_id"] + ) + ) + + await create_key_on_cluster( + cluster_name, + key["tg_id"], + key["client_id"], + key["email"], + key["expiry_time"], + plan=key["tariff_id"], + session=session, + remnawave_link=key["remnawave_link"], + ) await asyncio.sleep(0.5) except Exception as e: logger.error( - f"Ошибка ΠΏΡ€ΠΈ синхронизации ΠΊΠ»ΡŽΡ‡Π° {key['client_id']} Π² {cluster_name}: {e}" + f"[Sync] Ошибка ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΊΠ»ΡŽΡ‡Π° {key['client_id']} Π² {cluster_name}: {e}" ) await callback_query.message.edit_text( @@ -622,7 +667,7 @@ async def handle_sync_cluster( ) except Exception as e: - logger.error(f"Ошибка синхронизации ΠΊΠ»ΡŽΡ‡Π΅ΠΉ Π² кластСрС {cluster_name}: {e}") + logger.error(f"[Sync] Ошибка синхронизации кластСра {cluster_name}: {e}") await callback_query.message.edit_text( text=f"❌ ΠŸΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»Π° ошибка ΠΏΡ€ΠΈ синхронизации: {e}", reply_markup=build_admin_back_kb("clusters"), diff --git a/handlers/keys/key_renew.py b/handlers/keys/key_renew.py index 75b2f000..8c54cdbf 100644 --- a/handlers/keys/key_renew.py +++ b/handlers/keys/key_renew.py @@ -110,7 +110,7 @@ async def process_callback_renew_key( builder = InlineKeyboardBuilder() for t in selected_tariffs: - button_text = f"πŸ“… {t['name']} β€” {t['price_rub']}β‚½" + button_text = f"{t['name']} β€” {t['price_rub']}β‚½" builder.row( InlineKeyboardButton( text=button_text,