Как написать телеграмм бота на php

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

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

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

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

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

Регистрация проходит в 5 простых этапов:

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

По итогу регистрации получаем наш токен — 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. Список всех смайлов в таком виде можно найти на специальном сайте.

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

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

Бесплатными площадками для продвижения могут послужить каталоги ботов Telegram Bot Store, TeleChappy или 50bots.

А анализировать активность пользователей можно с помощью бесплатного инструмента для аналитики ботов от Яндекса — Botan.

От редакции

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

PHP Telegram Bot

PHP Telegram Bot logo

A Telegram Bot based on the official Telegram Bot API

API Version
Join the bot support group on Telegram
Donate

Tests
Code Coverage
Code Quality
Latest Stable Version
Dependencies
Total Downloads
Downloads Month
Minimum PHP Version
License

Table of Contents

  • Introduction
  • Instructions
    • Create your first bot
    • Require this package with Composer
    • Choose how to retrieve Telegram updates
  • Using a custom Bot API server
  • Webhook installation
    • Self Signed Certificate
    • Unset Webhook
  • getUpdates installation
    • getUpdates without database
  • Filter Update
  • Support
    • Types
    • Inline Query
    • Methods
    • Send Message
    • Send Photo
    • Send Chat Action
    • getUserProfilePhoto
    • getFile and downloadFile
    • Send message to all active chats
  • Utils
    • MySQL storage (Recommended)
      • External Database connection
    • Channels Support
  • Commands
    • Predefined Commands
    • Custom Commands
    • Commands Configuration
    • Admin Commands
      • Set Admins
      • Channel Administration
  • Upload and Download directory path
  • Logging
  • Documentation
  • Assets
  • Example bot
  • Projects with this library
  • Troubleshooting
  • Contributing
  • Security
  • Donate
  • For enterprise
  • License
  • Credits

Introduction

This is a pure PHP Telegram Bot, fully extensible via plugins.

Telegram announced official support for a Bot API, allowing integrators of all sorts to bring automated interactions to the mobile platform.
This Bot aims to provide a platform where one can simply write a bot and have interactions in a matter of minutes.

The Bot can:

  • Retrieve updates with webhook and getUpdates methods.
  • Supports all types and methods according to Telegram Bot API 6.3 (November 2022).
  • Supports supergroups.
  • Handle commands in chat with other bots.
  • Manage Channel from the bot admin interface.
  • Full support for inline bots.
  • Inline keyboard.
  • Messages, InlineQuery and ChosenInlineQuery are stored in the Database.
  • Conversation feature.

This code is available on GitHub. Pull requests are welcome.

Instructions

Create your first bot

  1. Message @BotFather with the following text: /newbot

    If you don’t know how to message by username, click the search field on your Telegram app and type @BotFather, where you should be able to initiate a conversation. Be careful not to send it to the wrong contact, because some users have similar usernames to BotFather.

    BotFather initial conversation

  2. @BotFather replies with:

    Alright, a new bot. How are we going to call it? Please choose a name for your bot.
    
  3. Type whatever name you want for your bot.

  4. @BotFather replies with:

    Good. Now let's choose a username for your bot. It must end in `bot`. Like this, for example: TetrisBot or tetris_bot.
    
  5. Type whatever username you want for your bot, minimum 5 characters, and must end with bot. For example: telesample_bot

  6. @BotFather replies with:

    Done! Congratulations on your new bot. You will find it at
    telegram.me/telesample_bot. You can now add a description, about
    section and profile picture for your bot, see /help for a list of
    commands.
    
    Use this token to access the HTTP API:
    123456789:AAG90e14-0f8-40183D-18491dDE
    
    For a description of the Bot API, see this page:
    https://core.telegram.org/bots/api
    
  7. Note down the ‘token’ mentioned above.

Optionally set the bot privacy:

  1. Send /setprivacy to @BotFather.

    BotFather later conversation

  2. @BotFather replies with:

    Choose a bot to change group messages settings.
    
  3. Type (or select) @telesample_bot (change to the username you set at step 5
    above, but start it with @)

  4. @BotFather replies with:

    'Enable' - your bot will only receive messages that either start with the '/' symbol or mention the bot by username.
    'Disable' - your bot will receive all messages that people send to groups.
    Current status is: ENABLED
    
  5. Type (or select) Disable to let your bot receive all messages sent to a group.

  6. @BotFather replies with:

    Success! The new status is: DISABLED. /help
    

Require this package with Composer

Install this package through Composer.
Edit your project’s composer.json file to require longman/telegram-bot.

Create composer.json file

{
    "name": "yourproject/yourproject",
    "type": "project",
    "require": {
        "php": ">=7.3",
        "longman/telegram-bot": "*"
    }
}

