Наш магазин на eBay Наш магазин на AliExpress Наш канал в telegram

Инструкция по созданию Telegram ботов. Часть 3. Пишем простого чат-бота для Telegram на чистом php (webhook)

Создавать в Telegram аккаунты ботов мы уже научились (в предыдущей части), пора чего-нибудь накодить. Сегодня я покажу как создать простого чат-бота для Telegram на чистом, незамутнённом php, без всяких дополнительных библиотек и фреймворков. Такой чат-бот может использоваться, например, для организации чата на сайте или в интернет-магазине. При этом для связи с Telegram наш бот будет использовать вебхуки.

Итак, у нас есть домен (MYDOMEN), место на сервере от какого-либо хостера, поддержка https, а также мы зарегистрировали в Telegram аккаунт бота (BOTNAME) и получили токен (BOTTOKEN). Теперь нам нужно написать программу самого бота.

В общем виде у нашего бота будет следующий функционал:

  • сообщения, отправляемые юзерами боту, пересылаются ботом админу с пометкой от кого это сообщение
  • сообщения, отправляемые админом боту, пересылаются указанному юзеру (админ в своём сообщении должен указать кому оно предназначено)

Сначала опишем задуманный выше функционал более детально. Пусть наш бот понимает 3 команды: /start, /help, /send. Формат и выполняемые действия у этих команд будут такими:

  • /start, /help — отвечают юзеру приветствием и выдают список команд с описанием
  • /send message или /send chat_id message (в зависимости от того, кто эту команду отправляет)
    • Если команда отправлена не админом, — она отправляет в чат бота с админом сообщение chat_id: message, где chat_id — идентификатор чата бота с юзером от которого это сообщение отправлено. В этом случае указывать chat_id в самой команде не нужно.
    • Если команда отправлена админом, — она отправляет в чат с идентификатором chat_id сообщение message. В этом случае в команде нужно указать chat_id адресата.

Вот теперь переходим к кодингу.

Создаём папочку MYBOT, в ней файл bot.php, открываем его в каком-нибудь приличном блокноте, типа notepad++ или akelpad (сразу настраиваем кодировку «utf8 without bom») и пишем:

Код под катом

<?php
/* токен бота, базовый URL для управления им и идентификатор чата бота с админом */
$bot_access_token = 'BOTTOKEN';
$admin_chat_id = 'ADMINCHATID';
$bot_api = 'https://api.telegram.org/bot'.$bot_access_token;
 
// получаем то, что передано боту в POST-сообщении и
// распарсиваем в ассоциативный массив
$input_array = json_decode(file_get_contents('php://input'),TRUE);
 
$chat_id = $input_array['message']['chat']['id']; // выделяем идентификатор чата
$message = $input_array['message']['text'];       // выделяем сообщение
 
// начинаем распарсивать полученное сообщение
$command = '';          // команды нет
$user_chat_id = '';     // адресат не определён
$user_text = '';        // текст от юзера пустой
$admin_text = '';       // текст сообщения от админа тоже пустой
 
$message_length = strlen($message);   // определяем длину сообщения
if($message_length!=0){               // если сообщение не нулевое
    $fs_pos = strpos($message,' ');   // определяем позицию первого пробела
    if($fs_pos === false){            // если пробелов нет,
        $command = $message;          //  то это целиком команда, без текста
    }
    else{                             // если пробелы есть,
        // выделяем команду и текст
        $command = substr($message,0,$fs_pos);
        $user_text = substr($message,$fs_pos+1,$message_length-$fs_pos-1);
 
        $user_text_length = strlen($user_text);    // определяем длину выделенного текста
        // если команда от админа и после неё есть текст - продолжаем парсить
        if(($chat_id == $admin_chat_id)&&($command === '/send') && ($user_text_length!=0)){
            // определяем позицию второго пробела
            $ss_pos = strpos($user_text,' ');
            if($ss_pos === false){                 // если второго пробела нет
                $user_chat_id = $user_text;        // то это целиком id чата назначения,
                $user_text = '';                   // а user_text - пустой
			}
            else{                     // если пробелы есть
                // выделяем id чата назначения и текст
                $user_chat_id = substr($user_text,0,$ss_pos);
                $admin_text = substr($user_text,$ss_pos+1,$user_text_length-$ss_pos-1);
            }
        }
    }
}
 
