Вчерашние кнопки живут внизу экрана. Но бывают другие, которые висят прямо под конкретным сообщением. Открой любой нормальный бот и увидишь их: «Купить», «Подробнее», «Назад». Они называются inline-кнопки, и сегодня мы их сделаем.
После урока сможешь: объяснить тему «Кнопки под сообщением: inline» и выполнить связанный с ней учебный шаг без подсказки.
Чем inline отличается от reply
Reply-кнопка при нажатии присылает обычный текст. А inline-кнопка присылает не текст, а особый сигнал, который называют callback (читается «колбэк»). Пользователь в чате ничего не печатает, а бот понимает, какую кнопку нажали. Ловить нажатие будем не обычным обработчиком, а отдельным, для callback.
Показываем inline-кнопки
Сделаем команду /menu, которая покажет кнопки под сообщением.
@bot.message_handler(commands=['menu'])
def menu(message):
keyboard = types.InlineKeyboardMarkup()
keyboard.add(types.InlineKeyboardButton("Шутка", callback_data="joke"))
keyboard.add(types.InlineKeyboardButton("Совет", callback_data="advice"))
bot.send_message(message.chat.id, "Выбери, что прислать:", reply_markup=keyboard)
types.InlineKeyboardButton("Шутка", callback_data="joke") это кнопка с двумя кусочками: надпись, которую видит человек, и callback_data — тихое слово-метка, которое прилетит боту при нажатии. Человек его не видит, оно для программы. Метки joke и advice можешь назвать как удобно.
Ловим нажатие
@bot.callback_query_handler(func=lambda call: True)
def on_click(call):
if call.data == "joke":
bot.send_message(call.message.chat.id, "Программист заходит в лифт, а там кнопки 0 и 1.")
elif call.data == "advice":
bot.send_message(call.message.chat.id, "Не бойся ошибок. Бойся не сохраниться.")
bot.answer_callback_query(call.id)
@bot.callback_query_handler(...)новая табличка на двери, ловит именно нажатия inline-кнопок. Внутрь прилетает не message, аcall— информация о нажатии.call.dataэто метка, которую мы задали. По ней через if понимаем, какую кнопку нажали. Адрес чата теперьcall.message.chat.id.bot.answer_callback_query(call.id)говорит Telegram «я принял нажатие». Без неё на кнопке крутятся часики, как будто бот завис.
Ловушка: часики висят, хотя answer_callback_query есть
Строчка
bot.answer_callback_queryна месте, а часики на кнопке всё равно крутятся? Знакомая ловушка. Дело почти всегда не в этой строке. Две частые причины: (1) ты дописал строку, но не перезапустил бота, и он работает по старому коду, где её ещё нет; (2) запущены две копии бота сразу, они мешают друг другу. И то, и другое лечится перезапуском: останови бота (Ctrl+C), проверь, что нигде больше он не запущен, и запусти файл заново. Часики оживут. Подробный разбор обеих ловушек — в уроке «Бот молчит? Чиним», причины 6 и 7.
Контрольный вопрос. У inline-кнопки есть тихая метка, которую бот получает при нажатии. Как называется параметр этой метки? Напиши одно слово.
Подсказка: types.InlineKeyboardButton(«Шутка», ____=»joke»)
Онлайн-проверка ответа появится позже
Задание. Сделай команду /menu с 2-3 inline-кнопками, на каждую свой ответ. Не забудь answer_callback_query, чтобы убрать часики. Пришли скриншот меню с кнопками под сообщением и ответа на нажатие.
Подсказка: InlineKeyboardMarkup + InlineKeyboardButton с callback_data, ловить callback_query_handler по call.data.
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Онлайн-проверка ответа появится позже
Зачёт, если:
✅ команда /menu показывает 2-3 inline-кнопки под сообщением;
✅ на каждую кнопку свой ответ, часики после нажатия пропадают (есть answer_callback_query);
✅ прислан скриншот меню и ответа на нажатие.
