Бот для Телеграм (Telegram Bot) на php

26.10.2016

Пример простого бота для телеграм.

Он умеет получать сообщения пользователя и отвечать на них.

Данный способ работы основан на вебхуках, поэтому стоит учесть, что для его работы потребуется домен с SSL (HTTPS).


Файл "точка входа", его нужно выполнить в консоли сервера для установки веб хука.

main.php (Download)

 <?php
error_reporting(E_ALL);
ini_set('display_errors', 'On');

use Oddler\Telegram\CurrentTelegramBot as CTBot;

require_once (__DIR__.'/protected/config.php');
require_once (__DIR__.'/protected/CurrentTelegramBot.php');

/**
 *
 * Документация: https://core.telegram.org/api
 *
 * Запускать нужно через консоль:
 *
 * php main.php - установка хука
 * php main.php unset - удаление хука
 */

// Переменная существует только при вызове из консоли
$argv = isset($argv)?$argv:[];

$oTelegramBot = new CTBot();
$oTelegramBot->dispath($argv);

Класс для работы с API телеграмма.

TelegramApi.php (Download)

 <?php
/**
 * Created by PhpStorm.
 * User: Oddler
 * Date: 17.11.2018
 * Time: 13:03
 */

namespace Oddler\Telegram;


class TelegramApi
{
    protected function _error_log ($sMessage){
        //$sFile = __DIR__.'/bot.log';
        //file_put_contents($sFile, date("m.d.Y H:i:s").': '.$sMessage."\n".file_get_contents($sFile));
        error_log($sMessage);
    }

    /**
     * Делает запрос к серверу
     *
     * @param resource $handle
     *
     * @return boolean
     */
    protected function _exec_curl_request($handle)
    {
        $response = curl_exec($handle);
        if ($response === false) {
            $errno = curl_errno($handle);
            $error = curl_error($handle);
            $this->_error_log("Curl returned error $errno: $error");
            curl_close($handle);
            return false;
        }
        $http_code = intval(curl_getinfo($handle, CURLINFO_HTTP_CODE));
        curl_close($handle);

        if ($http_code >= 500) {
            // do not wat to DDOS server if something goes wrong
            sleep(10);
            return false;
        }
        else if ($http_code != 200)  {
            $response = json_decode($response, true);
            if ($http_code == 401) {
                $this->_error_log("Invalid access token provided: {$response['error_code']}: {$response['description']}");
            }
            else {
                $this->_error_log("Request has failed with error {$response['error_code']}: {$response['description']}");
            }
            return false;
        }
        else
        {
            $response = json_decode($response, true);
            if (isset($response['description'])) {
                $this->_error_log("Request was successfull: {$response['description']}");
            }
            $response = $response['result'];
        }

        return $response;
    }

    /**
     * Подготовка запроса
     *
     * @param string $method
     * @param array $parameters
     *
     * @return boolean
     */
//    public function apiCall2($method, $parameters)
//    {
//        if (!is_string($method)) {
//            $this->_error_log("Method name must be a string");
//            return false;
//        }
//
//        if (!$parameters) {
//            $parameters = array();
//        }
//        else if (!is_array($parameters)) {
//            $this->_error_log("Parameters must be an array");
//            return false;
//        }
//
//        foreach($parameters as $key => & $val) {
//            // encoding to JSON array parameters, for example reply_markup
//            if (!is_numeric($val) && !is_string($val)) {
//                $val = json_encode($val);
//            }
//        }
//
//        $url = API_URL . $method . '?' . http_build_query($parameters);
//        $handle = curl_init($url);
//        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
//        curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
//        curl_setopt($handle, CURLOPT_TIMEOUT, 60);
//        return $this->_exec_curl_request($handle);
//    }

    /**
     * Подготовка Json запроса
     *
     * @param string $method
     * @param array $parameters
     *
     * @return boolean
     */
    public function apiCall($method, $parameters)
    {
        if (!is_string($method))
        {
            $this->_error_log("Method name must be a string");
            return false;
        }

        if (!$parameters)
        {
            $parameters = array();
        }
        else if (!is_array($parameters))
        {
            $this->_error_log("Parameters must be an array");
            return false;
        }

        $parameters["method"] = $method;
        $handle = curl_init(API_URL);
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($handle, CURLOPT_TIMEOUT, 60);
        curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($parameters));
        curl_setopt($handle, CURLOPT_HTTPHEADER, array(
            "Content-Type: application/json"
        ));
        return $this->_exec_curl_request($handle);
    }

}

Класс с основными методами бота.

TelegramBot.php (Download)

 <?php
/**
 * Created by PhpStorm.
 * User: Oddler
 * Date: 17.11.2018
 * Time: 13:13
 */

namespace Oddler\Telegram;

require_once (__DIR__.'/TelegramApi.php');

