denisok94/telegram-bot

0.1.3 2025-08-17 14:56 UTC

This package is auto-updated.

Last update: 2025-08-18 07:50:52 UTC


README

Установка

Run:

composer require --prefer-dist denisok94/telegram-bot
# or
php composer.phar require --prefer-dist denisok94/telegram-bot

or add to the require section of your composer.json file:

"denisok94/telegram-bot": "*"
composer update
# or
php composer.phar update

Описание

Method Description
setData(string $data) Сообщение от пользователя которое прислал Телеграм
getChatId(): ?int Ид чата в котором идёт беседа
getType(): string Тип присланного сообщения/события
isAdmin() Является автор сообщения адсином бота
getText(): ?string Текст сообщения
sendMessage(string|array $data) Отправить сообщение
sendPhoto(array $data) Отправить картинку
sendDocument(array $data) Отправить файл (фото/видео/музыку/гифку и т.д.)
sendChatAction(string $action) Отправка индикации набора текста
editMessage(string $message_id, string|array $data) Обновить сообщение (только собственные сообщения бота)
deleteMessage(int $chat_id, int $message_id) Удалить сообщение
deleteMessages(int $chat_id, array $message_id) Удалить сообщения
sendInlineResults(InlineQuery $query, array $results) Ответ на inline-запрос
getFileInfo(string $file_id) Получить информацию о файле и ссылку для скачивания
downloadFileById(string $file_id, string $savePath) Скачать файл по его ид
downloadFileByUrl(string $url, string $savePath) Скачать файл по url
sendApiQuery(string $method, $data = [], bool $raw = false) Отправляем свой кастомный запрос к API Telegram, подробнее обо всех методах на руском
Property Tupe Description
$bot_name string
$admin_id int|null
$data array Оригинальное сообщение от Telegram
$update_id int|null
$type string|bool Тип сообщения
$message Message|null Класс сообщеия
$event CallbackQuery|InlineQuery|null Класс события

Планы

  • ☑ Обработка inline_query сообщений
  • ☐ Обработка api mini app
  • ☐ Отдельные методы отправки для каждого типа файла (видео, аудио, стикеров и тд)
  • ☐ Массовая отправка фото (галереи)
  • ☐ Массовая отправка других типов файлов (если возможно)
  • ☐ Доработка шаблонов ответа для inline_query
  • ☐ Реакции на сообщения
  • ☐ Реакции на события в группах/каналах
  • ☐ Поддержка типов событий edited_channel_post, my_chat_member и других
  • ☐ Всё переделать
checked unchecked crossed
_

Использование

Регистрация webhook

указывает Телеграму url, куда ему отправлять нам сообщения отправленные боту

$bot = new Bot('123456:qwerty');
$url = "https://ваш-домен.ru/webhook.php";
$bot->setWebhook($url);
// or
$bot->setWebhook([
    'url' => $url,
    'max_connections' => 5,
    'allowed_updates' => json_encode(["message", "callback_query"]),
]);
// удалить текущий webhook
$bot->deleteWebhook();

Примеры

// webhook.php
use denisok94\telegram\Bot;

$bot = new Bot([
    'bot_token' => $botToken,
    'bot_name' => $bot_name,
    'admin_id' => $admin_id,
]);
// получаем сообщение от Телеграмма
$bot->setData(file_get_contents('php://input'));

if ($chat_id = $bot->getChatId()) {
    $type = $bot->getType();
    if ($type == 'bot_command') { // отправлена команда "/command"
        $message = $bot->getText();
        $message = str_replace($bot_name, "", $message);
        switch ($message) {
            case '/start':
                // Получили текст start и проверяем, от админа сообщение или нет
                if ($bot->isAdmin()) {
                    $text = 'Привет, создатель!';
                } else {
                    $text = 'Здравствуйте, товарищ!';
                }
                $resp = $bot->sendMessage([
                    'chat_id' => $chat_id,
                    'text' => $text,
                    'reply_markup' => json_encode([
                        'keyboard' => [
                            [
                                [
                                    'text' => 'Button 1',
                                    'callback_data' => 'keyboard_test_2',
                                ],
                                [
                                    'text' => 'Button 2',
                                    'callback_data' => 'keyboard_test_2',
                                ]
                            ]
                        ],
                        'one_time_keyboard' => true,
                        'resize_keyboard' => true,
                    ])
                ]);
                break;
            case '/help':
                $resp = $bot->sendMessage('Чем я могу Вам помочь?');
                break;
        }
    } else if ($type == 'message') { // Простой текст
        $message = $bot->getText();
        switch ($message) {
            case 'Button 1':
            case 'Button 2':
                $resp = $bot->sendMessage('Button =)');
                break;
            case 'Свяжи с оператором!!':
                $resp = $bot->sendMessage('Все операторы заняты! =)');
                break;
        }
    } else {
        $resp = $bot->sendMessage([
            'chat_id' => $chat_id,
            'text' => 'Я пока не умею обрабатывать такие данные. Подождите, когда разработчик придумает, как реагировать на такие сообщения.',
            "reply_to_message_id" => $bot->message->id ?? null,
            'reply_markup' => json_encode([
                'keyboard' => [
                    [
                        [
                            'text' => 'Свяжи с оператором!!',
                            'callback_data' => 'keyboard_help',
                        ],
                    ]
                ],
                'one_time_keyboard' => true,
                'resize_keyboard' => true,
            ]),
        ]);
    }
    if ($resp->ok != true) {
        $bot->sendMessage([
            'chat_id' => $bot->admin_id,
            'text' => "<pre>\n" . print_r($resp,true) . "\n</pre>",
            'parse_mode' => 'html',
        ]);
    }
}

