Как создать Telegram-бота с помощью PHP?

Как создать Telegram-бота с помощью PHP?

Как создать 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 TelegramBotApi;



//  в класс передаем наш токен

$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 TelegramBotApi;

use TelegramBotObjectsUpdate 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 .= "xE2x9ExA1 " . $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 DoctrineCommonAnnotationsAnnotationReader;



/**

 * @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, которая выведет ошибки, возникшие при обработке команд.

Источник

НЕТ КОММЕНТАРИЕВ

Оставить комментарий