Skip to content

Commit d2d0578

Browse files
authored
Merge pull request #5 from profcomff/copilot/fix-142d4adc-0389-484f-bf4b-7aecef7c32d2
Fix ban functionality to accept Telegram ID and username with collision detection
2 parents 350976a + 5d1be30 commit d2d0578

2 files changed

Lines changed: 135 additions & 26 deletions

File tree

handlers/admin/ban_handlers.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ async def ban_list_add(message: types.Message):
4545
logger.info("Начало процесса добавления пользователя в бан.")
4646
await bot.send_message(
4747
message.from_user.id,
48-
"Введите id пользователя, которого необходимо забанить:",
48+
"Введите идентификатор пользователя, которого необходимо забанить:\n"
49+
"• Внутренний ID базы данных (например: 123 или db:123)\n"
50+
"• Telegram ID (например: 987654321)\n"
51+
"• Username (например: @username)\n"
52+
"\n💡 При совпадении ID используйте db:123 для точного указания внутреннего ID",
4953
reply_markup=admin_cancel_markup(),
5054
)
5155
await AdminData.user_ban.set()
@@ -119,7 +123,11 @@ async def ban_list_remove(message: types.Message):
119123
logger.info("Начало процесса вывода пользователя из бана.")
120124
await bot.send_message(
121125
message.from_user.id,
122-
"Введите id пользователя, которого необходимо убрать из бан листа:",
126+
"Введите идентификатор пользователя, которого необходимо убрать из бан листа:\n"
127+
"• Внутренний ID базы данных (например: 123 или db:123)\n"
128+
"• Telegram ID (например: 987654321)\n"
129+
"• Username (например: @username)\n"
130+
"\n💡 При совпадении ID используйте db:123 для точного указания внутреннего ID",
123131
reply_markup=admin_cancel_markup(),
124132
)
125133
await AdminData.user_unban.set()
@@ -168,7 +176,9 @@ async def comment_to_unban_answer(message: types.Message, state: FSMContext):
168176
async def save_to_unban(unbanned_user_id, comment):
169177
"""Сохранение в БД, что пользователь выведен из бана."""
170178
with Session() as db_session:
171-
db_session.query(BanList).filter(BanList.banned_user_id == unbanned_user_id).update(
179+
db_session.query(BanList).filter(
180+
BanList.banned_user_id == unbanned_user_id
181+
).update(
172182
{
173183
"ban_status": 0,
174184
"date_of_unban": datetime.date.today(),

handlers/admin/validators/validators.py

Lines changed: 122 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from sqlalchemy import exists
55

66
from controllerBD.db_loader import Session
7-
from controllerBD.models import Users
7+
from controllerBD.models import Username, Users
88
from handlers.user.ban_check import check_id_in_ban_with_status
99
from loader import bot, logger
1010

@@ -17,37 +17,136 @@ async def comment_validator(text):
1717

1818

1919
async 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

3640
async 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

53152
async def check_id_in_base(user_id):

0 commit comments

Comments
 (0)