Работа с файлами

Отправить/загрузить файлы в чат

$chat_id = $bot->getChatId();
$file_path = __DIR__ . '/files/denis_Charlotte.png';
if (file_exists($file_path)) {
    $resp = $bot->sendDocument([
        'chat_id' => $chat_id,
        'caption' => 'Отправка картинки документом',
        'document' => curl_file_create($file_path, 'image/png', basename($file_path))
    ]);
    $resp = $bot->sendPhoto([
        'chat_id' => $chat_id,
        'caption' => 'Отправка картинки',
        'photo' => curl_file_create($file_path, 'image/png', basename($file_path))
    ]);
}

Повторно отправить файл используя ид телеграма

$chat_id = $bot->getChatId();
$file_id = "FILE_ID_ОТ_ТЕЛЕГРАМ";
if (file_exists($file_path)) {
    $resp = $bot->sendDocument([
        'chat_id' => $chat_id,
        'caption' => 'Отправка картинки документом',
        'document' => $file_id
    ]);
    $resp = $bot->sendPhoto([
        'chat_id' => $chat_id,
        'caption' => 'Отправка картинки',
        'photo' => $file_id
    ]);
}

Отправить несколько фото (до 10)

$chat_id = $bot->getChatId();
// Показываем, что бот отправляет фото
$resp = $bot->sendChatAction('upload_photo');
// Массив путей к файлам
$photo_paths = [
   __DIR__. '/files/screenshots0.jpg',
   __DIR__. '/files/screenshots1.jpg',
   __DIR__. '/files/screenshots2.jpg',
];
$arrayQuery = [
    'chat_id' => $chat_id,
    'media' => json_encode([
        ['type' => 'photo', 'media' => 'attach://screenshots0.jpg', 'caption' => 'Описание альбома'],
        ['type' => 'photo', 'media' => 'attach://screenshots1.jpg'],
        ['type' => 'photo', 'media' => 'attach://screenshots2.jpg'],
    ]),
    'screenshots0.jpg' => curl_file_create($photo_paths[0], 'image/jpeg', basename($photo_paths[0])),
    'screenshots1.jpg' => curl_file_create($photo_paths[1], 'image/jpeg', basename($photo_paths[1])),
    'screenshots2.jpg' => curl_file_create($photo_paths[2], 'image/jpeg', basename($photo_paths[2])),
];

$resp = $bot->sendApiQuery('sendMediaGroup', $arrayQuery, true);

Скачать полученный файл

$message = $bot->message;
$type = $message->document_type;
if ($type != 'photo') {
    $file_id = $message->{$type}->file_id;
    $file_name = $message->{$type}->file_name;
    $savePath = __DIR__ . '/' . $file_name;
    try {
        // бот сам получить информацию о файле и скачает его в нужное место
        $bot->downloadFileById($file_id, $savePath);
    } catch (Throwable $th) {
        // Ошибка при скачивании файла
    }
} else if ($message->photo) { // вариант 2
    $photo = $message->photo[array_key_last($message->photo)];
    $file_id = $photo->file_id;
    // сами получаем информацию об файле
    $file = $bot->getFileInfo($file_id);
    if ($file instanceof \denisok94\telegram\model\FileInfo) {
        // проверяем что всё ли ок
        $extension = pathinfo($file->file_path, PATHINFO_EXTENSION);
        $file_name = pathinfo($file->file_path, PATHINFO_BASENAME);
        $savePath = __DIR__ ."/$file_name.$extension";
        // и скачиваем по ссывлке куда нам надо и потом прверяем
        $bot->downloadFileByUrl($file->file_url, $savePath);
        if (file_exists($savePath)) {
            // code
        } else {
            // Ошибка при скачивании файла
        }
    } else {
        // Не удалось получить информацию об файле, см $file->description
    }
}

inline_keyboard и callback_query

