Cоздание простого Telegram-бота на PHP

КДПВ (~280КБ) Недавно назрела необходимость создать простого бота, который бы взаимодействовал с классами и методами из материнского проекта (сайта). В принципе можно было бы писать на любом языке, а потом написать некий коннектор, взаимодействие между этим всем. Но лично для меня было в разы проще написать самого бота также на PHP.

Впрочем приступим к делу. Первым делом обсудим что нам понадобится:

  1. PHP 5.6+
  2. NGINX или Apache в качестве веб-сервера.
  3. В случае с Nginx понадобится ещё php-fpm, например.
  4. Сертификат от LetsEncrypt (то есть без домена никак, но разве это проблема в 2016 году? Сейчас можно с легкостью купить домен в зоне .xyz за доллар-два).
  5. ОПЦИОНАЛЬНО: MySQL-совместимая база данных. То есть непосредственно MySQL или MariaDB.

То есть вам нужен готовый вебсервер, с настроенным PHP и SSL-соединением. База данных опциональна и будет использоваться для создания интерактивных диалогов, в которых бот будет учитывать прошлые сообщения. Как настроить SSL в случае с NGINX, вы можете прочитать здесь.

Для чего SSL спросите вы? Для того чтобы работать с Telegram, используя вебхуки. Они надежней и удобнее, классического Long Polling. Для тех кто совсем не понимает о чем я, поясняю:

  • Long Polling: Наш сервер бы постоянно опрашивал Telegram об обновлениях.
  • Webhooks: Telegram сам будет посылать эти обновления нам на сервер.

То есть ваш сервер будет отвечать как минимум быстрее, будет меньше нагружен и не будет делать лишнюю работу. Помимо этого этот метод надежнее в работе.

Итак, вы настроили сервер, для проверки можете создать в корне (к примеру у вас он может быть здесь: /var/www/project1) файл test.php и в теле написать:

<?php
phpinfo();
?>

Теперь перейдите в браузере на https://domain.xyz/test.php, вы должны получить страницу с конфигурацией вашего PHP. Помимо этого убедитесь, что SSL настроен корректно (к примеру на сайте SSLLabs).

Сервер готов, можно начинать создание бота.

akalongman/php-telegram-bot -- самая удобная библиотека

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

Интересно также то, что есть команды администратора бота, которые позволяют быстро узнать список пользователей, которые им пользуются, возможность рассылки объявлений и т.д.

Разумеется большинство этих команд будут использовать базу даннах, так что настоятельно рекомендую настроить. Поэтому, изучив эти команды, вы сможете написать бота практически любой сложности. В последствии эти команды можно будет отключить и использовать только свои.

Для меня PHP был изначально новым языком, поэтому все что я делал -- я делал, по сути, в первый раз. Поэтому для некоторых вещи, описанные ниже, будут весьма очевидными. Первым делом нам потребуется Composer, нечто вроде пакетного менеджера для PHP, с его помощью мы сможем легко поддерживать актуальную версию библиотеки:

cd /var/www/project1
curl -sS https://getcomposer.org/installer | php

Разумеется не забудьте указать свой путь до проекта.

После выполнения этой команды Composer автоматически установится в директорию проекта. Теперь установим саму библиотеку php-telegram-bot:

php composer.phar require longman/telegram-bot

Библиотека установлена и теперь мы можем переходить непосредственно к созданию самого бота. Создайте файл hook.php в корневой директории и каталог commands. Наполните файл hook.php следующим содержимым:

<?php
require_once __DIR__ . "/vendor/autoload.php";

// Получите токен у бота @BotFather
$API_KEY = your_token;
// Получите свой User ID у бота @MyTelegramID_bot
$USER_ID = your_userid;
// Придумайте своему боту имя
$BOT_NAME = "Your Bot";

// Данные базы данных
$mysql_credentials = [
   'host'     => 'localhost',
   'user'     => 'db_user',
   'password' => 'db_pass',
   'database' => 'db',
];

use Longman\TelegramBot\Telegram;
use Longman\TelegramBot\TelegramLog;

try {
	// Инициализация бота
	$telegram = new Telegram($API_KEY, $BOT_NAME);

	// Подключение базы данных
	$telegram->enableMySQL($mysql_credentials);

	// Добавление папки commands,
	// в которой будут лежать ваши личные комманды
	$telegram->addCommandsPath(__DIR__ . "/commands");

	// Добавление администратора бота
	$telegram->enableAdmin((int)$USER_ID);

	// Включение логов
	TelegramLog::initUpdateLog($BOT_NAME . '_update.log');

	// Опционально. Здесь вы можете указать кастомный объект update,
	// чтобы поймать ошибки через var_dump.
	//$telegram->setCustomInput("");

	// Основной обработчик событий
	$telegram->handle();

} catch (Longman\TelegramBot\Exception\TelegramException $e) {
	// В случае неудачи будет выведена ошибка
	var_dump($e);
}

Внимательно прочитайте комментарии, я описал каждую строчку.

Обработчик готов, теперь укажите Telegram вебхук. Другими словами адрес вашего сервера, на который Telegram должен посылать обновления. Просто введите в адресную строку подобный запрос, не забыв указать вместо YOURTOKEN свой токен, который вам выдал @BotFather: https://api.telegram.org/botYOURTOKEN/setwebhook?url=https://domain.xyz/hook.php

Бот почти готов, наберите в браузере https://domain.xyz/hook.php. Вы должны увидеть вывод и ошибку Input is empty!. Если всё так, то вероятно ваш бот настроен и готов к работе. Попросту напишите ему в Telegram и отправьте, к примеру команду /help. Если бот вам ответит -- настройка завешена.

В созданном вами каталоге commands создайте новый файл с названием вашей команды, например, myNewCustomCommand.php и наполните её следующим содержимым:

<?php
namespace Longman\TelegramBot\Commands\UserCommands;

use Longman\TelegramBot\Commands\UserCommand;
use Longman\TelegramBot\Request;

class myCustomCommand extends UserCommand {
	protected $name = 'mycustomcommand';
	protected $description = 'Для тестирования';
	protected $usage = '/mycustomcommand';
	protected $version = '1.0.0';

	public function execute()
	{
		// Основной код
		return Request::sendMessage($data);
	}
}

Используйте эту базу во всех своих командах. Смотрите примеры уже написаных команд, коих, благо, множество и пишите свои!