ReplyKeyboardRemove : Remove a keyboard
Upon receiving a message with this object, Telegram clients will remove the current custom keyboard and display the default letter-keyboard. By default, custom keyboards are displayed until a new keyboard is sent by a bot. An exception is made for one-time keyboards that are hidden immediately after the user presses a button (see ReplyKeyboardMarkup ).
Usage
ReplyKeyboardRemove(remove_keyboard = TRUE, selective = NULL)
Arguments
Requests clients to remove the custom keyboard. (user will not be able to summon this keyboard; if you want to hide the keyboard from sight but keep it accessible, use one_time_keyboard in ReplyKeyboardMarkup ). Defaults to TRUE .
(Optional). Use this parameter if you want to show the keyboard to specific users only.
Examples
## Not run: # Initialize bot botУправление сообщениями в боте телеграм
Класс types.Message является основным классом в библиотеке aiogram для представления сообщений в Telegram. Он содержит различные методы и атрибуты для работы с сообщениями.
Некоторые из наиболее часто используемых атрибутов и методов класса `types.Message`:
- message_id : Уникальный идентификатор сообщения.
- from_user : Объект types.User , представляющий отправителя сообщения.
- date : Дата и время отправки сообщения.
- chat : Объект `types.Chat`, представляющий чат, в котором было отправлено сообщение.
- forward_from : Объект types.User , представляющий отправителя оригинального сообщения, если оно было переслано.
- forward_from_chat : Объект types.Chat , представляющий чат, из которого было переслано оригинальное сообщение, если оно было переслано из группы или канала.
- forward_from_message_id : Идентификатор оригинального сообщения, если оно было переслано.
- text : Текст сообщения.
- entities : Список объектов types.MessageEntity , представляющих различные сущности в тексте сообщения, такие как упоминания пользователей, хэштеги и т.д.
- reply_to_message : Объект types.Message , представляющий сообщение, на которое данное сообщение является ответом.
- reply_markup : Объект `types.InlineKeyboardMarkup` или `types.ReplyKeyboardMarkup`, представляющий клавиатуру, привязанную к сообщению.
- delete() : Метод для удаления сообщения.
- edit_text() : Метод для редактирования текста сообщения.
- reply() : Метод для отправки ответного сообщения.
Примеры, приведенные в этой статье работают на версии aiogram 2x
Методы, которые позволяют отправлять сообщения
Для отправки текстового сообщения в библиотеке aiogram можно использовать несколько методов. Некоторые из них:
- bot.send_message(chat_id, text) : Этот метод позволяет отправить текстовое сообщение в указанный чат. Необходимо указать идентификатор чата ( chat_id ) и текст сообщения ( text ).
await bot.send_message(chat_id, "Привет, мир!")
- message.answer(text) , который позволяет отправить ответное сообщение на текущее сообщение. Этот метод является альтернативой методу message.reply(text) .
await message.answer("Спасибо за ваше сообщение!")
Метод message.answer() автоматически определяет идентификатор чата и идентификатор сообщения, на которое нужно ответить, поэтому вам не нужно указывать их явно.
- message.reply(text) : Этот метод позволяет отправить ответное сообщение на текущее сообщение. Необходимо указать текст ответного сообщения ( text ).
await message.reply("Спасибо за ваше сообщение!")
- message.edit_text(text) : Этот метод позволяет отредактировать текст текущего сообщения. Необходимо указать новый текст сообщения ( text ).
await message.edit_text("Новый текст сообщения")
- bot.send_message(chat_id, text, reply_to_message_id) : Этот метод позволяет отправить текстовое сообщение в указанный чат в качестве ответа на другое сообщение. Необходимо указать идентификатор чата ( chat_id ), текст сообщения ( text ) и идентификатор сообщения, на которое данное сообщение будет ответом ( reply_to_message_id ).
await bot.send_message(chat_id, "Ответ на ваше сообщение", reply_to_message_id=message_id)
Различия между send_message, answer и reply
Метод bot.send_message отправляет сообщение в произвольный чат, который указывается в параметре chat_id . Метод answer() , позволяет отправить сообщение в ответ на предыдущее сообщение в текущем чате. При этом, сообщение, на которое дается ответ не пересылается. Метод reply() , позволяет отправить сообщение в ответ на предыдущее сообщение в текущем чате. Cообщение, на которое дается ответ также отправляется.

