from __future__ import annotations from typing import Any, Awaitable, Callable from aiogram import BaseMiddleware from aiogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, Message, TelegramObject from bot.clients.budget_api import YandexLoginRequired YANDEX_REQUIRED_TEXT = """\ Чтобы пользоваться ботом, войдите через Яндекс. Так Telegram, сайт и приложение — один аккаунт, и бюджеты не потеряются. Откройте ссылку, примите документы и нажмите «Войти через Яндекс». Потом вернитесь в бот и напишите /start. """ def yandex_login_keyboard(login_url: str) -> InlineKeyboardMarkup | None: url = (login_url or "").strip() if not url.startswith(("https://", "http://")): return None return InlineKeyboardMarkup( inline_keyboard=[[InlineKeyboardButton(text="Войти через Яндекс", url=url)]] ) class YandexLoginGateMiddleware(BaseMiddleware): async def __call__( self, handler: Callable[[TelegramObject, dict[str, Any]], Awaitable[Any]], event: TelegramObject, data: dict[str, Any], ) -> Any: user = getattr(event, "from_user", None) service = data.get("budget_service") ensure = getattr(service, "ensure_yandex_login", None) if user is None or not callable(ensure): return await handler(event, data) try: await ensure(user.id) except YandexLoginRequired as exc: markup = yandex_login_keyboard(exc.login_url) if isinstance(event, Message): await event.answer(YANDEX_REQUIRED_TEXT, reply_markup=markup) elif isinstance(event, CallbackQuery): await event.answer() if event.message: await event.message.answer(YANDEX_REQUIRED_TEXT, reply_markup=markup) return None return await handler(event, data)