Files
2026-05-06 20:47:53 +00:00

91 lines
3.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import re
from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import CallbackQuery, InlineKeyboardButton, Message
from aiogram.utils.keyboard import InlineKeyboardBuilder
from core.settings.web_config import is_email_binding_enabled
from database.identities import get_identity_by_email, get_or_create_identity_for_tg
from handlers.buttons import BACK
from handlers.utils import edit_or_send_message
from logger import logger
router = Router(name="email_binding")
EMAIL_RE = re.compile(r"^[^\s@]+@[^\s@]+\.[^\s@]+$")
class EmailBindingState(StatesGroup):
waiting_for_email = State()
@router.callback_query(F.data == "bind_email")
async def prompt_email(callback: CallbackQuery, state: FSMContext, session) -> None:
if not is_email_binding_enabled():
await callback.answer("Привязка почты отключена", show_alert=True)
return
identity = await get_or_create_identity_for_tg(session, callback.from_user.id)
if identity.email:
await callback.answer("Почта уже привязана", show_alert=True)
return
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text=BACK, callback_data="profile"))
await edit_or_send_message(
target_message=callback.message,
text=(
"📧 <b>Привязка почты</b>\n\n"
"Укажите email — он понадобится для входа на сайт, "
"если возникнут проблемы с Telegram.\n\n"
"Отправьте адрес сообщением."
),
reply_markup=builder.as_markup(),
)
await state.set_state(EmailBindingState.waiting_for_email)
await callback.answer()
@router.message(EmailBindingState.waiting_for_email)
async def receive_email(message: Message, state: FSMContext, session) -> None:
raw = (message.text or "").strip().lower()
if not EMAIL_RE.match(raw) or len(raw) > 255:
await message.answer("❌ Неверный формат email. Попробуйте ещё раз.")
return
existing = await get_identity_by_email(session, raw)
if existing and existing.tg_id and existing.tg_id != message.from_user.id:
await message.answer("❌ Этот email уже занят другим пользователем.")
return
identity = await get_or_create_identity_for_tg(session, message.from_user.id)
if identity.email:
await state.clear()
await message.answer("ℹ️ Почта уже была привязана.")
return
if existing and existing.id != identity.id:
logger.warning(
"email_binding: identity collision tg_id=%s wants email=%s already on identity_id=%s",
message.from_user.id,
raw,
existing.id,
)
await message.answer("❌ Этот email уже занят. Используйте другой.")
return
identity.email = raw
await session.flush()
await state.clear()
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="👤 В кабинет", callback_data="profile"))
await message.answer(
f"✅ Почта <code>{raw}</code> привязана.",
reply_markup=builder.as_markup(),
)