Пишем первого бота для Telegram

Бот состоит из «скелета», расположенного на серверах Telegram, который осуществляет базовый функционал (связь по каналу приложение — сервер, показ описания, запуск и останов бота и т.п.), и «мяса», т.е. реализованного нами функционала бота, код которого должен располагаться на каком-нибудь хостинге.

Для взаимодействия «скелета» и «мяса» существует два способа — через функцию обратного вызова или через опрос по таймеру. То есть тут всё классически, для программистов ничего необычного. Для реализации первого способа нужен хостинг с поддержкой протокола https (т.е. с ключами SSL), для второго — возможность запуска фонового процесса для реализации опроса по таймеру.

Сегодня мы рассмотрим создание простейшего шаблонного бота, который на фразу «Привет» отвечает собственным приветствием. Чтобы не забивать голову поисками или созданиями сертификатов для https, предлагаю воспользоваться готовым бесплатным решением — облачным сервисом Cloud9, сайты на котором по умолчанию работают по протоколу https. Кроме того, он обладает всеми средствами, необходимыми для написания кода (облачная IDE). Конечно, хостинг там временный, работает только в течение работы над проектом, но зато очень упрощает проверку и тестирование кода. В дальнейшем же мы найдём более подходящее место для хостинга.

Рождение бота

  1. Для зачатия нашего бота нам понадобится бот-отец @BotFather. Добавляем его в контакты Telegram и отправляем ему команду /newbot. BotFather предложит дать имя нашему боту. Это имя будет отображаться в чате при общении с ботом, так что смело можем использовать кириллицу и пробелы. Если в дальнейшем вы захотите поменять это имя, то просто воспользуйтесь командой /setname.
  2. Далее BotFather предложит задать username (имя пользователя) для бота. Имя должно быть от 5 до 32 символов и заканчиваться словом bot, которое при желании можно отделить символом нижнего подчёркивания. Если введённое username уже будет в его базе, BotFather предложит вам ввести другое имя. В ответ на ввод правильного имени BotFather зарегистрирует нового бота и выдаст вам маркер (token) для доступа к программному интерфейсу нашего бота. Маркер представляет собой просто уникальный набор символов.

Всё, ваш бот рождён! Вы можете найти его и добавить в контакты. Но пока ещё он ничего не умеет.

Базовое наполнение бота

Давайте добавим к нашему боту базовый функционал. Заметьте, что мы снова обойдёмся без среды разработки и хостинга. Пока всё будет проходить в рамках мессенджера и серверов Telegram.

  1. Добавим нашему боту текст, который он будет выводить при добавлении его в контакты. Отправляем команду /setdescription. BotFather попросит указать имя бота, описание к которому мы задаём. Указываем имя, не забывая впереди указывать символ «@». В ответ BotFather запрашивает описание вашего бота. Вводим не более 512 символов, можно кириллицей, и отправляем.
  2. Добавляем боту в раздел его профиля «о роботе» текст описания. Используем команду /setabouttext. Далее — всё, как и в предыдущем пункте. Этот текст будет виден на странице информации о боте.
  3. Добавляем аватарку. Для этого используем команду /setuserpic. Изображение должно быть формата jpg или png, быть квадратным, и иметь размеры не менее 300х300. Загружать его нужно как «Фото», или просто перетащить мышкой в окно чата. Не забываем указывать имя своего бота, начиная с символа «@».
  4. Добавим подсказки имеющихся команд. Они будут появляться, как только вы набираете в поле сообщения прямой слеш (/) или нажимаете кнопку с тем же обозначением. Чтобы добавить подсказки команд, отправляем боту BotFather команду /setcommands и далее действуем, как и в предыдущих пунктах. Команды должны быть написаны на латинице. Поскольку мы будем использовать только русскоязычную команду «привет», продублируем её на английском, и введём в подсказку команду «hello». В будущем, добавляя список из нескольких команд, сохраните его где-нибудь под рукой, например, в комментариях исходника, потому что после его коррекции придётся опять загружать его целиком.

Подключение функционала

Подключение нашего внешнего файла с дополнительным кодом бота, как я уже писал выше, возможно двумя способами: Webhook для безопасного протокола https и long polling для обычного http. Второй способ более тормозной, потому что вместо прямого обращения бота к внешнему коду сразу после получения команды, в случае long polling внешний код сам через равные промежутки времени будет обращаться к чату и ждать ответа. Мы будем ориентироваться на первый вариант.

Cloud9

Регистрируемся на сайте Cloud9. Это облачная интегрированная среда разработки, в которой можно и написать, и временно опубликовать свой сайт. К сожалению, функционирование вашего сайта будет заморожено, если в течение некоторого времени над проектом никто не будет работать, и возобновлено в случае продолжения работ. Но для разработки и тестирования бота эта среда подходит нам как нельзя лучше.

Впоследствии, бота можно будет развернуть уже на настоящем хостинге, таком, как, например, Heroku, однако на бесплатном тарифе там тоже есть свои особенности — он будет работать не более 18 часов в сутки. Пока запросов на сайт нет, он засыпает и экономит своё время. При обращении он просыпается, поэтому возможна некоторая задержка первого ответа от бота. Пока пользователей у бота немного, этот вариант вполне может обеспечить круглосуточную работу.

