Как написать бота на пхп

Обсудить …

05.07.2021     👁 21771


Здравствуйте, дорогие читатели. Раз вы здесь, то пришли вы сюда из поиска по фразе «бот для телеграм на пхп». И работающего бота вы сделать сможете, прочитав данную статью. Вопросы для чего вам бот в Телеграм, здесь не обсуждаются, хотя мы сами используем собственного публичного бота @novelsite_bot для информирования о нас и наших услугах и сборе заявок. А также у нас есть закрытый бот, который мы используем как информатор в CRM (уведомления, свои задачи) и как показала практика — это действительно удобно.

Итак, 

Создадим простого бота для мессенджера Telegram с использованием PHP. Данная статья создана исключительно в поучительных целях и не претендует на полноту или правильность подхода. Весь код бота очень простой и может быть освоен начинающими PHP-разработчиками. 

Предупреждаю сразу профессионалов и перфекционистов от программирования — вам здесь делать нечего devil. Никаких фреймворков и гитхабов! Все будет очень просто и примитивно, но работать будет. И это главное. Всем счастья smiley

Шаг 1: подготовка

Что нам понадобится:

  1. Веб-сервер с работающим PHP 5.6 и выше — не локальный веб-сервер, а веб-сервер на хостинге, что важно! Так как сервисы Telegram должны будут видеть вашего бота по внешней URL-ссылке;
  2. Веб-сервер должен работать через https — то есть на веб-сервере должен быть установлен давно (больше суток назад) зарегистрированный SSL-сертификат. Достаточно будет бесплатного Let’s Encrypt SSL-сертификата;
  3. Доступ к файлам на этом сервере, конечно же — иначе как мы что-то сделаем;
  4. Установленная кодовая страница UTF-8 на сервере по-умолчанию или добавьте в файл .htacces в корне сайта строку AddDefaultCharset utf-8;
  5. Аккаунт в мессенджере Telegram;

Шаг 2. Регистрация вашего бота в Телеграм

Да, да. Бот еще даже не создан, но перед этим его уже нужно зарегистрировать, чтобы получить уникальный идентификатор, чтобы в дальнейшем обращаться к BOT API Telegram.

  • Для этого заходим в Телеграм в специального бота @BotFather и присоеденяемся к нему — кнопка Присоединится, при этом бот выдаст команду /start — это базовая команда любого бота;
  • @BotFather вас поприветствует и можно посмотреть все команды, введя /help
  • Создаем бота, введя /newbot
  • И вводим имя бота и username, чтобы не заморачиваться — введите одинаково, но помните, что username вводится на латинице и в конце должно быть _bot, например:
    username: verysimple_bot — подходит
    username: verysimplebot — не подходит
  • Далее @BotFather вас поздравит и выдаст ключ или токен бота для HTTP API — по сути это строка из номера (ID) бота и набора случайных символов, примерно в таком виде:
    1234567899:AAKJhkkjhkjhKhKhjkhkhk_kJhgkjhJhgjghjhG
    Запомните свой токен — он нам понадобится дальше.
  • Далее можно задать картинку (аватар) бота, введя /setuserpic
    — Можно использовать любую вашу картинку в формате JPG, PNG, загрузив её после этой команды.
  • Можно приступать к программированию…

Шаг 3. Создаем код бота

Будем делать прямо в корне сервера (не самый верный подход, можно создать папку bot, а в ней уже файл verysimple_bot.php). Для этого на сервере создадим файл verysimple_bot.php в котором и будет весь код бота. Не забываем, что весь код в файле verysimple_bot.php должен быть в кодировке UTF-8.

Для редактирования файлов кода и заброске их на сервер удобно использовать FAR Manager — в нем есть и подсветка синтаксиса и FTP/SFTP клиент для копирования файла на сервер.

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

/**
*   Very simple chat bot @verysimple_bot by Novelsite.ru
*   05.07.2021
*/
header('Content-Type: text/html; charset=utf-8'); // на всякий случай досообщим PHP, что все в кодировке UTF-8

$site_dir = dirname(dirname(__FILE__)).'/'; // корень сайта
$bot_token = '1234567899:AAKJhkkjhkjhKhKhjkhkhk_kJhgkjhJhgjghjhG'; // токен вашего бота
$data = file_get_contents('php://input'); // весь ввод перенаправляем в $data
$data = json_decode($data, true); // декодируем json-закодированные-текстовые данные в PHP-массив

// Для отладки, добавим запись полученных декодированных данных в файл message.txt, 
// который можно смотреть и понимать, что происходит при запросе к боту
// Позже, когда все будет работать закомментируйте эту строку:
file_put_contents(__DIR__ . '/message.txt', print_r($data, true));

// Основной код: получаем сообщение, что юзер отправил боту и 
// заполняем переменные для дальнейшего использования
if (!empty($data['message']['text'])) {
    $chat_id = $data['message']['from']['id'];
    $user_name = $data['message']['from']['username'];
    $first_name = $data['message']['from']['first_name'];
    $last_name = $data['message']['from']['last_name'];
    $text = trim($data['message']['text']);
    $text_array = explode(" ", $text);
    
    if ($text == '/help') {
        $text_return = "Привет, $first_name $last_name, вот команды, что я понимаю: 
/help - список команд
/about - о нас
";
        message_to_telegram($bot_token, $chat_id, $text_return);
    }
    elseif ($text == '/about') {
        $text_return = "verysimple_bot:
Я пример самого простого бота для телеграм, написанного на простом PHP.
Мой код можно скачивать, дополнять, исправлять. Код доступен в этой статье:
https://www.novelsite.ru/kak-sozdat-prostogo-bota-dlya-telegram-na-php.html
";
        message_to_telegram($bot_token, $chat_id, $text_return);
    }

}

// функция отправки сообщени в от бота в диалог с юзером
function message_to_telegram($bot_token, $chat_id, $text, $reply_markup = '')
{
    $ch = curl_init();
    $ch_post = [
        CURLOPT_URL => 'https://api.telegram.org/bot' . $bot_token . '/sendMessage',
        CURLOPT_POST => TRUE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_POSTFIELDS => [
            'chat_id' => $chat_id,
            'parse_mode' => 'HTML',
            'text' => $text,
            'reply_markup' => $reply_markup,
        ]
    ];

    curl_setopt_array($ch, $ch_post);
    curl_exec($ch);
}

Шаг 4. Делаем WebHook и конкретизируем код бота

Итак, базовый код бота мы сделали. Он сможет отвечать на 2 команды: /help (Помощь) и /about (Информация о нас). Но как теперь это заставить работать и, как работает функция message_to_telegram

  1. Чтобы все заработало, нужно сособщить сервису Телеграм, что наш бот лежит там-то — используй его код для такого-то бота verysimple_bot.
    Для этого нужно сформировать ссылку, которая называется WebHook и её мы и сообщим телеграму:

    https://api.telegram.org/bot1234567899:AAKJhkkjhkjhKhKhjkhkhk_kJhgkjhJhgjghjhG/setWebhook?url=https://www.mysite.ru/verysimple_bot.php

    Не забываем где красное заменяем на свои данные!
    Как сформируете эту ссылку — вставьте её в браузер и запустите!

    Если все пройдет правильно, то ответ на эту ссылку в браузере будет примерно такой:
      {«ok»:true,»result»:true,»description»:»Webhook was set»}  

  2. Функция message_to_telegram отправляет сообщение через Telegram Bot API в диалог бота, формируя массив в нужном формате через вызов библиотеки CURL (обычно встроена в PHP). С CURL более правильно и структурировано работает с https-запросами.

    То есть мы обращаемся к телеграм бот API, указав ему нашего бота и сделав запрос /sendMessage и передав наш текст, а бот Api уже «запихает» это сообщение в мессенджер Телеграм — и мы увидем реультат. Получается цепочка:

    1. Пользователь в диалоге с ботом пишет запрос, например /help
    2. Telegram Bot API через WebHook, что мы установили, берет этот запрос и отправляет в код бота
    3. Мы в боте получаем его, анализируем, видим  например, /help и через Telegram Bot API и
      функцию message_to_telegram отправляем ответ — который появлется в диалоге как ответ бота.

Шаг 5. Добавим возможность делать заявки через бота

Заявкой будем считать сообщение или вопрос, которое можно будет отправить через нашего бота какому-то пользователю, назовем его менеджер компании. То есть нам нужно организовать такую цепочку:

  1. Пользователь запрашивает у бота «Оставить заявку», например набрав команду /order
  2. Бот входит в режим ожидания текста Заявки
  3. Если пользователь ввел текст и нажал Enter, только тогда отослать это сообщение заранее запрограммированному по менеджеру компании.

Получим идентификатор chat_id пользователя кому нужно отсылать заявки:

  1. Помните наш файл message.txt — вот он сейчас понадобится
  2. Присоединяемся к нашему боту тем пользователем, кому будем слать заявки (менеджер компании)
  3. Сразу открываем файл message.txt и смотрим блок: [chat]

                [chat] => Array
                    (
                        [id] => 123456789
                        [first_name] => manager
                        [last_name] => company
                        [username] => username
                        [type] => private
                    )

  4. Сохраняем это в коде бота сверху и добавим переменную состояния бота:
$order_chat_id = '123456789';  //chat_id менеджера компании для заявок
$bot_state = ''; // состояние бота, по-умолчанию пустое

Сохраняем состояние бота для каждого пользователя

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

