Telegram Боты на Aiogram 3.x: Инлайн кнопки и CallBack Дата

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Приветствую всех! В этой статье мы продолжим исследовать возможности библиотеки Aiogram 3 и рассмотрим тему инлайн кнопок и CallBack данных. На данный момент мы уже:

  • Определились со структурой бота;

  • Настроили нашего Telegram-бота на базе Aiogram 3;

  • Разобрались с командами, включая аргументы, командное меню и фильтры Command и CommandStart;

  • Освоили работу с текстовыми кнопками (в предыдущей публикации я максимально подробно разобрал эту тему);

  • Коснулись магических фильтров и обсудили прочие аспекты взаимодействия с ботом.

После тщательных размышлений я пришёл к выводу, что логичным продолжением будет изучение CallBack хендлеров и CallBack данных. Эти технологии открывают безграничные возможности для создания интерактивных и сложных сценариев взаимодействия с пользователями.

В данной статье мы рассмотрим:

  • Что такое CallBack хендлеры;

  • Разновидности CallBack хендлеров (ссылки, веб-приложения, обычные CallBack данные);

  • Научимся создавать более сложные конструкции через магические фильтры в контексте CallBack.

  • Поработаем с библиотекой Faker

  • Напишем функцию по генерации случайного пользователя и коснемся темы форматирования сообщений

  • Я покажу вам как работает имитация действий в боте (будем имитировать набор текста ботом)

Приступим к углубленному изучению этих аспектов и постараемся максимально использовать возможности, которые предоставляет нам библиотека Aiogram 3.

Что такое CallBack в Aiogram 3

CallBack в Aiogram 3 — это способ обработки взаимодействий пользователей с ботом, когда они нажимают на инлайн кнопки. Когда пользователь нажимает на такую кнопку, бот получает специальное сообщение — CallBack, с информацией о том, какую кнопку нажали. Эта информация называется CallBack дата.

Проще говоря, CallBack позволяет боту реагировать на нажатия инлайн кнопок, выполняя определённые действия в ответ на это. Это очень удобно для создания интерактивных и динамических ботов, которые могут менять своё поведение в зависимости от выбора пользователя.

CallBack кнопки могут работать, как в формате текстовых кнопок. Это когда текст на кнопке равняется той информации (CallBack дате), которую пользователь передает боту. Бывает полезным, например, если в вашем боте нет текстовых клавиатур (в рамках общего стиля например), а есть только InlineKeyboard. В таком случае можно, к примеру, в инлайн кнопку Home передать CallData home, но обычно в практике обычно CallBack дата кардинально отличается от надписи на кнопке.

Сейчас я дам пару текстовых примеров из моей реальной практики, чтобы стало более понятно, а после приступим к написанию кода.

Например, у вас бот службы поддержки (порядка 5-6 проектов разной сложности делал в формате «support bot»). Пользователь отправляет некое сообщение в бота, бот перехватывает это сообщение, параллельно захватив телеграмм айди пользователя (в прошлой статье я показывал как достать телеграмм айди из объекта message).

Далее он отправляет это сообщение менеджерам службы поддержки с инлайн кнопкой «Ответить». Менеджер нажимает на эту кнопку, и бот ждёт ответного сообщения (подробнее рассмотрим в теме FSM). И тут основная фишка в том, что кликнув на кнопку «Ответить», менеджер не просто запускает сценарий ответа на сообщение, но и сразу указывает боту, что этот ответ должен полететь конкретному пользователю (хотите статью о том, как написать простую службу поддержки?). В данном случае бот достает телеграмм айди пользователя из CallData (сегодня мы сделаем нечто похожее).

Другой пример (тоже из службы поддержки):

В ботах периодически бывают так называемые FAQ (разделы с часто задаваемыми вопросами). Был опыт, когда я в админ панели прописывал функционал, позволяющий захватить вопрос и ответ на него (FSM), далее это всё записывалось в базу данных под определённым айдишником.

После, когда пользователь заходит в раздел FAQ, бот отправляет запрос в базу данных и при помощи генератора инлайн кнопок (InlineKeyboardBuilder по типу такого же как для текстовых кнопок) происходит генерация клавиатуры с вопросом и ответом.

Далее боту достаточно всего одного хендлера для того чтобы массово обрабатывать сразу все ответы на любые вопросы. Ниже пример реализации:

@qst_router.callback_query(F.data.startswith('qst_'))
async def cmd_start(call: CallbackQuery, state: FSMContext):
    await state.clear()
    await call.answer()
    qst_id = int(call.data.replace('qst_', ''))
    async with ChatActionSender(bot=bot, chat_id=call.from_user.id, action="typing"):
        info = await pg_db.select_data('questions', {'where_conditions': [{'id': qst_id}]})
        await call.message.answer(info.get('answer'), reply_markup=main_kb(call.from_user.id))

Сильно не вдавайтесь сейчас в подробности кода, в будущих статьях я вас научу делать каждую реализацию. Тут просто смысл в демонстрации мощи CallBackData — буквально пару строк кода способны закрыть огромный блок FAQ (масштабирование, по сути, неограниченное).

