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()