Напишем две функции: set_bot_state($chat_id, $data) и get_bot_state($chat_id) — которые сохраняют текущее состояние бота и получают соответсвенно, для нужного пользователя. Сохранять будем в подпапке /users на сервере, которую создадим предварительно не забыв дать права на запись. Состояния будут хранится все в тех же текстовых файлах с именами chat_id пользователей и содержать последнюю команду:

// сохранить состояние бота для пользователя
function set_bot_state ($chat_id, $data)
{
    file_put_contents(__DIR__ . '/users/'.$chat_id.'.txt', $data);
}

// получить текущее состояние бота для пользователя
function get_bot_state ($chat_id)
{
    if (file_exists(__DIR__ . '/users/'.$chat_id.'.txt')) {
        $data = file_get_contents(__DIR__ . '/users/'.$chat_id.'.txt');
        return $data;
    }
    else {
        return '';
    }
}

Теперь дополним код бота, добавив запись и отлов состояния и отправив заявку менеджеру компании, если состояние отправки заявки.

/**
*   Very simple chat bot @verysimple_bot by Novelsite.ru
*   05.07.2021
*/
header('Content-Type: text/html; charset=utf-8'); // на всякий случай досообщим PHP, что все в кодировке UTF-8

$site_dir = dirname(dirname(__FILE__)).'/'; // корень сайта
$bot_token = '1234567899:AAKJhkkjhkjhKhKhjkhkhk_kJhgkjhJhgjghjhG'; // токен вашего бота
$data = file_get_contents('php://input'); // весь ввод перенаправляем в $data
$data = json_decode($data, true); // декодируем json-закодированные-текстовые данные в PHP-массив

$order_chat_id = '123456789';  //chat_id менеджера компании для заявок
$bot_state = ''; // состояние бота, по-умолчанию пустое

// Для отладки, добавим запись полученных декодированных данных в файл message.txt, 
// который можно смотреть и понимать, что происходит при запросе к боту
// Позже, когда все будет работать закомментируйте эту строку:
file_put_contents(__DIR__ . '/message.txt', print_r($data, true));

// Основной код: получаем сообщение, что юзер отправил боту и 
// заполняем переменные для дальнейшего использования
if (!empty($data['message']['text'])) {
    $chat_id = $data['message']['from']['id'];
    $user_name = $data['message']['from']['username'];
    $first_name = $data['message']['from']['first_name'];
    $last_name = $data['message']['from']['last_name'];
    $text = trim($data['message']['text']);
    $text_array = explode(" ", $text);

	// получим текущее состояние бота, если оно есть
	$bot_state = get_bot_state ($chat_id);

    // если текущее состояние бота отправка заявки, то отправим заявку менеджеру компании на $order_chat_id
    if (substr($bot_state, 0, 6) == '/order') {
        $text_return = "
Заявка от @$user_name:
Имя: $first_name $last_name 
$text
";
        message_to_telegram($bot_token, $order_chat_id, $text_return);
        set_bot_state ($chat_id, ''); // не забудем почистить состояние на пустоту, после отправки заявки
    }
    // если состояние бота пустое -- то обычные запросы
    else {
    
    	// вывод информации Помощь
        if ($text == '/help') {
            $text_return = "Привет, $first_name $last_name, вот команды, что я понимаю: 
    /help - список команд
    /about - о нас
    /order - оставить заявку
    ";
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/help');
        }
        
        // вывод информации о нас
        elseif ($text == '/about') {
            $text_return = "verysimple_bot:
    Я пример самого простого бота для телеграм, написанного на простом PHP.
    Мой код можно скачивать, дополнять, исправлять. Код доступен в этой статье:
    https://www.novelsite.ru/kak-sozdat-prostogo-bota-dlya-telegram-na-php.html
    ";
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/about');
        }
        
        // переход в режим Заявки
        elseif ($text == '/order') {
            $text_return = "$first_name $last_name, для подтверждения Заявки введите текст вашей заявки и нажмите отправить. 
Наши специалисты свяжутся с вами в ближайшее время!
";
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/order');
        }
	}
}

// функция отправки сообщения от бота в диалог с юзером
function message_to_telegram($bot_token, $chat_id, $text, $reply_markup = '')
{
    $ch = curl_init();
    $ch_post = [
        CURLOPT_URL => 'https://api.telegram.org/bot' . $bot_token . '/sendMessage',
        CURLOPT_POST => TRUE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_POSTFIELDS => [
            'chat_id' => $chat_id,
            'parse_mode' => 'HTML',
            'text' => $text,
            'reply_markup' => $reply_markup,
        ]
    ];

    curl_setopt_array($ch, $ch_post);
    curl_exec($ch);
}

// сохранить состояние бота для пользователя
function set_bot_state ($chat_id, $data)
{
    file_put_contents(__DIR__ . '/users/'.$chat_id.'.txt', $data);
}

// получить текущее состояние бота для пользователя
function get_bot_state ($chat_id)
{
    if (file_exists(__DIR__ . '/users/'.$chat_id.'.txt')) {
        $data = file_get_contents(__DIR__ . '/users/'.$chat_id.'.txt');
        return $data;
    }
    else {
        return '';
    }
}

  • Скачать данный пример: verysimple_bot.php (2 kb)

Шаг 6. Регистрация команд бота

Теперь, если у вас все работает и бот отзывается на все команды, можно будет зарегистрировать эти команды у отца ботов @BotFather

  • Заходим к боту @BotFather
  • Запрашиваем установку команд /setcommands 
  • Выбираем нашего бота 
  • Вбиваем команды (без слешей вначале):
    help — список команд
    about — о нас
    order — оставить заявку
  • Все — теперь в вашем боте появится список команд, если нажать в диалоге /
     

Вот и все — простой бот работает! Всем спасибо, если дочитали и что-то заработало.


Николай Комарков



Обсудить в телеграм-канале

Обсуждение статьи в телеграм-канале


Russian (Pусский) translation by Sergey Zhuk (you can also view the original English article)

Если вы читаете это, то скорее всего понимаете, что боты для чатов является популярным трендом в 2016 году.

Эволюция ботов заключается не только в искусственном интеллекте. Ботом может быть инструмент в вашем мессенджере с простым интерфейсом, который может быть использован для расширения функционала сайта или сервиса, или использован как отдельное приложение. Боты легки в разработке и установке, и еще один плюс заключается в том, что мессенджеры  могут использоваться на любом устройстве: ноутбуках, смартфонах и планшетах. Вот почему все сходят с ума по ботам.

И наиболее популярным мессенджером с открытым API для ботов является Telegram.

Что мы собираемся делать

В этой статье мы создадим простой бот-секундомер для Telegram. Я покажу вам как создавать собственного бота, связываться с аналитикой, напишем немножко кода и в конце добавим своего бота в магазин ботов.

Кстати я заранее приготовил демо, так что вы можете протестировать бота, просто добавив @stopwatchbot в свой контакт лист в Telegram.

Создаем бота с помощью BotFather

Первым шагом при создании бота нужно зарегистрировать аккаунт для своего бота в Telegram. И для этого есть собственный бот, который называется BotFather. Просто добавьте его в свой контакт лист и вы сможете создавать и настраивать ботов Telegram, просто напечатав команду /newbot и следуя инструкциям от BotFather.

BotFather running TelegramBotFather running TelegramBotFather running Telegram

После регистрации вашего нового бота, вы получите сообщение с поздравлением и токен для авторизации. Мы скоро будем использовать этот токен для авторизации бота и отправки запросов к Bot API.

Позднее вы сможете использовать BotFather для добавления описаний и фото к профилям ваших ботов, регенерации токенов, задания списка доступных боту команд, удаления аккаунтов и прочее. Чтобы получить полный список команд, просто напечатайте /help в чате с BotFather.

Соединяемся с Botan Analytics

Не существует никакой встроенной аналитики в Telegrem Bots API, но все равно важно знать, сколько пользователей у вас есть, как они себя ведут и какие команды используют чаще других. Конечно можно собрать такую информацию, используя собственный движок, но если мы собираемся сфокусироваться на функционале самого бота, а не метриках, то нужно использовать решение из коробки.

И для этого уже есть простой инструмент, который называется Botan. Он основан на Yandex AppMetric и абсолютно бесплатный. Используя Botan, можно сегментировать вашу аудиторию, получать информацию о профилях пользователей, получить наиболее часто используемые команды, а так же получить красивые графики прямо в вашем мессенджере:

Bot Analytics GraphBot Analytics GraphBot Analytics Graph

Для того чтобы начать, нужно зарегистрировать ваше бота в Botan и получить свой токен. И опять же это можно сделать в боте, используя BotanioBot:

Registering a bot in TelegramRegistering a bot in TelegramRegistering a bot in Telegram

Просто нажмите на «Add bot» на вашей клавиатуре в диалоговом окне, введите ник вашего бота, и получите ваш токен для трекинга. Теперь Botanio готов регистрировать события вашего бота, а вы можете получать статистику по пользователям, сессиям и событиям прямо в вашем мессенджере.

Создание и регистрация SSL Webhook

В Telegram есть два способа получения сообщений от пользователей: длинный опрос и webhooks.

A diagram of the Telegram APIA diagram of the Telegram APIA diagram of the Telegram API

Обычно с долгим опросом, вам необходимо запрашивать новые сообщения из API, а с webhooks вы устанавливаете свой обратный вызов, который будет вызван API Telegram, если появится новое сообщение от пользователя. Я предпочитаю использовать webhooks потому что это больше похоже на взаимодействие в реальном времени, так что в этой статье мы так же будем использовать этот способ. Теперь нам нужно выбрать URL для обратного вызова нашего webhook, который будет вызван по HTTPS протоколу, и нужно установить его достаточно безопасным, и расположить свой скрипт в безопасной директории как сказано в руководстве:

