Compare commits

..

No commits in common. "54e6f938e700cbd24920d913bbc991f857217cf5" and "ebf1167fea13bcfd0b46a28b4471acafac940d33" have entirely different histories.

3 changed files with 15 additions and 154 deletions

View File

@ -40,7 +40,7 @@ class ClientHandlers:
await message.answer(f"❌ Произошла ошибка при создании профиля. Попробуйте позже.\n {e}")
async def cmd_info(self, message: types.Message):
"""Обработчик команды /info с выводом конфига и статистики."""
"""Обработчик команды /info."""
args = (message.text or "").strip().split(maxsplit=1)
if len(args) < 2:
await message.answer(
@ -52,50 +52,23 @@ class ClientHandlers:
telegram_id = args[1].lstrip("@").strip()
try:
(vless_client, vless_stats), (ss_client, ss_stats) = \
self.client_service.get_client_info_with_stats(telegram_id)
vless_client, ss_client = self.client_service.get_client_info(telegram_id)
def format_info(client, stats, name):
def format_info(client, name):
if not client:
return f"❌ Клиент <b>{name}</b> не найден.\n"
# Конфиг клиента
json_info = json.dumps(client, ensure_ascii=False, indent=2)
text = f"🔹 <b>{name}</b>:\n<pre>{json_info}</pre>"
# Статистика
if stats:
up = stats.get("up", 0)
down = stats.get("down", 0)
total = up + down
def human_size(num):
for unit in ["B", "KB", "MB", "GB", "TB"]:
if num < 1024:
return f"{num:.2f} {unit}"
num /= 1024
return f"{num:.2f} PB"
text += (
f"\n📊 Трафик: ↑ {human_size(up)} / ↓ {human_size(down)}"
f"{human_size(total)})"
)
else:
text += "\n📊 Статистика не найдена."
return text
return f"🔹 <b>{name}</b>:\n<pre>{json_info}</pre>"
response = (
format_info(vless_client, vless_stats, "VLESS")
+ "\n\n"
+ format_info(ss_client, ss_stats, "Shadowsocks")
format_info(vless_client, "VLESS") +
"\n\n" +
format_info(ss_client, "Shadowsocks")
)
await message.answer(response, parse_mode=ParseMode.HTML)
except BadLogin:
await message.answer("❌ Ошибка входа в панель XUI.")
except Exception as e:
logger.error(f"Ошибка получения информации: {e}")
await message.answer("❌ Ошибка при получении информации. Проверь лог.")
await message.answer("❌ Ошибка при получении информации. Проверь лог.")

View File

@ -132,20 +132,10 @@ class ClientService:
return False
async def create_client_profile(self, telegram_id: str) -> Tuple[bool, str]:
"""Создание полного профиля клиента (VLESS + Shadowsocks) с проверкой существующего."""
"""Создание полного профиля клиента (VLESS + Shadowsocks)."""
try:
# Сначала проверяем, есть ли уже клиенты
vless_client, ss_client = self.get_client_info(telegram_id)
if vless_client or ss_client:
subscription_link = self.get_subscription_link(telegram_id)
logger.info(f"Клиент для {telegram_id} уже существует.")
return True, (
f" Клиент для <b>{telegram_id}</b> уже существует.\n"
f"🔗 Подписочная ссылка:\n<code>{subscription_link}</code>"
)
# Генерируем новые креды
vless_email, ss_email, vless_uuid, ss_password = self.generate_client_credentials(telegram_id)
logger.info(f"Создаём клиентов для telegram_id={telegram_id}")
# Создаём VLESS клиента
@ -161,13 +151,13 @@ class ClientService:
# Создаём Shadowsocks клиента
ss_success = await self.create_shadowsocks_client(telegram_id, ss_password)
if not ss_success:
return False, "Ошибка при создании Shadowsocks клиента"
# Подписочная ссылка
subscription_link = self.get_subscription_link(telegram_id)
success_message = (
f"✅ Профиль для <b>{telegram_id}</b> успешно создан!\n"
f"✅ Профиль для {telegram_id} успешно создан!\n"
f"🔗 Подписочная ссылка:\n<code>{subscription_link}</code>"
)
@ -177,43 +167,6 @@ class ClientService:
logger.error(f"Ошибка при создании профиля: {e}")
return False, "Произошла ошибка при создании профиля"
# async def create_client_profile(self, telegram_id: str) -> Tuple[bool, str]:
# """Создание полного профиля клиента (VLESS + Shadowsocks)."""
# try:
# vless_email, ss_email, vless_uuid, ss_password = self.generate_client_credentials(telegram_id)
#
# logger.info(f"Создаём клиентов для telegram_id={telegram_id}")
#
# # Создаём VLESS клиента
# vless_success = self.xui_service.add_vless_client(
# inbound_id=INBOUND_VLESS_ID,
# email=vless_email,
# uuid=vless_uuid,
# telegram_id=telegram_id
# )
#
# if not vless_success:
# return False, "Ошибка при создании VLESS клиента"
#
# # Создаём Shadowsocks клиента
# ss_success = await self.create_shadowsocks_client(telegram_id, ss_password)
#
# if not ss_success:
# return False, "Ошибка при создании Shadowsocks клиента"
#
# subscription_link = self.get_subscription_link(telegram_id)
# success_message = (
# f"✅ Профиль для {telegram_id} успешно создан!\n"
# f"🔗 Подписочная ссылка:\n<code>{subscription_link}</code>"
# )
#
# return True, success_message
#
# except Exception as e:
# logger.error(f"Ошибка при создании профиля: {e}")
# return False, "Произошла ошибка при создании профиля"
def get_client_info(self, telegram_id: str) -> Tuple[Optional[Dict[str, Any]], Optional[Dict[str, Any]]]:
"""Получение информации о клиентах."""
vless_email = f"{telegram_id}_vl_ssl"
@ -222,25 +175,4 @@ class ClientService:
vless_client = self.xui_service.get_client(INBOUND_VLESS_ID, vless_email)
ss_client = self.xui_service.get_client(INBOUND_SS_ID, ss_email)
return vless_client, ss_client
def get_client_info_with_stats(self, telegram_id: str):
"""Возвращает клиентов и их статистику по Telegram ID."""
vless_client, ss_client = self.get_client_info(telegram_id)
vless_stats = None
ss_stats = None
if vless_client:
vless_stats = self.xui_service.get_client_stats(
inbound_id=INBOUND_VLESS_ID,
email=vless_client["email"]
)
if ss_client:
ss_stats = self.xui_service.get_client_stats(
inbound_id=INBOUND_SS_ID,
email=ss_client["email"]
)
return (vless_client, vless_stats), (ss_client, ss_stats)
return vless_client, ss_client

View File

@ -40,58 +40,14 @@ class XUIService:
raise
def get_client(self, inbound_id: int, email: str) -> Optional[Dict[str, Any]]:
"""Получение информации о клиенте (работает и для SS, и для VLESS)."""
"""Получение информации о клиенте."""
try:
self.login()
inbounds = self.xui.get_inbounds()
if "obj" not in inbounds:
logger.error("Некорректный ответ от XUI при запросе inbounds")
return None
for inbound in inbounds["obj"]:
if inbound["id"] != inbound_id:
continue
settings = json.loads(inbound["settings"])
for client in settings.get("clients", []):
if client.get("email") == email:
# У SS-клиентов id нет — подставляем email
if "id" not in client:
client["id"] = client["email"]
return client
logger.warning(f"Клиент {email} не найден в inbound {inbound_id}")
return None
return self.xui.get_client(inbound_id=inbound_id, email=email)
except Exception as e:
logger.error(f"Ошибка получения клиента {email}: {e}")
return None
def get_client_stats(self, inbound_id: int, email: str) -> Optional[Dict[str, Any]]:
"""Получение статистики клиента по inbound и email."""
try:
self.login()
inbounds = self.xui.get_inbounds()
if "obj" not in inbounds:
logger.error("Некорректный ответ от XUI при запросе inbounds")
return None
for inbound in inbounds["obj"]:
if inbound["id"] != inbound_id:
continue
for client_stat in inbound.get("clientStats", []):
if client_stat.get("email") == email:
return client_stat
logger.warning(f"Статистика по клиенту {email} не найдена в inbound {inbound_id}")
return None
except Exception as e:
logger.error(f"Ошибка получения статистики клиента {email}: {e}")
return None
def add_vless_client(
self,
inbound_id: int,