abstract class TelegramBot
{
    /*
     * @var object api
     */
    protected $_oApi = null;

    /**
     * TelegramBot constructor.
     */
    public function __construct() {
        $this->_oApi = new TelegramApi();
    }

    /**
     * Подготовка запроса (обертка для метода объекта TelegramApi)
     *
     * @param string $method
     * @param array $parameters
     *
     * @return boolean
     */
    protected function _apiCall($method, $parameters){
        return $this->_oApi->apiCall($method, $parameters);
    }

    /**
     * Обработка полученных сообщений
     *
     * @param array $message
     *
     * @return void
     */
    protected abstract function _processMessage($message);

    /**
     * Устанавливаем web Hook
     *
     * @param array $argv Массив переданных скрипту аргументов
     *
     * @return void
     */
    protected function _setHook($argv)
    {
        // if run from console, set or delete webhook
        $this->_apiCall('setWebhook', array(
            'url' => isset($argv[1]) && $argv[1] == 'unset' ? '' : WEBHOOK_URL
        ));
        exit;
    }

    /**
     * Обработка запроса
     *
     * @return void
     */
    protected function _processRequest()
    {
        $content = file_get_contents("php://input");
        $update = json_decode($content, true);
        if (!$update) {
            // receive wrong update, must not happen
            exit;
        }

        if (isset($update["message"])) {
            $this->_processMessage($update["message"]);
        }
    }

    /**
     * Обработка запроса
     * @param array $argv Массив переданных скрипту аргументов
     */
    public function dispath($argv){
        try {
            // Если вызавн из консоли
            if (php_sapi_name() == 'cli'){
                $this->_setHook($argv);
            } else { // Если вызавн по https
                $this->_processRequest();
            }
        } catch (\Exception $e) {
            echo 'Выброшено исключение: ',  $e->getMessage(), "\n";
        }
    }

}

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

CurrentTelegramBot.php (Download)

 <?php
/**
 * Created by PhpStorm.
 * User: Oddler
 * Date: 17.11.2018
 * Time: 16:07
 */

namespace Oddler\Telegram;

require_once (__DIR__.'/TelegramBot.php');

class CurrentTelegramBot extends TelegramBot
{
    protected function _processPhoto($message){
        //$sText = '852456';
        // Получаем фото максимального размера
        $aPhoto = $message['photo'][count($message['photo'])-1];
        $id_file = $aPhoto['file_id'];
        $aRet = $this->_apiCall("getFile", array(
            'file_id' => $id_file
        ));

        //$sText = print_r($aRet, TRUE);
        $sFileName = basename($aRet['file_path']);

        // Скачиваем во временную папку
        copy('https://api.telegram.org/file/bot'.TOKEN.'/'.$aRet['file_path'],
             __DIR__.'/../TMP/'.$sFileName
        );

        // Возвращает в чат, реплаем ссылку
        $this->_apiCall("sendMessage", array(
            'chat_id' => $message['chat']['id'],
            'parse_mode' => 'html',
            "reply_to_message_id" => $message['message_id'],
            "text" => '<a href="'.SITE_URL.'/images/'.$sFileName.'">'.$sFileName.'</a>'
        ));
    }


    /**
     * Обработка полученных сообщений
     *
     * @param array $message
     *
     * @return void
     */
    protected function _processMessage($message)
    {
        // process incoming message
        $id_message = $message['message_id'];
        $id_chat = $message['chat']['id'];
        if (isset($message['text']))
        {
            // incoming text message
            $text = $message['text'];
            if (strpos($text, "/start") === 0)
            {
                $this->_apiCall("sendMessage", array(
                    'chat_id' => $id_chat,
                    "text" => 'Hello',
                    'reply_markup' => array(
                        'keyboard' => array(
                            array(
                                'Hello',
                                'Hi'
                            )
                        ) ,
                        'one_time_keyboard' => true,
                        'resize_keyboard' => true
                    )
                ));
            }
            else if ($text === "Hello" || $text === "Hi")
            {
                $this->_apiCall("sendMessage", array(
                    'chat_id' => $id_chat,
                    "text" => 'Nice to meet you'
                ));
            }
            else if ($text === "123")
            {
                $this->_apiCall("sendMessage", array(
                    'chat_id' => $id_chat,
                    "text" => print_r($message, TRUE)
                ));
            }
            else
            {
                $this->_apiCall("sendMessage", array(
                    'chat_id' => $id_chat,
                    "reply_to_message_id" => $id_message,
                    "text" => 'Cool'
                ));
            }
        }
        else if (isset($message['photo']))
        {
            $this->_processPhoto($message);
        }
        else
        {
            $this->_apiCall("sendMessage", array(
                'chat_id' => $id_chat,
                "text" => print_r($message, TRUE)
            ));
        }
    }

}

Скачать паком


Категории: PHP, Class
Яндекс.Метрика