Callback data telegram что это
Перейти к содержимому

Callback data telegram что это

  • автор:

 

Клавиатура как способ взаимодействия с ботом

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

При открытии бота по умолчанию сразу доступна кнопка Старт, при нажатии, на которую будет начат диалог и в бот будет отправлена команда /start . Уже здесь мы можем поймать эту команду, обработать и выполнить какие-то действия. Вместе с этой командой в бот отправляется минимальная информация о пользователе:

  1. id — уникальный идентификатор пользователя в Telegram
  2. last_name — значение поля фамилия, может быть пустым
  3. first_name — значение поля имя, может быть пустым
  4. username — уникальное значение текстовый идентификатор, может быть пустым
  5. language_code — кодовое обозначение выбранного языка интерфейса приложения (en, ru . )
  6. is_bot — флаг, определяющий пользователя как бота, в случае с ботом равен 1, в случае с пользователем пустое значение

Полезный инструмент

У каждого бота есть ссылка, которая открывает диалог с ним в Telegram — https://telegram.me/ИМЯ_БОТА. К этой ссылке можно добавить параметры start или startgroup со значениями. Значение может быть длиной от 1 до 64 символов и состоять из букв латинского алфавита (больших — A-Z и маленьких — a-z), цифр — 0-9, нижнего подчеркивания _ и тире -.

Telegram Bot API рекомендует использовать base64url для кодирования параметров с двоичным и другими типами контента.

По ссылке с параметром start будет открыт диалог с ботом, с кнопкой Старт в месте поля ввода. Если используется параметр startgroup, пользователю будет предложено выбрать группу для добавления бота.

Как только пользователь подтвердит действие (нажмет кнопку Пуск в своем приложении или выберет группу для добавления бота), ваш бот получит сообщение от этого пользователя в таком формате:

Для удобства пользователя, можно через настройки Commands вашего бота у @BotFather, задать список поддерживаемых ботом команд. Тогда при вводе знака слеш / , пользователь увидит все команды и сможет сразу их отправить, просто нажав на одну из них. Каждая команда состоит из собственно командного слова, начинающегося со слеша и короткого описания:

Клавиатуры и их возможности

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

В этом случае нам помогут клавиатуры. Ее нужно просто после старта диалога с ботом вывести на экран пользователю, и когда тот нажмет на нужную ему кнопку, боту отправиться заложенная вами правильная команда. В этом случае уходим от возможных ошибок, интерфейс бота выглядит более приветливо и профессионально. Качество бота повышается.

С каждым сообщением бот может отправлять разный набор кнопок как по количеству, так и по назначению. Кнопки можно расположить непосредственно под сообщением (InlineKeyboardButton), или зафиксировать под тестовым полем для ввода сообщения (KeyboardButton). Различия в них очень существенные на мой взгляд. Давайте рассмотрим некоторые их возможности.

KeyboardButton

Этот объект представляет одну кнопку клавиатуры, располагающуюся под текстовым полем для отправки сообщения. Поставляется она в интерфейс приложения в наборе с другими аналогичными кнопками через объект ReplyKeyboardMarkup. В качестве параметров с ним можно передать:

  1. text — текст который будет на отображен на кнопке, обязательный параметр, поддерживает текст и смайлики (эмодзи)
  2. request_contact — если параметр установлен в true, пользователь отправит в бот свой номер телефона на который зарегистрирован аккаунт
  3. request_location — если параметр установлен в true, пользователь отправит в бот свое текущее местоположение

Если будет заполнен только обязательный параметр text, то при нажатии на кнопку будет отправлено текстовое сообщение с содержанием из этого параметра. Если будет включено дополнительно одно из необязательных параметров или локация, или контакт, то будет отправлен или контакт, или локация соответственно. Необязательные параметры взаимоисключающие.