Возможно, вы найдёте другой бесплатный хостинг с поддержкой SSL, который бы функционировал круглосуточно и без ограничений, но для разработки и отладки бота Cloud9 является наиболее удобной средой. Далее речь пойдёт о коде на PHP, но после регистрации на сайте Cloud9 вы можете выбрать для работы и другие языки.

Итак, регистрируемся, выбираем имя проекта (для порядка сделаем одинаковым с именем бота), можем выбрать приватность (в бесплатном случае для приватности доступен только один из ваших проектов). Далее можем указать Git или адрес живого сайта для его клонирования в Cloud9, а можем оставить это поле пустым, и тогда среда сама создаст шаблонный проект сайта. Затем выбираем шаблон среды, в котором будет крутиться наш бот (я выбрал «PHP, Apache and MySQL preconfigured») и нажимаем кнопку «Create workspace».

Создаётся ваше рабочее пространство и открывается редактор проекта. Если проект создан с нуля, то для удобства меняем имя основного файла hello-world.php на имя нашего бота. Также добавляем файл index.php со следующим содержанием (текст ИМЯ_ВАШЕГО_БОТА замените на имя сввоего бота):

  1. <?php
  2. header('Location: https://telegram.me/ИМЯ_ВАШЕГО_БОТА');

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

Пишем код бота

Шаблонный код нашего бота будет такой:

  1. <?php
  2. /**
    * URL-адрес бота и его маркер.
    */
  3. $access_token = 'ВАШ_МАРКЕР';
  4. $api = 'https://api.telegram.org/bot' . $access_token;
  5. /**
    * Зададим основные переменные.
    */
  6. $output = json_decode(file_get_contents('php://input'), TRUE); // Получим то, что передано скрипту ботом в POST-сообщении и распарсим
  7. $chat_id = $output['message']['chat']['id']; // Выделим идентификатор чата
  8. $first_name = $output['message']['chat']['first_name']; // Выделим имя собеседника
  9. $message = $output['message']['text']; // Выделим сообщение собеседника
  10. /**
    * Получим команды от пользователя.
    * Переведём их для удобства в нижний регистр
    */
  11. switch(strtolower_ru($message)) {
  12.   case ('привет'):
  13.   case ('/hello'):
  14.     sendMessage($chat_id, 'Привет, '. $first_name . '! ' . $emoji['preload'] );
  15.     break;
  16.   case ('/start'):
  17.     break;
  18.   default:
  19.     sendMessage($chat_id, 'Неизвестная команда!' );
  20.     break;
  21. }
  22. /**
    * Функция отправки сообщения в чат sendMessage().
    */
  23. function sendMessage($chat_id, $message) {
  24.   file_get_contents($GLOBALS['api'] . '/sendMessage?chat_id=' . $chat_id . '&text=' . urlencode($message));
  25. }
  26. /**
    * Функция перевода символов в нижний регистр, учитывающая кириллицу
    */
  27. function strtolower_ru($text) {
  28.   $alfavitlover = array('ё','й','ц','у','к','е','н','г', 'ш','щ','з','х','ъ','ф','ы','в', 'а','п','р','о','л','д','ж','э', 'я','ч','с','м','и','т','ь','б','ю');
  29.   $alfavitupper = array('Ё','Й','Ц','У','К','Е','Н','Г', 'Ш','Щ','З','Х','Ъ','Ф','Ы','В', 'А','П','Р','О','Л','Д','Ж','Э', 'Я','Ч','С','М','И','Т','Ь','Б','Ю');
  30.   return str_replace($alfavitupper,$alfavitlover,strtolower($text));
  31. }

Подробно рассматривать работу кода я не буду — он прост и сопровождён комментариями. Для завершения написания кода вам надо будет просто вставить присланный ранее ботом BotFather маркер (token) вместо текста «ВАШ_МАРКЕР». Он будет участвовать в формировании адреса, по которому этот код будет находить вашего бота.

Нажимаем кнопку Run Project. Сайт становится видим в сети и его код готов быть вызванным из бота.

Привязка бота к коду

Чтобы бот вызывал написанный нами внешний код, нам надо сообщить ему адрес нашего php-файла. Для этого копируем в строку браузера следующую ссылку:

https://api.telegram.org/botВАШ_МАРКЕР/setWebhook?url=URL_PHP_ФАЙЛА

Текст ВАШ_МАРКЕР заменяем присланным ранее маркером, а текст URL_PHP_ФАЙЛА заменяем на полный URL php-файла с нашим кодом. Имя сайта берём из строки, появившейся снизу на вкладке Apache & PHP, и добавляем к нему имя php-файла. После перехода по этому адресу браузер в случае успешной привязки возвращает текст:

{"ok":true,"result":true,"description":"Webhook was set"}

Теперь переходим в Telegram и проверяем работу бота. Отправим ему команду /hello или надпись «Привет» получим соответствующий ответ.

Замечу в заключение, что правку кода в Cloud9 можно выполнять на ходу, не останавливая выполнение проекта.