Пишем простого чат-бота для Telegram на PHP

Шукюров Заур, разработчик @KinomanBot и @GaidarForum_bot, написал руководство по созданию простого чат-бота.

24 июня 2015 года разработчики Telegram открыли платформу для создания ботов (программ, которые выполняют определенные действия по заданному алгоритму). За полтора года работы платформы набралось много интересных чат-ботов, решающих множество проблем и позволяющих с пользой провести время в мессенджере.

Шаг 1: регистрация бота у @BotFather

Прежде чем начать писать код, нового бота нужно зарегистрировать у «папы всех ботов» — @BotFather, чтобы получить токен (ключ) для работы с Telegram API. Регистрация проходит в 5 простых этапов:

  • Открываете чат с @BotFather.
  • Вводите или выбираете из списка команду /newbot.
  • Отправляете желаемое название для бота.
  • Пишете юзернейм бота, по которому его будут находить через поиск. Обязательно на конце вашего юзернейма должно быть слово «bot» или »_bot». Например, NetologyRSSbot.
  • По желанию можно сразу настроить полное или краткое описание, список команд и аватарку.
  • @BotFather

    По итогу регистрации получаем наш токен — 375466075: AAEARK0r2nXjB67JiB35JCXXhKEyT42Px8s.

    Будьте осторожны: никогда и никому не показывайте токен, иначе ваш бот может быть скомпрометирован. Если по несчастливой случайности кто-то нехороший все-таки узнал ваш токен, то заменить его можно всё в том же @BotFather, нажав на кнопку «Revoke current token» в разделе «API Token».

    Шаг 2: выбираем способ обработки запросов

    Исходя из официальной документации, Telegram API основан на простых HTTP-запросах. Существует всего два различных способа обрабатывать запросы, которые пользователи будут посылать боту:

  • Проверять «вручную», используя «Long Polling».
  • Доверить всё Telegram, поставив «Webhook». В этом случае любой запрос от пользователя Telegram сам будет посылать нам на сервер.
  • Мы остановимся на втором варианте, но у него есть ограничение: у вас на сайте обязательно должен быть установлен SSL-сертификат, чтобы все запросы проходили через безопасный протокол HTTPS. Самоподписанные и бесплатные сертификаты «Lets Encrypt», которые поддерживает большинство хостингов, также подходят.

    Пример настройки самоподписанного сертификата из официальной документации Telegram.

    Шаг 3: пишем код

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

    Перво-наперво привязываем через метод SetWebhook бота к нашему файлу-обработчику. Сделать это можно при помощи библиотеки, но есть вариант быстрее и проще — это построить вот такую ссылку:

    https://api.telegram.org/bot375466075: AAEARK0r2nXjB67JiB35JCXXhKEyT42Px8s/setWebhook? url=https://yoursitehere.ru/directory/bot.php,

    где

    375466075: AAEARK0r2nXjB67JiB35JCXXhKEyT42Px8s — это наш токен,

    https://yousitehere.ru/directory/bot.php — ссылка на файл-обработчик на нашем сайте.

    Открыв в браузере эту ссылку, должен прийти JSON-ответ со значением «Webhook was set», что будет означать, что вебхук установлен, и теперь все запросы от пользователей будут присылаться по адресу файла-обработчика.

    Переходим к самому главному — обработке этих самых запросов и написанию функционала бота. Ниже представлен полный листинг файла-обработчика:

    ? php

    include ('vendor/autoload.php'); //Подключаем библиотеку

    use TelegramBotApi;

    $telegram = new Api ('375466075: AAEARK0r2nXjB67JiB35JCXXhKEyT42Px8s'); //Устанавливаем токен, полученный у BotFather

    $result = $telegram — getWebhookUpdates (); //Передаем в переменную $result полную информацию о сообщении пользователя

    $text = $result[«message»][«text»]; //Текст сообщения

    $chat_id = $result[«message»][«chat»][«id»]; //Уникальный идентификатор пользователя

    $name = $result[«message»][«from»][«username»]; //Юзернейм пользователя

    $keyboard = [[«Последние статьи»],[«Картинка»],[«Гифка»]]; //Клавиатура

    if ($text){

    if ($text == »/start») {

    $reply = «Добро пожаловать в бота!»;

    $reply_markup = $telegram-replyKeyboardMarkup ([ 'keyboard' = $keyboard, 'resize_keyboard' = true, 'one_time_keyboard' = false ]);

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'text' = $reply, 'reply_markup' = $reply_markup ]);

    }elseif ($text == »/help») {

    $reply = «Информация с помощью.»;

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'text' = $reply ]);

    }elseif ($text == «Картинка») {

    $url = «https://68.media.tumblr.com/6d830b4f2c455f9cb6cd4ebe5011d2b8/tumblr_oj49kevkUz1v4bb1no1_500.jpg»;

    $telegram-sendPhoto ([ 'chat_id' = $chat_id, 'photo' = $url, 'caption' = «Описание.» ]);

    }elseif ($text == «Гифка») {

    $url = «https://68.media.tumblr.com/bd08f2aa85a6eb8b7a9f4b07c0807d71/tumblr_ofrc94sG1e1sjmm5ao1_400.gif»;

    $telegram-sendDocument ([ 'chat_id' = $chat_id, 'document' = $url, 'caption' = «Описание.» ]);

    }elseif ($text == «Последние статьи») {

    $html=simplexml_load_file ('http://netology.ru/blog/rss.xml');

    foreach ($html-channel-item as $item) {

    $reply .= »xE2x9ExA1 ».$item-title.» (a href='».$item-link.»'читать/a)n»;

    }

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'parse_mode' = 'HTML', 'disable_web_page_preview' = true, 'text' = $reply ]);

    }else{

    $reply = «По запросу «b».$text.»/b» ничего не найдено.»;

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'parse_mode'= 'HTML', 'text' = $reply ]);

    }

    }else{

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'text' = «Отправьте текстовое сообщение.» ]);

    }

    ?

    Разберем всё по порядку.

    1. Сначала мы подключаем скачанную библиотеку, указав путь (лучше полный) до файла автозагрузчика.

    include ('vendor/autoload.php'); //Подключаем библиотеку

    use TelegramBotApi;

    2. Создаем экземпляр класса в переменной $telegram и передаем в него наш токен. В переменной $result получаем информацию о сообщении, которое пришлет нам Telegram.

    $telegram = new Api ('375466075: AAEARK0r2nXjB67JiB35JCXXhKEyT42Px8s'); //Устанавливаем токен, полученный у BotFather

    $result = $telegram — getWebhookUpdates (); //Передаем в переменную $result полную информацию о сообщении пользователя

    3. Затем определяем главные переменные: текстовое сообщение, уникальный идентификатор пользователя и его юзернейм. Если предстоит работа с БД, то не забывайте про фильтрацию (или лучше используйте PDO).

    $text = $result[«message»][«text»]; //Текст сообщения

    $chat_id = $result[«message»][«chat»][«id»]; //Уникальный идентификатор пользователя
    $name = $result[«message»][«from»][«username»]; //Юзернейм пользователя

    4. Создаем нашу клавиатуру, состоящую из трех кнопок.

    $keyboard = [[«Последние статьи»],[«Картинка»],[«Гифка»]]; //Клавиатура

    5. Теперь, когда мы обозначили все переменные, можно перейти к обработке полученного сообщения. Для этого можно использовать конструкцию switch-case либо if-else. Так как принципиальной разницы между ними нет, остановимся на втором варианте, как наиболее привычном.

    В самом начале проверяем, заполнена ли переменная $text и является ли сообщение пользователя текстовым.

    if ($text){

    //код

    }else{

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'text' = «Отправьте текстовое сообщение.» ]);

    }

    Если нет, то отправляем пользователю с помощью метода sendMessage сообщение с просьбой ввести текстовое сообщение.

    6. Рассмотрим вариант, когда пользователь прислал сообщение с командами /start или /help

    if ($text == »/start») {

    $reply = «Добро пожаловать в бота!»;

    $reply_markup = $telegram-replyKeyboardMarkup ([ 'keyboard' = $keyboard, 'resize_keyboard' = true, 'one_time_keyboard' = false ]);

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'text' = $reply, 'reply_markup' = $reply_markup ]);

    }elseif ($text == »/help») {

    $reply = «Информация с помощью.»;

    $reply_markup = $telegram-replyKeyboardMarkup ([ 'keyboard' = $keyboard, 'resize_keyboard' = true, 'one_time_keyboard' = false ]);

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'text' = $reply, 'reply_markup' = $reply_markup ]);

    }

    В этом случае помимо текста из переменной $reply будет подгружаться клавиатура, состоящая из трёх кнопок: «Последние статьи», «Картинка» и «Гифка». Реализуется это с помощью метода replyKeyboardMarkup, параметрами которого являются:

    • 'keyboard' = $keyboard, передаем нашу клавиатуру;
    • 'resize_keyboard' = true, клавиатура будет сжата в размерах;
    • 'one_time_keyboard' = false, клавиатура не исчезнет после нажатия на какую-то кнопку.

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

    }elseif ($text == «Картинка») {

    $url = «https://68.media.tumblr.com/6d830b4f2c455f9cb6cd4ebe5011d2b8/tumblr_oj49kevkUz1v4bb1no1_500.jpg»;

    $telegram-sendPhoto ([ 'chat_id' = $chat_id, 'photo' = $url, 'caption' = «Описание.» ]);

    }elseif ($text == «Гифка») {

    $url = «https://68.media.tumblr.com/bd08f2aa85a6eb8b7a9f4b07c0807d71/tumblr_ofrc94sG1e1sjmm5ao1_400.gif»;

    $telegram-sendDocument ([ 'chat_id' = $chat_id, 'document' = $url, 'caption' = «Описание.» ]);

    }elseif ($text == «Последние статьи») {

    $html=simplexml_load_file ('http://netology.ru/blog/rss.xml');

    foreach ($html-channel-item as $item) {

    $reply .= »xE2x9ExA1 ».$item-title.» (a href='».$item-link.»'читать/a)n»;

    }

    $telegram-sendMessage ([ 'chat_id' = $chat_id, 'parse_mode' = 'HTML', 'disable_web_page_preview' = true, 'text' = $reply ]);

    }

    8. Для отправки картинки используется метод sendPhoto, для отправки гифки — sendDocument. В обоих случаях Telegram позволяет передавать прямую ссылку на файл, что безусловно очень удобно, но не так быстро, как если бы мы передавали file_id уже отправленной на сервера Telegram картинки или гифки.

    9. Для получения последних статей используется простой парсинг RSS ленты Нетологии при помощи встроенной в PHP функции simplexml_load_file.

    В параметрах метода sendMessage можно заметить два новых значения:

  • 'parse_mode' = 'HTML', чтобы в сообщение можно было вставить HTML-теги (b, a, i, code или pre).
  • 'disable_web_page_preview' = true, чтобы к сообщению со ссылкой не подгружалось превью.
  • 10. В качестве смайла (стрелка вправо) используются символы xE2x9ExA1. Список всех смайлов в таком виде можно найти на специальном сайте.

    Результаты

    11. После того, как вы протестируете бота и будете уверены в его работоспособности, можно отправлять его на всеобщее обозрение.

    Благодаря удобному API, боты Telegram могут стать хорошей платформой для автоматизации рутинных действий, настройки уведомлений, удобному и быстрому получению информации и созданию игр. Бесплатными площадками для продвижения могут послужить каталоги ботов Telegram Bot Store, TeleChappy или 50bots. А анализировать активность пользователей можно с помощью бесплатного инструмента для аналитики ботов от Яндекса — Botan.

    От редакции

    PHP — один из самых популярных языков программирования. Его легко изучать, с ним легко работать, у него мощное сообщество. 5 мая «Нетология» запускает курс «PHP/SQL: back-end разработка и базы данных», где ведущие программисты расскажут об управляющих конструкциях, циклах, функциях, о строках и массивах. Вы узнаете все про реляционные базы данных и язык запросов SQL, научитесь устанавливать и настраивать веб-сервер nginx и php, управлять базами данных различной сложности. Ждем вас!