Если вы хотите убедится что запрос Webhook действительно исходит от Telegream, мы рекомендуем использовать секретный путь в URL, например:https://www.example.com/<token>. Так как никто больше не знает токена для вашего бота, то вы можете быть уверены, что запрос идет от нас.

Если у вас подтвержденный SSL сертификат, то все что вам нужно, это открыть ваш URL в браузере:

1
https://api.telegram.org:443/bot[token]/setwebhook?url=[webhook]

Иначе необходимо сгенерировать самоподписанный сертификат. Вот пример команды в Linux для этого:

1
openssl req -newkey rsa:2048 -sha256 -nodes -keyout /path/to/certificate.key -x509 -days 365  -out /path/to/certificate.crt -subj "/C=IT/ST=state/L=location/O=description/CN=yourdomain.com"

И не забудьте открыть SSL порт:

Чтобы подтвердить ваш сертификат и сделать ваш домен для webhook доверительным, необходимо загрузить свой публичный ключ:

1
curl 

2
  -F "url=https://yourdomain.com/path/to/script.php" 

3
  -F "certificate=/path/to/certificate.key" 

4
  "https://api.telegram.org/bot[token]/setwebhook"

В итоге вы получите следующий JSON ответ:

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

В нем сказано что webhook был установлен и мы готовы начать работу с ботом.

Создаем базу данных

Теперь нам нужно создать базу данных для наших таймеров. Что мы собираемся в ней хранить? Когда пользователь дает команду секундомеру начать отсчет, мы будем брать ID чата и сохранять строку с ID чата и текущим временем Unix. Следовательно мы сохраним строку с отметкой времени и ID чата.

Чтобы показывать текущее время секундомера, мы будем брать сохраненную метку времени и сравнивать ее с текущим временем. Разница и будет текущее время в секундах. Если пользователь останавливает секундомер, то мы просто удаляем строчку с данным ID чата.

Итак давайте создадим базу данных и таблицу для хранения информации для секундомера:

1
CREATE TABLE IF NOT EXISTS `stopwatch` (
2
  `chat_id` int(10) unsigned NOT NULL,
3
  `timestamp` int(10) unsigned NOT NULL,
4
  PRIMARY KEY (`chat_id`)
5
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Создание класса Stopwatch

Наконец мы готовы начать писать код. Создадим класс для работы с базой данных в файле stopwatch.php и начнем с конструктора, который устанавливает два приватных свойства, где мы будем хранить ID чата и соединение с MySQL:

1
class Stopwatch
2
{
3
    /** @var mysqli */
4
    private $mysqli;
5
    /** @var int */
6
    private $stopwatch_id;
7
    /**

8
     * Stopwatch constructor

9
     * @param mysqli $mysqli

10
     * @param $stopwatch_id

11
     */
12
    public function __construct(mysqli $mysqli, $stopwatch_id)
13
    {
14
        $this->mysqli = $mysqli;
15
        $this->stopwatch_id = intval($stopwatch_id);
16
    }
17
}

Когда пользователь запускает таймер, мы берем текущую временную метку Unix и сохраняем ее вместе с ID чата в методе start():

1
public function start()
2
{
3
    $timestamp = time();
4
    $query = "

5
        INSERT INTO  `stopwatch` (`chat_id`, `timestamp`)

6
        VALUES ('$this->stopwatch_id', '$timestamp')

7
        ON DUPLICATE KEY UPDATE timestamp = '$timestamp'        

8
    ";
9
    return $this->mysqli->query($query);
10
}

Если таймер останавливается, то нам нужно удалить строку из базы данных:

1
/**

2
 * Delete row with stopwatch id

3
 * @return bool|mysqli_result

4
 */
5
public function stop()
6
{
7
$query = "

8
    DELETE FROM `stopwatch`

9
    WHERE `chat_id` = $this->stopwatch_id

10
    ";
11
    return $this->mysqli->query($query);
12
}

И вот главная часть нашего класса. Когда пользователь запрашивает статус нашего таймера, нам нужно найти строку с секундомером из текущей беседы и подсчитать разницу в секундах между сохраненной временной меткой и текущим временем. К счастью временная метка Unix является целым числом, так что мы просто можем вычесть одно из другого. Чтобы отформатировать результирующее значение в виде времени, мы используем функцию gmdate.

1
/**

2
 * Find row with stopwatch id and return difference in seconds from saved Unix time and current time

3
 * @return string

4
 */
5
public function status()
6
{
7
    $query = "

8
        SELECT `timestamp` FROM  `stopwatch`

9
        WHERE `chat_id` = $this->stopwatch_id        

10
    ";
11
    $timestamp = $this->mysqli->query($query)->fetch_row();
12
    if (!empty($timestamp)) {
13
        return gmdate("H:i:s", time() - reset($timestamp));
14
    }
15
}

Как видите, если в базе данных нет значения, то метод status() ничего не вернет, и мы обработаем значение null как остановленный таймер.

Выбор библиотеки PHP

Есть много PHP библиотек для работы с Telegram API, но на момент написания этой статьи лишь одна поддерживала одновременно Telegram Bot API и трекинг Botan. Она называется PHP Telegram Bot API.

Для установки библиотеки используем Composer:

1
composer require telegram-bot/api

Если вам не нужна аналитика, то попробуйте Bot API PHP SDK с интеграцией в Laravel или PHP Telegram Bot.

Запуск Webhook скрипта

И вот мы переходим к главной части — мы создаем скрипт для обработки обратных вызовов от Telegram Bot API. Создадим файл index.php и включим в него автозагрузчик Composer и новый класс Stopwatch. Откроем соединение MySQL, создадим нового клиента Telegram API и запустим его:

1
require_once 'vendor/autoload.php';
2
require_once 'stopwatch.php';
3

4
// connect to database

5
$mysqli = new mysqli('database_host', 'database_user', 'database_password', 'database_name');
6
if (!empty($mysqli->connect_errno)) {
7
    throw new Exception($mysqli->connect_error, $mysqli->connect_errno);
8
}
9

10
// create a bot

11
$bot = new TelegramBotApiClient('bot_token', 'botanio_token');
12
// run, bot, run!

13
$bot->run();

Создание команд

Теперь нужно настроить ответ бота на команду /start. Эта команда используется для старта всех ботов Telegram, и пользователям будет показано наше сообщение с приветствием.

1
$bot->command('start', function ($message) use ($bot) {
2
    $answer = 'Howdy! Welcome to the stopwatch. Use bot commands or keyboard to control your time.';
3
    $bot->sendMessage($message->getChat()->getId(), $answer);
4
});

Здесь в методе command() мы определим замыкание для получения команды. Замыкание получает ID текущего чата и отправляет сообщение с приветствием. Так же все зарегистрированные команды автоматически по имени команды.

Для запуска секундомера, мы определим команду /go:

1
$bot->command('go', function ($message) use ($bot, $mysqli) {
2
    $stopwatch = new Stopwatch($mysqli, $message->getChat()->getId());
3
    $stopwatch->start();
4
    $bot->sendMessage($message->getChat()->getId(), 'Stopwatch started. Go!');
5
});

Она создаст объект класса Stopwatch и запустит таймер, вызывав метод start(), который мы определили ранее.

Чтобы определить команду /status, делаем аналогично. Просто вызываем метод status() и возврашаем результат. Если метод вернул null, сообщаем пользователю, что таймер не был запущен.

1
$bot->command('status', function ($message) use ($bot, $mysqli) {
2
    $stopwatch = new Stopwatch($mysqli, $message->getChat()->getId());
3
    $answer = $stopwatch->status();
4
    if (empty($answer)) {
5
        $answer = 'Timer is not started.';
6
    }
7
    $bot->sendMessage($message->getChat()->getId(), $answer);
8
});

А если пользователь останавливает таймер, то нам нужно сначала получить статус, показать результирующее время, а затем остановить таймер, используя метод stop().

1
$bot->command('stop', function ($message) use ($bot, $mysqli) {
2
    $stopwatch = new Stopwatch($mysqli, $message->getChat()->getId());
3
    $answer = $stopwatch->status();
4
    if (!empty($answer)) {
5
        $answer = 'Your time is ' . $answer . PHP_EOL;
6
    }
7
    $stopwatch->stop();
8
    $bot->sendMessage($message->getChat()->getId(), $answer . 'Stopwatch stopped. Enjoy your time!');
9
});

И это все! Теперь вы можете загрузить все необходимые файлы в вашу директорию для webhook и протестировать своего бота.

Добавление клавиатуры

Чтобы предложить пользователю, какие команды он может выполнять, мы можем к сообщению добавить клавиатуру. Наш таймер может быть в двух состояниях: запущен или остановлен. Для того чтобы показать пользователю клавиатуру, нам нужно просто переопределить метод sendMessage():

1
$keyboard = new TelegramBotApiTypesReplyKeyboardMarkup([['/go', '/status']], null, true);
2

3
$bot->sendMessage($message->getChat()->getId(), $answer, false, null, null, $keyboards);
4
});

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

Добавление бота в Store

Хорошо, теперь у нас есть работающий бот, и мы хотим показать его миру. Лучшим способом будет зарегистрировать бота в каталоге ботов. Сейчас у Telegram нет официального каталога, но есть несколько неофициальных, и самый большой из них — Storebot.me, в котором уже зарегистрированы тысячи ботов.

