add temporary Remnawave API functions for user import / add UTM code validation in ads creation
This commit is contained in:
@@ -4,6 +4,7 @@ from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
from sqlalchemy import delete, select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
import re
|
||||
|
||||
from config import USERNAME_BOT
|
||||
from database import create_tracking_source, get_tracking_source_stats
|
||||
@@ -50,7 +51,8 @@ async def handle_ads_name_input(message: Message, state: FSMContext):
|
||||
await state.update_data(name=name)
|
||||
await state.set_state(AdminAdsState.waiting_for_new_code)
|
||||
await message.answer(
|
||||
f"🔗 Введите <b>код ссылки</b> для: <code>{name}</code>.",
|
||||
f"🔗 Введите <b>код ссылки</b> для: <code>{name}</code>.\n\n"
|
||||
f"💡 <b>Правила:</b> только латинские буквы и цифры",
|
||||
reply_markup=build_cancel_input_kb(),
|
||||
)
|
||||
|
||||
@@ -62,6 +64,15 @@ async def handle_ads_code_input(
|
||||
code = message.text.strip()
|
||||
data = await state.get_data()
|
||||
name = data["name"]
|
||||
|
||||
if not re.match(r'^[a-zA-Z0-9]+$', code):
|
||||
await message.answer(
|
||||
"❌ Код может содержать только латинские буквы и цифры\n"
|
||||
"Введите код заново:",
|
||||
reply_markup=build_cancel_input_kb(),
|
||||
)
|
||||
return
|
||||
|
||||
code_with_prefix = f"utm_{code}"
|
||||
|
||||
try:
|
||||
|
||||
@@ -12,6 +12,7 @@ import os, subprocess, sys
|
||||
import json
|
||||
from aiogram import Bot
|
||||
from panels.remnawave import RemnawaveAPI
|
||||
from panels.remnawave_time import get_all_users_time, login_remnawave
|
||||
from tempfile import NamedTemporaryFile
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
@@ -426,16 +427,32 @@ async def show_remnawave_clients(callback: CallbackQuery, session: AsyncSession)
|
||||
return
|
||||
|
||||
server = servers[0]
|
||||
api = RemnawaveAPI(base_url=server.api_url)
|
||||
# api = RemnawaveAPI(base_url=server.api_url)
|
||||
#
|
||||
# if not await api.login(username=REMNAWAVE_LOGIN, password=REMNAWAVE_PASSWORD):
|
||||
# await callback.message.edit_text(
|
||||
# "❌ Не удалось авторизоваться на Remnawave панели.",
|
||||
# reply_markup=build_back_to_db_menu(),
|
||||
# )
|
||||
# return
|
||||
#
|
||||
# users = await api.get_all_users()
|
||||
# if not users:
|
||||
# await callback.message.edit_text(
|
||||
# "📭 На панели нет клиентов.",
|
||||
# reply_markup=build_back_to_db_menu(),
|
||||
# )
|
||||
# return
|
||||
|
||||
if not await api.login(username=REMNAWAVE_LOGIN, password=REMNAWAVE_PASSWORD):
|
||||
token = await login_remnawave(server.api_url, REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD)
|
||||
if not token:
|
||||
await callback.message.edit_text(
|
||||
"❌ Не удалось авторизоваться на Remnawave панели.",
|
||||
reply_markup=build_back_to_db_menu(),
|
||||
)
|
||||
return
|
||||
|
||||
users = await api.get_all_users()
|
||||
users = await get_all_users_time(server.api_url, REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD)
|
||||
if not users:
|
||||
await callback.message.edit_text(
|
||||
"📭 На панели нет клиентов.",
|
||||
@@ -560,4 +577,4 @@ async def import_remnawave_keys(session: AsyncSession, users: list[dict], server
|
||||
|
||||
await session.commit()
|
||||
logger.info(f"[IMPORT] Всего добавлено ключей: {added}")
|
||||
return added
|
||||
return added
|
||||
@@ -0,0 +1,98 @@
|
||||
import aiohttp
|
||||
from typing import List, Dict, Any
|
||||
from logger import logger
|
||||
from config import REMNAWAVE_TOKEN_LOGIN_ENABLED, REMNAWAVE_ACCESS_TOKEN, REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD
|
||||
|
||||
|
||||
async def login_remnawave(api_url: str, username: str, password: str) -> str | None:
|
||||
if REMNAWAVE_TOKEN_LOGIN_ENABLED and REMNAWAVE_ACCESS_TOKEN:
|
||||
logger.info("[Remnawave API] Используется авторизация по токену")
|
||||
return REMNAWAVE_ACCESS_TOKEN
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
auth_data = {
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
|
||||
try:
|
||||
auth_response = await session.post(f"{api_url}/auth/login", json=auth_data)
|
||||
|
||||
if auth_response.status != 200:
|
||||
logger.error(f"[Remnawave API] Ошибка HTTP статуса: {auth_response.status}")
|
||||
return None
|
||||
|
||||
auth_result = await auth_response.json()
|
||||
token = None
|
||||
if auth_result.get("success") and auth_result.get("data", {}).get("token"):
|
||||
token = auth_result.get("data", {}).get("token")
|
||||
elif auth_result.get("response", {}).get("accessToken"):
|
||||
token = auth_result.get("response", {}).get("accessToken")
|
||||
elif auth_result.get("token"):
|
||||
token = auth_result.get("token")
|
||||
|
||||
if not token:
|
||||
logger.error(f"[Remnawave API] Токен не найден в ответе")
|
||||
|
||||
return token
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[Remnawave API] Ошибка при авторизации: {e}")
|
||||
return None
|
||||
|
||||
|
||||
async def get_all_users_time(api_url: str, username: str, password: str) -> List[Dict[str, Any]]:
|
||||
all_users = []
|
||||
page_size = 250
|
||||
start = 0
|
||||
|
||||
token = await login_remnawave(api_url, username, password)
|
||||
if not token:
|
||||
logger.error("[Remnawave API] Не удалось получить токен авторизации")
|
||||
return []
|
||||
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
while True:
|
||||
params = {
|
||||
"size": page_size,
|
||||
"start": start
|
||||
}
|
||||
|
||||
users_endpoint = f"{api_url}/users"
|
||||
|
||||
users_response = await session.get(users_endpoint, params=params, headers=headers)
|
||||
|
||||
if users_response.status != 200:
|
||||
break
|
||||
|
||||
users_result = await users_response.json()
|
||||
|
||||
if users_result.get("success") is False:
|
||||
break
|
||||
|
||||
users_data = None
|
||||
if "response" in users_result:
|
||||
users_data = users_result.get("response", {})
|
||||
elif "data" in users_result:
|
||||
users_data = users_result.get("data", {})
|
||||
else:
|
||||
users_data = users_result
|
||||
|
||||
if not users_data:
|
||||
break
|
||||
|
||||
users = users_data.get("users", [])
|
||||
total = users_data.get("total", 0)
|
||||
|
||||
if not users:
|
||||
break
|
||||
|
||||
all_users.extend(users)
|
||||
start += len(users)
|
||||
|
||||
if len(users) < page_size or start >= total:
|
||||
break
|
||||
|
||||
return all_users
|
||||
Reference in New Issue
Block a user