Пример готового бота, который умеет отправлять сообщения
from aiogram import Bot, Dispatcher, types from aiogram.contrib.fsm_storage.memory import MemoryStorage # Установите токен вашего бота BOT_TOKEN = 'YOUR_BOT_TOKEN' bot = Bot(token=BOT_TOKEN) dp = Dispatcher(bot, storage=MemoryStorage()) @dp.message_handler(commands=['start']) async def handle_start(message: types.Message): # Отправляем приветственное сообщение await message.reply('Привет! Я бот. Как дела?') @dp.message_handler(commands=['help']) async def handle_help(message: types.Message): # Отправляем сообщение с инструкциями по использованию бота help_message = """ Привет! Я бот. Вот некоторые доступные команды: - /start: Начать взаимодействие с ботом - /help: Получить справку о командах бота """ await message.reply(help_message) @dp.message_handler() async def handle_message(message: types.Message): # Отправляем эхо-ответ на полученное сообщение await message.reply(f'Вы отправили сообщение: ') if __name__ == '__main__': from aiogram import executor executor.start_polling(dp, skip_updates=True)
В этом примере бот будет отвечать на команды /start и /help , а также на любые другие текстовые сообщения, отправленные пользователем. При получении команды /start он отправит приветственное сообщение, а при получении команды /help отправит справку о командах бота. Для всех остальных сообщений бот отправит эхо-ответ с содержимым полученного сообщения.
Просто замените 'YOUR_BOT_TOKEN' на фактический токен вашего бота, запустите скрипт, и ваш бот будет готов к работе. Вы можете добавить дополнительные команды и функциональность, чтобы адаптировать его под свои потребности.
Отправка других типов контента с помощью бота
В библиотеке aiogram вы можете отправлять различные типы контента помимо простого текста. Вот некоторые из наиболее распространенных типов контента, которые вы можете отправлять с помощью aiogram:
1. Фотографии: Метод send_photo используется для отправки фотографий. Вы можете указать путь к файлу фотографии на вашем сервере или использовать URL-адрес изображения в Интернете. Пример использования:
await bot.send_photo(chat_id, photo=open('photo.jpg', 'rb'), caption='Красивая фотография')
2. Аудио: Метод send_audio используется для отправки аудиофайлов. Вы можете указать путь к файлу аудио или использовать URL-адрес аудиофайла в Интернете. Пример использования:
await bot.send_audio(chat_id, audio=open('audio.mp3', 'rb'), caption='Музыкальный трек')
3. Документы: Метод `send_document` используется для отправки документов. Вы можете указать путь к файлу документа на вашем сервере или использовать URL-адрес документа в Интернете. Пример использования:
await bot.send_document(chat_id, document=open('document.pdf', 'rb'), caption='PDF-документ')
4. Видео: Метод send_video используется для отправки видеофайлов. Вы можете указать путь к файлу видео или использовать URL-адрес видеофайла в Интернете. Пример использования:
await bot.send_video(chat_id, video=open('video.mp4', 'rb'), caption='Видео-ролик')
5. Голосовые сообщения: Метод send_voice используется для отправки голосовых сообщений. Вы можете указать путь к файлу голосового сообщения на вашем сервере или использовать URL-адрес голосового сообщения в Интернете. Пример использования:
await bot.send_voice(chat_id, voice=open('voice.ogg', 'rb'), caption='Голосовое сообщение')
Пример реализации бота с возможностью отправки разного типа контента
from aiogram import Bot, Dispatcher, types from aiogram.contrib.fsm_storage.memory import MemoryStorage # Установите токен вашего бота BOT_TOKEN = 'YOUR_BOT_TOKEN' bot = Bot(token=BOT_TOKEN) dp = Dispatcher(bot, storage=MemoryStorage()) @dp.message_handler(commands=['start']) async def handle_start(message: types.Message): # Отправляем приветственное сообщение await message.reply('Привет! Я бот. Как дела?') @dp.message_handler(commands=['text']) async def handle_text(message: types.Message): # Отправляем текстовое сообщение await message.reply('Пример текстового сообщения') @dp.message_handler(commands=['video']) async def handle_video(message: types.Message): # Отправляем видеофайл await bot.send_video(message.chat.id, video=open('video.mp4', 'rb')) @dp.message_handler(commands=['audio']) async def handle_audio(message: types.Message): # Отправляем аудиофайл await bot.send_audio(message.chat.id, audio=open('audio.mp3', 'rb')) @dp.message_handler(commands=['document']) async def handle_document(message: types.Message): # Отправляем документ await bot.send_document(message.chat.id, document=open('document.pdf', 'rb')) @dp.message_handler(commands=['photo']) async def handle_photo(message: types.Message): # Отправляем фотографию await bot.send_photo(message.chat.id, photo=open('photo.jpg', 'rb')) @dp.message_handler(commands=['voice']) async def handle_voice(message: types.Message): # Отправляем голосовое сообщение await bot.send_voice(message.chat.id, voice=open('voice.ogg', 'rb')) if __name__ == '__main__': from aiogram import executor executor.start_polling(dp, skip_updates=True)
В этом примере бот реагирует на различные команды ( /start , /text , /video , /audio , /document , /photo , /voice ). Когда пользователь отправляет одну из этих команд, бот отправляет соответствующий контент в ответ.
Просто замените 'YOUR_BOT_TOKEN' на фактический токен вашего бота, а также укажите пути к файлам видео, аудио, документа, фотографии и голосового сообщения. После этого запустите скрипт, и ваш бот будет готов к работе. Вы можете добавить дополнительные команды и функциональность, чтобы адаптировать его под свои потребности.
Примеры ботов, работающих с сообщениями
Бот — фильтр ненормативной лексики
from aiogram import Bot, Dispatcher, types from aiogram.contrib.fsm_storage.memory import MemoryStorage # Установите токен вашего бота BOT_TOKEN = 'YOUR_BOT_TOKEN' bot = Bot(token=BOT_TOKEN) dp = Dispatcher(bot, storage=MemoryStorage()) # Список запрещенных слов forbidden_words = ['ругаться', 'оскорблять', 'ненормативная_лексика'] @dp.message_handler() async def handle_message(message: types.Message): text = message.text.lower() # Проверяем наличие запрещенных слов в сообщении if any(word in text for word in forbidden_words): # Отправляем предупреждение await message.reply('В чате нельзя ругаться!') if __name__ == '__main__': from aiogram import executor executor.start_polling(dp, skip_updates=True)
В этом примере бот реагирует на все сообщения в чате и проверяет наличие запрещенных слов из списка forbidden_words в тексте сообщения. Если хотя бы одно из запрещенных слов обнаружено, бот отправляет предупреждение о недопустимости ругательства.
Просто замените 'YOUR_BOT_TOKEN' на фактический токен вашего бота и расширьте список forbidden_words в соответствии с вашими требованиями. Запустите скрипт, и ваш бот будет готов к мониторингу сообщений и отправке предупреждений о ненормативной лексике.
Как убрать клавиатуру бота (aiogram)?
Встала задача, чтобы при нажатии обычной кнопки передачи геопозиции бот отвечал сообщением с инлайн-кнопками, но при этом пропадала кнопка передачи геопозиции. В await message.answer я могу либо указывать инлайн-клавиатуру, либо удаление обычной клавиатуры:
await message.answer("text", reply_markup=markup)
await message.answer("text", reply_markup=types.ReplyKeyboardRemove())
Как я могу это объединить?
Отслеживать
840 9 9 серебряных знаков 20 20 бронзовых знаков
задан 18 фев в 21:36
33 5 5 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вот Вам вариант решения, возможно он не самый оптимальный, но, все же, является действенным и полностью соответствует Вашему запросу.
Код выполняет следующий алгоритм: 1) Пользователь инициирует /start и получает обычную кнопку "Отправить геопозицию"; 2) Пользователь решается на это не самое безопасное действие и отправляет свою геопозицию; 3) Ваш добропорядочный бот оправляет пользователю сообщенние с его геопозицией (в этом тестовом примере); 4) К этому сообщению бот прикрепляет 2 инлайн кнопки; 5) В тоже время бот выполняет процедуру удаления обычной кнопки "Отправить геопозицию".
Для пользователя пункты 3-5 происходят одновременно 🙂
P.s. После нажатия кнопки /start кнопка возвращается во своя оси. И можно смело выполнять все заново.
from aiogram import Bot, Dispatcher, types from aiogram.types import ParseMode from aiogram.utils import exceptions, executor API_TOKEN = '' bot = Bot(token=API_TOKEN, parse_mode=ParseMode.HTML) dp = Dispatcher(bot) # Обработчик команды /start @dp.message_handler(commands=['start']) async def start_handler(message: types.Message): keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True) button = types.KeyboardButton(text="Отправить геопозицию", request_location=True) keyboard.add(button) await message.answer("Добро пожаловать! Нажмите кнопку, чтобы отправить свою геопозицию.", reply_markup=keyboard) # Обработчик получения геопозиции @dp.message_handler(content_types=types.ContentType.LOCATION) async def location_handler(message: types.Message): latitude = message.location.latitude longitude = message.location.longitude keyboard = types.InlineKeyboardMarkup() button1 = types.InlineKeyboardButton(text="Первая кнопка", callback_data='btn1') button2 = types.InlineKeyboardButton(text="Вторая кнопка", callback_data='btn2') keyboard.add(button1, button2) keyboard_to_delete = types.ReplyKeyboardRemove() await message.answer(f"Ваша геопозиция: , ", reply_markup=keyboard) try: # Пытаемся удалить кнопку "Отправить геопозицию" await bot.delete_message(chat_id=message.chat.id, message_id=message.message_id - 1) except exceptions.MessageToDeleteNotFound: # Если кнопка уже удалена, то продолжаем выполнение кода pass # Обработчик нажатий на кнопки инлайн-клавиатуры @dp.callback_query_handler(lambda callback_query: True) async def callback_handler(callback_query: types.CallbackQuery): if callback_query.data == 'btn1': await bot.answer_callback_query(callback_query.id, "Вы нажали первую кнопку.") elif callback_query.data == 'btn2': await bot.answer_callback_query(callback_query.id, "Вы нажали вторую кнопку.") if __name__ == '__main__': executor.start_polling(dp, skip_updates=True)
Урок 5. Клавиатуры и кнопки
В сегодняшнем уроке мы разберём шаблоны сообщений и инлайн-клавиатуры и научимся применять встроенные в aiogram методы для составления сложных клавиатур.
Не забывайте своевременно обновлять библиотеку командой python3.6 -m pip install aiogram -U ! Урок проводится с использованием версии 1.2.3
Весь код, использованный в уроке, как обычно доступен на GitHub
Для начала стоит понять, в чем основное различие ReplyKeyboardMarkup и InlineKeyboardMarkup :
ReplyKeyboardMarkup — это шаблоны сообщений. К примеру, ваш бот задаёт пользователю вопрос и предлагает варианты ответа. Пользователь может самостоятельно напечатать ответ, либо нажать на готовую кнопку. Такая клавиатура показывается вместо основной и не привязана ни к какому сообщению. В кнопки такой клавиатуры нельзя заложить никакой информации, нельзя запрограммировать для неё подобный если пользователь нажимает кнопку с текстом «abc» отправить текст «qwerty» алгоритм, отправлено будет только то, что написано на кнопке (есть два исключения, о которых ниже).
InlineKeyboardMarkup — это уже настоящая кастомная клавиатура. С её помощью мы можем выполнять более сложные действия. Она привязывается к сообщению, с которым была отправлена. В кнопки можно заложить любой текст размером от 1 до 64 байт (будьте осторожны, недобросовестные клиенты позволяют изменять эти данные). Инлайн кнопки позволяют скрыть в себе внутреннюю телеграм ссылку, ссылку на внешний ресурс, а также шорткат для инлайн запроса (об инлайн режиме в одном из следующих уроков).
И ту и другую клавиатуру можно редактировать, но разными способами. Первая обновляется при отправке сообщения с новой клавиатурой типа ReplyKeyboardMarkup , вторую можно редактировать вместе с сообщением, к которому она прикреплена (или только саму разметку).
Переходим к коду
Создадим отдельный модуль с клавиатурами, которые будем использовать в основной программе.
В первую очередь импортируем необходимые нам модули и создаём первую клавиатуру:
from aiogram.types import ReplyKeyboardRemove, \ ReplyKeyboardMarkup, KeyboardButton, \ InlineKeyboardMarkup, InlineKeyboardButton button_hi = KeyboardButton('Привет! ') greet_kb = ReplyKeyboardMarkup() greet_kb.add(button_hi)
При инициализации класса KeyboardButton необходимо передать один обязательный параметр - текст, который пользователь будет отправлять по нажатию на эту кнопку. У объекта класса ReplyKeyboardMarkup есть несколько методов, позволяющих добавить кнопку, в данном случае мы используем add . Таким образом мы получили первую готовую клавиатуру.
Создаём обработчик, который будет отправлять нам сообщение и наш шаблон (напомню, что отправить отдельно клавиатуру никак нельзя, она является параметром к сообщению).
@dp.message_handler(commands=['start']) async def process_start_command(message: types.Message): await message.reply("Привет!", reply_markup=kb.greet_kb)
Запускаем и проверяем:

