Добавление админа по ссылке VK (не только числовой ID)

Бот принимает ссылку (https://vk.com/gruzdevas), короткое имя (gruzdevas),
@имя или числовой ID и сам определяет user_id (короткое имя — через VK API
users.get). Резолвер _resolve_vk_user_id применён к добавлению и удалению админа.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kenik
2026-06-25 19:06:45 +03:00
parent 0ec849d80f
commit f14b8769e5
+47 -11
View File
@@ -207,6 +207,32 @@ class VKBotApplication:
logger.error(f"Не удалось получить имя VK для {user_id}: {e}") logger.error(f"Не удалось получить имя VK для {user_id}: {e}")
return None return None
def _resolve_vk_user_id(self, raw: str) -> Optional[int]:
"""Из ссылки / короткого имени / ID получает числовой VK user_id (или None).
Принимает что угодно: https://vk.com/gruzdevas, vk.com/id123, @gruzdevas,
gruzdevas, 123456. Короткое имя резолвится через VK API.
"""
s = (raw or "").strip()
s = re.sub(r"^https?://", "", s, flags=re.I) # убираем протокол
s = re.sub(r"^(m\.)?vk\.com/", "", s, flags=re.I) # убираем домен
s = s.split("?")[0].split("/")[0].strip().strip("@").strip() # берём первый сегмент
if not s:
return None
m = re.match(r"^id(\d+)$", s, flags=re.I) # id123456
if m:
return int(m.group(1))
if s.isdigit(): # чистое число
return int(s)
if self.vk: # короткое имя → через API
try:
info = self.vk.users.get(user_ids=s)
if info:
return int(info[0]["id"])
except Exception as e:
logger.error(f"Не удалось определить VK id по '{s}': {e}")
return None
@staticmethod @staticmethod
def _progress_bar(step: int, total: int = 3) -> str: def _progress_bar(step: int, total: int = 3) -> str:
"""Визуальный прогресс шага формы: ▰▰▱ Шаг 2 из 3.""" """Визуальный прогресс шага формы: ▰▰▱ Шаг 2 из 3."""
@@ -267,11 +293,18 @@ class VKBotApplication:
if not self._is_super_admin(user_id): if not self._is_super_admin(user_id):
self.send_message(user_id, "⛔ Добавлять админов может только супер-админ.") self.send_message(user_id, "⛔ Добавлять админов может только супер-админ.")
return return
arg = text.split(" ", 2)[-1].strip() raw = text
if not arg.lstrip("-").isdigit(): if text.lower().startswith("админ доб"):
self.send_message(user_id, "⚠️ Формат: админ доб [VK_ID числом]") raw = text[len("админ доб"):].strip()
new_id = self._resolve_vk_user_id(raw)
if not new_id:
self.send_message(
user_id,
"⚠️ Не смог определить пользователя.\n"
"Пришлите ссылку на страницу VK (например, https://vk.com/gruzdevas), "
"короткое имя (gruzdevas) или числовой ID."
)
return return
new_id = int(arg)
if db.add_admin(new_id): if db.add_admin(new_id):
self._admins_cache = None # инвалидируем кэш админов self._admins_cache = None # инвалидируем кэш админов
self.send_message(user_id, f"✅ Пользователь vk.com/id{new_id} теперь администратор.") self.send_message(user_id, f"✅ Пользователь vk.com/id{new_id} теперь администратор.")
@@ -288,11 +321,13 @@ class VKBotApplication:
if not self._is_super_admin(user_id): if not self._is_super_admin(user_id):
self.send_message(user_id, "⛔ Удалять админов может только супер-админ.") self.send_message(user_id, "⛔ Удалять админов может только супер-админ.")
return return
arg = text.split(" ", 2)[-1].strip() raw = text
if not arg.lstrip("-").isdigit(): if text.lower().startswith("админ удал"):
self.send_message(user_id, "⚠️ Формат: админ удал [VK_ID числом]") raw = text[len("админ удал"):].strip()
rem_id = self._resolve_vk_user_id(raw)
if not rem_id:
self.send_message(user_id, "⚠️ Не смог определить пользователя. Пришлите ссылку/имя/ID.")
return return
rem_id = int(arg)
if db.remove_admin(rem_id): if db.remove_admin(rem_id):
self._admins_cache = None # инвалидируем кэш админов self._admins_cache = None # инвалидируем кэш админов
self.send_message(user_id, f"✅ Пользователь vk.com/id{rem_id} больше не администратор.") self.send_message(user_id, f"✅ Пользователь vk.com/id{rem_id} больше не администратор.")
@@ -489,8 +524,9 @@ class VKBotApplication:
self.send_message(user_id, "⛔ Только супер-админ.") self.send_message(user_id, "⛔ Только супер-админ.")
return return
db.update_user_state(user_id, "ADMIN_ADMIN_ADD") db.update_user_state(user_id, "ADMIN_ADMIN_ADD")
self.send_message(user_id, " Пришлите VK ID нового администратора (числом).\n" self.send_message(user_id, " Пришлите ссылку на страницу нового администратора в VK\n"
"ID можно узнать на vk.com/<id> или через сервисы определения id.", "(например, https://vk.com/gruzdevas). Можно также короткое имя "
"или числовой ID — бот сам разберётся.",
keyboard=get_cancel_admin_keyboard()) keyboard=get_cancel_admin_keyboard())
return return
elif text_lower in ["🗑 удалить админа", "удалить админа"]: elif text_lower in ["🗑 удалить админа", "удалить админа"]:
@@ -2099,7 +2135,7 @@ class VKBotApplication:
db.update_user_state(user_id, "FREE_CHAT") db.update_user_state(user_id, "FREE_CHAT")
self._send_admin_panel(user_id) self._send_admin_panel(user_id)
return return
self._handle_admin_add_admin(user_id, "админ доб " + pick_id(text)) self._handle_admin_add_admin(user_id, text) # передаём сырой текст (ссылка/имя/ID)
db.update_user_state(user_id, "FREE_CHAT") db.update_user_state(user_id, "FREE_CHAT")
return return