Помимо набора кнопок в объект ReplyKeyboardMarkup можно передать еще ряд параметров:

  1. keyboard — массив кнопок (объекты KeyboardButton)
  2. resize_keyboard — если предать true, то клавиатура подгонится по высоте до возможного минимума.
  3. one_time_keyboard — возможность скрывать клавиатуру после ее использования
  4. selective — если надо показать клавиатуру только определенным пользователям

При необходимости удалить клавиатуру используйте объект ReplyKeyboardRemove.

InlineKeyboardButton

Это объект одной кнопки встроенной клавиатуры. Располагается набор таких кнопок сразу под сообщением. С помощью этого объекта можно передать кнопке url, или использовать его для голосования как одним из вариантов. В любом случае можно сделать много интересного и полезного. Рассмотрим его возможности на практике чуть ниже. Передается в наборе с другими аналогичными кнопками через объект InlineKeyboardMarkup. Принимает параметры:

  1. text — текст который будет на отображен на кнопке, обязательный параметр, поддерживает текст и смайлики (эмодзи)
  2. url — адрес на который будет направлен пользователь
  3. callback_data — строка 1-64 символа будет передан боту через объект CallbackQuery
  4. switch_inline_query — после нажатия будет предложен выбор чата где будет использован бот во встроенном режиме, пример @gif dog
  5. switch_inline_query_current_chat — после нажатия вставит команду для использования бота во встроенном режиме в текущем чате
  6. callback_game — описание игры, которая будет запущена при нажатии пользователем кнопки.
  7. pay — кнопка будет использована как кнопка оплаты

Теперь немного практики

Предлагаю рассмотреть поближе возможности клавиатур. Для примера я сделаю 4 кнопки: 2 KeyboardButton и 2 InlineKeyboardButton. Для этого будем работать с теми же инструментами, которые были в предыдущей статье. Добавим только несколько новых методов.

Логика скрипта будет простая, при старте бот будет выводить сообщение о готовности и 2 кнопки Голосовать и Помощь. При нажатии на кнопку Помощь — выведется сообщение с небольшой инструкцией, а при нажатии на кнопку Голосовать на экране появиться сообщение и под ним 2 кнопки, при нажатии на которые произойдет увеличения счетчика.

Чтобы обрабатывать команды от всех типов кнопок нам надо составить условия проверки. В моем примере от кнопки KeyboardButton команда приходит в виде обычного текстового сообщения вместе с объектом Message под ключом text, а от кнопки InlineKeyboardButton в объекте CallbackQuery под ключом data.

Кнопки будем отправлять в параметре reply_markup в методе sendMessage. Набор кнопок идет в таком формате:

Создадим два метода для разных клавиатур, на входе принимают массив строк кнопок, на выходе строку в формате JSON.

Сам набор кнопок будет выглядеть вот так.

Во встроенных кнопках (inlineKeyboardButton) в качестве значения параметра callback_data будем передавать служебную информацию в виде action_type_count1_count2 , где

  1. action — действие, в нашем случае это vote
  2. type — тип кнопки: 1 — левая, 0 — правая
  3. count1 — текущее значение левой кнопки
  4. count2 — текущее состояние правой кнопки

В значении параметра text передаем бинарный код эмодзи в кодировке UTF-8 (список эмодзи), которые преобразуются из шестнадцатеричных данных в двоичные данные функцией hex2bin, и еще выведем текущее числовое значение счетчика кнопки.

Теперь нам остается только описать механизм определения команды и механизм ее обработки. Поэтому в методе init() создадим конструкцию оператора switch

Давайте разберемся, что в этом коде происходит. Оператор switch принимает значение $message, которое может быть, как просто текст сообщения (в том числе команды), так и значение объекта callbackQuery.

  1. При получении команды /start — мы выводим приветственное слово и набор кнопок: Голосовать, Помощь.
  2. При получении команды Помощь, выводим простое текстовое сообщение.
  3. При получении команды Голосовать, выводим текстовое сообщение и набор встроенных кнопок с параметром callback_data.
  4. При получении не запланированного значения, выводим текстовое сообщение.
  5. И самое интересное это когда принимаем значение в начале которого стоит action , в нашем случае это vote. Мы формируем новую клавиатуру изменяем в ней текстовое значение, увеличиваем счетчик у нажатой кнопки и подставляем новую служебную информацию в параметрах callback_data.

