Установка 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=loc-team.test 80
Или
ngrok http loc-team.test --host-header=loc-team.test
Установка Вэб-хука для бота 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)
Не писать ответ