И в нем есть бот… для регистрации бота в каталоге ботов! Добавляем @storebot в свой контакт лист, пишем команду /add и следуем инструкциям. Вас попросят ввести имя бота, описание, выбрать одну из стандартных категорий, и подтвердить права на бота отправкой токена.

Через некоторое время ваш бот пройдет процесс подтверждения я появится в чартах Storebot. Теперь вы и ваши пользователи могу голосовать, находить и оценивать вашего бота в store, чтобы помочь ему подняться в каталоге.

Заключение

Мы прошли длинный путь, от создания простого бота до регистрации его в store, сделав его доступным для реальных пользователей. Как вы могли убедиться, существует много инструментов, которые сделают вашу жизнь проще при создании собственного бота, и не нужно писать много кода для создания простого бота. Теперь вы готовы к созданию собственного бота!

Если у вас есть какие-либо вопросы, не стесняйтесь задавать их в комментариях под статьей.

Для дальнейшего чтения 

  • Боты Telegram
  • BotFather
  • Botan
  • PHP Telegram Bot API
  • Telegram Bot Store

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

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

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

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

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

Screenshot_1.png

@BotFather

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

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

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

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

  1. Проверять «вручную», используя «Long Polling».
  2. Доверить всё Telegram, поставив «Webhook». В этом случае любой запрос от пользователя Telegram сам будет посылать нам на сервер.

Мы остановимся на втором варианте, но у него есть ограничение: у вас на сайте обязательно должен быть установлен SSL-сертификат, чтобы все запросы проходили через безопасный протокол HTTPS. Самоподписанные и бесплатные сертификаты «Let’s 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 можно заметить два новых значения:

  1. ‘parse_mode’ => ‘HTML’, чтобы в сообщение можно было вставить HTML-теги (<b>, <a>, <i>, <code> или <pre>).
  2. ‘disable_web_page_preview’ => true, чтобы к сообщению со ссылкой не подгружалось превью.

10. В качестве смайла (стрелка вправо) используются символы xE2x9ExA1. Список всех смайлов в таком виде можно найти на специальном сайте.

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

Результаты

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

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

От редакции

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

Телеграм Нетологии

Примеры как зарегистрировать бота в Telegram, описание и взаимодействие с основными методами API. Документация на core.telegram.org и tlgrm.ru (неофициальный, на русском).

Все запросы к API должны осуществляться по HTTPS, подойдет бесплатный сертификат «Let’s Encrypt».

1

Регистрация бота

Для регистрации нового бота нужно написать «папе ботов» @BotFather команду /newbot

Регистрация бота в Telegram

Следующим сообщением отправляем название для бота, обязательно на конце имени должно быть слово «bot» или «_bot». Ответным сообщением получим токен:

Получение токена к bot API Telegram

Тут же можно настроить описание и аватарку:

/setname Имя
/setdescription Краткое описание
/setabouttext Описание бота
/setuserpic Юзерпик

Далее нужно поставить «Webhook» чтобы все сообщения из Telegram приходили на PHP скрипт (https://example.com/bot.php). Для этого нужно пройти по ссылке в которой подставлены полученный токен и адрес скрипта.

https://api.telegram.org/bot<token>/setWebhook?url=https://example.com/bot.php

В ответе будет

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

При смене токена, установку вебхука нужно повторить.

2

Входящие сообщения

Сообщения приходят POST-запросом, с типом application/json. Получить его в PHP можно следующим образом:

$data = file_get_contents('php://input');
$data = json_decode($data, true);

PHP

Чтобы посмотреть входящие данные, их придется дампить в файл:

file_put_contents(__DIR__ . '/message.txt', print_r($data, true));

PHP

Текстовое сообщение

Запрос от Телеграм:

Array (
	[update_id] => 17584194
	[message] => Array (
		[message_id] => 26
		[from] => Array (
			[id] => 123456789
				[is_bot] => 
				[first_name] => UserName
				[language_code] => ru-US
			)
		[chat] => Array (
			[id] => 123456789
			[first_name] => UserName
			[type] => private
		)
		[date] => 1541888068
		[text] => Привет бот!
	)
)

Получим текст сообщения:

if (!empty($data['message']['text'])) {
	$text = $data['message']['text'];
	echo $text;
}

PHP

Фотографии

При отправки фото боту, на скрипт приходит массив превьюшек, последним элементом будет оригинальное фото. Максимальный размер файла 20МБ.

Запрос от Телеграм:

Array (
	[update_id] => 17584194
	[message] => Array (
		[message_id] => 38
		[from] => Array (
			[id] => 123456789
			[is_bot] => 
			[first_name] => UserName
			[language_code] => ru-US
		)
		[chat] => Array (
			[id] => 123456789
			[first_name] => UserName
			[type] => private
		)
		[date] => 1541924962
		[photo] => Array (
			[0] => Array (
				[file_id] => AgADAgADUqexG7u8OEudBvlhgMzKC1agOQ8ABC6Bx26USA7Mw3gAAgI
				[file_size] => 1196
				[width] => 51
				[height] => 90
			)
			[1] => Array (
				[file_id] => AgttAgADUqoxG7u8OEudBvlhgMzKC1agOQ8ABKwp_3jDPrIlxHgAAgI
				[file_size] => 21146
				[width] => 180
				[height] => 320
			)
			[2] => Array (
				[file_id] => AgADAgADUqyxG7u8OEudBvlhgMzKC1agOQ8ABAN8gJWpUT1MxXgAAgI
				[file_size] => 90940
				[width] => 449
				[height] => 800
			)
			[3] => Array (
				[file_id] => AgADAgADUqouu7u8OEudBvlhgMzKC1agOQ8ABIqVC1nEpbLDwngAAgI
				[file_size] => 114363
				[width] => 719
				[height] => 1280
			)
		)
	)
)

Чтобы скачать файл нужно отправить POST или GET запрос на получение c параметром file_id изображения по URL:

https://api.telegram.org/bot<token>/getFile

В ответ придет информация о файле:

Array (
	[ok] => 1
	[result] => Array (
		[file_id] => AgADAgADUqoxG5u88E0dBvlhgMzKC1agOQ8ABIqVC1nEpbLDwngAAgI
		[file_size] => 114363
		[file_path] => photos/file_1.jpg
	)
)

Далее его можно скачать по ссылке:

https://api.telegram.org/file/bot<token>/<file_path>

В PHP сохранение файла на сервер можно реализовать следующим образом:

$token = '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11';

if (!empty($data['message']['photo'])) {
	$photo = array_pop($data['message']['photo']);
	
	$ch = curl_init('https://api.telegram.org/bot' . $token . '/getFile');  
	curl_setopt($ch, CURLOPT_POST, 1);  
	curl_setopt($ch, CURLOPT_POSTFIELDS, array('file_id' => $photo['file_id']));
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HEADER, false);
	$res = curl_exec($ch);
	curl_close($ch);
	
	$res = json_decode($res, true);
	if ($res['ok']) {
		$src  = 'https://api.telegram.org/file/bot' . $token . '/' . $res['result']['file_path'];
		$dest = __DIR__ . '/' . time() . '-' . basename($src);
		copy($src, $dest);
	}
}

PHP

Документ

Запрос от Телеграм:

Array (
	[update_id] => 17474201
	[message] => Array (
		[message_id] => 44
		[from] => Array (
			[id] => 123456789
			[is_bot] => 
			[first_name] => UserName
			[language_code] => ru-US
		)
		[chat] => Array (
			[id] => 123456789
			[first_name] => UserName
			[type] => private
		)
		[date] => 1541925844
		[document] => Array (
			[file_name] => IMG_7947.JPG
			[mime_type] => image/jpeg
			[thumb] => Array (
					[file_id] => AAQCABMNv_QOAATwQugveIZBldZ3AAIC
					[file_size] => 2644
					[width] => 67
					[height] => 90
				)
			[file_id] => BQADAgADtQEAAqu9OEhzn2cEz8LpkgI
			[file_size] => 1976218
		)
	)
)

Скачивание файлов происходит по такой же схеме как у фотографий.

if (!empty($data['message']['document'])) {
	$file_id = $data['message']['document']['file_id'];
	
	$ch = curl_init('https://api.telegram.org/bot' . $token . '/getFile');  
	curl_setopt($ch, CURLOPT_POST, 1);  
	curl_setopt($ch, CURLOPT_POSTFIELDS, array('file_id' => $file_id));
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HEADER, false);
	$res = curl_exec($ch);
	curl_close($ch);
	
	$res = json_decode($res, true);
	if ($res['ok']) {
		$src  = 'https://api.telegram.org/file/bot' . $token . '/' . $res['result']['file_path'];
		$dest = __DIR__ . '/' . time() . '-' . basename($src);
		copy($src, $dest);
	}
}

PHP

3

Ответы бота

Отправка текста

$response = array(
	'chat_id' => $data['message']['chat']['id'],
	'text' => 'Хай!'
);	
		
$ch = curl_init('https://api.telegram.org/bot' . $token . '/sendMessage');  
curl_setopt($ch, CURLOPT_POST, 1);  
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);

PHP

Отправка картинки

$response = array(
	'chat_id' => $data['message']['chat']['id'],
	'photo' => curl_file_create(__DIR__ . '/image.png')
);	
		
$ch = curl_init('https://api.telegram.org/bot' . $token . '/sendPhoto');  
curl_setopt($ch, CURLOPT_POST, 1);  
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);

PHP

Отправка файла

$response = array(
	'chat_id' => $data['message']['chat']['id'],
	'document' => curl_file_create(__DIR__ . '/file.xls')
);	
		
$ch = curl_init('https://api.telegram.org/bot' . $token . '/sendDocument');  
curl_setopt($ch, CURLOPT_POST, 1);  
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
curl_close($ch);

PHP

4

Пример скрипта

Скрипт простейшего бота @SnippRu. Он отвечает на вопросы и сохраняет файлы и изображение на сервере.

<?php

$data = file_get_contents('php://input');
$data = json_decode($data, true);

if (empty($data['message']['chat']['id'])) {
	exit();
}

define('TOKEN', '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11');

// Функция вызова методов API.
function sendTelegram($method, $response)
{
	$ch = curl_init('https://api.telegram.org/bot' . TOKEN . '/' . $method);  
	curl_setopt($ch, CURLOPT_POST, 1);  
	curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HEADER, false);
	$res = curl_exec($ch);
	curl_close($ch);

	return $res;
}

// Прислали фото.
if (!empty($data['message']['photo'])) {
	$photo = array_pop($data['message']['photo']);
	$res = sendTelegram(
		'getFile', 
		array(
			'file_id' => $photo['file_id']
		)
	);
	
	$res = json_decode($res, true);
	if ($res['ok']) {
		$src = 'https://api.telegram.org/file/bot' . TOKEN . '/' . $res['result']['file_path'];
		$dest = __DIR__ . '/' . time() . '-' . basename($src);

		if (copy($src, $dest)) {
			sendTelegram(
				'sendMessage', 
				array(
					'chat_id' => $data['message']['chat']['id'],
					'text' => 'Фото сохранено'
				)
			);
			
		}
	}
	
	exit();	
}

// Прислали файл.
if (!empty($data['message']['document'])) {
	$res = sendTelegram(
		'getFile', 
		array(
			'file_id' => $data['message']['document']['file_id']
		)
	);
	
	$res = json_decode($res, true);
	if ($res['ok']) {
		$src = 'https://api.telegram.org/file/bot' . TOKEN . '/' . $res['result']['file_path'];
		$dest = __DIR__ . '/' . time() . '-' . $data['message']['document']['file_name'];

		if (copy($src, $dest)) {
			sendTelegram(
				'sendMessage', 
				array(
					'chat_id' => $data['message']['chat']['id'],
					'text' => 'Файл сохранён'
				)
			);	
		}
	}
	
	exit();	
}

// Ответ на текстовые сообщения.
if (!empty($data['message']['text'])) {
	$text = $data['message']['text'];

	if (mb_stripos($text, 'привет') !== false) {
		sendTelegram(
			'sendMessage', 
			array(
				'chat_id' => $data['message']['chat']['id'],
				'text' => 'Хай!'
			)
		);

		exit();	
	} 

	// Отправка фото.
	if (mb_stripos($text, 'фото') !== false) {
		sendTelegram(
			'sendPhoto', 
			array(
				'chat_id' => $data['message']['chat']['id'],
				'photo' => curl_file_create(__DIR__ . '/torin.jpg')
			)
		);
		
		exit();	
	}

	// Отправка файла.
	if (mb_stripos($text, 'файл') !== false) {
		sendTelegram(
			'sendDocument', 
			array(
				'chat_id' => $data['message']['chat']['id'],
				'document' => curl_file_create(__DIR__ . '/example.xls')
			)
		);

		exit();	
	}
}

PHP

Предисловие

У меня появилась необходимость создать telegram бота на php, так как это один из основных языков, который я использую в своих разработках. Безусловно, для этого есть большие библиотеки, например на github, среди них есть достаточно хорошие, но часть из них либо плохо, либо вообще не документированы. Также сложности возникают, когда нужно немного поменять или добавить функционал, необходимо изучить десятки файлов, устранять возникающие ошибки, когда нужно просто добавить кнопку. Для простых действий можно вполне обойтись библиотекой Guzzle, для удобства построения запросов, вместо стандартного CURL, так как telegram API просто обрабатывает запросы в формате JSON и возвращает результат, как и многие другие API.

Скачать исходники, описанные ниже, можно в конце статьи.

Все запросы к telegram API обрабатываются следующим образом, это всего лишь запрос на адрес: https://api.telegram.org/bot/METHOD_NAME. Где после bot подставляется полученный от @BotFather токен, затем /название_метода. Ссылка на оф. сайт, с описанием всех методов telegram API https://core.telegram.org/bots/api#available-methods

Вариант описанный в данной статье подойдет для тех, кто знает как устанавливать пакеты при помощи composer, имеет хотя бы небольшой опыт использования php. А также для тех, кто желает разобраться с самого начала, как происходит процесс создания telegram ботов, от получения токена, до обработки и отправки сообщений.

Оглавление статьи:

  • Шаг 1 — Подготовка среды
  • Шаг 2 — Получение токена
  • Шаг 3 — Регистрация вебхука
  • Шаг 4 — Прием и обработка сообщений от пользователей
  • Шаг 5 — Обработка команд
  • Шаг 6 — Добавление кнопок в чат и обработка нажатий

Шаг 1 — Подготовка среды

Для работы нам потребуется:

  • Зарегистрированный telegram аккаунт;
  • Зарегистрированное доменное имя и SSL-сертификат, так как используются HTTPS-запросы к Telegram Bot API;
  • Хостинг или VPS или же свой сервер, с доступом к нему, в моем случае — это свой сервер в дата-центре.
  • Установленный на сервере PHP, Apache, NGINX, Composer. Я использую версию PHP 8.
  • Текстовый редактор, подойдет Notepad++, я использую Phpshtorm, но так было не всегда.

Шаг 2 — Получение токена

Токен бота — это как его идентификатор в системе, он необходим для формирования запросов к api. Процесс его получения достаточно простой, в строке поиска telegram вводим @BotFather и находим аккаунт.

@BotFather

Переходим в чат с @BotFather и пишем команду /newbot

В ответ получаем:

Alright, a new bot. How are we going to call it? Please choose a name for your bot. — Что означает: Хорошо, новый бот. Как мы собираемся это назвать? Пожалуйста, выберите имя для вашего бота.

шаг 1 создание telegram бота

Отправляем следующим сообщением название бота, в примере: testingbot, получаем ответ: Good. Now let’s choose a username for your bot. It must end in `bot`. Like this, for example: TetrisBot or tetris_bot. — Что означает: Хорошо. Теперь давайте выберем имя пользователя для вашего бота. Оно должно заканчиваться на `бот`. Вот так, например: Tetris Bot или tetris_bot.

Шаг 1 получение токена для telegram бота

Следующим сообщением я отправил testing99_bot, но получил ответ, что такое имя пользователя занято : Sorry, this username is already taken. Please try something different. Такое сообщение свидетельствует о том, что такое имя пользователя занято. Значит необходимо выбрать другое, в итоге вот такое было свободно botfortest99_bot. И мы получаем такое сообщение, содержащее токен токен.

Done! Congratulations on your new bot. You will find it at t.me/botfortest99_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. By the way, when you’ve finished creating your cool bot, ping our Bot Support if you want a better username for it. Just make sure the bot is fully operational before you do this.

Use this token to access the HTTP API:

5236473451:AAEAjVbZY0kbxOLwBFYTV4j1YXRs77HmJEI

Keep your token secure and store it safely, it can be used by anyone to control your bot.

For a description of the Bot API, see this page: https://core.telegram.org/bots/api

На момент публикации статьи этот бот и токен будет удален, поэтому я не переживаю за его размещение здесь.

шаг 3 получения токена для telegram бота

Шаг 3 — Регистрация хука

Регистрация вебхука — это явное указание, по какому https адресу должен вызываться наш php-файл обработчик. Для начала его нужно создать, например index.php или любой другой.

Для установки вебхука(скрипта), который будет обрабатывать команды и отвечать на сообщения, необходимо открыть в браузере такую строку:

https://api.telegram.org/bot5236473451:AAEAjVbZY0kbxOLwBFYTV4j1YXRs77HmJEI/setWebhook?url=https://ae-nekrasov.ru/devbot/index.php

url для установки хука telegram bot

В результате открытия этой строки в браузере и нажатии кнопки enter, мы получаем такое сообщение : {«ok»:true,»result»:true,»description»:»Webhook was set»} — это означает, что вебхук установлен и теперь отправленные боту сообщения будут приходить на этот адрес.

регистрация вебхука telegram-бот

Шаг 4 — Прием и обработка сообщений от пользователей

Чтобы принимать и обрабатывать сообщения нужно понять модель взаимодействия с telegram API и куда и в каком формате нам будут приходить сообщения.

Так как в данной статье будет рассмотрен вариант, с применением вебхука, после отправки сообщения боту, telegram API будет отправлять нам данные, которые он получил от пользователя, на указанный URL — адрес(см. Шаг 3.). Самый интересный момент в этом куда, в массив $_GET, $_POST или $_REQUEST? На самом деле не в один из них, данные будут приходить в «php://input» и получить их и просмотреть можно будет, разместив в файле index.php такой код:

<?php
$tmpdata = json_decode(file_get_contents("php://input"),true);

$arrdataapi = print_r($tmpdata, true);

file_put_contents('apidata.txt', "Данные от бота: $arrdataapi", FILE_APPEND);

В коде выше мы считываем необработанные данные из php://input и сразу же их преобразуем в ассоциативный массив, функцией json_decode, передав ей вторым параметром true. Затем в переменную $arrdataapi сохраняем распечатанный массив, функцией print_r, передав ей вторым параметром true, применение данного способа описано здесь.

