from aiogram import Router, types
from aiogram.filters import Command
from aiogram.enums.parse_mode import ParseMode
import logging
import aiohttp
from instences.config import BASE_URL_FASTAPI
router = Router()
logger = logging.getLogger(__name__)
async def call_api(method, endpoint, data=None, base_url=BASE_URL_FASTAPI):
"""
Универсальный HTTP-запрос к FastAPI для рефералок.
Ожидаем от бекенда:
GET /user/{telegram_id}/referrals -> {
"invited_count": int,
"bonus_total": float
}
"""
url = f"{base_url}{endpoint}"
logger.info(
f"[referrals] Инициализация запроса: {method} {url} с данными {data}")
try:
async with aiohttp.ClientSession() as session:
async with session.request(
method,
url,
json=data,
headers={"Content-Type": "application/json"},
) as response:
logger.info(
f"[referrals] Получен ответ от {url}: статус {response.status}"
)
if response.status in {200, 201}:
result = await response.json()
logger.debug(f"[referrals] Ответ JSON: {result}")
return result
if response.status == 404:
logger.debug(
f"[referrals] Код {response.status}, возвращаю None"
)
return None
logger.error(
f"[referrals] Ошибка в запросе: статус {response.status}, причина {response.reason}"
)
return "ERROR"
except Exception as e:
logger.exception(
f"[referrals] Исключение при выполнении запроса к {url}: {e}")
return "ERROR"
async def _build_referral_text(bot, user_id: int) -> str:
"""
Текст реферальной программы + статистика, если есть.
"""
me = await bot.get_me()
bot_username = me.username or "LarkVPN_bot"
link = f"https://t.me/{bot_username}?start=ref_{user_id}"
# Базовый текст: без фейковых тире и нулевых рублей
text = (
"👥 Реферальная программа\n\n"
"Зови друзей в Lark VPN и получай бонусы на баланс.\n\n"
f"🔗 Твоя ссылка:\n{link}\n\n"
)
invited_line = ""
bonus_line = ""
stats = await call_api("GET", f"/user/{user_id}/referrals")
if isinstance(stats, dict):
invited = stats.get("invited_count")
bonus = stats.get("bonus_total")
if invited is not None:
try:
invited_int = int(invited)
except (TypeError, ValueError):
invited_int = None
if invited_int is not None:
invited_line = f"👤 Приглашено: {invited_int}\n"
if bonus is not None:
try:
bonus_val = float(bonus)
except (TypeError, ValueError):
bonus_val = None
# Строку с бонусами показываем только если реально что-то начислено
if bonus_val is not None and bonus_val > 0:
bonus_line = f"💰 Начислено бонусов: {bonus_val:.2f} ₽\n"
else:
logger.warning(
f"[referrals] Не удалось получить статистику для user_id={user_id}: {stats}"
)
if invited_line:
text += invited_line
if bonus_line:
text += bonus_line
if invited_line or bonus_line:
text += "\n"
text += (
"Бонусы падают автоматически, когда приглашённые пополняют баланс."
)
return text
@router.message(Command("referrals"))
async def referrals_command(message: types.Message):
"""
Команда /referrals — показывает текст реферальной программы.
"""
logger.info(f"Получена команда /referrals от {message.from_user.id}")
try:
text = await _build_referral_text(message.bot, message.from_user.id)
await message.answer(text, parse_mode=ParseMode.HTML)
except Exception as e:
logger.exception(f"Ошибка в обработчике /referrals: {e}")
await message.answer("Произошла ошибка. Попробуй позже.")
@router.callback_query(lambda callback: callback.data == "referral")
async def referrals_callback(callback: types.CallbackQuery):
"""
Кнопка «Реферальная программа» (если где-то есть).
"""
try:
text = await _build_referral_text(
callback.message.bot,
callback.from_user.id,
)
await callback.message.edit_text(
text,
parse_mode=ParseMode.HTML,
)
except Exception as e:
logger.exception(f"Ошибка в обработчике callback 'referral': {e}")
await callback.message.answer("Произошла ошибка. Попробуй позже.")
finally:
await callback.answer()