From d6fbc3df1345513b31f22042f65f85136615a947 Mon Sep 17 00:00:00 2001 From: wasrusgen Date: Wed, 13 May 2026 07:34:25 +0300 Subject: [PATCH] =?UTF-8?q?bot:=20=D1=83=D0=B1=D1=80=D0=B0=D1=82=D1=8C=20r?= =?UTF-8?q?eply-keyboard,=20=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20inline=20button?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reply-keyboard web_app кнопки на мобиле тоже не передают initData (или с issues). Оставляем только inline-кнопки в самом сообщении — они работают на Telegram Desktop side-panel + на мобильных. /start теперь шлёт ОДНО сообщение с inline-keyboard внутри. /menu — пере-открыть выбор роли. /hide — убрать reply-keyboard (если осталась от предыдущих версий). --- bot/handlers/start.py | 51 ++++++++++--------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/bot/handlers/start.py b/bot/handlers/start.py index f0fa88b..5e00e22 100644 --- a/bot/handlers/start.py +++ b/bot/handlers/start.py @@ -1,13 +1,11 @@ import time -from aiogram import F, Router +from aiogram import Router from aiogram.filters import Command, CommandStart from aiogram.types import ( InlineKeyboardButton, InlineKeyboardMarkup, - KeyboardButton, Message, - ReplyKeyboardMarkup, ReplyKeyboardRemove, WebAppInfo, ) @@ -22,7 +20,6 @@ router = Router(name="start") # ============================================================ def _bust_cache(url: str) -> str: - """Append unique timestamp so Telegram WebView не кеширует между сессиями.""" sep = "&" if "?" in url else "?" return f"{url}{sep}t={int(time.time())}" @@ -38,9 +35,10 @@ def _wapp(miniapp_url: str, role: str) -> WebAppInfo: # ============================================================ -# Inline keyboard — выбор роли прямо в сообщении /start. -# На Telegram Desktop side-panel reply-keyboard НЕ передаёт initData. -# Inline-кнопки открываются в МОДАЛЬНОМ режиме где initData валидно. +# Inline keyboard — единственный способ открыть MiniApp. +# Reply-кнопки с web_app не передают initData ни на Desktop side-panel, +# ни на мобильных. Inline-buttons открывают MiniApp в modal-режиме, +# где initData валидно передаётся на обеих платформах. # ============================================================ def role_choice_inline(miniapp_url: str) -> InlineKeyboardMarkup: @@ -57,41 +55,15 @@ def role_choice_inline(miniapp_url: str) -> InlineKeyboardMarkup: ) -# ============================================================ -# Reply keyboard — постоянная панель снизу (для мобильных). -# ============================================================ - -def role_choice_kb(miniapp_url: str) -> ReplyKeyboardMarkup: - return ReplyKeyboardMarkup( - keyboard=[ - [ - KeyboardButton(text="👤 Я менеджер", web_app=_wapp(miniapp_url, "manager")), - KeyboardButton(text="🏠 Я клиент", web_app=_wapp(miniapp_url, "client")), - ], - [ - KeyboardButton(text="🔧 Я сотрудник", web_app=_wapp(miniapp_url, "staff")), - ], - ], - resize_keyboard=True, - is_persistent=True, - input_field_placeholder="Выберите кто вы…", - ) - - # ============================================================ # Commands # ============================================================ @router.message(CommandStart()) async def cmd_start(message: Message, config: Config) -> None: - # Сначала отправляем reply-keyboard (постоянная панель снизу для мобильных) - await message.answer( - "👋 Здравствуйте, я бот-помощник от Руслана ВАСИЛЬЕВА.", - reply_markup=role_choice_kb(config.miniapp_url), - ) - # Затем inline-keyboard внутри отдельного сообщения — кнопки тут открывают MiniApp - # в МОДАЛЬНОМ режиме (важно для Telegram Desktop) + # Сразу убираем нижнюю reply-клавиатуру если она от предыдущих версий висит await message.answer( + "👋 Здравствуйте, я бот-помощник от Руслана ВАСИЛЬЕВА.\n\n" "Выберите, кто вы — кабинет откроется одним тапом.\n\n" "«Сотрудник» — для замерщиков и сборщиков ЗОВ.", reply_markup=role_choice_inline(config.miniapp_url), @@ -104,15 +76,14 @@ async def cmd_menu(message: Message, config: Config) -> None: "Выберите роль:", reply_markup=role_choice_inline(config.miniapp_url), ) - await message.answer( - "Или используйте панель снизу.", - reply_markup=role_choice_kb(config.miniapp_url), - ) @router.message(Command("hide")) async def cmd_hide(message: Message) -> None: - await message.answer("Клавиатура скрыта. Вернуть — /menu", reply_markup=ReplyKeyboardRemove()) + await message.answer( + "Нижняя клавиатура убрана. Для выбора роли — /menu", + reply_markup=ReplyKeyboardRemove(), + ) # ============================================================