and run composer update

or

run this command in your command line:

composer require longman/telegram-bot

Choose how to retrieve Telegram updates

The bot can handle updates with Webhook or getUpdates method:

Webhook getUpdates
Description Telegram sends the updates directly to your host You have to fetch Telegram updates manually
Host with https Required Not required
MySQL Not required (Not) Required

Using a custom Bot API server

For advanced users only!

As from Telegram Bot API 5.0, users can run their own Bot API server to handle updates.
This means, that the PHP Telegram Bot needs to be configured to serve that custom URI.
Additionally, you can define the URI where uploaded files to the bot can be downloaded (note the {API_KEY} placeholder).

LongmanTelegramBotRequest::setCustomBotApiUri(
    $api_base_uri          = 'https://your-bot-api-server', // Default: https://api.telegram.org
    $api_base_download_uri = '/path/to/files/{API_KEY}'     // Default: /file/bot{API_KEY}
);

Note: If you are running your bot in --local mode, you won’t need the Request::downloadFile() method, since you can then access your files directly from the absolute path returned by Request::getFile().

Webhook installation

Note: For a more detailed explanation, head over to the example-bot repository and follow the instructions there.

In order to set a Webhook you need a server with HTTPS and composer support.
(For a self signed certificate you need to add some extra code)

Create set.php with the following contents:

<?php
// Load composer
require __DIR__ . '/vendor/autoload.php';

$bot_api_key  = 'your:bot_api_key';
$bot_username = 'username_bot';
$hook_url     = 'https://your-domain/path/to/hook.php';

try {
    // Create Telegram API object
    $telegram = new LongmanTelegramBotTelegram($bot_api_key, $bot_username);

    // Set webhook
    $result = $telegram->setWebhook($hook_url);
    if ($result->isOk()) {
        echo $result->getDescription();
    }
} catch (LongmanTelegramBotExceptionTelegramException $e) {
    // log telegram errors
    // echo $e->getMessage();
}

Open your set.php via the browser to register the webhook with Telegram.
You should see Webhook was set.

Now, create hook.php with the following contents:

<?php
// Load composer
require __DIR__ . '/vendor/autoload.php';

$bot_api_key  = 'your:bot_api_key';
$bot_username = 'username_bot';

try {
    // Create Telegram API object
    $telegram = new LongmanTelegramBotTelegram($bot_api_key, $bot_username);

    // Handle telegram webhook request
    $telegram->handle();
} catch (LongmanTelegramBotExceptionTelegramException $e) {
    // Silence is golden!
    // log telegram errors
    // echo $e->getMessage();
}

Self Signed Certificate

Upload the certificate and add the path as a parameter in set.php:

$result = $telegram->setWebhook($hook_url, ['certificate' => '/path/to/certificate']);

Unset Webhook

Edit unset.php with your bot credentials and execute it.

getUpdates installation

For best performance, the MySQL database should be enabled for the getUpdates method!

Create getUpdatesCLI.php with the following contents:

#!/usr/bin/env php
<?php
require __DIR__ . '/vendor/autoload.php';

$bot_api_key  = 'your:bot_api_key';
$bot_username = 'username_bot';

$mysql_credentials = [
   'host'     => 'localhost',
   'port'     => 3306, // optional
   'user'     => 'dbuser',
   'password' => 'dbpass',
   'database' => 'dbname',
];

try {
    // Create Telegram API object
    $telegram = new LongmanTelegramBotTelegram($bot_api_key, $bot_username);

    // Enable MySQL
    $telegram->enableMySql($mysql_credentials);

    // Handle telegram getUpdates request
    $telegram->handleGetUpdates();
} catch (LongmanTelegramBotExceptionTelegramException $e) {
    // log telegram errors
    // echo $e->getMessage();
}

Next, give the file permission to execute:

$ chmod +x getUpdatesCLI.php

Lastly, run it!

getUpdates without database

If you choose to / or are obliged to use the getUpdates method without a database, you can replace the $telegram->useMySQL(...); line above with:

$telegram->useGetUpdatesWithoutDatabase();

Filter Update

❗ Note that by default, Telegram will send any new update types that may be added in the future. This may cause commands that don’t take this into account to break!

It is suggested that you specifically define which update types your bot can receive and handle correctly.

You can define which update types are sent to your bot by defining them when setting the webhook or passing an array of allowed types when using getUpdates.

use LongmanTelegramBotEntitiesUpdate;

// For all update types currently implemented in this library:
// $allowed_updates = Update::getUpdateTypes();

// Define the list of allowed Update types manually:
$allowed_updates = [
    Update::TYPE_MESSAGE,
    Update::TYPE_CHANNEL_POST,
    // etc.
];

// When setting the webhook.
$telegram->setWebhook($hook_url, ['allowed_updates' => $allowed_updates]);

// When handling the getUpdates method.
$telegram->handleGetUpdates(['allowed_updates' => $allowed_updates]);

Alternatively, Update processing can be allowed or denied by defining a custom update filter.

Let’s say we only want to allow messages from a user with ID 428, we can do the following before handling the request:

$telegram->setUpdateFilter(function (Update $update, Telegram $telegram, &$reason = 'Update denied by update_filter') {
    $user_id = $update->getMessage()->getFrom()->getId();
    if ($user_id === 428) {
        return true;
    }

    $reason = "Invalid user with ID {$user_id}";
    return false;
});

The reason for denying an update can be defined with the $reason parameter. This text gets written to the debug log.

Support

Types

All types are implemented according to Telegram API 6.3 (November 2022).

Inline Query

Full support for inline query according to Telegram API 6.3 (November 2022).

Methods

All methods are implemented according to Telegram API 6.3 (November 2022).

Send Message

Messages longer than 4096 characters are split up into multiple messages.

$result = Request::sendMessage([
    'chat_id' => $chat_id,
    'text'    => 'Your utf8 text 😜 ...',
]);

Send Photo

To send a local photo, add it properly to the $data parameter using the file path:

$result = Request::sendPhoto([
    'chat_id' => $chat_id,
    'photo'   => Request::encodeFile('/path/to/pic.jpg'),
]);

If you know the file_id of a previously uploaded file, just use it directly in the data array:

$result = Request::sendPhoto([
    'chat_id' => $chat_id,
    'photo'   => 'AAQCCBNtIhAoAAss4tLEZ3x6HzqVAAqC',
]);

To send a remote photo, use the direct URL instead:

$result = Request::sendPhoto([
    'chat_id' => $chat_id,
    'photo'   => 'https://example.com/path/to/pic.jpg',
]);

sendAudio, sendDocument, sendAnimation, sendSticker, sendVideo, sendVoice and sendVideoNote all work in the same way, just check the API documentation for the exact usage.
See the ImageCommand.php for a full example.

Send Chat Action

Request::sendChatAction([
    'chat_id' => $chat_id,
    'action'  => LongmanTelegramBotChatAction::TYPING,
]);

getUserProfilePhoto

Retrieve the user photo. (see WhoamiCommand.php for a full example)

getFile and downloadFile

Get the file path and download it. (see WhoamiCommand.php for a full example)

Send message to all active chats

To do this you have to enable the MySQL connection.
Here’s an example of use (check DB::selectChats() for parameter usage):

$results = Request::sendToActiveChats(
    'sendMessage', // Callback function to execute (see Request.php methods)
    ['text' => 'Hey! Check out the new features!!'], // Param to evaluate the request
    [
        'groups'      => true,
        'supergroups' => true,
        'channels'    => false,
        'users'       => true,
    ]
);

You can also broadcast a message to users, from the private chat with your bot. Take a look at the admin commands below.

Utils

MySQL storage (Recommended)

If you want to save messages/users/chats for further usage in commands, create a new database (utf8mb4_unicode_520_ci), import structure.sql and enable MySQL support BEFORE handle() method:

$mysql_credentials = [
   'host'     => 'localhost',
   'port'     => 3306, // optional
   'user'     => 'dbuser',
   'password' => 'dbpass',
   'database' => 'dbname',
];

$telegram->enableMySql($mysql_credentials);

You can set a custom prefix to all the tables while you are enabling MySQL:

$telegram->enableMySql($mysql_credentials, $bot_username . '_');

You can also store inline query and chosen inline query data in the database.

External Database connection

It is possible to provide the library with an external MySQL PDO connection.
Here’s how to configure it:

$telegram->enableExternalMySql($external_pdo_connection);
//$telegram->enableExternalMySql($external_pdo_connection, $table_prefix)

Channels Support

All methods implemented can be used to manage channels.
With admin commands you can manage your channels directly with your bot private chat.

Commands

Predefined Commands

The bot is able to recognise commands in a chat with multiple bots (/command@mybot).

It can also execute commands that get triggered by events, so-called Service Messages.

Custom Commands

Maybe you would like to develop your own commands.
There is a guide to help you create your own commands.

Also, be sure to have a look at the example commands to learn more about custom commands and how they work.

You can add your custom commands in different ways:

// Add a folder that contains command files
$telegram->addCommandsPath('/path/to/command/files');
//$telegram->addCommandsPaths(['/path/to/command/files', '/another/path']);

