feat(proj): init

This commit is contained in:
vl.arkhangelskii
2026-09-21 04:06:43 +03:00
commit c956b94983
1076 changed files with 50876 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
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)