"""Валидация и форматирование пользовательского ввода.""" import re from typing import Optional # Регулярные выражения для валидации # Российский номер для нормализации 8XXX / 7XXX -> +7XXX RU_PHONE_REGEX = re.compile(r"^\+?[78]\d{10}$") # Международный формат (E.164): + и 10–15 цифр. Принимаем и иностранные номера. INTL_PHONE_REGEX = re.compile(r"^\+?\d{10,15}$") # Имя: буквы (кириллица/латиница), пробел, дефис, апостроф; длина 2–50 NAME_REGEX = re.compile(r"^[A-Za-zА-Яа-яЁё][A-Za-zА-Яа-яЁё \-']{1,49}$") def normalize_phone(text: str) -> Optional[str]: """Очищает и нормализует телефон. Возвращает нормализованный номер или None, если формат неверен.""" phone_cleaned = re.sub(r"[\s\-\(\)]", "", text) # Российские номера приводим к виду +7XXXXXXXXXX if phone_cleaned.startswith("8") and len(phone_cleaned) == 11: phone_cleaned = "+7" + phone_cleaned[1:] elif phone_cleaned.startswith("7") and len(phone_cleaned) == 11: phone_cleaned = "+" + phone_cleaned # Принимаем как российский, так и любой международный номер в формате E.164 if RU_PHONE_REGEX.match(phone_cleaned) or INTL_PHONE_REGEX.match(phone_cleaned): return phone_cleaned return None def format_phone_display(phone: str) -> str: """Красивое отображение номера: +7 (999) 123-45-67 для РФ, иначе как есть.""" if not phone: return phone digits = re.sub(r"\D", "", phone) if len(digits) == 11 and digits[0] in ("7", "8"): d = digits return f"+7 ({d[1:4]}) {d[4:7]}-{d[7:9]}-{d[9:11]}" return phone def is_valid_name(text: str) -> bool: """Имя должно состоять только из букв, пробела, дефиса или апострофа (без цифр и спецсимволов).""" return bool(NAME_REGEX.match(text.strip()))