Отлично, клавиатура появилась! Но эта одна кнопка с маленьким текстом занимает очень много места. Телеграм позволяет автоматически уменьшить размер, для этого необходимо передать в инициализатор класса ReplyKeyboardMarkup параметру resize_keyboard значение True . Создадим новую клавиатуру:
greet_kb1 = ReplyKeyboardMarkup(resize_keyboard=True).add(button_hi)
Мы передали параметр в инициализатор и следом сразу добавили уже существующую кнопку. Отправляем новую версию клавиатуры:
@dp.message_handler(commands=['hi1']) async def process_hi1_command(message: types.Message): await message.reply("Первое - изменяем размер клавиатуры", reply_markup=kb.greet_kb1)

Очевидно, так как у нас нет обработчика обычных сообщений, текст, отправляемый нажатием на эту кнопку, остаётся без ответа. При желании можно добавить функцию эхо из первого урока. А что ещё можно было заметить при использовании этой кнопки? Что она остаётся всё там же, даже если мы после нажатия хотели бы вернуться к привычной клавиатуре. Да, нажать одну кнопку, чтобы переключиться, не сложно. Но если клавиатура в принципе не подразумевает повторного нажатия прямо сейчас? И для этого тоже есть решение:
# keyboards.py greet_kb2 = ReplyKeyboardMarkup( resize_keyboard=True, one_time_keyboard=True ).add(button_hi) # bot.py @dp.message_handler(commands=['hi2']) async def process_hi2_command(message: types.Message): await message.reply("Второе - прячем клавиатуру после одного нажатия", reply_markup=kb.greet_kb2)
Эти параметры можно комбинировать. Вследствие чего мы получили маленькую клавиатуру, которая скрывается после одной отправки. Но пользователь может снова её открыть нажатием на соответствующую кнопку в поле ввода.
Добавляем больше кнопок
Рассмотрим подробно работу встроенных методов для создания более сложных клавиатур, а именно row , insert и add . Создаём кнопки, которые мы сможем использовать повторно и генерируем несколько разных клавиатур:
button1 = KeyboardButton('1️⃣') button2 = KeyboardButton('2️⃣') button3 = KeyboardButton('3️⃣') markup3 = ReplyKeyboardMarkup().add( button1).add(button2).add(button3) markup4 = ReplyKeyboardMarkup().row( button1, button2, button3 ) markup5 = ReplyKeyboardMarkup().row( button1, button2, button3 ).add(KeyboardButton('Средний ряд')) button4 = KeyboardButton('4️⃣') button5 = KeyboardButton('5️⃣') button6 = KeyboardButton('6️⃣') markup5.row(button4, button5) markup5.insert(button6)
Важно: сейчас мы отталкиваемся от того, что клавиатура по умолчанию имеет 3 кнопки в ряд. О том, как изменить это значение, будет в примере с инлайн клавиатурами - этот параметр идентичен для обоих видов.
- Метод add принимает в себя любое количество кнопок, всегда начинает добавление с новой строки и переносит ряд при достижении значения установленной ширины.
- Метод row тоже принимает любое количество, но при этом не переносит кнопки на новый ряд, а добавляет всё полученное в одну строчку.
- Метод insert работает по схеме схожей с add , но только начинает добавлять к последнему ряду. И только если там уже достигнута максимальная ширина, начинает новую строку. Взглянем на него ещё раз при создании следующей клавиатуры.
Отправляем все готовые кнопки и смотрим на результат:
@dp.message_handler(commands=['hi3']) async def process_hi3_command(message: types.Message): await message.reply("Третье - добавляем больше кнопок", reply_markup=kb.markup3)

