Как сделать клавиатуру в телеграмм боте
ReplyKeyboard — это обычная клавиатура с кнопками которая располагается в чате Telegram внизу окна.
Импортируем модуль разметки клавиатуры ReplyKeyboardMarkup и создадаем клавиатуру.
Разметка клавиатуры (меню) — это просто список в списке с названием кнопок. И каждый новый список — это новый ряд кнопок.
Кнопка посылает в чат текст, который на ней написан. Переименуем одну из кнопок на «Начать». При ее нажатии будет отправляться слово «Начать», так как это текст а не команда, его обрабатывает функция parrot.
Для того чтобы выполнялось некое действие при нажатии кнопки, напишем обработчик для проверки текста. Обратите внимание, при каждом изменении кода необходимо перезапускать бота.
Обучим Telegram бота присылать анекдот при нажатии пользователем на кнопку "Анекдот" или при отправке слова Анекдот. Анекдоты будем брать с тематического сайта из интернета. Для этого нам потребуется библиотека requests и BeautifulSoup.
— BeautifulSoup — библиотека для парсинга HTML и XML документов.
В терминале PyCharm с помощью команд pip install requests и pip install bs4 устанавливаем нужные нам библиотеки. Обратите внимание на виртуальное окружение, оно должно быть активировано.
1. Импортируем скаченные библиотеки в файл с кодом;
2. Создадим кнопку с названием «Анекдот», при нажатии которой Telegram бот будет присылать анекдот в чат;
3. Напишем обработчик слова «Анекдот»;
4. Создадим функцию get_anecdote().
Если обратили внимание в телефонной версии Telegram приложения, кнопки занимают очень много места. Telegram позволяет автоматически уменьшить размер, для этого передадим в инициализатор класса ReplyKeyboardMarkup параметр resize_keyboard значение True. После изменений кода перезапустите бота и в чате Telegram очистите историю.
Добавляем изменения программы в Git репозиторий и по необходимости выкладываем на сайт GitHub. Написанный код в этой статье можно скачать (скопировать) на GitHub .
Сегодняшняя статья будет посвящена тому, каким образом можно создать для бота пользовательскую клавиатуру, что это даёт и как со всем этим работать. Все приводимые в статье примеры кода будут на php.
Пользовательские клавиатуры в Telegram бывают двух видов: Inline и Reply.
Описывающие клавиатуры объекты представляют собой многомерные массивы, содержащие наборы записей о каждой из кнопок (подпись, данные колбэка, открываемый при нажатии url и так далее).
Таким образом, для генерирования клавиатуры нам нужно сформировать в коде соответствующего типа объект, описывающий создаваемую клавиатуру (назовём этот объект, например, $keyboard), закодировать этот объект в виде json-строки и добавить эту json-строку в качестве параметра reply_markup при отправке запроса (GET или POST) telegram-боту.
// создаём $keyboard - объект, описывающий клавиатуру
$keyboard = [
"inline_keyboard" =>
[ /* первый ряд кнопок - массив из наборов */
[ /* первые две кнопки вызывают колбэк, а третья - открытие url-а */
[ "text" => "button 1",
"callback_data" => "data 1"
],
[ "text" => "button 2",
"callback_data" => "data 2"
],
[ "text" => "button 3",
"url" => $any_url
]
]
/* здесь мог бы быть второй массив для второго ряда кнопок и так далее */
]
];
.
.
// далее нужно просто добавить этот параметр в запрос (GET или POST) в качестве параметра reply_markup
// например, при использовании в GET-запросе:
$keyboard_json = json_encode($keyboard); // перекодируем в json
// формируем url для get-запроса и добавляем к этому url-у параметр reply_markup с описанием нашей клавиатуры
$url=$telegram_api_url.$bot_token.'/sendMessage?chat_id='.$chat_id.'&text='.urlencode($text_message).'&parse_mode=HTML'.'&reply_markup='.$keyboard_json;
// осталось только выполнить GET-запрос, например с помощью file_get_contents (ну или curl :))
file_get_contents($url); // отправляем get-запрос на сформированный url
Для удаления reply-клавиатуры нужно в параметре reply_markup послать объект, типа ReplyKeyboardRemove.
// создаём $remove_keyboard - объект, описывающий удаление reply-клавиатуры
$remove_keyboard = [
"remove_keyboard" => true
];
.
.
// далее нужно просто добавить этот объект в запрос (GET или POST) в качестве параметра reply_markup
// например, при использовании в GET-запросе:
$remove_keyboard_json = json_encode($remove_keyboard); // перекодируем в json
// формируем url для get-запроса и добавляем к этому url-у параметр reply_markup с описывающим удаление клавиатуры объектом
$url=$telegram_api_url.$bot_token.'/sendMessage?chat_id='.$chat_id.'&text='.urlencode($text_message).'&parse_mode=HTML'.'&reply_markup='.$remove_keyboard_json;
// осталось только выполнить GET-запрос, например с помощью file_get_contents (ну или curl :))
file_get_contents($url); // отправляем get-запрос на сформированный url
" [
"update_id":xxxxxxxxxx,
"callback_query":
"id":"xxxxxxxxxxx",
"from":
"id":xxxxxxxxx,
"first_name":"xxxxxxx",
"last_name":"xxxxxxx",
"username":"xxxxxxxxx",
"language_code":"ru"
>,
"message":
"message_id":xxxx,
"from":
"id":xxxxxxxxx,
"first_name":"xxxxxxxx",
"username":"xxxxxxx"
>,
"chat":
"id":xxxxxxxx,
"first_name":"xxxxxxx",
"last_name":"xxxxxxxx",
"username":"xxxxxxx",
"type":"private"
>,
"date":1499854111,
"text":"test"
>,
"chat_instance":"xxxxxxxxxxxx",
"data":"1"
>
>
]
>"
Вот и всё. Как видите, всё достаточно просто и понятно. В telegram вообще всегда всё просто, понятно и подробно описано. Вообще не понимаю, зачем нужны всякие библиотеки и фреймворки. Все они выглядят гораздо страшнее и монструознее, чем исходные описания из API. Это при том, что все эти фреймворки добавляют коду веса, ошибок и нестабильности. Уф, надо вступить в какое-нибудь движение за чистоту кода. Ну ладно, это я уже отвлёкся. Пока!
Взаимодействие пользователя с ботом должно быть интуитивным. Пользователь должен понимать, как общаться с ботом чтобы получить необходимый результат. Давайте рассмотрим какие есть способы взаимодействия с ботом.
При открытии бота по умолчанию сразу доступна кнопка Старт, при нажатии, на которую будет начат диалог и в бот будет отправлена команда /start . Уже здесь мы можем поймать эту команду, обработать и выполнить какие-то действия. Вместе с этой командой в бот отправляется минимальная информация о пользователе:
- id - уникальный идентификатор пользователя в Telegram
- last_name - значение поля фамилия, может быть пустым
- first_name - значение поля имя, может быть пустым
- username - уникальное значение текстовый идентификатор, может быть пустым
- language_code - кодовое обозначение выбранного языка интерфейса приложения (en, ru . )
- is_bot - флаг, определяющий пользователя как бота, в случае с ботом равен 1, в случае с пользователем пустое значение
Полезный инструмент
Telegram Bot API рекомендует использовать base64url для кодирования параметров с двоичным и другими типами контента.
По ссылке с параметром start будет открыт диалог с ботом, с кнопкой Старт в месте поля ввода. Если используется параметр startgroup, пользователю будет предложено выбрать группу для добавления бота.
Клавиатуры и их возможности
KeyboardButton
Помимо набора кнопок в объект ReplyKeyboardMarkup можно передать еще ряд параметров:
- keyboard - массив кнопок (объекты KeyboardButton)
- resize_keyboard - если предать true, то клавиатура подгонится по высоте до возможного минимума.
- one_time_keyboard - возможность скрывать клавиатуру после ее использования
- selective - если надо показать клавиатуру только определенным пользователям
При необходимости удалить клавиатуру используйте объект ReplyKeyboardRemove.
InlineKeyboardButton
- text - текст который будет на отображен на кнопке, обязательный параметр, поддерживает текст и смайлики (эмодзи)
- url - адрес на который будет направлен пользователь
- callback_data - строка 1-64 символа будет передан боту через объект CallbackQuery
- switch_inline_query - после нажатия будет предложен выбор чата где будет использован бот во встроенном режиме, пример @gif dog
- switch_inline_query_current_chat - после нажатия вставит команду для использования бота во встроенном режиме в текущем чате
- callback_game - описание игры, которая будет запущена при нажатии пользователем кнопки.
- pay - кнопка будет использована как кнопка оплаты
Теперь немного практики
Предлагаю рассмотреть поближе возможности клавиатур. Для примера я сделаю 4 кнопки: 2 KeyboardButton и 2 InlineKeyboardButton. Для этого будем работать с теми же инструментами, которые были в предыдущей статье. Добавим только несколько новых методов.
Кнопки будем отправлять в параметре reply_markup в методе sendMessage. Набор кнопок идет в таком формате:
Создадим два метода для разных клавиатур, на входе принимают массив строк кнопок, на выходе строку в формате JSON.
Сам набор кнопок будет выглядеть вот так.
Во встроенных кнопках (inlineKeyboardButton) в качестве значения параметра callback_data будем передавать служебную информацию в виде action_type_count1_count2 , где
- action - действие, в нашем случае это vote
- type - тип кнопки: 1 - левая, 0 - правая
- count1 - текущее значение левой кнопки
- count2 - текущее состояние правой кнопки
В значении параметра text передаем бинарный код эмодзи в кодировке UTF-8 (список эмодзи), которые преобразуются из шестнадцатеричных данных в двоичные данные функцией hex2bin, и еще выведем текущее числовое значение счетчика кнопки.
Теперь нам остается только описать механизм определения команды и механизм ее обработки. Поэтому в методе init() создадим конструкцию оператора switch
Для создания новой клавиатуры мы используем метод setParams(), а для отправки изменений мы используем метод changeVote(). Здесь остановим внимание на методах Bot API
Подводим итоги
Мы рассмотрели некоторые способы взаимодействия между пользователем и ботом, в основном это элементы интерфейса бота. Исходный код можно скачать по этой ссылке. Далее нас ждет знакомство с медиа-файлами.
Комментарии
Внимание!
Убедитесь, что эта страница открыта в браузере, а не в приложении Telegram. В противном случае авторизация пройдет только в приложении Telegram.
мне нужно 30 шт вывести из базы
30 in лучше выводить с постраничной навигацией по 10 шт например, у Телеграм если не ошибаюсь установлено ограничение. У меня была ситуация, когда на 32 строке кнопок был косяк, но постраничка решила проблему.
А вывести не сложно если из базы получить массив то стандартными функциями (foreach, for, do while . ) php можно спокойно это сделать.
что нужно дописать этому боту сюда-
чтобы он вел лог отдельно для кажлого чайт айди в папке log ?
Здравствуйте а как кнопкам меню задать стиль ширину и длину? К сожалению Телеграм это не позволяет регулировать. жалко что вам скрин нельзя прислать, может я не правильно спросил, а как их перенести по принципу <br> что б они в столбик были? Если я правильно понял ваш вопрос, то это можно сделать просто - разбить массив на вложенность кратное необходимому кол-во строк. Откройте ветку на форуме, там удобнее. Только вопрос по больше разверните, что именно вам нужно узнать.Значение будет лежать:
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
В этой главе мы повысим юзабилити нашего бота за счёт добавления клавиатуры, которая сделает интерфейс бота интуитивно понятным, и простым в использовании.
3.1 Какие типы клавиатур поддерживает телеграм бот
На момент написания книги telegram.bot позволяет вам создать клавиатуры двух типов:
Ниже мы разберём несколько примеров.
3.2 Reply клавиатура
Как я уже писал выше, это основная клавиатура управления ботом.
Выше приведён пример из официальной справки пакета telegram.bot . Для создания клавиатуры используется функция ReplyKeyboardMarkup() , которая в свою очередь принимает список списков кнопок, которые создаются функцией KeyboardButton() .
Почему в ReplyKeyboardMarkup() необходимо передавать не просто список, а список списков? Дело в том, что вы передаёте основной список, и в нём отдельными списками вы задаёте каждый ряд кнопок, т.к. в один ряд можно расположить несколько кнопок.
Аргумент resize_keyboard позволяет автоматически подбирать оптимальный размер кнопок клавиатуры, а аргумент one_time_keyboard позволяет скрывать клавиатуру после каждого нажатия на кнопку.
Давайте напишем простейшего бота, у которого будет 3 кнопки: * Чат ID - Запросить чат ID диалога с ботом * Моё имя - Запросить своё имя * Мой логин - Запросить своё имя пользователя в телеграм
Запустите приведённый выше пример кода, предварительно заменив ‘ТОКЕН ВАШЕГО БОТА’ на реальный токен, который вы получили при создании бота через BotFather.
После запуска задайте боту команду /start , т.к. именно её мы определили для запуска клавиатуры.
Если на данный момент вам сложно разобрать приведённый пример кода, с созданием методов, фильтров и обработчиков, то следует вернуться к предыдущей главе, в которой я подробно всё это описал.
Мы создали 4 метода:
- start - Запуск клавиатуры
- chat_id - Запрос идентификатора чата
- my_name - Запрос своего имени
- my_username - Запрос своего логина
И создали 4 обработчика, которые по заданным командам и фильтрам будут выполнять указанные методы.
Сама клавиатура создаётся внутри метода start() командой ReplyKeyboardMarkup() .
В нашем случае все кнопки мы расположили друг под другом, но мы можем расположить их в один ряд, внеся изменения в список списков кнопок. Т.к. один ряд внутри клавиатуры создаётся через вложенный список кнопок, то для того, что бы вывести наши кнопки в один ряд надо переписать часть кода по построению клавиатуры вот так:
Отправляется клавиатура в чат методом sendMessage() , в аргументе reply_markup .
3.3 Inline клавиатура
Изначально вам необходимо добавить боту метод, для вызова Inline клавиатуры.
Для ответа на нажатие Inline кнопки также можно использовать метод бота answerCallbackQuery() , который может вывести уведомление в интерфейсе telegram, пользователю нажавшему Inline кнопку.
Данные отправленные с Inline кнопки не являются текстом, поэтому для их обработки необходимо создать специальный обработчик с помощью команды CallbackQueryHandler() .
Код построения Inline клавиатуры который приводится в официальной справке пакета telegram.bot .
Строить Inline клавиатуру необходимо с помощью команды InlineKeyboardMarkup() , по такому же принципу, как и Reply клавиатуру. В InlineKeyboardMarkup() необходимо передать список, списков Inline кнопок, каждая отдельная кнопка создаётся функцией InlineKeyboardButton() .
Inline кнопка может либо передавать боту какие-то данные с помощью аргумента callback_data , либо открывать какую-либо HTML страницу, заданную с помощью аргумента url .
В результате будет список, в котором каждый элемент так же является списком Inline кнопок, которые необходимо объединить в один ряд.
Далее мы рассмотрим несколько примеров ботов с Inline кнопками.
3.3.1 Пример простейшего бота с поддержкой InLine кнопок
Запустите приведённый выше пример кода, предварительно заменив ‘ТОКЕН ВАШЕГО БОТА’ на реальный токен, который вы получили при создании бота через BotFather.
Результат:
Мы создали два метода:
- test - Для отправки в чат Inline клавиатуры
- answer_cb - Для обработки отправленных с клавиатуры данных.
Данные, которые будут отправлены с каждой кнопки задаются в аргументе callback_data , при создании кнопки. Получить отправленные с кнопки данные можно с помощью конструкции update$callback_query$data , внутри метода answer_cb.
Что бы бот реагировал на Inline клавиатуру, метод answer_cb обрабатывается специальным обработчиком: CallbackQueryHandler(answer_cb) . Который запускает указанный метод по нажатию Inline кнопки. Обработчик CallbackQueryHandler принимает два аргумента:
- callback - Метод который необходимо запустить
- pattern - Фильтр по данным, которые привязаны к кнопке с помощью аргумента callback_data .
Соответвенно с помощью аргумента pattern мы можем под нажатие каждой кнопки написать отдельный метод:
Запустите приведённый выше пример кода, предварительно заменив ‘ТОКЕН ВАШЕГО БОТА’ на реальный токен, который вы получили при создании бота через BotFather.
Теперь мы написали 2 отдельных метода, т.е. по одному методу, под нажатие каждой кнопки, и использовали аргумент pattern , при создании их обработчиков:
Заканчивается код метода answer_cb командой bot$answerCallbackQuery(callback_query_id = update$callback_query$id) , которая сообщает боту, что данные с inline клавиатуры получены.
3.3.2 Пример бота, который сообщает текущую погоду по выбранному городу
Давайте попробуем написать бота, который запрашивает данные о погоде.
В этом примере кода мы будем использовать несколько дополнительных пакетов:
Код бота, который сообщает текущую погоду по выбранному городу
Запустите приведённый выше пример кода, предварительно заменив ‘ТОКЕН ВАШЕГО БОТА’ на реальный токен, который вы получили при создании бота через BotFather.
В результате наш бот будет работать примерно так:
Схематически данного бота можно изобрать вот так:
Мы создали 3 метода, доступные внутри нашего погодного бота:
- start - Запуск основной клавиатуры бота
- weather - Запуск Inline клавиатуры для выбора города
- answer_cb - Основной метод, который по заданному городу запрашивает в API погоду, и отправляет её в чат.
Метод start у нас запускается командой /start , что реализовано обработчиком CommandHandler('start', start) .
Для запуска метода weather мы создали одноимённый фильтр:
И в конце концов, основной наш метод answer_cb реагирует на нажатие Inline кнопок, что реализовано специальным обработчиком: CallbackQueryHandler(answer_cb) .
Данного бота я привожу для того, что бы показать вам, как вывести Inline кнопки которые ведут на веб страницы.
Логика данного бота схожа с предыдущим, изначально мы запускаем основную клавиатуру командой /start . Далее бот даёт нам на выбор список из 6 хабов, мы выбираем интересующий нас хаб, и получаем 5 самых свежих публикаций из выбранного Хаба.
Как вы понимаете, в данном случае нам необходимо получить список статей, и для этого мы будем использовать специальный пакет habR , который позволяет запрашивать из хабры статьи и некоторую статистику по ним в R.
Установить пакет habR можно только из github, для чего вам понадобится дополнительный пакет devtools . Для установки воспользуйтесь приведённым ниже кодом.
Теперь рассмотрим код построения описанного выше бота:
Код бот который выводит список наиболее свежих статей по выбранному Хабу
Запустите приведённый выше пример кода, предварительно заменив ‘ТОКЕН ВАШЕГО БОТА’ на реальный токен, который вы получили при создании бота через BotFather.
В итоге мы получим вот такой результат:
Список доступных для выбора Хабов мы вбили хардкодом, в методе habs :
Список статей из указанного Хаба мы получаем командой habr_hub_posts() , из пакета habR . При этом указываем, что нам не требуется список статей за всё время, а только первая страница на которой располагаются 20 статей. Из полученной таблицы с помощью команды head() оставляем только 5 самых верхних, которые и являются самыми свежими статьями.
Логика очень схожа с предыдущим ботом, но в данном случае Inline клавиатуру со списком статей мы генерируем динамически с помощью функции lapply() .
В текст кнопки мы подставляем название статьи posts$title[x] , а в аргумент url ссылку на статью: url = posts$link[x] .
Далее, создаём фильтр, обработчики и запускаем нашего бота.
3.4 Заключение
Теперь написанные вами боты будут значительно удобней в работе, за счёт того, что управление ими будет осуществляться с клавиатуры, а не вводом команд. Как минимум при взаимодействии с ботом через смартфон клавиатура ощутимо упростит процесс его использования.
В следующей главе мы разберёмся как строить логический диалог с ботом, и работать с базами данных.
3.5 Тесты и задания
3.5.1 Тесты
Для закрепления материла рекомендую вам пройти тест доступный по ссылке.
3.5.2 Задания
- Создайте бота, который будет поддерживать Reply клавиатуру. На Reply клавиатуре будет всего одна кнопка “Время.” По нажатию на неё будет появляться Inline клавиатура с выбором из 6 часовых поясов.
- Africa/Cairo
- America/Chicago
- Europe/Moscow
- Asia/Bangkok
- Europe/Kiev
- Australia/Sydney
Кнопки Inline клавиатуры необходимо расположить по 2 в ряд, соответвенно в три ряда.
Где это континент, например Europe, а это город, например Kiev. Дату и время надо брать в ответе из компонента datetime .
Читайте также: