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