@dp.message_handler(commands=['hi4']) async def process_hi4_command(message: types.Message): await message.reply("Четвертое - расставляем кнопки в ряд", reply_markup=kb.markup4)

@dp.message_handler(commands=['hi5']) async def process_hi5_command(message: types.Message): await message.reply("Пятое - добавляем ряды кнопок", reply_markup=kb.markup5)

Думаю, здесь достаточно наглядно видно работу методов добавления кнопок в разметку.
И последнее по этому виду клавиатур. ReplyKeyboardMarkup позволяет запросить у пользователя его контакт или локацию. Это те самые два исключения из правила, когда при нажатии кнопки будет отправлено не то, что написано на ней. Их можно отправлять как по одной, так и в составе более сложной клавиатуры. Добавим обе кнопки и посмотрим, что будет (обращу внимание читателя на то, что нельзя одной кнопкой запросить сразу и то и то):
# keyboards.py markup_request = ReplyKeyboardMarkup(resize_keyboard=True).add( KeyboardButton('Отправить свой контакт ☎️', request_contact=True) ).add( KeyboardButton('Отправить свою локацию ️', request_location=True) ) #bot.py @dp.message_handler(commands=['hi6']) async def process_hi6_command(message: types.Message): await message.reply("Шестое - запрашиваем контакт и геолокацию\nЭти две кнопки не зависят друг от друга", reply_markup=kb.markup_request)
При нажатии на каждую из этих кнопок клиент (приложение Телеграм) спросит, уверены ли вы, что хотите поделиться с ботом этими данными и при утвердительном ответе отправит их.

