Советы PHP-разработчика

Блог содержащий короткие заметки касающиеся программирования для web.

Пишем телеграмм бота на PHP

Пишем телеграмм бота на PHP

Сейчас почти каждый порядочный человек зарегистрирован в телеграмм и в связи с этим растет популярность ботов для него. Рассмотрим создание такого.

Постановка задачи

Реализовать простого бота на PHP с двумя командами:

  • /start - отправка приветственного сообщения (эта команда вызывается всегда при добавлении бота и нажатия кнопки "Start" в чате)
  • /quote - отправка случайной цитаты

Что потребуется

  • PHP 5.5+
  • установленный composer
  • телеграмм клиент

Ограничения

Бот для телеграмм может работать одним из двух вариантов:

  • опрашивать api по крону через метод getUpdates. Для этого придется хранить идентификатор последнего сообщения и обрабатывать только новые.
  • установить callback бота на ваш url. В данном случае обрабатываем входящие сообщения мгновенно, не заботимся об очереди, но потребуется https домен.

Остановимся на втором варианте.

Часть 1. Регистрация и настройка бота

Для начала необходимо создать нового бота. Добавляем себе в контакт-лист "крестного отца" @BotFather. Отправляем команду /newbot и самое сложное - придумываем название и имя бота. Есть небольшое ограничение, которое позволяет отличить бота от реального человека - это наличие суффикса bot в имени. Например, MyAwesomeBot или my_awesome_bot.

Когда бот создан, вы получаете его токен вида 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11. Сразу установим наши команды для удобства использования. Для этого отправим /setcommands для BotFather. Он предложит выбрать одного из ваших ботов и задать для него список доступных команд в указанном виде. Отправим в ответ

start - Регистрация бота
quote - Случайная цитата

Важно заметить, что эти команды не имеют ничего общего с теми, что мы будем реализовывать в скрипте. Это просто "выпадающие подсказки". На этом административная часть закончена, перейдем к программной.

Часть 2. Реализация самого приложения

Создаем новую директорию и переходим туда. Далее устанавливаем расширение для работы с telegram-api с помощью composer:

composer require telegram-bot/api "^2.3"

Создадим директорию web и укажем ее в качестве web-root для нашего домена в настройках сервера. Тут будут храниться наши скрипты доступные из web. Такая структура крайне желательна, так как она не дает получить доступ к остальным файлам с кодом, что является хорошей практикой в плане безопасности.

Настройки бота и список цитат вынесем в отдельный файл data/config.php

<?php

return [
    'botToken' => '123456789:AAABBBCCCAAABBBCCCAAABBBCCCAAABBBCC',
    'quotes' => [
        [
            'author' => 'Mahatma Gandhi',
            'quote' => 'Live as if you were to die tomorrow. Learn as if you were to live forever.',
        ],
        [
            'author' => 'Albert Einstein',
            'quote' => 'Two things are infinite: the universe and human stupidity; and I\'m not sure about the universe.',
        ],
        [
            'author' => 'Oscar Wilde',
            'quote' => 'Be yourself; everyone else is already taken.',
        ],
        // ...
    ],
];

Заменяем botToken на полученный от BotFather и дополняем файл своими цитатами.

Далее нам необходимо произвести регистрацию web-хука. Сделать это можно только через API, поэтому создадим одноразовый файл set-webhook.php внутри папки web со следующим содержимым:

<?php

// подключаем автозагрузчик composer-а
require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
// подключаем конфиг приложения
$config = require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'config.php';

use TelegramBot\Api\BotApi;

// создаем экземпляр класса для работы с API
$bot = new BotApi($config['botToken']);
// устанавливаем web-hook
echo $bot->setWebhook('https://awesome.website.ru/my-secret-webhook.php');

Важно! Название my-secret-webhook.php дано просто для примера. В реальных условиях оно должно иметь несвязанную тарабарщину (например, mu4OG-70sYakjrPcLf_DqHwTX4Ijr6B-.php). Это сократит возможность несанкционированного доступа к файлу с целью передачи "плохих данных" в скрипт.

Теперь обращаемся к файлу set-webhook.php из браузера. На странице должна отобразиться цифра "1". После этого удаляем файл, он больше не потребуется.

Теперь впереди осталось то, ради чего все затевалось - реализация логики работы самого бота. Создадим файл web/my-secret-webhook.php

<?php

require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
$config = require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'config.php';

use TelegramBot\Api\BotApi;
use TelegramBot\Api\Client;
use TelegramBot\Api\Types\Message;

/** @var Client|BotApi $bot */
$bot = new Client($config['botToken']);
// регистрируем команду start и указываем для нее callback
$bot->command('start', function ($message) use ($bot) {
    /** @var Message $message */
    $bot->sendMessage($message->getChat()->getId(), 'Welcome dear friend!');
});
// регистрируем команду quote и указываем для нее callback
$bot->command('quote', function ($message) use ($bot, $config) {
    /** @var Message $message */
    mt_srand();
    $randomQuote = $config['quotes'][mt_rand(0, count($config['quotes']) - 1)];
    $bot->sendMessage($message->getChat()->getId(), $randomQuote['quote'] . PHP_EOL . $randomQuote['author']);
});
// запускаем обработку полученных данных
$bot->run();

Как видно из кода выше, все достаточно просто, так как большая часть логики уже реализована за нас, остается только пользоваться.

Данная статья содержит один из самых простых примеров реализации телеграмм бота на php и имеет ряд недостатков. Например

  • весь код реализации содержится в одном входном файле
  • не отлавливаются исключения и не логируются ошибки
  • валидность конфигурации не проверяется и написана не в самом удобном виде

Есть и другое применение ботов - это отправка оповещений о каких-либо действиях (например, новое письмо с сайта или изменение статуса заказа), но это тема для отдельной статьи.

Что почитать:

  • 2017-11-29 08:31:38