Отправляем нашему боту несколько сообщений и посмотрим, что будет в файле apidata.txt.

Отправка сообщений telegram боту

Содержимое файла apidata.txt

Данные от бота: Array
(
    [update_id] => 570811583
    [message] => Array
        (
            [message_id] => 6
            [from] => Array
                (
                    [id] => 816955688
                    [is_bot] => 
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [language_code] => ru
                )

            [chat] => Array
                (
                    [id] => 816955688
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [type] => private
                )

            2023 => 1649421871
            [teхt] => /start
            [entities] => Array
                (
                    [0] => Array
                        (
                            [offset] => 0
                            [length] => 6
                            [type] => bot_command
                        )

                )

        )

)
Данные от бота: Array
(
    [update_id] => 570811584
    [message] => Array
        (
            [message_id] => 7
            [from] => Array
                (
                    [id] => 816955688
                    [is_bot] => 
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [language_code] => ru
                )

            [chat] => Array
                (
                    [id] => 816955688
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [type] => private
                )

            2023 => 1649421873
            [teхt] => 123
        )

)
Данные от бота: Array
(
    [update_id] => 570811585
    [message] => Array
        (
            [message_id] => 8
            [from] => Array
                (
                    [id] => 816955688
                    [is_bot] => 
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [language_code] => ru
                )

            [chat] => Array
                (
                    [id] => 816955688
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [type] => private
                )

            2023 => 1649421877
            [teхt] => привет
        )

)
Данные от бота: Array
(
    [update_id] => 570811586
    [message] => Array
        (
            [message_id] => 9
            [from] => Array
                (
                    [id] => 816955688
                    [is_bot] => 
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [language_code] => ru
                )

            [chat] => Array
                (
                    [id] => 816955688
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [type] => private
                )

            2023 => 1649421879
            [teхt] => /help
            [entities] => Array
                (
                    [0] => Array
                        (
                            [offset] => 0
                            [length] => 5
                            [type] => bot_command
                        )

                )

        )

)
Данные от бота: Array
(
    [update_id] => 570811587
    [message] => Array
        (
            [message_id] => 10
            [from] => Array
                (
                    [id] => 816955688
                    [is_bot] => 
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [language_code] => ru
                )

            [chat] => Array
                (
                    [id] => 816955688
                    [first_name] => Александр
                    [last_name] => Некрасов
                    [username] => ANeK
                    [type] => private
                )

            2023 => 1649421896
            [photo] => Array
                (
                    [0] => Array
                        (
                            [file_id] => AgACAgIAAxkBAAMKYlAuSD6Q2PTZbXHAdnbUwKEcGeAAAi-8MRshN4BKa9oVsEHatVEBAAMCAANzAAMjBA
                            [file_unique_id] => AQADL7wxGyE3gEp4
                            [file_size] => 1522
                            [width] => 90
                            [height] => 64
                        )

                    [1] => Array
                        (
                            [file_id] => AgACAgIAAxkBAAMKYlAuSD6Q2PTZbXHAdnbUwKEcGeAAAi-8MRshN4BKa9oVsEHatVEBAAMCAANtAAMjBA
                            [file_unique_id] => AQADL7wxGyE3gEpy
                            [file_size] => 21642
                            [width] => 320
                            [height] => 226
                        )

                    [2] => Array
                        (
                            [file_id] => AgACAgIAAxkBAAMKYlAuSD6Q2PTZbXHAdnbUwKEcGeAAAi-8MRshN4BKa9oVsEHatVEBAAMCAAN4AAMjBA
                            [file_unique_id] => AQADL7wxGyE3gEp9
                            [file_size] => 76889
                            [width] => 800
                            [height] => 566
                        )

                )

        )

)

Просмотрев содержимое файла, мы видим, что достаточно много данных нам отправляет telegram API. Исходя из этого, можно перейти к построению обработчика. Дальнейшие действия предполагают, что подготовка среды(см. Шаг1) Вы прошли и Вам будет понятно, что происходит дальше.

В директорию, где находится файл index.php размещаем файл composer.json, со следующим содержимым :

{
 "require": {
        "guzzlehttp/guzzle": "^6.0"
    },
  "autoload": {
    "psr-4": { "": "src/" }
  }
}

И выполняем в терминале команду composer require, в результате мы увидим что-то вроде:

Search for a package: 
./composer.json has been updated
Running composer update 
Loading composer repositories with package information
Updating dependencies
Lock file operations: 8 installs, 0 updates, 0 removals
  - Locking guzzlehttp/guzzle (6.5.5)
  - Locking guzzlehttp/promises (1.5.1)
  - Locking guzzlehttp/psr7 (1.8.5)
  - Locking psr/http-message (1.0.1)
  - Locking ralouphie/getallheaders (3.0.3)
  - Locking symfony/polyfill-intl-idn (v1.25.0)
  - Locking symfony/polyfill-intl-normalizer (v1.25.0)
  - Locking symfony/polyfill-php72 (v1.25.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 8 installs, 0 updates, 0 removals
  - Downloading guzzlehttp/psr7 (1.8.5)
  - Installing symfony/polyfill-php72 (v1.25.0): Extracting archive
  - Installing symfony/polyfill-intl-normalizer (v1.25.0): Extracting archive
  - Installing symfony/polyfill-intl-idn (v1.25.0): Extracting archive
  - Installing ralouphie/getallheaders (3.0.3): Extracting archive
  - Installing psr/http-message (1.0.1): Extracting archive
  - Installing guzzlehttp/psr7 (1.8.5): Extracting archive
  - Installing guzzlehttp/promises (1.5.1): Extracting archive
  - Installing guzzlehttp/guzzle (6.5.5): Extracting archive
2 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
5 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

Это означает, что необходимые пакеты с зависимостями установились, появилась папка vendor. Для своих классов создаем директорию src, в корне проекта. Там разместим первый класс Api и файл соответственно называется Api.php, со следующим содержимым:

<?php

require '../vendor/autoload.php';
use GuzzleHttpClient;

class Api extends Client
{
    /**
     *
     * @description Небольшой класс для работы с телеграмм АПИ
     * Основные функции для отправки сообщений и немного еще...
     * Данный класс описан под php версии 8+ для использования на более ранних версиях необходимо
     * убрать описание возвращаемых значений у методов, например : array
     */

    protected $conftoken;
    public $basicChatData;

    public function __construct($token)
    {
        parent::__construct();
        $this->conftoken = $token;
        $this->basicChatData = $this->getDataChat();
    }


    /**
     *
     * @return array $result - базовые данные чата
     * @throws JsonException
     *
     */

    public function getDataChat(): array
    {
        return json_decode(file_get_contents("php://input"), true, 512, JSON_THROW_ON_ERROR);
    }


    /**
     *
     * @param string $message - сообщение от бота
     * @return mixed - результат выполнения
     * @throws JsonException
     *
     */

    public function sendMessage(string $message): mixed
    {
        $params = array("chat_id" => $this->basicChatData["message"]["chat"]["id"],"text"=>$message);
        $response = $this->request('POST', "https://api.telegram.org/bot$this->conftoken/sendMessage",['json'=>$params],['http_errors' => false]);
        return json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR);
    }
}

В коде выше, был создан класс Api и внутри него метод sendMessage, на основе данных описанных в официальной документации telegram API по отправке сообщений https://core.telegram.org/bots/api#sendmessage

Чтобы класс можно было использовать, необходимо выполнить команду в терминале composer dump-autoload -o

Теперь модифицируем файл index.php, чтобы он был такого содержимого:

<?php
set_include_path(__DIR__);
require 'vendor/autoload.php';

$bot = new Api("5236473451:AAEAjVbZY0kbxOLwBFYTV4j1YXRs77HmJEI");

$bot->sendMessage("Привет");

Если Вы все сделали по инструкции описанной выше, то теперь на любые сообщения бот будет отвечать «Привет». Небольшая gif-ка с результатом работы.

Работа telegram бота первые шаги

Работает, естественно отвечать на все сообщения «Привет» — это не окончательная функциональность. Теперь нужно как-то обработать входящие сообщения и исходя из содержимого уже отправлять ответ.

Немного модифицируем класс Api, добавим новый метод, который будет возвращать отправленное сообщение боту, добавляемый код:

    /**
     *
     * @return mixed - сообщение отправленное боту
     * 
     */

    public function getMessage(): mixed
    {
        return $this->basicChatData['message']['text'];
    }

Также модифицируем файл index.php, новый код:

<?php
set_include_path(__DIR__);
require 'vendor/autoload.php';


$bot = new Api("5236473451:AAEAjVbZY0kbxOLwBFYTV4j1YXRs77HmJEI");


$message = $bot->getMessage();

$bot->sendMessage($message);

Теперь бот просто будет повторюшкой, он будет отправлять нам то, что мы ему, ниже gif-ка с примером работы:

telegram бот повторюшка

Модифицируем index.php, добавим if else ветвления, чтобы отвечать уже в зависимости от того, что нам отправит пользователь, новый код:

<?php
set_include_path(__DIR__);
require 'vendor/autoload.php';


$bot = new Api("5236473451:AAEAjVbZY0kbxOLwBFYTV4j1YXRs77HmJEI");

$message = $bot->getMessage();

if($message == "Привет" || $message == "привет"){
    
    $bot->sendMessage("Привет");
    
}elseif($message == "Как дела?" || $message == "как дела?"){
    
    $bot->sendMessage("У меня отлично, как у тебя?");
    
}elseif($message == "Кто ты?" || $message == "кто ты?"){
    
    $bot->sendMessage("Я telegram бот, созданный недавно!");
    
}

Теперь бот отвечает специальным ответом, в зависимости от вопроса, ниже gif-ка с примером работы:

пример общения с telegram ботом

Естественно, можно модифицировать код, с поиском подстроки в строке или применением регулярных выражений, чтобы не зависеть от регистра сообщения и наличия вопросительных или восклицательных знаков, но это уже сосем другая история.

Шаг 5 — Обработка команд

Команды можно обрабатывать как и текст сообщений, но чтобы при вводе / выпадал список команд с описанием, нужно через @BotFather их настроить, для этого:

  • 1 — в чате с @BotFather вводим /mybots
  • 2 — выбираем бота, для которого необходимо настроить команды
  • 3 — нажимаем кнопку Edit Bot
  • 4 — нажимаем кнопку Edit Commandst
  • 5 — вводим название команды пробел — пробел описание, например help — Помощь по управлению.

Команды нужно вводить в одном сообщении, иначе новые затрат старые, а также важно понимать, что это не обработка команд, а всего лишь визуальное оформление.

команды для telegram бота

Шаг 6 — Добавление кнопок в чат и обработка нажатий

В рамках данной статьи рассмотрим два варианта кнопок:

Вариант 1. Кнопки в зоне основной клавиатуры

встроенная клавиатура telegram bot

Вариант 2. Кнопки под сообщением

кнопки под сообщением telegram bot

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

Второй вариант обрабатывается немного иначе, я для этого использую даже другой метод отправки сообщения, после нажатия на такую клавиатуру, это обусловлено тем, что при нажатии кнопок в режиме callback query, к нам придет немного другой формат массива с данными, точнее данные([from],[message],[chat]) будут вложены в массив [‘callback_query’]

Для экспериментов с кнопками, необходимо добавить в файл Api.php несколько методов, фрагмент добавляемого кода:

    /**
     *
     * @return mixed - возвращает данные из массива ['callback_query']
     * если было нажатие, на кнопки под сообщением
     *
     */

    public function getCallBackQuery(): mixed
    {
        return $this->basicChatData['callback_query']['data'];
    }

    /**
     * Метод для ответа при обработки нажатия кнопок под сообщение
     * @param string $message - сообщение от бота
     * @return mixed - результат выполнения
     * @throws JsonException
     */

    public function sendMessageCallBackData(string $message): mixed
    {
        $params = array("chat_id" => $this->basicChatData['callback_query']["message"]["chat"]["id"],"text"=>$message);
        $response = $this->request('POST', "https://api.telegram.org/bot$this->conftoken/sendMessage",['json'=>$params],['http_errors' => false]);
        return json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR);
    }
    
   /**
     * Метод отправки кнопок вместе с сообщением
     * @param string $message - сообщение от бота
     * @param array $inlineKeyboard - клавиатура
     * @return mixed - результат выполнения
     * @throws JsonException
     */

    public function sendMessageWithInlineKeyboard(string $message, array $inlineKeyboard): mixed
    {
            $params = array("chat_id" => $this->basicChatData["message"]["chat"]["id"],"text"=>$message,"reply_markup" => array("inline_keyboard"=>$inlineKeyboard));
            $response = $this->request('POST', "https://api.telegram.org/bot$this->conftoken/sendMessage",['json'=>$params],['http_errors' => false]);
            return json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR);
    }

    /**
     * Метод вызова кнопок в зоне основной клавиатуры
     * @param string $message - сообщение от бота
     * @param array $keyboard - клавиатура
     * @return mixed $result - результат выполнения
     * @throws JsonException
     */

    public function sendMessageWithBaseKeyboard(string $message, array $keyboard): mixed
    {
            $params = array("chat_id" => $this->basicChatData["message"]["chat"]["id"],"text" => $message, "reply_markup" => array("keyboard" => $keyboard, "resize_keyboard" => true));
            $response = $this->request('POST', "https://api.telegram.org/bot$this->conftoken/sendMessage",['json'=>$params],['http_errors' => false]);
            return json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR);
    }

В комментариях к методам описано, для чего каждый из них необходим. Первый метод необходим, чтобы в файле index.php попасть в ветвление, где происходит обработка нажатия кнопок под сообщением. Второй метод немного отличается от стандартного, где происходит отправка сообщений, он необходим для отправки сообщения, когда нажаты кнопки выведенные под сообщением. Третий метод выводит кнопки под сообщением. Четвертый выводит кнопки в зоне стандартной клавиатуры и смайлов.

Также необходимо обновить файл index.php, его новый код:

<?php
set_include_path(__DIR__);
require 'vendor/autoload.php';


$bot = new Api("5236473451:AAEAjVbZY0kbxOLwBFYTV4j1YXRs77HmJEI");

$message = $bot->getMessage();

$callBackQuery = $bot->getCallBackQuery();




if($callBackQuery){



if($callBackQuery == "444"){

    $bot->sendMessageCallBackData("Нажата кнопка 1");

}elseif($callBackQuery == "555"){

    $bot->sendMessageCallBackData("Нажата кнопка 2");

}elseif($callBackQuery == "777"){

    $bot->sendMessageCallBackData("Нажата кнопка 3");

}


}

// формат клавиатуры снизу в зоне вывода стандартной

$keyboard2 = array(
    array(
        array(
            "text" => "888"
        ),
        array(
            "text" => "999"
        ),
    )
);


// формат клавиатуры для вывода под сообщением

$arrInlineKey =  array(
    array(
        array('text'=>'Кнопка 1','callback_data'=>'444'),
        array('text'=>'Кнопка 2','callback_data'=>'555'),
        array('text'=>'Кнопка 3','callback_data'=>'777'),
    )
);


if($message == "Привет" || $message == "привет"){

    $bot->sendMessage("Привет");

}elseif($message == "Как дела?" || $message == "как дела?"){

    $bot->sendMessage("У меня отлично, как у тебя?");

}elseif($message == "Кто ты?" || $message == "кто ты?"){

    $bot->sendMessage("Я telegram бот, созданный недавно!");

}elseif($message == "/help"){

    $bot->sendMessage("Вызвана команда /help");

}elseif($message == "клавиатура"){

    $bot->sendMessageWithInlineKeyboard("Кнопки под сообщением n тут могут быть любые кнопки n еще строка текста n еще строка текста", $arrInlineKey);

}elseif($message == "клавиатура2"){

    $bot->sendMessageWithBaseKeyboard("Вызвана клавиатура", $keyboard2);

}elseif($message == "888"){

    $bot->sendMessage("Нажата кнопка 888");

}elseif($message == "999"){

    $bot->sendMessage("Нажата кнопка 999");

}

Если Вы все делали по инструкции, то должен быть такой результат, как на gif-ке ниже:

пример работы telegram бота

Естественно, в этой статье описаны самые азы, в реальности на кнопки можно подвесить загрузку какой-либо информации из внешних источников, например crm-систем, отправку данных куда-то и многое другое.

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

Также выкладываю архив с исходниками, данный токен будет удален, для использования, Вам будет необходимо передать свой, $bot = new Api(«ВАШ_ТОКЕН»);

Для установки, распакуйте архив в папку проекта, куда будет настроен Ваш вебхук, запустите команду composer require и команду composer dump-autoload -o

Добавляйте свои методы, или модифицируйте написанные мной. Ссылка на оф. сайт, с описанием всех методов telegram API https://core.telegram.org/bots/api#available-methods Всем успехов в разработке!

Скачать исходники

Рекламный блок, для развития проекта

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

В первом уроке мы с вами рассмотрим основные понятия связанные с API. Я вам расскажу что такое API методы, хуки, покажу на примере Telegram построение URL для создания запросов и расскажу о том как создаются простые API запросы на PHP.

Полный список всех записей курса находится на сайте или в публикациях на Хабр.

Для отправки и получения запросов через API, вам лучше использовать виртуальный хостинг, так как локальный хостинг не сможет получать данные через хуки.

Основные понятия

Давайте рассмотрим основные понятия для работы с API.

API (Application Programming Interface) — это набор способов и правил, по которым различные программы общаются между собой и обмениваются данными.

Метод API — это определённое действие, которое должно выполнить приложение основываясь на полученных данных (отправить сообщение, вернуть список чатов, отправить картинку и т.д.)

Token (токен) — это уникальный ключ бота, необходимый для отправки запросов.

Как отправлять HTTP запросы на PHP

Для отправки HTTP запросов можно использовать функцию file_get_contents(), где в качестве первого главного параметра указывается ссылка. Данная функция отлично подходит для отправки GET запросов, но к сожалению с помощью функции file_get_contents() нельзя отправлять POST запросы и поэтому для отправки POST запросов мы будем использовать библиотеку Curl.

Curl — это библиотека предназначенная для получения и передачи данных через такие протоколы, как HTTP, FTP, HTTPS.

Подробнее о Curl вы можете почитать на моём сайте.

Виды взаимодействия с приложением через API

Существует 2 вида взаимодействия с приложением через API. Первое это от клиента к серверу, а второе от сервера к клиентуКлиентом в данном случае является ваше приложение (сайт), а в качестве сервера выступает сайт на который вы отправляете запросы (в нашем случае, это Telegram).

API запрос — это способ общения с программой, по средствам отправки данных от клиента — серверу.

Hooks (Хуки) — это способ общения с программой, по средствам отправки данных от сервера — клиенту. То есть при определённых изменениях в программе, сервер (приложение) будет отправлять данные на указанный скрипта клиента.

Документация для работы с API Telegram