Рассмотрим подробнее последний метод для составления клавиатур - insert . Он похож на метод add , но начинает добавлять кнопки не с нового ряда, а сначала проверяет, заполнен ли до конца последний ряд. И если нет, то сначала добавляет кнопки туда, а переносит строку только при достижении указанного лимита.
# keyboards.py markup_big = ReplyKeyboardMarkup() markup_big.add( button1, button2, button3, button4, button5, button6 ) markup_big.row( button1, button2, button3, button4, button5, button6 ) markup_big.row(button4, button2) markup_big.add(button3, button2) markup_big.insert(button1) markup_big.insert(button6) markup_big.insert(KeyboardButton('9️⃣')) # bot.py @dp.message_handler(commands=['hi7']) async def process_hi7_command(message: types.Message): await message.reply("Седьмое - все методы вместе", reply_markup=kb.markup_big)
После каждой отправки ботом пользователю клавиатуры, последняя заменяет предыдущую. Поэтому пользователь всегда может открыть её, даже когда по контексту она не нужна. Для того, чтобы у пользователя в клиенте клавиатура убралась совсем, нужно отправить ему ReplyKeboardRemove :
@dp.message_handler(commands=['rm']) async def process_rm_command(message: types.Message): await message.reply("Убираем шаблоны сообщений", reply_markup=kb.ReplyKeyboardRemove())
Получив сообщение с такой клавиатурой, клиент уберёт шаблоны полностью.
Инлайн клавиатуры
Теперь перейдем к инлайн клавиатурам. Они имеют больше параметров, поэтому позволяют нам делать больше разных вещей. Самое популярное использование — как кнопка, являющаяся шорткатом для какого-то действия. То есть «если пользователь нажал кнопку X, сделать Y». И под Y можно понимать вообще что угодно, так как это уже не ограничивается даже API. Рассмотрим наглядно, для этого передадим в инициализатор значение callback_data :
# keyboards.py inline_btn_1 = InlineKeyboardButton('Первая кнопка!', callback_data='button1') inline_kb1 = InlineKeyboardMarkup().add(inline_btn_1) #bot.py @dp.message_handler(commands=['1']) async def process_command_1(message: types.Message): await message.reply("Первая инлайн кнопка", reply_markup=kb.inline_kb1)
Нажимаем кнопку и.. ничего не происходит! Почему? Если у бота было включено логгирование, то вы могли заметить, что приходит обновление типа CallbackQuery . Так вот именно его нам и нужно отлавливать. Добавляем нужный хэндлер (я предпочитаю ставить их выше, но относительно хэндлеров обычных сообщений значения это не имеет):
@dp.callback_query_handler(func=lambda c: c.data == 'button1') async def process_callback_button1(callback_query: types.CallbackQuery): await bot.answer_callback_query(callback_query.id) await bot.send_message(callback_query.from_user.id, 'Нажата первая кнопка!')
Здесь мы делаем проверку прямо в хэндлере. Аргумент func ожидает функцию, которая принимает один параметр (туда передаётся апдейт), и хэндлер срабатывает, если возвращается истина. Этот аргумент можно использовать и в других хэндлерах, мы уже использовали его в уроке по FSM.
Внутри мы можем делать вообще что угодно, так как работаем с обычным питоном. Подача корма для кошки? Управление светом? Пределом является только ваша фантазия.
Хорошим тоном будет отвечать на все колбеки - для этого есть метод answerCallbackQuery . В документации сказано, что ответ ожидается клиентом, и дать его нужно обязательно, даже если вы не собираетесь передавать что-либо. Этого времени предостаточно, чтобы собрать необходимые данные и прислать их. При этом во время ожидания на кнопке будут крутиться часики, показывающие, то клиент ждёт ответа, поэтому если мы не хотим, чтобы пользователь наблюдал их, то нужно не забывать отвечать. Обязательный аргумент - айди запроса, на который мы отвечаем. Остальные параметры рассмотрим ниже. А в данном случае мы для наглядности отправим сообщение с информацией о том, что нажата первая кнопка. Запускаем снова, жмём кнопку и таки получаем ответ:

