diff --git a/bot.py b/bot.py index 291c830..4b7c16b 100644 --- a/bot.py +++ b/bot.py @@ -225,12 +225,12 @@ class VKBotApplication: 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. + Принимает что угодно: https://vk.com/gruzdevas, https://vk.ru/gruzdevas, + m.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 = re.sub(r"^https?://", "", 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() # берём первый сегмент if not s: return None diff --git a/keyboards.py b/keyboards.py index 3e7897e..fd61c24 100644 --- a/keyboards.py +++ b/keyboards.py @@ -34,16 +34,21 @@ def _kb(rows, back=False, ask_manager=False, back_menu=True): back_menu — кнопка «В главное меню ↩️». """ keyboard = VkKeyboard(one_time=False) - for i, row in enumerate(rows): - if i: + has = False # была ли уже добавлена хоть одна кнопка (чтобы не создавать пустой ряд) + for row in rows: + if has: keyboard.add_line() for label in row: keyboard.add_button(label, color=VkKeyboardColor.SECONDARY) + has = True if ask_manager: - keyboard.add_line() + if has: + keyboard.add_line() keyboard.add_button("Задать вопрос менеджеру 💬", color=VkKeyboardColor.SECONDARY) + has = True if back or back_menu: - keyboard.add_line() + if has: + keyboard.add_line() if back: keyboard.add_button("Назад ⬅️", color=VkKeyboardColor.SECONDARY) if back_menu: diff --git a/tests/test_flow.py b/tests/test_flow.py index df65705..54e3dde 100644 --- a/tests/test_flow.py +++ b/tests/test_flow.py @@ -213,6 +213,40 @@ def test_admin_edit_link(app): 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): """Админ может отключить себе уведомления от клиентов — _notify_operators его пропускает.""" op = _admin()