Как же хочется иногда навести суеты. А еще хочется навести красоты. Красоты для пользователей своих проектов. Чтобы им было удобно и приятно пользоваться плодами нашего умственного труда.
А что сейчас считается модным? Конечно же - минимум механических действий с получением максимального результата.
Иначе говоря, я не хочу печатать какую-то команду боту, я хочу просто нажимать на кнопочки и получать то, что мне нужно.
Итак, существует всего два типа людей... Ой, существует всего два типа клавиатур у телеграм ботов: те, что заменяют обычную клавиатуру и те, что прикрепляются к сообщениям.
Но обо всем по порядку.
Reply Keyboard
Технически - самая простая клавиатура. При активации, перекрывает обычную клавиатуру с буквами. Используется для пошагового взаимодействия с пользователем.
Если объяснять очень грубо - внутри каждой кнопки находится текст. Нажатие на эту кнопку отправляет сообщение с текстом внутри нее. Но давайте от теории к практике:
- Импортируем необходимые модули для нашей клавиатуры:
from telebot.types import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove
- Создадим нашу клавиатуру
kb = ReplyKeyboardMarkup()
- Добавим в нее кнопки "да" и "нет"
Можно так:
Можно так:
А можно вообще так:
Все три записи абсолютно идентичны.
А для чего мы вообще создавали эту клавиатуру? Как ее вывести пользователю?
Любая клавиатура прикрепляется к сообщению бота в параметре reply_markup.
- Создадим обработчик команды /start и к сообщению бота прикрепим нашу клавиатуру:
@bot.message_handler(commands=['start'])
def start_message(message):
bot.send_message(message.chat.id, 'Начнем диалог?', reply_markup=kb)
Какие большие и некрасивые кнопки у нас получились.
- Используем параметр resize_keyboard при создании клавиатуры:
kb = ReplyKeyboardMarkup(resize_keyboard=True)
kb.add('Да', 'Нет')
Все здорово и красиво, но при нажатии на кнопки ничего не происходит. Вы просто отправляете сообщения в чат. Технически, да, при нажатии на KeyboardButton, автоматически формируется и отправляется текстовое сообщение.
Возникает вопрос: как правильно нам его обработать?
В теории, мы можем написать два обработчика текстовых сообщений, по типу:
@bot.message_handler(func=lambda message: message.text == 'Да')
@bot.message_handler(func=lambda message: message.text == 'Нет')
Но нужно помнить то, что эти обработчики будут перехватывать все сообщения с текстом "Да" и "Нет", что нас абсолютно не устраивает. Так мы плавно подходим к последовательности сообщений, к методу register_next_step_handler.
bot.register_next_step_handler()
Метод помогает строить многоуровневое меню, либо вести диалог с пользователем.
Как это работает:
При вызове метода мы должны передать минимум 2 аргумента: переменную, которую мы передаем дальше, и в какую функцию мы передаем.
- Давайте напишем нашу новую функцию:
Заметьте, у функции нет никакого декоратора, она будет отрабатывать только тогда, когда ее вызовут.
- Дописываем нашу изначальную функцию:
- Проверяем, как это работает:
Заметим: наша клавиатура никуда не исчезла, но новые нажатия на нее не дают никакого результата.
- Прописываем автоматическое закрытие клавиатуры:
Можно написать так, однако, я советую выносить функцию закрытия в отдельную переменную:
@bot.message_handler(commands=['start'])
def start_message(message):
bot.send_message(message.chat.id, 'Начнем диалог?', reply_markup=kb)
bot.register_next_step_handler(message, second_message)
def second_message(old_message):
bot.send_message(old_message.chat.id, f'Твой выбор был {old_message.text}', reply_markup=kb_remove)
Убирать клавиатуру полностью нужно только тогда, когда ваш прогнозируемый диалог подошел к концу.
А можно ли передать в функцию больше одной переменной?
Конечно, да! Пробуем:
def second_message(message):
first_text = message.text
second_msg = bot.send_message(message.chat.id, f'Сделай второй выбор', reply_markup=kb)
additional_param = 'Текстовая переменная'
bot.register_next_step_handler(second_msg, third_message, first_text, additional_param)
Здесь мы создали переменную "additional_param", в которую мы поместили простой текст.
- В методе register_next_step_handler мы передаем по очереди:
- Новое сообщение
- Вызываемую функцию
- Любое количество дополнительных переменных (функция должна будет принять их все)
def third_message(second_mess, start_text, new_param):
bot.send_message(second_mess.chat.id, f'''Текст твоих сообщений:
Первое: {start_text}
Второе: {second_mess.text}
Дополнительная переменная из второй функции: {new_param}
''', reply_markup=kb_remove)
При попадании в функцию third_message():
- переменная second_msg стала second_mess
- first_text стала start_text
- additional_param стала new_param.
Смотрим, как это отрабатывает:
Такую последовательность сообщений можно вести бесконечно, но лучше не увлекаться и делать меню в 2-3 уровня.
В следующей статье поговорим о кнопках, прикрепляемых к сообщениям.