В этот раз установим ширину клавиатуры 2 и посмотрим, что будет.
Ну и так как методы добавления новых элементов мы уже разобрали, добавим сразу все доступные кнопки и отправим получившуюся клавиатуру, не забыв добавить хэндлер кнопок:
# keyboards.py inline_kb_full = InlineKeyboardMarkup(row_width=2).add(inline_btn_1) inline_kb_full.add(InlineKeyboardButton('Вторая кнопка', callback_data='btn2')) inline_btn_3 = InlineKeyboardButton('кнопка 3', callback_data='btn3') inline_btn_4 = InlineKeyboardButton('кнопка 4', callback_data='btn4') inline_btn_5 = InlineKeyboardButton('кнопка 5', callback_data='btn5') inline_kb_full.add(inline_btn_3, inline_btn_4, inline_btn_5) inline_kb_full.row(inline_btn_3, inline_btn_4, inline_btn_5) inline_kb_full.insert(InlineKeyboardButton("query=''", switch_inline_query='')) inline_kb_full.insert(InlineKeyboardButton("query='qwerty'", switch_inline_query='qwerty')) inline_kb_full.insert(InlineKeyboardButton("Inline в этом же чате", switch_inline_query_current_chat='wasd')) inline_kb_full.add(InlineKeyboardButton('Уроки aiogram', url='https://surik00.gitbooks.io/aiogram-lessons/content/')) # bot.py @dp.callback_query_handler(func=lambda c: c.data and c.data.startswith('btn')) async def process_callback_kb1btn1(callback_query: types.CallbackQuery): code = callback_query.data[-1] if code.isdigit(): code = int(code) if code == 2: await bot.answer_callback_query(callback_query.id, text='Нажата вторая кнопка') elif code == 5: await bot.answer_callback_query( callback_query.id, text='Нажата кнопка с номером 5.\nА этот текст может быть длиной до 200 символов ', show_alert=True) else: await bot.answer_callback_query(callback_query.id) await bot.send_message(callback_query.from_user.id, f'Нажата инлайн кнопка! code=') @dp.message_handler(commands=['2']) async def process_command_2(message: types.Message): await message.reply("Отправляю все возможные кнопки", reply_markup=kb.inline_kb_full)

