Фикс: пустой ряд в клавиатуре ломал отправку («Задать вопрос» молчал) + vk.ru в резолвере
1) _kb при пустых рядах создавал ПУСТОЙ первый ряд (add_line до кнопок) — VK отклонял такую клавиатуру, из-за чего сообщения шага «Задать вопрос», «другая игра», «нужен совет» не отправлялись (состояние при этом менялось). Теперь add_line ставится только между реальными кнопками — пустых рядов нет. 2) _resolve_vk_user_id теперь понимает домен vk.ru (и www./m.), а не только vk.com — ссылку https://vk.ru/screenname на добавление админа бот принимает. Тесты: test_funnel_keyboards_no_empty_rows, test_resolve_vk_links. pytest 40 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -225,12 +225,12 @@ class VKBotApplication:
|
|||||||
def _resolve_vk_user_id(self, raw: str) -> Optional[int]:
|
def _resolve_vk_user_id(self, raw: str) -> Optional[int]:
|
||||||
"""Из ссылки / короткого имени / ID получает числовой VK user_id (или None).
|
"""Из ссылки / короткого имени / ID получает числовой VK user_id (или None).
|
||||||
|
|
||||||
Принимает что угодно: https://vk.com/gruzdevas, vk.com/id123, @gruzdevas,
|
Принимает что угодно: https://vk.com/gruzdevas, https://vk.ru/gruzdevas,
|
||||||
gruzdevas, 123456. Короткое имя резолвится через VK API.
|
m.vk.com/id123, @gruzdevas, gruzdevas, 123456. Короткое имя резолвится через VK API.
|
||||||
"""
|
"""
|
||||||
s = (raw or "").strip()
|
s = (raw or "").strip()
|
||||||
s = re.sub(r"^https?://", "", s, flags=re.I) # убираем протокол
|
s = re.sub(r"^https?://", "", s, flags=re.I) # убираем протокол
|
||||||
s = re.sub(r"^(m\.)?vk\.com/", "", s, flags=re.I) # убираем домен
|
s = re.sub(r"^(www\.|m\.)?vk\.(com|ru)/", "", s, flags=re.I) # убираем домен (vk.com / vk.ru)
|
||||||
s = s.split("?")[0].split("/")[0].strip().strip("@").strip() # берём первый сегмент
|
s = s.split("?")[0].split("/")[0].strip().strip("@").strip() # берём первый сегмент
|
||||||
if not s:
|
if not s:
|
||||||
return None
|
return None
|
||||||
|
|||||||
+9
-4
@@ -34,16 +34,21 @@ def _kb(rows, back=False, ask_manager=False, back_menu=True):
|
|||||||
back_menu — кнопка «В главное меню ↩️».
|
back_menu — кнопка «В главное меню ↩️».
|
||||||
"""
|
"""
|
||||||
keyboard = VkKeyboard(one_time=False)
|
keyboard = VkKeyboard(one_time=False)
|
||||||
for i, row in enumerate(rows):
|
has = False # была ли уже добавлена хоть одна кнопка (чтобы не создавать пустой ряд)
|
||||||
if i:
|
for row in rows:
|
||||||
|
if has:
|
||||||
keyboard.add_line()
|
keyboard.add_line()
|
||||||
for label in row:
|
for label in row:
|
||||||
keyboard.add_button(label, color=VkKeyboardColor.SECONDARY)
|
keyboard.add_button(label, color=VkKeyboardColor.SECONDARY)
|
||||||
|
has = True
|
||||||
if ask_manager:
|
if ask_manager:
|
||||||
keyboard.add_line()
|
if has:
|
||||||
|
keyboard.add_line()
|
||||||
keyboard.add_button("Задать вопрос менеджеру 💬", color=VkKeyboardColor.SECONDARY)
|
keyboard.add_button("Задать вопрос менеджеру 💬", color=VkKeyboardColor.SECONDARY)
|
||||||
|
has = True
|
||||||
if back or back_menu:
|
if back or back_menu:
|
||||||
keyboard.add_line()
|
if has:
|
||||||
|
keyboard.add_line()
|
||||||
if back:
|
if back:
|
||||||
keyboard.add_button("Назад ⬅️", color=VkKeyboardColor.SECONDARY)
|
keyboard.add_button("Назад ⬅️", color=VkKeyboardColor.SECONDARY)
|
||||||
if back_menu:
|
if back_menu:
|
||||||
|
|||||||
@@ -213,6 +213,40 @@ def test_admin_edit_link(app):
|
|||||||
assert app._link("group_4") == "https://infocyber.pro/pay/group4"
|
assert app._link("group_4") == "https://infocyber.pro/pay/group4"
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_vk_ru_and_com_links(app):
|
||||||
|
"""Резолвер принимает ссылки vk.ru и vk.com (id-форма работает без сети)."""
|
||||||
|
assert app._resolve_vk_user_id("https://vk.ru/id350793273") == 350793273
|
||||||
|
assert app._resolve_vk_user_id("https://vk.com/id777") == 777
|
||||||
|
assert app._resolve_vk_user_id("http://m.vk.ru/id42") == 42
|
||||||
|
assert app._resolve_vk_user_id("www.vk.com/id5") == 5
|
||||||
|
assert app._resolve_vk_user_id("id99") == 99
|
||||||
|
assert app._resolve_vk_user_id("12345") == 12345
|
||||||
|
|
||||||
|
|
||||||
|
def test_funnel_keyboards_no_empty_rows():
|
||||||
|
"""VK отклоняет клавиатуру с пустым рядом — таких быть не должно ни в одной."""
|
||||||
|
import json, keyboards
|
||||||
|
kbs = [
|
||||||
|
keyboards.get_baza_menu_only_keyboard(), keyboards.get_baza_forwho_keyboard(),
|
||||||
|
keyboards.get_baza_age_keyboard(), keyboards.get_baza_game_keyboard(),
|
||||||
|
keyboards.get_baza_level_keyboard(), keyboards.get_baza_format_keyboard(),
|
||||||
|
keyboards.get_baza_group_keyboard(), keyboards.get_baza_individual_keyboard(),
|
||||||
|
keyboards.get_baza_int_level_keyboard(),
|
||||||
|
]
|
||||||
|
for kb in kbs:
|
||||||
|
for row in json.loads(kb)["buttons"]:
|
||||||
|
assert len(row) > 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_vk_links(app):
|
||||||
|
"""Ссылки vk.ru и vk.com (и голый id) корректно приводятся к числовому id."""
|
||||||
|
assert app._resolve_vk_user_id("https://vk.ru/id350793273") == 350793273
|
||||||
|
assert app._resolve_vk_user_id("https://vk.com/id777") == 777
|
||||||
|
assert app._resolve_vk_user_id("vk.ru/id42") == 42
|
||||||
|
assert app._resolve_vk_user_id("id100") == 100
|
||||||
|
assert app._resolve_vk_user_id("999") == 999
|
||||||
|
|
||||||
|
|
||||||
def test_admin_mute_notifications(app):
|
def test_admin_mute_notifications(app):
|
||||||
"""Админ может отключить себе уведомления от клиентов — _notify_operators его пропускает."""
|
"""Админ может отключить себе уведомления от клиентов — _notify_operators его пропускает."""
|
||||||
op = _admin()
|
op = _admin()
|
||||||
|
|||||||
Reference in New Issue
Block a user