44from sqlalchemy import exists
55
66from controllerBD .db_loader import Session
7- from controllerBD .models import Users
7+ from controllerBD .models import Username , Users
88from handlers .user .ban_check import check_id_in_ban_with_status
99from loader import bot , logger
1010
@@ -17,37 +17,136 @@ async def comment_validator(text):
1717
1818
1919async def ban_validator (message : types .Message ):
20- """Валидация id пользователя для добавления в бан."""
21- if re .fullmatch (r"^\d{1,10}$" , message .text ):
22- if await check_id_in_base (message .text ):
23- if not await check_id_in_ban_with_status (message .text , 1 ):
24- logger .info ("Валидация пройдена." )
25- return True
26- await bot .send_message (message .from_user .id , "Пользователь уже забаннен." )
27- return False
20+ """Валидация пользователя для добавления в бан."""
21+ success , db_id , result_message = await resolve_user_input_to_db_id (message .text )
22+
23+ if not success :
24+ await bot .send_message (message .from_user .id , result_message )
25+ return False
26+
27+ # Проверяем, не забаннен ли уже пользователь
28+ if await check_id_in_ban_with_status (db_id , 1 ):
2829 await bot .send_message (
29- message .from_user .id , "Пользователя с таким id не существует. "
30+ message .from_user .id , f"Пользователь уже забаннен. { result_message } "
3031 )
3132 return False
32- await bot .send_message (message .from_user .id , "Неверный ввод, введите число." )
33- return False
33+
34+ logger .info (f"Валидация пройдена. { result_message } " )
35+ # Сохраняем найденный DB ID в message.text для дальнейшего использования
36+ message .text = str (db_id )
37+ return True
3438
3539
3640async def unban_validator (message : types .Message ):
37- """Валидация id пользователя для вывода из бана."""
38- if re .fullmatch (r"^\d{1,10}$" , message .text ):
39- if await check_id_in_base (message .text ):
40- if await check_id_in_ban_with_status (message .text , 1 ):
41- logger .info ("Валидация пройдена." )
42- return True
43- await bot .send_message (message .from_user .id , "Пользователь не забаннен." )
44- return False
41+ """Валидация пользователя для вывода из бана."""
42+ success , db_id , result_message = await resolve_user_input_to_db_id (message .text )
43+
44+ if not success :
45+ await bot .send_message (message .from_user .id , result_message )
46+ return False
47+
48+ # Проверяем, забаннен ли пользователь
49+ if not await check_id_in_ban_with_status (db_id , 1 ):
4550 await bot .send_message (
46- message .from_user .id , "Пользователя с таким id не существует. "
51+ message .from_user .id , f"Пользователь не забаннен. { result_message } "
4752 )
4853 return False
49- await bot .send_message (message .from_user .id , "Неверный ввод, введите число." )
50- return False
54+
55+ logger .info (f"Валидация пройдена. { result_message } " )
56+ # Сохраняем найденный DB ID в message.text для дальнейшего использования
57+ message .text = str (db_id )
58+ return True
59+
60+
61+ async def resolve_user_input_to_db_id (user_input : str ):
62+ """
63+ Пытается определить внутренний ID пользователя по различным типам ввода:
64+ - Внутренний ID базы данных (числовой)
65+ - Telegram ID (числовой, но больше)
66+ - Username (начинается с @)
67+ - Явный внутренний ID (db:123) для разрешения коллизий
68+
69+ Возвращает кортеж (success: bool, db_id: int | None, message: str)
70+ """
71+ user_input = user_input .strip ()
72+
73+ with Session () as db_session :
74+ # Случай 1: Ввод - это username (начинается с @)
75+ if user_input .startswith ("@" ):
76+ username = user_input [1 :] # Убираем @
77+ user_record = (
78+ db_session .query (Username ).filter (Username .username == username ).first ()
79+ )
80+ if user_record :
81+ return (
82+ True ,
83+ user_record .id ,
84+ f"Найден пользователь с username @{ username } " ,
85+ )
86+ return False , None , f"Пользователь с username @{ username } не найден"
87+
88+ # Случай 2: Явное указание внутреннего ID (db:123)
89+ if user_input .startswith ("db:" ):
90+ try :
91+ db_id = int (user_input [3 :])
92+ internal_user = (
93+ db_session .query (Users ).filter (Users .id == db_id ).first ()
94+ )
95+ if internal_user :
96+ return (
97+ True ,
98+ db_id ,
99+ f"Найден пользователь по явно указанному внутреннему ID: { internal_user .name } " ,
100+ )
101+ return False , None , f"Пользователь с внутренним ID { db_id } не найден"
102+ except ValueError :
103+ return False , None , "Неверный формат после 'db:'. Используйте db:123"
104+
105+ # Случай 3: Числовой ввод (может быть коллизия)
106+ if re .fullmatch (r"^\d{1,15}$" , user_input ):
107+ user_id = int (user_input )
108+
109+ # Проверяем оба типа ID одновременно для обнаружения коллизий
110+ internal_user = db_session .query (Users ).filter (Users .id == user_id ).first ()
111+ telegram_user = (
112+ db_session .query (Users ).filter (Users .teleg_id == user_id ).first ()
113+ )
114+
115+ # Случай 1: Найден только по внутреннему ID
116+ if internal_user and not telegram_user :
117+ return (
118+ True ,
119+ user_id ,
120+ f"Найден пользователь по внутреннему ID: { internal_user .name } " ,
121+ )
122+
123+ # Случай 2: Найден только по Telegram ID
124+ if telegram_user and not internal_user :
125+ return (
126+ True ,
127+ telegram_user .id ,
128+ f"Найден пользователь по Telegram ID: { telegram_user .name } " ,
129+ )
130+
131+ # Случай 3: КОЛЛИЗИЯ - найден и по внутреннему ID, и по Telegram ID
132+ if internal_user and telegram_user :
133+ # Приоритет отдаем Telegram ID, так как это чаще используется админами
134+ return (
135+ True ,
136+ telegram_user .id ,
137+ f"⚠️ ВНИМАНИЕ: ID { user_id } найден у двух пользователей! "
138+ f"Выбран по Telegram ID: { telegram_user .name } . "
139+ f"Для точности используйте @username или укажите 'db:{ user_id } ' для внутреннего ID." ,
140+ )
141+
142+ # Случай 4: Не найден ни по одному типу ID
143+ return (
144+ False ,
145+ None ,
146+ f"Пользователь с ID { user_id } не найден ни в внутренней базе, ни среди Telegram ID" ,
147+ )
148+
149+ return False , None , "Неверный формат ввода. Введите число (ID) или username с @"
51150
52151
53152async def check_id_in_base (user_id ):
0 commit comments