Установка Botman
Предполагаю, что вы уже зарегистрировали бот через BotFather..
Botman — это по инстрмент для удобной и быстрой разработки ботов под любые платформы. Представляет из себя компонент для фреймворка Laravel. Однако если вы не знакомы с Laravel, то это не будет большой проблемой, так как экосистема Botman достаточно изолирована и самодостаточна. Вам хватит знаний PHP.
Установить Botman starter kit командой
composer create-project --prefer-dist botman/studio <directory>
После этого возможно появится ошибка, если установлен Composer 2. Тогда нужно выполнить команду
composer update
Еще одна необходимая команда после установки
php artisan key:generate
Затем нужно подгрузить модуль для работы с Телеграм
composer require botman/driver-telegram
Запустить сервер
php artisan serve
Как вести разработку чат-бота Telegram на локальном домене? Использовать Ngrok!
Если вы ведете разработку на локальной машине без внешнего IP, то возникнет трудность с регистрацией вэб Хука для обработки сообщений телеграм. Но проблема эта легко решается сервисом ngrok.com, от даст возможность связать локальный домен с доменом вида https://99328bcc9109.ngrok.io/
, доступным в интернете. Еще очень удобно, что этот сервис сам генерирует https, даже если исходный домен без SSL.
Настройки Ngrok (бесплатный аккаунт)
Для начала нужно скачать эту программу себе на компьютер, разархивировать, запустить и ввести команду
authtoken [Ваш токен]
php artisan serve
+ Ngrok
Если вы используете команду php artisan serve
для реализации веб-сервера, то скорее всего вам будет достаточно будет ввести команду (запустите ngrok.exe и там введите эту команду)
ngrok http 127.0.0.1:8000
Увидите примерно это:
Теперь ваш локальный http://127.0.0.1:8000
доступен по адресу https://df4c2ff466f6.ngrok.io
. Класс!
OpenServer + Ngrok
OpenServer — это комплект утилит для реализации локального сервера, в том числе локальных доменов.
Если просто ввести команду ngrok http cb.test
(cb.test — локальный домен), почему-то при заходе на поддомен Ngrok возникает синий экран с надписью "Как вы здесь оказались? Для перенаправления IP на нужный домен создайте алиас в настройках."
Поэтому следует указывать немного другую команду чтобы Ngrok работал корректно в связке с OpenServer:
ngrok http --host-header=cb.test 80
Важный нюанс про бесплатный аккаунт Ngrok
При каждом вызове команды ngrok http ...
будет генерироваться новый поддомен. Это не очень здорово, но совсем не критично, просто нужно заново установить Вэб-хук для вашего бота.
Установка Вэб-хука для бота Telegram в Botman
Перед установкой вэб-хука нужно
Создать бота через BotFather
Добавить в ваш .env
файл строчку с токеном из BotFather
TELEGRAM_TOKEN='Ваш_токен'
Установка Вэб-хука для бота Telegram в Botman
Вводим команду
php artisan botman:telegram:register --output
В ответ на вопрос What is the target url for the telegram bot?
Вводим https адрес, полученный из Ngrok, с прибавленным путем /botman
, например вот такой:
https://df4c2ff466f6.ngrok.io/botman
Настройка завершена! Ваш локальный домен теперь используется в качестве веб-кука для бота!
Построение бота в Botman
Обработка входящих сообщений
В файле routes\botman.php
прописываются команды, на которые будет реагировать ваш бот
Обработать входящее сообщение можно прямо тут же, хотя лучше использовать контроллер
$botman->hears('Hi', function ($bot) { $bot->reply("Hello! @" . $bot->getUser()->getUsername()); });
Данные пользователя
$botman->hears('Кто я', function ($bot) { $bot->reply("@" . $bot->getUser()->getUsername() . " - твой Username"); $bot->reply($bot->getUser()->getId() . " - твой Id"); });
Разные варианты вопроса
$botman->hears(['yo', 'oy'], function ($bot) { $bot->reply("@" . $bot->getUser()->getUsername()." - твой Username"); });
Пример с использованием контроллера
$botman->hears('/start', BotManController::class . '@start');
Означает, что команда /start
будет обработана методом start
в контроллере BotManController
. В этот метод будет передан объект класса BotMan
namespace App\Http\Controllers; use BotMan\BotMan\BotMan; class BotManController extends Controller { public function start(BotMan $bot){ $bot->reply("Bot started"); } }
Составить диалог
По-настоящему раскрывает свой потенциал Botman именно в обслуживании диалогов. Вы можете создавать достаточно сложные диалоги, при этом их структура будет упорядоченной и лаконичной. Документация на английском
Для создания файла с диалогом введите команду. Появится новый файл в app\Conversations
.
php artisan botman:make:conversation SimpleConversation
В этом методе сначала есть только метод run()
. Но давайте постепенно добавим туда пару вопросов.
Пример диалога (Conversation) в Botman
В файле routes\botman.php
добавляем строчку с активацией диалога:
$botman->hears('/simple', function($bot){ $bot->startConversation(new \App\Conversations\SimpleConversation()); });
И заполним диалог. Пока все очень просто. Сначала бот спросит имя, затем email. Ответы на вопросы будут сохраняться.
namespace App\Conversations; use BotMan\BotMan\Messages\Conversations\Conversation; use BotMan\BotMan\Messages\Incoming\Answer; class SimpleConversation extends Conversation { public $user = []; public function askEmail() { $this->ask('Напиши свой E-mail, плз', function (Answer $answer) { $this->user['email'] = $answer->getText(); $this->say('Спасибо '.$this->user['name'].', теперь оправлю тебе тонну спама на ' . $this->user['email']); //return $this->askGender(); }); } public function askName() { $this->ask('Привет, как тебя зовут?', function (Answer $answer) { // Сохраняем результат, и он будет доступен и в других вопросах/ответах $this->user['name'] = $answer->getText(); $this->say('Приятно познакомиться, ' . $this->user['name']); // переход к следующему вопросу $this->askEmail(); }); } // Этот метод запускается при создании диалога public function run() { return $this->askName(); } }
Добавим кнопки в диалог
добавьте метод askGender()
, и раскомментируйте return $this->askGender();
в методе askEmail()
.
public function askGender() { $question = Question::create('Ваш гендер') ->addButtons([ Button::create('Женский')->value('woman'), Button::create('Мужской')->value('man'), Button::create('Другое')->value('other'), ]); $this->ask($question, function (Answer $answer) { // Если кликнули по кнопке if ($answer->isInteractiveMessageReply()) { switch($answer->getValue()){ case "woman": $this->bot->reply($this->user['name'].", ты прекрасна!"); break; case "man": $this->bot->reply($this->user['name'].", твой дух силен!"); break; case "other": $this->bot->reply($this->user['name'].", ты загадка!"); break; } }else{ // Если ввели тект, то задаем вопрос заново $this->bot->reply("Вы ввели текстом ". $answer->getText(). ", но надо нажать на кнопку.."); return $this->askGender(); } }); }
Дебаг в Botman
Первое, что нужно знать - это сброс кэша во время диалогов. Чтобы заново начать общение выполните команду
php artisan cache:clear
Логирование и дебаг вашего приложение по-умолчанию достаточно скудный. Если ошибка на сервере, то вы просто получаете 500 ошибку в своем Ngrok.exe. Неприятным дополнением является то, что ошибка зацикливается, так как Telegram повторяет запросы к серверу. Чтобы их остановить нужно чтобы ваше приложение дало хоть какой-то ответ. А потом уже ищите в чем проблема по коду. В Laravel (Botman — это пакет/расширение для Laravel) ошибки записываются в файл storage\logs\laravel.log
.
Функция для логирования в Laravel:
info('some string', $some_array);
Чтобы избежать зацикливания ошибки можно настроить приложение чтобы оно возвращало JSON при 500 ошибке. Telegram не будет опрашивать ваш сервер в надежде получить какой-то ответ. Он увидит, что какая-то "шляпа", и успокоится.
Для этого в файле app\Exceptions\Handler.php
метод render()
Теперь вы можете отслеживать ошибки тут http://127.0.0.1:4040, если пользуетесь Ngrok.
public function render($request, Exception $exception) { return response()->json([ 'type' => get_class($exception), 'message' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'trace' => $exception->getTrace(), 'previous' => $exception->getPrevious(), ]); }
Хорошо бы еще отслеживать исходящие данные. Для этого я использовал костыль. Наверняка есть способы лучше, но...
В файле vendor\botman\driver-telegram\src\TelegramDriver.php
В методе sendPayload
перед return
добавляем:
info('TG p', $payload);
В методе sendRequest
перед return
добавляем:
info('TG r', $parameters);
Теперь в файл логирования storage\logs\laravel.log
будут попадать дынные ответа
Как отправить свой запрос, используя API Телеграма в обход оберток Botman
Пример из routes\botman.php
Документация Telegram - https://core.telegram.org/bots/api#sendmessage
$botman->hears('yo', function (BotMan $bot) { $bot->sendRequest('sendMessage', ['text' => 'text..', 'reply_markup' => json_encode([ 'inline_keyboard' => [ [ ['text' => '11', 'callback_data' => "1-1"], ['text' => 'yo', 'callback_data' => "YO"] ], [ ['text' => 'yo', 'callback_data' => "YO"] ], [ ['text' => 'yo', 'callback_data' => "YO"] ], ] ], 256)]); });
Обновление текста и кнопок во время диалога
Подробное описание в отдельной статье — Добавить в botman editMessageText для Telegram
Комментарии (0)
Не писать ответ