Для создания новой клавиатуры мы используем метод setParams(), а для отправки изменений мы используем метод changeVote(). Здесь остановим внимание на методах Bot API

    — меняем клавиатуру у заданного сообщения — позволяет выводить уведомление о проделанной работе CallbackQuery, мы его используем, уведомляя пользователя что он удачно проголосовал.

Подводим итоги

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

Комментарии

Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте бот @SiteAuthBot, нажмите кнопку Старт/Start. Следуйте инструкциям бота.

Внимание!
Убедитесь, что эта страница открыта в браузере, а не в приложении Telegram. В противном случае авторизация пройдет только в приложении Telegram.

30 in лучше выводить с постраничной навигацией по 10 шт например, у Телеграм если не ошибаюсь установлено ограничение. У меня была ситуация, когда на 32 строке кнопок был косяк, но постраничка решила проблему.

А вывести не сложно если из базы получить массив то стандартными функциями (foreach, for, do while . ) php можно спокойно это сделать.

что нужно дописать этому боту сюда-

чтобы он вел лог отдельно для кажлого чайт айди в папке log ?

Например если вы переходите по ссылке https://t.me/your_bot/start=123456789

Значение будет лежать:
1. Если приводить к объекту json_decode(file_get_contents(‘php://input’))->message->text
2. Если приводить к ассоциативному массиву json_decode(file_get_contents(‘php://input’), true)[‘message’][‘text’]

Это значение будет /start 123456789

ТАК я формирую ссылку

но когда я перехожу по ссылке мне выдает ошибку

Старт выглядит также как у вас

1. Просьба оформить топик на форуме все еще актуальна.
2. У вас нет необходимого case поэтому условие проваливается в default, обратите внимание я вам выше писал, какое значение вам будет прилетать /start 123456789, где 123456789 в вашем случае это подставленный $chat_id

Кнопки¶

В этой главе мы познакомимся с такой замечательной фичей Telegram-ботов, как кнопки. Прежде всего, чтобы избежать путаницы, определимся с названиями. То, что цепляется к низу экрана вашего устройства, будем называть обычными кнопками, а то, что цепляется непосредственно к сообщениям, назовём инлайн-кнопками. Ещё раз картинкой:

Обычные кнопки¶

Кнопки как шаблоны¶

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

Напишем хэндлер, который будет при нажатии на команду /start отправлять сообщение с двумя кнопками:

Несмотря на то, что Telegram Bot API допускает указывать просто строки вместо объектов KeyboardButton , при попытке использовать строку aiogram 3.x выкинет ошибку валидации и это не баг, а фича.
Живите теперь с этим ��‍♂️

Что ж, запустим бота и обалдеем от громадных кнопок:

Как-то некрасиво. Во-первых, хочется сделать кнопки поменьше, а во-вторых, расположить их горизонтально.
Почему вообще они такие большие? Дело в том, что по умолчанию «кнопочная» клавиатура должна занимать на смартфонах столько же места, сколько и обычная буквенная. Для уменьшения кнопок к объекту клавиатуры надо указать дополнительный параметр resize_keyboard=True .
Но как заменить вертикальные кнопки на горизонтальные? С точки зрения Bot API, клавиатура — это массив массивов кнопок, а если говорить проще, массив рядов. Перепишем наш код, чтобы было красиво, а для пущей важности добавим параметр input_field_placeholder , который заменит текст в пустой строке ввода, когда активна обычная клавиатура:

Смотрим — действительно красиво:

Осталось научить бота реагировать на нажатие таких кнопок. Как уже было сказано выше, необходимо делать проверку на полное совпадение текста. Сделаем это двумя способами: через специальный фильтр Text и обычной лямбдой (лямбду постараемся далее не использовать, в последующих главах её можно будет заменить на немного магии):

Чтобы удалить кнопки, необходимо отправить новое сообщение со специальной «удаляющей» клавиатурой типа ReplyKeyboardRemove . Например: await message.reply(«Отличный выбор!», reply_markup=types.ReplyKeyboardRemove())

 

Keyboard Builder¶

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

  • add(<KeyboardButton>) — добавляет кнопку в память сборщика;
  • adjust(int1, int2, int3. ) — делает строки по int1, int2, int3. кнопок;
  • as_markup() — возвращает готовый объект клавиатуры;
  • button(<params>) — добавляет кнопку с заданными параметрами, тип кнопки (Reply или Inline) определяется автоматически.

Создадим пронумерованную клавиатуру размером 4×4:

У объекта обычной клавиатуры есть ещё две полезных опции: one_time_keyboard для автоматического скрытия кнопок после нажатия и selective для показа клавиатуры лишь некоторым участникам группы. Их использование остаётся для самостоятельного изучения.

Специальные обычные кнопки¶

На момент написания этой главы в Telegram существует три специальных вида обычных кнопок, не являющихся обычными шаблонами сообщений. Это кнопки для:

  • отправки текущей геолокации (флаг request_location );
  • отправки своего контакта с номером телефона (флаг request_contact );
  • создания опроса/викторины (объект KeyboardButtonPollType).

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

Впрочем, проще один раз увидеть код:

Инлайн-кнопки¶

URL-кнопки¶

В отличие от обычных кнопок, инлайновые цепляются не к низу экрана, а к сообщению, с которым были отправлены. В этой главе мы рассмотрим два типа таких кнопок: URL и Callback. Ещё один — Switch — будет рассмотрен в главе про инлайн-режим.

Login- и Pay-кнопки в книге рассматриваться не будут вообще. Если у кого-то есть желание помочь хотя бы с рабочим кодом для авторизации или оплаты, пожалуйста, создайте Pull Request на GitHub. Спасибо!

Самые простые инлайн-кнопки относятся к типу URL, т.е. «ссылка». Поддерживаются только протоколы HTTP(S) и tg://

Отдельно остановимся на среднем блоке кода. Дело в том, что в марте 2019 года разработчики Telegram добавили возможность отключать переход к профилю пользователя у пересланного сообщения. При попытке создать URL-кнопку с ID юзера, у которого отключен переход по форварду, бот получит ошибку Bad Request: BUTTON_USER_PRIVACY_RESTRICTED . Соответственно, прежде чем показывать такую кнопку, необходимо выяснить состояние упомянутой настройки. Для этого можно вызвать метод getChat и в ответе проверить состояние поля has_private_forwards . Если оно равно True , значит, попытка добавить URL-ID кнопку приведёт к ошибке.

Колбэки¶

С URL-кнопками больше обсуждать, по сути, нечего, поэтому перейдём к гвоздю сегодняшней программы — Callback-кнопкам. Это очень мощная штука, которую вы можете встретить практически везде. Кнопки-реакции у постов (лайки), меню у @BotFather и т.д. Суть в чём: у колбэк-кнопок есть специальное значение (data), по которому ваше приложение опознаёт, что нажато и что надо сделать. И выбор правильного data очень важен! Стоит также отметить, что, в отличие от обычных кнопок, нажатие на колбэк-кнопку позволяет сделать практически что угодно, от заказа пиццы до запуска вычислений на кластере суперкомпьютеров.

Напишем хэндлер, который по команде /random будет отправлять сообщение с колбэк-кнопкой:

Но как же обработать нажатие? Если раньше мы использовали хэндлер message для обработки входящих сообщений, то теперь будем использовать callback_query_handler для обработки колбэков. Ориентироваться будем на «значение» кнопки, т.е. на её data:

Несмотря на то, что параметр кнопки callback_data , а значение data лежит в одноимённом поле data объекта CallbackQuery, собственный фильтр aiogram называется text .

Ой, а что это за часики? Оказывается, сервер Telegram ждёт от нас подтверждения о доставке колбэка, иначе в течение 30 секунд будет показывать специальную иконку. Чтобы скрыть часики, нужно вызвать метод answer() у колбэка (или использовать метод API answer_callback_query() ). В общем случае, в метод answer() можно ничего не передавать, но можно вызвать специальное окошко (всплывающее сверху или поверх экрана):

В функции send_random_value мы вызывали метод answer() не у message , а у callback.message . Это связано с тем, что колбэк-хэндлеры работают не с сообщениями (тип Message), а с колбэками (тип CallbackQuery), у которого другие поля, и само сообщение — всего лишь его часть. Учтите также, что message — это сообщение, к которому была прицеплена кнопка (т.е. отправитель такого сообщения — сам бот). Если хотите узнать, кто нажал на кнопку, смотрите поле from (в вашем коде это будет callback.from_user , т.к. слово from зарезервировано в Python)

Когда вызывать answer() ?

В общем случае, главное — просто не забыть сообщить Telegram о получении колбэк-запроса, но я рекомендую ставить вызов answer() в самом конце, и вот почему: если вдруг в процессе обработки колбэка случится какая-то ошибка и бот нарвётся на необработанное исключение, пользователь увидит неубирающиеся полминуты часики и поймёт, что что-то не так. В противном случае, часики исчезнут, а пользователь останется в неведении, выполнился его запрос успешно или нет.

Перейдём к примеру посложнее. Пусть пользователю предлагается сообщение с числом 0, а внизу три кнопки: +1, -1 и Подтвердить. Первыми двумя он может редактировать число, а последняя удаляет всю клавиатуру, фиксируя изменения. Хранить значения будем в памяти в словаре (про конечные автоматы поговорим как-нибудь в другой раз).

И, казалось бы, всё работает:

Но теперь представим, что ушлый пользователь сделал следующее: вызвал команду /numbers (значение 0), увеличил значение до 1, снова вызвал /numbers (значение сбросилось до 0) и отредактировал и нажал кнопку «+1» на первом сообщении. Что произойдёт? Бот по-честному отправит запрос на редактирование текста со значением 1, но т.к. на том сообщении уже стоит цифра 1, то Bot API вернёт ошибку, что старый и новый тексты совпадают, а бот словит исключение: Bad Request: message is not modified: specified new message content and reply markup are exactly the same as a current content and reply markup of the message

С этой ошибкой вы, скорее всего, будете поначалу часто сталкиваться, пытаясь редактировать сообщения. Вообще говоря, подобная ошибка часто говорит о проблемах с логикой генерации/обновления данных в сообщении, но иногда, как в примере выше, может быть ожидаемым поведением.

В данном случае проигнорируем ошибку целиком, т.к. нам важен лишь итоговый результат, который точно будет правильным. Ошибка MessageNotModified относится к категории Bad Request, поэтому у нас есть выбор: проигнорировать весь подобный класс ошибок, либо отловить весь класс BadRequest и попытаться по тексту ошибки опознать конкретную причину. Чтобы не слишком усложнять пример, обойдёмся первым способом и немного обновим функцию update_num_text() :

Если теперь вы попробуете повторить пример выше, то указанное исключение в этом блоке кода бот просто-напросто проигнорирует.

Фабрика колбэков¶

Когда вы оперируете какими-то простыми колбэками с общим префиксом, типа order_1 , order_2 . вам может показаться, что довольно легко вызывать split() и делить строку по какому-то разделителю. А теперь представьте, что вам нужно хранить не одно значение, а три: order_1_1994_2731519 . Что здесь артикул, цена, количество? А может быть, тут вообще год выпуска? Да и разбиение строки начинает выглядеть страшно: .split(«_»)[2] . А почему не 1 или 3?

В какой-то момент возникает необходимость структурировать содержимое таких callback data, и в aiogram есть решение! Вы создаёте объекты типа CallbackData , указываете префикс, описываете структуру, а дальше фреймворк самостоятельно собирает строку с данными колбэка и, что важнее, корректно разбирает входящее значение. Снова разберёмся на конкретном примере; создадим класс NumbersCallbackFactory с префиксом fabnum и двумя полями action и value . Поле action определяет, что делать, менять значение (change) или зафиксировать (finish), а поле value показывает, на сколько изменять значение. Оно помечено как Optional[int] , т.к. если action равен «finish», то значение указывать бессмысленно. Код:

Наш класс обязательно должен наследоваться от CallbackData и принимать значение префикса. Префикс — это общая подстрока в начале, по которой фреймворк будет определять, какая структура лежит в колбэке.

Теперь напишем функцию генерации клавиатуры. Здесь нам пригодится метод button() , который автоматически будет создавать кнопку с нужным типом, а от нас требуется только передать аргументы. В качестве аргумента callback_data вместо строки будем указывать экземпляр нашего класса NumbersCallbackFactory :

Методы отправки сообщения и его редактирования оставляем теми же (в названиях и командах добавим суффикс _fab ):

Наконец, переходим к главному — обработке колбэков. Для этого в декоратор надо передать класс, колбэки с которым мы ловим, с вызванным методом filter() . Также появляется дополнительный аргумент с названием callback_data (имя должно быть именно таким!), и имеющим тот же тип, что и фильтруемый класс:

Ещё немного конкретизируем наши хэндлеры и сделаем отдельный обработчик для числовых кнопок и для кнопки «Подтвердить». Фильтровать будем по значению action и в этом нам помогут «магические фильтры» aiogram 3.x. Серьёзно, они так и называются: Magic Filter. Подробнее сие чародейство рассмотрим в другой главе, а сейчас просто воспользуемся «магией» и примем это на веру:

На первый взгляд то, что мы сделали, может показаться сложным, но в действительности фабрика колбэков позволяет создавать продвинутые колбэк-кнопки и удобно дробить код на логические сущности. Увидеть применение фабрики на практике вы можете в боте для игры в «Сапёра», написанным вашим любимым автором 🙂

Callback data telegram что это

Java Telegram Bot Api

Java библиотека, созданная для работы с Telegram Bot API

  • Полная поддержка всех методов BOT API 6.2
  • Поддержка Telegram паспорта и дешифровки (Decryption API);
  • Поддержка платежей; .

Также JAR со всеми зависимостями можно найти в релизах.

Сетевые операции основаны на библиотеке OkHttp.

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

Для получения обновлений вы можете:

  • вызвать метод getUpdates;
  • распарсить входящий запрос по Webhook;
  • установить слушателя для получения обновлений.

Класс Update просто копирует ответ, полученный от Telegram.

Использование метода getUpdates()

Метод getUpdates возвращает 100 самых ранних необработанных обновлений. Для пометки обновления, как обработанного, используйте параметр смещения при вызове getUpdates следующим образом: offset = updateId последнего обработанного обновления + 1
Все обновления, updateId которых меньше, чем смещение, будут помечены на сервере как обработанные и больше не будут возвращаться.

Используя веб хук Вы можете распарсить запрос в Update

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

При этом getUpdates будет выполняться в цикле.

Слушатель должен возвращать id последнего обработанного (подтвержденного) обновления.

  • Для подтверждения обработки всех обновлений используйте UpdatesListener.CONFIRMED_UPDATES_ALL , этого будет достаточно в большинстве случаев;
  • Для того чтобы не подтверждать обработку обновлений, используйте UpdatesListener.CONFIRMED_UPDATES_NONE , эти обновления будут передоставлены;
  • Чтобы установить определенное обновление, как последнее обработанное, возвращайте его updateId.

Для прекращения получения обновлений

Все типы такие же, как и оригинальные. Поля типов — методы в нижнем CamelCase.

 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *