from hmac import compare_digest from telegram import Update from telegram.constants import ChatType from telegram.ext import ApplicationHandlerStop, ContextTypes from .telegram_utils import ( get_services, get_storage, reply_markdown, require_user_id, ) def passwords_match(candidate: str, expected: str) -> bool: return compare_digest( candidate.encode("utf-8"), expected.encode("utf-8"), ) async def authentication_guard( update: Update, context: ContextTypes.DEFAULT_TYPE, ) -> None: user_id = require_user_id(update) if user_id is None: raise ApplicationHandlerStop storage = get_storage(context) if storage.is_user_authorized(user_id): return message = update.effective_message chat = update.effective_chat if chat is not None and chat.type != ChatType.PRIVATE: if message: await reply_markdown( message, "🔐 **Сначала авторизуйся в личном чате с ботом.**", ) raise ApplicationHandlerStop candidate = message.text.strip() if message and message.text else "" password = get_services(context).assistant_password if candidate and passwords_match(candidate, password): storage.authorize_user(user_id) await reply_markdown( message, "✅ **Пароль принят.** Доступ открыт — повторно вводить его не нужно.", ) raise ApplicationHandlerStop if candidate and not candidate.startswith("/"): await reply_markdown( message, "🔐 **Неверный пароль.** Попробуй ещё раз.", ) raise ApplicationHandlerStop if message: await reply_markdown( message, "🔐 **Для доступа к боту введи пароль** одним текстовым сообщением.", ) elif update.inline_query: await update.inline_query.answer([], cache_time=0) raise ApplicationHandlerStop