Ну ладно, я могу очень долго говорить про CallBack, так как технология, по моему мнению, шикарная. Если сейчас пока не понятно что к чему – не переживайте. Дочитав эту статью, вы точно разберётесь с темой CallBack.

Приступаем к коду.

Код я буду писать в том же проекте, что и писал в прошлых статьях (если хотите такой же шаблон как у меня – читайте первую статью по теме aiogram – там я подробно расписал свой каркас бота стартового).

Давайте в нашем пакете keyboards создадим новый файл под Inline клавиатуры и дадим ему название inline_kbs.py:

В него сразу импортируем следующие модули:

from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo
from aiogram.utils.keyboard import InlineKeyboardBuilder

Импортируемые модули в файле inline_kbs.py

  1. from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo

    • InlineKeyboardMarkup: Этот класс используется для создания разметки инлайн клавиатуры. Разметка определяет, как будут располагаться кнопки на клавиатуре и как они будут взаимодействовать с пользователем.

    • InlineKeyboardButton: Этот класс представляет собой отдельную кнопку на инлайн клавиатуре. С помощью него мы можем задавать текст кнопки и действие, которое произойдет при нажатии на неё, например, отправку CallBack данных.

    • WebAppInfo: Этот класс используется для создания кнопок, которые открывают веб-приложения внутри Telegram (тема заслуживает отдельного большого обсуждения, так что далее просто покажу, что оно существует). С его помощью можно определить URL веб-приложения, которое будет открыто при нажатии на кнопку. Это полезно для интеграции внешних веб-сервисов и приложений с ботом.

  2. from aiogram.utils.keyboard import InlineKeyboardBuilder

    • InlineKeyboardBuilder: Это удобный инструмент для построения инлайн клавиатур. С его помощью можно легко и быстро создавать клавиатуры, добавляя кнопки и определяя их расположение. Этот класс помогает упрощать процесс создания сложных разметок клавиатур, делая код более читаемым и удобным для поддержки. Работает похожим образом с ReplyKeyboardBuilder, но со своими особенностями, о которых мы сегодня поговорим.

Инлайн клавиатура со ссылками

def ease_link_kb():
    inline_kb_list = [
        [InlineKeyboardButton(text="Мой хабр", url='https://habr.com/ru/users/yakvenalex/')],
        [InlineKeyboardButton(text="Мой Telegram", url='tg://resolve?domain=yakvenalexx')],
        [InlineKeyboardButton(text="Веб приложение", web_app=WebAppInfo(url="https://tg-promo-bot.ru/questions"))]
    ]
    return InlineKeyboardMarkup(inline_keyboard=inline_kb_list)

Объяснение кода:

  1. Определение функции ease_link_kb():

    • Функция ease_link_kb предназначена для создания и возвращения инлайн клавиатуры с кнопками, которые ведут к различным ссылкам различных типов.

  2. Создание списка кнопок inline_kb_list:

    • Внутри функции создаётся список inline_kb_list, который содержит вложенные списки с объектами InlineKeyboardButton. Каждая вложенная структура представляет собой отдельную строку кнопок на инлайн клавиатуре.

  3. Кнопка с ссылкой на мой аккаунт в Хабре:

    • [InlineKeyboardButton(text="Мой хабр", url='https://habr.com/ru/users/yakvenalex/')]:

      • Создаётся кнопка с текстом "Мой хабр", которая при нажатии перенаправляет пользователя на страницу Хабра.

  4. Кнопка с ссылкой на мой Telegram аккаунт:

    • [InlineKeyboardButton(text="Мой Telegram", url='tg://resolve?domain=yakvenalexx')]:

      • Создаётся кнопка с текстом "Мой Telegram", которая при нажатии открывает Telegram и переходит к моему аккаунту.

  5. Кнопка для открытия веб-приложения:

    • [InlineKeyboardButton(text="Веб приложение", web_app=WebAppInfo(url="https://tg-promo-bot.ru/questions"))]:

      • Создаётся кнопка с текстом "Веб приложение", которая при нажатии открывает веб-приложение по указанному URL.

  6. Возвращение инлайн клавиатуры:

    • return InlineKeyboardMarkup(inline_keyboard=inline_kb_list):

      • Функция возвращает объект InlineKeyboardMarkup, который содержит разметку инлайн клавиатуры с указанными кнопками.

Этот пример демонстрирует, как создавать инлайн клавиатуру с различными типами ссылок, включая обычные URL, ссылки на аккаунты в Telegram и веб-приложения. Давайте тестировать.

Для тестов я предлагаю создать новый message handler, который будет вызываться текстом «Давай инлайн!». К нему прикрутим нашу инлайн клавиатуру и поклацаем ее.

@start_router.message(F.text == 'Давай инлайн!')
async def get_inline_btn_link(message: Message):
    await message.answer('Вот тебе инлайн клавиатура со ссылками!', reply_markup=ease_link_kb())

Думаю, что к настоящему моменту вы уже понимаете, что тут мы использовали магический фильтр F.text, который будет срабатывать на отправку текста 'Давай инлайн!', а чтоб было ещё интересней давайте мы создадим текстовую кнопку с текстом 'Давай инлайн!', а саму кнопку привяжем к главной клавиатуре (это вы уже умеете делать, если нет, то читайте прошлую статью).

Так теперь выглядит моя главная клавиатура
Так теперь выглядит моя главная клавиатура
Так выглядит инлайн клавиатура со ссылками
Так выглядит инлайн клавиатура со ссылками

Давайте теперь изучать каждую кнопку-ссылку:

После клика на обычную кнопку-ссылку появляется окно которое спрашивает хотим ли мы перейти по ссылке.

Хотите?
Хотите?

После клика на ссылку с моим профилем Telegram происходит переход без окна в мой профиль. До недавнего времени только ссылки формата «tg://resolve?domain=yakvenalexx» позволяли переходить в профиль без окна, но, при написании этого текста обнаружил что и при формате ссылки «https://t.me/yakvenalexx» окно не появлялось.

Теперь к интересному моменту ВЕБ-ПРИЛОЖЕНИЕ:

После клика по инлайн кнопке с «квадратиком» телеграмм отправит нам такое сообщение:

И это чистая правда. После эту информацию можно использовать
И это чистая правда. После эту информацию можно использовать
Пример простого приложения
Пример простого приложения

А после откроется то ВЕБ-ПРИЛОЖЕНИЕ, которое я создал. С ПК версии, возможно не так наглядно как с телефона. Сейчас продемонстрирую.

Анимированные кнопки
Анимированные кнопки

Обратите внимание на интерактивность. Веб-приложение становится, как бы, частью телеграмм бота, тем самым открывая неограниченные возможности. Вот так, например, я прописывал специальную анкету в одном из своих ботов:

Как я говорил выше – все это тема отдельной статьи. Может как-то обсудим.

Итак, к промежуточным выводам. Мы разобрали все варианты инлайн-клавиатур ссылок, а это значит, что можем переходить к более интересной части – CallBack Data!

Начнем с простой клавиатуры. Пускай в ней будет 2 инлайн-кнопки. Одна кнопка должна переводить пользователя на стартовый экран, а вторая запускает некое действие, например, выводит информацию о случайном пользователе (первое, что пришло в голову).

Для этого нам нужно подготовиться.

Сначала напишем функцию, которая будет генерировать информацию о случайном пользователе. Для этого воспользуемся интересной библиотекой Faker (возьмите её на заметку, часто пригождается).

Устанавливаем библиотеку:

pip install faker

Пишем функцию, которая будет генерировать случайного пользователя (как раз наш пакет с утилитами тут будет кстати).

Пишем код:

from faker import Faker

def get_random_person():
    # Создаем объект Faker с русской локализацией
    fake = Faker('ru_RU')

    # Генерируем случайные данные пользователя
    user = {
        'name': fake.name(),
        'address': fake.address(),
        'email': fake.email(),
        'phone_number': fake.phone_number(),
        'birth_date': fake.date_of_birth(),
        'company': fake.company(),
        'job': fake.job()
    }
    return user

Тут все достаточно просто. Импортируем модуль. При инициализации объекта fake укажем, что нас интересуют русские данные. Далее создадим простой словарь и захватим в него следующие данные: имя, адрес, email, телефон, дата рождения, компания и работа.

Далее мы напишем специальный хендлер, который при получении CallData «get_person» будет возвращать хорошо оформленное сообщение с информацией о пользователе (как раз немного углубим свои знания в теме форматирования текста в aiogram 3).

Сначала импортируем функцию для генерации случайного пользователя из пакета utils и CallbackQuery для удобства аннотаций.

from utils.utils import get_random_person
from aiogram.types import CallbackQuery

Теперь напишем сам хендлер. Я его пропишу полностью, а дальше дам объяснения.

@start_router.callback_query(F.data == 'get_person')
async def send_random_person(call: CallbackQuery):
    # await call.answer('Генерирую случайного пользователя')
    user = get_random_person()
    formatted_message = (
        f"						
Источник: https://habr.com/ru/articles/820877/


Интересные статьи

Интересные статьи

Hibernate — очень мощный и функциональный ORM (Object-Relational Mapping) фреймворк. Он связывает базы данных с помощью объектно-ориентированных языков программирования. Однако многие, начиная с ним р...
Исследовательский институт Toyota (TRI) объявил о революционном подходе к генеративному искусственному интеллекту, позволяющем обучать роботов новым навыкам за несколько часов.
Всем привет!В этой статье поделюсь своим опытом прохождения собеседований на позицию System analyst и как к ним подготовиться.Предыстория: на текущий момент самой подходящей для меня страной является ...
Иногда прогресс идёт слишком быстро и при этом одновременно слишком медленно. Насмотревшись на чудеса технологий и сравнив их с тем, что было десять лет назад, человек начинает представлять. Что уж ...
Всем привет. С вами я, stalker320, и сегодня я хотел бы рассказать про написание служебных скриптов, запускающихся в редакторе. Всем желающим прочесть - добро пожаловать под кат. ...