Добавить в botman editMessageText для Telegram
В Telegram bot API предусмотрен метод для изменения отправленного сообщения, и для изменения кнопок. К сожалению в текущей версии botman (telegram driver) нет встроенных функций для реализации этой задачи, поэтому пришлось дописать самому.
В чем проблема?
Не получается отправить запрос на изменение кнопок и или текста сообщения с помощью стандартного метода ask() . А использовать хочется именно его.
Это происходит потому, что мы формируем сообщение (текст и кнопки) классом BotMan\BotMan\Messages\Outgoing\Question , и передаем его в ask() . Дальше по цепочке вызывается метод reply() , за ним buildServicePayload() класса BotMan\Drivers\Telegram\TelegramDriver . В buildServicePayload() выявляется каким будет метод API, и условие построено таким образом, что при ..\Question ставится метод sendMessage . И все. А для изменения сообщения и или кнопок нужно использовать метод editMessageText .
Поэтому либо нужно делать аналог метода ask, со всей цепочкой вызова, либо внедряться в существующую систему. Я выбрал второй вариант, хотя изящество этого решения меня вовсе не впечатляет..
В этой заметке вы узнаете
- как использовать методы API Telegram editMessageReplyMarkup , editMessageText в Botman
- как создавать inline_keyboard с несколькими кнопками на строке, и использовать это в связке с методом ask()
Задача в том, чтобы иметь возможность вызывать $this->ask и не отправлять новое сообщение с кнопками и текстом, а менять уже отправленное. То есть сделать удобную навигацию по меню бота.
Можно отправить: новый текст / новые кнопки / новые кнопки и новый текст.
Надстройка, которую я предлагаю, интегрируется в vendor\botman\driver-telegram\src\TelegramDriver.php . Там нужно добавить дополнительные условия в методе buildServicePayload . Но сперва создадим 2 новых класса и 1 тестовый диалог.
Нюанс
Если пользователь отправил сообщение, то уже не получится изменить кнопки. И честно говоря для меня осталось загадкой почему. Ведь если кликать по этим кнопкам, то они отвечают. Но если, например, попросить пользователя либо выбрать из предлагаемых вариантов, либо ввести вручную ответ, то никак не получилось у меня добиться, чтобы менялся текст сообщения или кнопки именно после пользовательского ввода. И видимо так действительно нельзя сделать. По крайней мере в (весьма популярном и навороченном) боте магазина ВкусВилл так тоже не работает. Если совершен пользовательский ввод, то нужно отправлять новое сообщение, а не менять предыдущее. Однако в целом это лично — если мы бы меняли сообщения после пользовательского ввода, то рискнули бы оказаться в ситуации, когда наше изменяемое сообщение уже где-то скрылось в истории, а пользователь все продолжает вводить команды..
Решение задачи
Настройка кофнига, чтобы не пропадали кнопки
В файле config\botman\telegram.php
Класс для отправки сообщений
В Botman есть класс для отправки сообщений — это Question. Но я создаю свой класс чтобы иметь возможность добавлять по несколько кнопок на строку, и для единообразия кода..
Класс для редактирования сообщений
Тестовый диалог (Conversation)
Добавить route в routes\botman.php
Поместить код в файл
Пример достаточно расширенный, включающий разные варианты развития событий.
Внедряемся в TelegramDriver.php
Нюанс В процессе оказалось, что нет необходимости использовать метод editMessageReplyMarkup , если передавать текст. editMessageReplyMarkup используется только если текст менять не нужно, а кнопки нужно. В моей практике такого не было. И кроме того для этого нужно корректировать условие. Ведь переданный пустой текст — удаляет сообщение, и этого я и хочу, передавай пустую строку.
Редактируем сообщение через Телеграм Бот
Мы все ближе и ближе подходим к реализации интересного проекта. В моих планах написать цикл статей по построению бота по продаже товаров или услуг, своего рода интернет-магазин в Телеграме. У меня уже даже есть настроенная Яндекс.Касса. Но для этого нам нужно понимание процессов, которые будут происходить в работе такого бота. Мы уже многое умеем, и сегодня пополним свои знания в части редактирования и удаления сообщений.
Для того чтобы произвести какие-либо действия с сообщением нам нужно знать его message_id и chat_id . Эти данные мы можем получить в объекте, который будет нам отправлен в ответ на нашу публикацию сообщения от Bot API, далее для удобства можем сохранить их в удобном для нас виде, или можем получить их через объект CallbackQuery при событии через кнопку встроенной клавиатуры.
В своем примере я продемонстрирую работу через встроенную клавиатуру. Заодно еще познакомимся с объектом ForceReply.
Создаем тестовое сообщение
В качестве теста, я создал простое, текстовое сообщение с кнопками "Редактировать" и "Удалить". Приводить весь код скрипта я не буду, он повторяется из предыдущих статей, и в прикрепленном в конце статьи исходном коде он также будет присутствовать.
Редактируем сообщение
Редактирование здесь будет происходить в 2 этапа. Сначала мы предложим пользователю ввести новый текст сообщения, потом произведем действие по замене текста. Хранение данных организовывать не будем, все будем делать на лету. В связи с этим возникает вопрос как передать message_id на втором шаге?
При нажатии на кнопку "Редактировать" нам приходит объект CallbackQuery, в котором содержится message_id нужного нам сообщения, он находится в ['callback_query']['message']['message_id']. Сформируем текстовое сообщение-запрос, зашьем в него полученный message_id, и отправим пользователю. Дополнительно к сообщению прикрепим объект ForceReply.
Пользователь отправит нам в ответ новый текст для редактирования, также под ключом reply_to_message будет наш сформированный текст с message_id нужного нам сообщения. Достаем его и передаем в метод editMessageText.
Удаляем сообщение
Удалять сообщение как ни странно проще некуда. При нажатии на кнопку также передается объект CallbackQuery из которого берем message_id передаем его вместе с chat_id в метод deleteMessage.
Подводим итоги
Теперь мы еще на один шаг стали ближе к большому проекту. Исходный код примеров этой статьи вы можете скачать по этой ссылке.
Комментарии
Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте бот @SiteAuthBot, нажмите кнопку Старт/Start. Следуйте инструкциям бота.
Внимание!
Убедитесь, что эта страница открыта в браузере, а не в приложении Telegram. В противном случае авторизация пройдет только в приложении Telegram.
Method: messages.editMessage
If the length of the provided message is bigger than 4096, the message will be split in chunks and the method will be called multiple times, with the same parameters (except for the message), and an array of Updates will be returned instead.
Usage of parseMode:
Set parseMode to html to enable HTML parsing of the message.
Set parseMode to Markdown to enable markown AND html parsing of the message.
The following tags are currently supported:
You can also use normal markdown, note that to create mentions you must use the mention: syntax like in html:
MadelineProto supports all html entities supported by html_entity_decode.