// Add a command directly using the class name
$telegram->addCommandClass(MyCommand::class);
//$telegram->addCommandClasses([MyCommand::class, MyOtherCommand::class]);

Commands Configuration

With this method you can set some command specific parameters, for example:

// Google geocode/timezone API key for /date command
$telegram->setCommandConfig('date', [
    'google_api_key' => 'your_google_api_key_here',
]);

// OpenWeatherMap API key for /weather command
$telegram->setCommandConfig('weather', [
    'owm_api_key' => 'your_owm_api_key_here',
]);

Admin Commands

Enabling this feature, the bot admin can perform some super user commands like:

  • List all the chats started with the bot /chats
  • Clean up old database entries /cleanup
  • Show debug information about the bot /debug
  • Send message to all chats /sendtoall
  • Post any content to your channels /sendtochannel
  • Inspect a user or a chat with /whois

Take a look at all default admin commands stored in the src/Commands/AdminCommands/ folder.

Set Admins

You can specify one or more admins with this option:

// Single admin
$telegram->enableAdmin(your_telegram_user_id);

// Multiple admins
$telegram->enableAdmins([
    your_telegram_user_id,
    other_telegram_user_id,
]);

Telegram user id can be retrieved with the /whoami command.

Channel Administration

To enable this feature follow these steps:

  • Add your bot as channel administrator, this can be done with any Telegram client.
  • Enable admin interface for your user as explained in the admin section above.
  • Enter your channel name as a parameter for the /sendtochannel command:
$telegram->setCommandConfig('sendtochannel', [
    'your_channel' => [
        '@type_here_your_channel',
    ]
]);
  • If you want to manage more channels:
$telegram->setCommandConfig('sendtochannel', [
    'your_channel' => [
        '@type_here_your_channel',
        '@type_here_another_channel',
        '@and_so_on',
    ]
]);
  • Enjoy!

Upload and Download directory path

To use the Upload and Download functionality, you need to set the paths with:

$telegram->setDownloadPath('/your/path/Download');
$telegram->setUploadPath('/your/path/Upload');

Documentation

Take a look at the repo Wiki for further information and tutorials!
Feel free to improve!

Assets

All project assets can be found in the assets repository.

Example bot

We’re busy working on a full A-Z example bot, to help get you started with this library and to show you how to use all its features.
You can check the progress of the example-bot repository).

Projects with this library

Here’s a list of projects that feats this library, feel free to add yours!

  • Inline Games (@inlinegamesbot)
  • Super-Dice-Roll (@superdiceroll_bot)
  • tg-mentioned-bot
  • OSMdeWikiBot (@OSM_de)
  • pass-generator-webbot
  • Chess Quiz Bot

Troubleshooting

If you like living on the edge, please report any bugs you find on the PHP Telegram Bot issues page.

Contributing

See CONTRIBUTING for more information.

Security

See SECURITY for more information.

Donate

All work on this bot consists of many hours of coding during our free time, to provide you with a Telegram Bot library that is easy to use and extend.
If you enjoy using this library and would like to say thank you, donations are a great way to show your support.

Donations are invested back into the project 👍

Thank you for keeping this project alive 🙏

For enterprise

Available as part of the Tidelift Subscription.

The maintainers of PHP Telegram Bot and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

License

Please see the LICENSE included in this repository for a full copy of the MIT license, which this project is licensed under.

Credits

Credit list in CREDITS


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, управлять базами данных различной сложности. Ждем вас!

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

Обсудить …

05.07.2021     👁 21775


Здравствуйте, дорогие читатели. Раз вы здесь, то пришли вы сюда из поиска по фразе «бот для телеграм на пхп». И работающего бота вы сделать сможете, прочитав данную статью. Вопросы для чего вам бот в Телеграм, здесь не обсуждаются, хотя мы сами используем собственного публичного бота @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 — оставить заявку
  • Все — теперь в вашем боте появится список команд, если нажать в диалоге /
     

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


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



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

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


Примеры как зарегистрировать бота в 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

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

Программирование, PHP


Рекомендация: подборка платных и бесплатных курсов создания сайтов — https://katalog-kursov.ru/

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

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

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

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

  1. находим в телеграм бота BotFather и добавляем себе в контакт лист
  2. смотрим доступные команды бота с помощью команды /help

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

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

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

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

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

Вебхук — это своего рода ретранслятор, который все запросы от бота будет передавать на адрес, указанный при регистрации вебхука. Зарегистрировать вебхук очень просто, нужно просто отправить запрос вида https: //api.telegram.org/bot~token~/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 ', '', $command);
    $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 — возвращает события спортивных мероприятий

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