Все методы и параметры для запросов вы можете найти в официальной документации Telegram.

Telegram Bot API — https://core.tlgr.org/bots/api

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

Работа с документацией для Telegram

Документация для создания Telegram ботов разделена на несколько разделов.

В разделе Recent changes вы можете найти информацию об обновлениях Telegram. Здесь описаны версии и нововведения которые были внесены в функционал мессенджера.

Разделы Authorizing your bot и Making requests описывают способы авторизации ботов и способы создания запросов для работы с ботами.

Раздел Getting updates описывает способы получения обновлений взаимодействия с ботами. При взаимодействие пользователя с ботов, все его действия, по стандарту, записываются на сервера Telegram, и для того чтобы получить к ним доступ, необходимо отправить запрос getUpdates.

Отправив запрос getUpdates вы можете получить id последнего пользователя который написал боту, узнать его ник, текст сообщения и дату отправки. Если бот добавлен в сообщество, то вы можете получить id сообщества.

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

Следующий раздел, который нас интересует называется — Available types. Данный раздел описывает все типы данных которые возвращает нам Telegram. Когда ваш скрипт отправляет запрос, то обработав его, Telegram вернёт вам ответ в формате JSON строки, в котором описаны специальные параметры.

Например если вы отправляете сообщение, то Telegram вернёт вам массив в котором указаны id созданного сообщения, id пользователя, дата создания сообщения и много другое. Все эти данные вы можете разобрать и записать в базу данных.

Далее описан раздел, с которым нам придётся работать больше всего — это Available methods, методы для взаимодействия с ботом. Советую вам пройтись по всем методам и изучить все возможности работы с ботами.

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

Ну и в конце у нас описаны методы для работы со стикерами, играми в Telegram, методы для работы с оплатой в Telegram.

Структура URL для отправки запросов в Telegram

API Telegram имеет простую и понятную структуру урлов для отправки запросов.

Вот пример URL для создания запросов к боту:

https://api.telegram.org/bot{token}/{method}

{token} — это уникальный ключ, который выдаётся при создание бота;

{method} — это метод запроса по которому мы будем получать или отправлять определённые данные. В зависимости от названия метода, мы будем выполнять разные действия.

Примеры URL для запросов

Данные примеры используются только для наглядности построения URL, токен указанный в URL не привязан ни к одному боту!

Вот так выглядит отправка сообщений методом GET. Первая часть URL содержит домен api.telegram.org, далее прописываем строку bot с токеном который нам даётся при создание бота, после чего указываем метод sendMessage и перечисляем GET параметры.

https://api.telegram.org/bot546445612928:AAHjk6643OYgWHim_TICgsaF9NDDVXYnKzA/sendMessage?chat_id=<ID чата>&text=<text>

Отправка файлов в чат выглядит аналогично, только метод sendMessage заменяется на sendDocument. И здесь не перечисляются GET параметры, после указания метода, так как мы отправляем данные методом POST.

https://api.telegram.org/bot543264456928:AAHjk6643OYgWHim_TICgsaF9NDDVXYnKzA/sendDocument

Отправка изображений в чат:

https://api.telegram.org/bot546413456928:AAHjk6643OYgWHim_TICgsaF9NDDVXYnKzA/sendPhoto

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

Второй урок уже на Хабре — https://habr.com/ru/post/697000/

Диалоговый телеграм бот на PHP

На данную тему написано много статей на Хабре и просто в интернете. И я расскажу о своем опыте работы с телеграм ботом и моментами, которые «в лоб» не удалось решить.

Создание бота

Первое, с чего нужно начать, так это с создания бота. Есть официальная документация и там подробно расписаны шаги.

Если в описанной инструкции ничего не понятно, то вот пошаговая инструкция

  1. находим в телеграм бота BotFather и добавляем себе в контакт лист

  2. смотрим доступные команды бота с помощью команды /help

  3. выбираем /newbot и далее, следуя инструкции, выполняем необходимые действия (следующая картинка взята из google)

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

Связываем бота с приложениемсайтом

Начинается самое интересное, а также именно тут я столкнулся с первой проблемой.
Первым делом выбираем библиотеку на php по созданию бота. Я свой выбор остановил на этой библиотеке , так как мне она показалась самой удобной.

После подключения библиотеки нужно организовать взаимодействие бота с вашим сайтомприложением. Организовать это взаимодействие можно с помощью вебхуков .

Вебхук — это своего рода ретранслятор, который все запросы от бота будет передавать на адрес, указанный при регистрации вебхука. Зарегистрировать вебхук очень просто, нужно просто отправить запрос вида https: //api.telegram.org/bottoken/setWebhook?url=https: //example.ru/path , где
https: //example.ru/ — это ссылка на ваш сайт, куда будет перенаправлять бот запросы.
token — это токен, который вы получили при регистрации своего бота.
path — это часть url, на которую будут приходить обращения.

И вот именно тут возникает проблема. Оказывается вебхук можно зарегистрировать только в случае, если сайт находится на https. Если же ваш сайт на http, то зарегистрировать вебхук вам не получится.

Но выход есть, если вы не хотите покупать сертификат

Вы можете воспользоваться сервисом Let’s Encrypt
Переходим в раздел getting startted и следуем инструкции.

Написание кода бота

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

Разработчики telegram, для того чтобы пользователям было проще работать с ботами, просят всех разработчиков реализовывать поддержку следующих команд:

/start — начинает общение с пользователем (например, отправляет приветственное сообщение). В эту команду также можно передавать дополнительные аргументы.
/help — отображает сообщение с помощью по командам. Оно может представлять собой короткое сообщение о вашем боте и список доступных команд.

Все что нам нужно сделать, это в контроллере вашего приложениясайта написать следующий код:

$token = "токен";
$bot = new TelegramBotApiClient($token);
// команда для start
$bot->command('start', function ($message) use ($bot) {
    $answer = 'Добро пожаловать!';
    $bot->sendMessage($message->getChat()->getId(), $answer);
});

// команда для помощи
$bot->command('help', function ($message) use ($bot) {
    $answer = 'Команды:
/help - вывод справки';
    $bot->sendMessage($message->getChat()->getId(), $answer);
});

$bot->run();

Теперь если в окне телеграм бота написать /help, то будет выведен текст:

Команды:
/help — вывод справки

Что ж, мы написали список рекомендуемых команд. Далее мы можем реализовывать необходимые нам команды.

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

Для этого следует написать следующий код:

$bot->command('hello', function ($message) use ($bot) {
    $text = $message->getText();
    $param = str_replace('/hello ', '', $text);
    $answer = 'Неизвестная команда';
    if (!empty($param))
    {
    	$answer = 'Привет, ' . $param;
    }
    $bot->sendMessage($message->getChat()->getId(), $answer);
});

Получается все очень просто и быстро.

Заносим список команд бота

Для того, чтобы бот мог выдавать интерактивную справку

необходимо боту BotFather сообщить список команд.
Сделать это можно с помощью его команды /setcommands

Велосипедство

Описанный выше вариант не совсем удобен, потому что не хочется вбивать после команды текст, так как если использовать подсказки от бота, то это совсем нереально.

Значит нужно сделать так, чтобы бот запоминал команду, которую вы вводите. Это можно сделать с помощью любого хранилища (MySQL, memcached, redis, tarantool, Postgres, etc)
Все что нужно, это запоминать предыдущий ввод пользователя.

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

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

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

Для начала мы описываем точку входа в контроллер

function main()
{
	$telegram = new Telegram();
	// подключаем хранилище
	$storage = new Storage();
	// получаем объект сообщения
	$message = $telegram->getMessage();
	// получаем команду, если ее передали
	$command = $message->getCommand();
	// получаем текст, если его передали (тут лежит все, что не является командой)
	$text = $message->getParams($command);
	// если команда пустая, то мы проверяем, есть ли у пользователя на предыдущем шаге вызов команды и восстановливаем ее
	if (empty($command))
	{
	  $command = $storage->restoreCommand($message->getChat()->getId());
	}
	// запоминаем команду, котрую ввел пользователь
	$storage->storeCommand(
	    $message->getChat()->getId(),
	    $command
	);
	// логика подключения нашего метода для котроллера
	$this->chooseMethod($command, $message, $text);
}

Теперь рассмотрим один из методов.

function getnewtext(Message $telegram, $text)
{
	// если не передали текст, то выведем сообщение с разъяснением
	if (empty($text))
	{
	  $answer = "Введите слово или несколько слов для поиска. Именно по ним будет происходить поиск 5 свежих новостей.";
	  $telegram->sendMessage($telegram->getChat()->getId(), $answer);
	}
	else
	{
		// основаня логика
		$tgNews = new TelegramNews();
		$arData = $tgNews->getByWord($text, 'new');
		if (empty($arData))
		{
			$answer = 'Ничего не найдено';
		}
		else
		{
			$answer = common_setViewGetContent('telegram/get', [
			    'data' => $arData
			]);
		}
		$telegram->sendMessage($telegram->getChat()->getId(), $answer);
	}
}

Так стало все в разы приятнее, интерактивнее и удобнее.

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

UPD: боту добавлена возможность отдавать фото на некоторые виды запросов. Например на
/gettable — возвращает результирующую таблицу спортивных событий
/getevents — возвращает события спортивных мероприятий


PHP
Telegram

Понравилась статья? Поделить с друзьями:
  • Как написать бота для телеграмм на python
  • Как написать бота для твича
  • Как написать бота для страницы вк
  • Как написать бота для спама
  • Как написать бота для сайта