Наш канал в telegram

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

  1. Часть 1. Что такое Telegram боты и как они работают
  2. Часть 2. Регистрация аккаунтов Telegram ботов в картинках
  3. Часть 3. Пишем простого чат-бота для Telegram на чистом php (webhook)
  4. Часть 4. Прикручиваем MySQL к чат-боту для Telegram на php (webhook)
  5. Часть 5. Пишем Telegram бота для работы через long polling

Создавать в 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?url=''

Итак, файл залит, 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 бота для работы через long polling

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