Как создать Telegram-бота с помощью PHP?
Доброго времени суток! В данной статье я покажу Вам как просто можно создать Telegram-бота на PHP.
В качестве площадки для хостинга нашего бота мы будем использовать платформу Heroku, о которой я уже ранее писал статью. В качестве библиотеки для разработки бота возьмем вот эту irazasyed/telegram-bot-sdk. Но кроме нам также понадобится библиотека doctrine/annotations для удобной организации команд на которые будет реагировать бот.
Для начала нам нужно будет получить токен для бота. Для этого надо непосредственно в клиенте Telegram перейти к боту @BotFather, где набрав команду /newbot следовать инструкциям. После получения токена нам необходимо будем настроить так называемый веб-хук - URL, на который будут приходить команды, введенные пользователем в чате с ботом. Внизу ссылка в которой нужно заменить <%ТОКЕН_БОТА%> на токен Вашего бота, после чего для активации адреса нужно будет открыть его в браузере. Обратите внимание, что Telegram требует, чтобы адрес веб-хука был c настроенным SSL. К счастью, если бот размещается на Heroku, то все уже настроено и работает.
Вот сама ссылка:
https://api.bot.org/bot<%ТОКЕН_БОТА%>/setWebhook?url=https://myrusakovbot21.herokuapp.com/index.php
Все готово, теперь приступим к написанию кода - вот наш файл composer.json:
{
"name": "myrusakov/php-bot-webhook",
"type": "project",
"require": {
"irazasyed/telegram-bot-sdk": "^2.0",
"doctrine/annotations": "^1.13"
},
"autoload": {
"psr-4": {
"": "src/"
}
}
}
Файлы с классами будут лежать в папке src. Вот базовая струтура директорий проекта:
.
├── vendor
├── src
│ ├── MainCommand.php
│ └── CommandsCollector.php
├── index.php
├── composer.lock
├── composer.json
└── .gitignore
Файл index.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Telegram\Bot\Api;
// в класс передаем наш токен
$bot = new Api('%ТОКЕН БОТА%');
function BotApp(Api $bot, array $commands = [])
{
// получаем обновленные данные
$result = $bot->getWebhookUpdates();
$text = $result["message"]["text"]; //Текст сообщения
$chat_id = $result["message"]["chat"]["id"]; //Идентификатор пользователя
$name = $result["message"]["from"]["username"]; //Имя пользователя
// если есть текстовая команда
if ($text)
{
// пробегаемся по массиву команд
foreach ($commands as $commandText => $commandAction)
{
// смотрим, есть ли введенная текстовая команда в списке доступных
if ($commandText === $text)
{
// есть такая команда - получаем ее обработчики - название класса и метода
[$class, $method] = $commandAction;
// вызываем обработчик
$obj = new $class();
$obj->$method($bot, $result);
return;
}
}
// если команда не распознана срабатывает обработчик по умолчанию
[$class, $method] = $commands['fallback'];
$obj = new $class();
$obj->$method($bot, $result);
}
else
{
$bot->sendMessage(['chat_id' => $chat_id, 'parse_mode' => 'HTML', 'text' => "Привет <b>$name!</b> Я понимаю только текст."]);
}
}
// массив с классами команд - их может быть столько, сколько необходимо Вам
$actions = [MainCommand::class];
// проходится по классу и собирает команды, на которые срабатывает обработчик
$collector = new CommandsCollector();
// массива команд и соответствующих им обработчиков
$commands = [];
foreach($actions as $action)
{
$classCommands = $collector->collect($action);
$commands = array_merge($commands, $classCommands);
}
// запускаем бота
BotApp($bot, $commands);
Сопоставление команд с обработчиком происходит с помощью аннотаций. Для этого как раз и нужен пакет doctrine/annotations
Класс, который содержит обработчики команд
<?php
use Telegram\Bot\Api;
use Telegram\Bot\Objects\Update as ObjectsUpdate;
class MainCommand
{
/**
* @Command(text="привет")
*/
public function welcome(Api $bot, ObjectsUpdate $result)
{
$chat_id = $result["message"]["chat"]["id"];
$reply = "Информация с помощью.";
$bot->sendMessage(['chat_id' => $chat_id, 'text' => $reply]);
}
/**
* @Command(text="вакансии")
*/
public function vacanciesFeed(Api $bot, ObjectsUpdate $result)
{
$reply = '';
$url = 'https://career.habr.com/vacancies/rss?currency=RUR&sort=relevance&type=all';
$chat_id = $result["message"]["chat"]["id"];
$rss = simplexml_load_file($url);
foreach ($rss->channel->item as $item) {
$reply .= "\xE2\x9E\xA1 " . $item->title . " (<a href='" . $item->link . "'>читать</a>)\n";
}
$bot->sendMessage(['chat_id' => $chat_id, 'parse_mode' => 'HTML', 'disable_web_page_preview' => false, 'text' => $reply]);
}
/**
* @Command(text="fallback")
*/
public function fallback(Api $bot, ObjectsUpdate $result)
{
$text = $result["message"]["text"];
$chat_id = $result["message"]["chat"]["id"];
$reply = "По запросу \"<b>$text</b>\" ничего не найдено.";
$bot->sendMessage(['chat_id' => $chat_id, 'parse_mode' => 'HTML', 'text' => $reply]);
}
}
Формированием команд и их обработчиков занимается класс CommandsCollector:
<?php
use Doctrine\Common\Annotations\AnnotationReader;
/**
* @Annotation
* @Target({"CLASS","METHOD"})
*/
final class Command
{
public $text;
}
class CommandsCollector
{
/**
* Выбирает из класса все публичные методы, затем вытаскивает
* из них текст команд, на которые они должны срабатывать и формирует
* массив вида:
*
* [
* 'привет' => ['MainCommand', 'welcome']
* ]
*
* Т.е. на введенную пользователем команду будет срабатывать метод welcome класса MainCommand
*/
public function collect($class)
{
$reader = new AnnotationReader();
$refClass = new ReflectionClass($class);
$refMethods = $refClass -> getMethods(ReflectionMethod::IS_PUBLIC);
$commands = [];
foreach($refMethods as $method)
{
$command = $reader->getMethodAnnotation($method, Command::class);
if($command) {
$commands[$command->text] = [$method->class, $method->name];
}
}
return $commands;
}
}
После того, как код написан - нужно его разместить на платформе Heroku. Для этого нужно выполнить следующие команды в папке проекта (предполагается, что консольная утилита heroku уже установлена в системе и доступна в консоли как команда heroku):
$ cd myrusakov-telegram-bot # переходим в папку проекта - в моем случае она называется так
$ heroku login # вы должны быть зарегистрированы на Heroku и приложение myrusakovbot21 (в моем случае оно так называется) должно создано
$ heroku git:remote -a myrusakovbot21 # связываем наше приложение на компьютере с удаленным приложением на сервере
$ git add .
$ git commit -am "Initial commit"
$ git push heroku main
Таким образом, если не возникнет ошибок в ходе размещения бота на Heroku, то Ваш бот успешно размещен на сервере и готов принимать команды. Если же, после всего сделанного бот не запускается, то в папке приложения можно выполнить команду heroku logs -a myrusakovbot21, которая выведет ошибки, возникшие при обработке команд.
-
- Михаил Русаков
Комментарии (2):
Что этот бот умеет?
Ответить
Здравствуйте Возможности бота определяются командами, например: @Command(text="привет")
Ответить
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.