$type = $bot->getType();
$chat_id = $bot->getChatId();
if ($type == 'bot_command') {
    $message = $bot->getText();
    switch ($message) {
        case '/start':
            $resp = $bot->sendMessage([
                    'chat_id' => $chat_id,
                    'text' => 'test inline_keyboard',
                    'reply_markup' => json_encode([
                        'inline_keyboard' => [
                            [
                                [
                                    'text' => 'Button 1',
                                    'callback_data' => 'inline_test_1',
                                ]
                            ],
                            [
                                [
                                    'text' => 'Button 2',
                                    'callback_data' => 'inline_test_2',
                                ],
                                [
                                    'text' => 'Button 3',
                                    'callback_data' => 'inline_test_3',
                                ]
                            ]
                        ],
                        'resize_keyboard' => true,
                    ]),
                ]);
            break;
    }
} else if ($type == 'callback_query') {
    $message = $bot->getText();
    switch ($message) {
        case 'inline_test_1':
        case 'inline_test_2':
        case 'inline_test_3':
            $resp = $bot->editMessage($bot->message->id, [
                "text" => "Реакция принята!\n а теперь этап 2й)",
                'reply_markup' => json_encode([
                    'inline_keyboard' => [
                        [
                            [
                                'text' => '1',
                                'callback_data' => 'inline_test_4',
                            ],
                            [
                                'text' => '2',
                                'callback_data' => 'inline_test_5',
                            ]
                        ]
                    ],
                    'resize_keyboard' => true,
                ]),
            ]);
            break;
        case 'inline_test_4':
        case 'inline_test_5':
            $resp = $bot->editMessage($bot->message->id, "Спасибо за участие в опросе!");
            break;
    }
}

inline_query

в разработке... https://botphp.ru/docs/api#inlinequeryresult

$bot = new Bot('123456:qwerty');
$type = $bot->getType();
if ($type == 'inline_query') {
    $results = [];
    $search = $this->bot->getText();
    if (mb_strlen($search) < 10) {
        // испольование готовых шаблонов
        $article = new \denisok94\telegram\inline\Article();
        $article->id = uniqid();
        $article->title = "Маловато будет!";
        $article->description = "Для поиска необходимо минимум 10 символов";
        $article->thumb_url = 'https://example.com/photo.jpg';
        $article->input_message_content = [
            'message_text' => "-article: " . $article->id
        ];
        $results[] = $article;
    } else {
        // свой вариант, если шаблонов мало
        for ($i = 0; $i < 10; $i++) {
            $results[] = [
                'type' => 'article',
                'id' => uniqid(),
                'title' => "Результат $i",
                'description' => 'Описание',
                'thumb_url' => 'https://example.com/photo.jpg',
                'input_message_content' => [
                    'message_text' => 'Текст сообщения ' . $i // что будет отправлено при выборе пользователем
                ]
            ];
        }
    }
    $resp = $this->bot->sendInlineResults($results); // максимум 50 результатов за раз
} else if ($type == 'message') {
    $message = $bot->getText();
    // получит выбранный объект
    if (isset($bot->data['message']['via_bot'])) {
        $bot_id = $bot->data['message']['via_bot']['id'];
        // проверяем, что это выбор от нашего бота (малолди в чате есть другие)
        switch ($message) {
            case 'Текст сообщения 1':
            case 'Текст сообщения 2':
            default:
                $resp = $this->bot->sendMessage('Выбранный объект: "' . $message . '"');
                break;
        }
    }
}

MiniApp

<script src="https://telegram.org/js/telegram-web-app.js"></script>
<script>
    document.addEventListener('DOMContentLoaded', function ()
    {
        const tg = Telegram.WebApp;
        // Получаем данные initData
        const initData = tg.initData;
        tg.ready(); // сообщаем Telegram, что готовы
        // отправляем данные на валидацию
        fetch("api/get-user", {
            method: "POST",
            headers: {"Content-Type": "application/json"},
            body: JSON.stringify({ initData })
        })
            .then(response => response.json())
            .then(data => {
                console.log("Ответ:", data);
            })
            .catch(error => {
                console.error("Ошибка запроса:", error);
            });
    });
</script>
// ~ApiController
public function actionGetUser()
{
    try {
        // Получаем данные из параметра tgWebAppData
        $initData = json_decode(file_get_contents('php://input') ?? '', true)['initData'] ?? '';
        // Проверяем и декодируем данные
        $result = \denisok94\telegram\app\InitData::isValid($initData, $botToken, true);
        if ($result['isValid'] == true) {
            return $this->sendSuccess($result['data']['parsed']); // 200
        } else {
            $result['data'] = $result['data']['parsed'] ?? $initData;
            return $this->sendError("Bad Request", $result); // 400
        }
    } catch (\Exception $e) {
        return $this->sendError($e->getMessage()); // 500
    }
}