// после того, как всё распарсили, - начинаем проверять и выполнять
switch($command){
    case('/start'):
    case('/help'):
        sendMessage($chat_id,'Здравствуйте! Я робот, бла-бла-бла. Я знаю такие команды:
            /help - вывести список поддерживаемых команд
            /send <i>message</i> - послать <i>message</i> админу');
        // если это команда от админа, дописываем что можно только ему
        if($chat_id == $admin_chat_id){
            sendMessage($chat_id,'Поскольку вы админ, то можно ещё вот это:
            /send <i>chat_id</i> <i>message</i> - послать <i>message</i> в указанный чат');
        }
    break;
    case('/send'):    // отсылаем админу id чата юзера и его сообщение
        if($chat_id == $admin_chat_id){
            // посылаем текст по назначению (в указанный user_chat)
            sendMessage($user_chat_id, $admin_text);
        }
        else{
            sendMessage($admin_chat_id,$chat_id.': '.$user_text);
        }
    break;
    // команда /whoami добавлена чтобы админ мог узнать и записать
    // id своего чата с ботом, после этого её можно стереть
    case('/whoami'):
        sendMessage($chat_id,$chat_id);    // отсылаем юзеру id его чата с ботом
    break;
    default:
        sendMessage($chat_id,'неизвестная команда');
    break;
}
 
/* Функция отправки сообщения в чат с использованием метода sendMessage*/
function sendMessage($var_chat_id,$var_message){
    file_get_contents($GLOBALS['bot_api'].'/sendMessage?chat_id='.$var_chat_id.'&text='.urlencode($var_message));
}
?>;

[свернуть]

Вот и всё. Код, в общем-то, рабочий, теперь осталось залить папочку MYBOT с файлом bot.php к себе на сервак и установить на него webhook.

Для того, чтобы установить webhook, — достаточно просто отправить запрос вида:

https://api.telegram.org/bot[BOTTOKEN]/setWebhook?url=https://[MYDOMEN]/[MYBOT]/bot.php

Для того, чтобы отменить webhook — нужно отправить такой же запрос, но без урла, указывающего расположение бота. То есть вот такой:

https://api.telegram.org/bot[BOTTOKEN]/setWebhook

Итак, файл залит, webhook установлен. Первым делом нужно узнать id своего чата с ботом командой /whoami. Далее нужно отредактировать файл bot.php, вписав этот id в ADMINCHATID. После всего этого команду /whoami можно из файла bot.php удалять, она больше не нужна.

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

Во-первых, давайте вынесем токен нашего бота и id чата админа в отдельный файл config.php и запретим к нему доступ через .htaccess:

  • создаём файл config.php и переносим туда строки:
        $bot_access_token = 'BOTTOKEN';
        $admin_chat_id = 'ADMINCHATID';
  • вместо них пишем в файле bot.php следующее:
    include('config.php');
  • создаём файл .htaccess и пишем в нём следующее:
    Код под катом

    <IfModule mod_version.c>
        <IfVersion < 2.4>
            <Files "config.php">
                Order Allow,Deny
                Deny from All
            </Files>
        </IfVersion>
        <IfVersion >= 2.4>
            <Files "config.php">
                Require all denied
            </Files>
        </IfVersion>
    </IfModule>
    <IfModule !mod_version.c>
        <IfModule !mod_authz_core.c>
            <Files "config.php">
                Order Allow,Deny
                Deny from All
            </Files>
        </IfModule>
        <IfModule mod_authz_core.c>
            <Files "config.php">
                Require all denied
            </Files>
        </IfModule>
    </IfModule>

    [свернуть]

Перезаливаем всё это к себе на сервак, в папку MYBOT, и радуемся, — Ура! Теперь токен нашего бота никто не увидит. Ага, как бы не так, — config.php инклюдится в bot.php, так что при возникновении каких-то ошибок во время исполнения bot.php мы по-прежнему можем увидеть этот файл вместе с уже проинклюденным туда токеном.

Ради интереса можете просто набрать в адресной строке браузера http://[MYDOMEN]/[MYBOT]/bot.php и попробовать открыть эту страницу. Никакого json-объекта наш браузер при таком запросе, ясное дело, файлу bot.php не пришлёт. А значит, — распарсив то, чего нет, а потом ещё и попытавшись к этому обратиться, мы получим ошибку. При этом нам в браузер выкинут содержимое bot.php с указанием строки, где он обломался и (Внезапно!) с заветным токеном.

Придётся добавить хоть какую-то обработку ошибок. Давайте впишем в файл bot.php такие строки:

  • после строки
    $input_array = json_decode(file_get_contents('php://input'),TRUE);

    добавляем код

    if($input_array){
  • перед строкой
    /* Функция отправки сообщения в чат с использованием метода sendMessage*/

    добавляем код

    else{
        print("Hello, I am bot! My name is @[BOTNAME]. Bla-bla-bla...");
    }

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

Всё, чат-бот готов. Однако! Во-первых, хорошо бы сохранять какую-то информацию о юзерах, общающихся с нами через этого бота (id-шники юзеров, историю переписки, время и дату получения сообщений…). Во-вторых, мы не имеем возможности забанить юзеров, подключающихся к нашему боту, соответственно, рискуем получить через своего бота нескончаемый поток спама. В-третьих, было бы отлично иметь возможность добавлять и убирать админов, которым бот будет рассылать сообщения (такая себе претензия на call-центр).

Для решения этих задач мы в следующей части допишем ещё немного кода и прикрутим к нашему боту базу MySQL.

  1. Часть 1. Что такое Telegram боты и как они работают
  2. Часть 2. Регистрация аккаунтов Telegram ботов в картинках
  3. Часть 3. Пишем простого чат-бота для Telegram на чистом php (webhook)
  4. Часть 4. Прикручиваем MySQL к чат-боту для Telegram на php (webhook)
  5. Часть 5. Пишем Telegram бота на php для работы через longpolling
  6. Часть 6. Делаем пользовательскую клавиатуру для бота
  7. Дополнение. Как отправлять правильные https-запросы через curl и при чём здесь SSL-cертификаты

Добавить комментарий