Пройдёмся по строчкам по порядку, чтобы не осталось вопросов:
- мы создаём клавиатуру типа InlineKeyboardMarkup , указываем, что ширина строки должна быть не больше двух (напомню, что это не распространяется на метод row ) и сразу добавляем туда уже готовую кнопку
- далее добавляем кнопку, у которой указываем другие данные в параметре callback_data
- следом генерируем три новые кнопки и добавляем их дважды. Сначала методом add , затем через row . И так как ширина клавиатуры равна двум, то в первом случае происходит перенос третьей кнопки, во втором случае нет
- затем добавляем кнопки, у которых указываем уже не callback_data , а другие параметры. То, что мы добавим в switch_inline_query , будет автоматически использовано при нажатии кнопки: пользователю предложат выбрать чат, а там вызовется инлайн режим этого бота (в поле ввода сообщения добавится юзернейм бота), следом через пробел будет прописано то, что мы указали. Параметр может принимать пустую строку, тогда инлайн режим запустится без какого-либо запроса, но если будет указан текст, то он и добавится
- при использовании switch_inline_query_current_chat произойдёт ровно то же, что и в предыдущем пункте, но без выбора чата, а запустится в текущем (было сложно догадаться по названию, я знаю)
- ну и последний параметр url - добавляем ссылку на внешний ресурс, либо диплинк в самом Телеграме
Так как параметр клавиатуры row_width равен двум, то кнопки автоматически расставились соответствующе. Рассмотрим реакцию на кнопки по порядку: При нажатии первой срабатывает наш первый колбек, так как не важно, в какую клавиатуру добавлена кнопка, важно, какая у неё callback_data ☝️. Поэтому добавлять инлайн кнопку можно сколько угодно раз в любые инлайн клавиатуры.
Кнопки со второй по пятую имеют схожую структуру в callback_data , поэтому внутри хэндлера проверяем, какой код у нажатой кнопки и:
- если 2, то отвечаем на запрос и передаем информационное сообщение. Аргумент text это текст ответа на запрос. По умолчанию он будет показан вверху чата и сам скроется через пару секунд.
- если 5, то отвечаем так же, но указываем show_alert=True , таким образом мы сообщаем клиенту, что нужно показать окошко с текстом
- в ином случае просто отвечаем на колбек
И во всех случаях шлем сообщение пользователю:

Ещё можно отправить кнопку с игрой или платежом, но первое мы разберем в одном из следующих уроков, а о втором я уже упоминал в одном из предыдущих. При ответе на колбек можно ещё передать в ответ ссылку формата t.me/your_bot?start=XXXX , чтобы пользователь запустил вашего бота с определенным параметром, но диплинкинг мы тоже оставим для другого урока, так как здесь только о кнопках.
На последок не забываем добавить обработку команы /help и запускаем:
help_message = text( "Это урок по клавиатурам.", "Доступные команды:\n", "/start - приветствие", "\nШаблоны клавиатур:", "/hi1 - авто размер", "/hi2 - скрыть после нажатия", "/hi3 - больше кнопок", "/hi4 - кнопки в ряд", "/hi5 - больше рядов", "/hi6 - запрос локации и номера телефона", "/hi7 - все методы" "/rm - убрать шаблоны", "\nИнлайн клавиатуры:", "/1 - первая кнопка", "/2 - сразу много кнопок", sep="\n" ) @dp.message_handler(commands=['help']) async def process_help_command(message: types.Message): await message.reply(help_message) if __name__ == '__main__': executor.start_polling(dp)
Вот и всё!
В этом уроке мы разобрали как работать с клавиатурами в Телеграм
