Вход Регистрация
Файл: upload/core/vendor/longman/telegram-bot/src/Telegram.php
Строк: 1325
<?php

/**
 * This file is part of the TelegramBot package.
 *
 * (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace LongmanTelegramBot;

defined('TB_BASE_PATH') || define('TB_BASE_PATH'__DIR__);
defined('TB_BASE_COMMANDS_PATH') || define('TB_BASE_COMMANDS_PATH'TB_BASE_PATH '/Commands');

use 
Exception;
use 
InvalidArgumentException;
use 
LongmanTelegramBotCommandsAdminCommand;
use 
LongmanTelegramBotCommandsCommand;
use 
LongmanTelegramBotCommandsSystemCommand;
use 
LongmanTelegramBotCommandsUserCommand;
use 
LongmanTelegramBotEntitiesChat;
use 
LongmanTelegramBotEntitiesServerResponse;
use 
LongmanTelegramBotEntitiesUpdate;
use 
LongmanTelegramBotEntitiesUser;
use 
LongmanTelegramBotExceptionTelegramException;
use 
PDO;
use 
RecursiveDirectoryIterator;
use 
RecursiveIteratorIterator;
use 
RegexIterator;

class 
Telegram
{
    
/**
     * Version
     *
     * @var string
     */
    
protected $version '0.83.0';

    
/**
     * Telegram API key
     *
     * @var string
     */
    
protected $api_key '';

    
/**
     * Telegram Bot username
     *
     * @var string
     */
    
protected $bot_username '';

    
/**
     * Telegram Bot id
     *
     * @var int
     */
    
protected $bot_id 0;

    
/**
     * Raw request data (json) for webhook methods
     *
     * @var string
     */
    
protected $input '';

    
/**
     * Custom commands paths
     *
     * @var array
     */
    
protected $commands_paths = [];

    
/**
     * Custom command class names
     * ```
     * [
     *     'User' => [
     *         // command_name => command_class
     *         'start' => 'namespacetoStartCommand',
     *     ],
     *     'Admin' => [], //etc
     * ]
     * ```
     *
     * @var array
     */
    
protected $command_classes = [
        
Command::AUTH_USER   => [],
        
Command::AUTH_ADMIN  => [],
        
Command::AUTH_SYSTEM => [],
    ];

    
/**
     * Custom commands objects
     *
     * @var array
     */
    
protected $commands_objects = [];

    
/**
     * Current Update object
     *
     * @var Update
     */
    
protected $update;

    
/**
     * Upload path
     *
     * @var string
     */
    
protected $upload_path '';

    
/**
     * Download path
     *
     * @var string
     */
    
protected $download_path '';

    
/**
     * MySQL integration
     *
     * @var bool
     */
    
protected $mysql_enabled false;

    
/**
     * PDO object
     *
     * @var PDO
     */
    
protected $pdo;

    
/**
     * Commands config
     *
     * @var array
     */
    
protected $commands_config = [];

    
/**
     * Admins list
     *
     * @var array
     */
    
protected $admins_list = [];

    
/**
     * ServerResponse of the last Command execution
     *
     * @var ServerResponse
     */
    
protected $last_command_response;

    
/**
     * Check if runCommands() is running in this session
     *
     * @var bool
     */
    
protected $run_commands false;

    
/**
     * Is running getUpdates without DB enabled
     *
     * @var bool
     */
    
protected $getupdates_without_database false;

    
/**
     * Last update ID
     * Only used when running getUpdates without a database
     *
     * @var int
     */
    
protected $last_update_id;

    
/**
     * The command to be executed when there's a new message update and nothing more suitable is found
     */
    
public const GENERIC_MESSAGE_COMMAND 'genericmessage';

    
/**
     * The command to be executed by default (when no other relevant commands are applicable)
     */
    
public const GENERIC_COMMAND 'generic';

    
/**
     * Update filter method
     *
     * @var callable
     */
    
protected $update_filter;

    
/**
     * Telegram constructor.
     *
     * @param string $api_key
     * @param string $bot_username
     *
     * @throws TelegramException
     */
    
public function __construct(string $api_keystring $bot_username '')
    {
        if (empty(
$api_key)) {
            throw new 
TelegramException('API KEY not defined!');
        }
        
preg_match('/(d+):[w-]+/'$api_key$matches);
        if (!isset(
$matches[1])) {
            throw new 
TelegramException('Invalid API KEY defined!');
        }
        
$this->bot_id  = (int) $matches[1];
        
$this->api_key $api_key;

        
$this->bot_username $bot_username;

        
//Add default system commands path
        
$this->addCommandsPath(TB_BASE_COMMANDS_PATH '/SystemCommands');

        
Request::initialize($this);
    }

    
/**
     * Initialize Database connection
     *
     * @param array  $credentials
     * @param string $table_prefix
     * @param string $encoding
     *
     * @return Telegram
     * @throws TelegramException
     */
    
public function enableMySql(array $credentialsstring $table_prefix ''string $encoding 'utf8mb4'): Telegram
    
{
        
$this->pdo DB::initialize($credentials$this$table_prefix$encoding);
        
ConversationDB::initializeConversation();
        
$this->mysql_enabled true;

        return 
$this;
    }

    
/**
     * Initialize Database external connection
     *
     * @param PDO    $external_pdo_connection PDO database object
     * @param string $table_prefix
     *
     * @return Telegram
     * @throws TelegramException
     */
    
public function enableExternalMySql(PDO $external_pdo_connectionstring $table_prefix ''): Telegram
    
{
        
$this->pdo DB::externalInitialize($external_pdo_connection$this$table_prefix);
        
ConversationDB::initializeConversation();
        
$this->mysql_enabled true;

        return 
$this;
    }

    
/**
     * Get commands list
     *
     * @return array $commands
     * @throws TelegramException
     */
    
public function getCommandsList(): array
    {
        
$commands = [];

        foreach (
$this->commands_paths as $path) {
            try {
                
//Get all "*Command.php" files
                
$files = new RegexIterator(
                    new 
RecursiveIteratorIterator(
                        new 
RecursiveDirectoryIterator($path)
                    ),
                    
'/^.+Command.php$/'
                
);

                foreach (
$files as $file) {
                    
// Convert filename to command
                    
$command $this->classNameToCommandName(substr($file->getFilename(), 0, -4));

                    
// Invalid Classname
                    
if (is_null($command)) {
                        continue;
                    }

                    
// Already registered
                    
if (array_key_exists($command$commands)) {
                        continue;
                    }

                    require_once 
$file->getPathname();

                    
$command_obj $this->getCommandObject($command$file->getPathname());
                    if (
$command_obj instanceof Command) {
                        
$commands[$command] = $command_obj;
                    }
                }
            } catch (
Exception $e) {
                throw new 
TelegramException('Error getting commands from path: ' $path0$e);
            }
        }

        return 
$commands;
    }

    
/**
     * Get classname of predefined commands
     *
     * @see command_classes
     *
     * @param string $auth     Auth of command
     * @param string $command  Command name
     * @param string $filepath Path to the command file
     *
     * @return string|null
     */
    
public function getCommandClassName(string $authstring $commandstring $filepath ''): ?string
    
{
        
$command mb_strtolower($command);

        
// Invalid command
        
if (trim($command) === '') {
            return 
null;
        }

        
$auth    $this->ucFirstUnicode($auth);

        
// First, check for directly assigned command class.
        
if ($command_class $this->command_classes[$auth][$command] ?? null) {
            return 
$command_class;
        }

        
// Start with default namespace.
        
$command_namespace __NAMESPACE__ '\Commands\' . $auth . 'Commands';

        // Check if we can get the namespace from the file (if passed).
        if ($filepath && !($command_namespace = $this->getFileNamespace($filepath))) {
            return null;
        }

        $command_class = $command_namespace . '
\' . $this->commandNameToClassName($command);

        if (class_exists($command_class)) {
            return $command_class;
        }

        return null;
    }

    /**
     * Get an object instance of the passed command
     *
     * @param string $command
     * @param string $filepath
     *
     * @return Command|null
     */
    public function getCommandObject(string $command, string $filepath = ''): ?Command
    {
        if (isset($this->commands_objects[$command])) {
            return $this->commands_objects[$command];
        }

        $which = [Command::AUTH_SYSTEM];
        $this->isAdmin() && $which[] = Command::AUTH_ADMIN;
        $which[] = Command::AUTH_USER;

        foreach ($which as $auth) {
            $command_class = $this->getCommandClassName($auth, $command, $filepath);

            if ($command_class) {
                $command_obj = new $command_class($this, $this->update);

                if ($auth === Command::AUTH_SYSTEM && $command_obj instanceof SystemCommand) {
                    return $command_obj;
                }
                if ($auth === Command::AUTH_ADMIN && $command_obj instanceof AdminCommand) {
                    return $command_obj;
                }
                if ($auth === Command::AUTH_USER && $command_obj instanceof UserCommand) {
                    return $command_obj;
                }
            }
        }

        return null;
    }

    /**
     * Get namespace from php file by src path
     *
     * @param string $src (absolute path to file)
     *
     * @return string|null ("LongmanTelegramBotCommandsSystemCommands" for example)
     */
    protected function getFileNamespace(string $src): ?string
    {
        $content = file_get_contents($src);
        if (preg_match('
#^s*namespaces+(.+?);#m', $content, $m)) {
            
return $m[1];
        }

        return 
null;
    }

    
/**
     * Set custom input string for debug purposes
     *
     * @param string $input (json format)
     *
     * @return Telegram
     */
    
public function setCustomInput(string $input): Telegram
    
{
        
$this->input $input;

        return 
$this;
    }

    
/**
     * Get custom input string for debug purposes
     *
     * @return string
     */
    
public function getCustomInput(): string
    
{
        return 
$this->input;
    }

    
/**
     * Get the ServerResponse of the last Command execution
     *
     * @return ServerResponse
     */
    
public function getLastCommandResponse(): ServerResponse
    
{
        return 
$this->last_command_response;
    }

    
/**
     * Handle getUpdates method
     *
     * @todo Remove backwards compatibility for old signature and force $data to be an array.
     *
     * @param array|int|null $data
     * @param int|null       $timeout
     *
     * @return ServerResponse
     * @throws TelegramException
     */
    
public function handleGetUpdates($data null, ?int $timeout null): ServerResponse
    
{
        if (empty(
$this->bot_username)) {
            throw new 
TelegramException('Bot Username is not defined!');
        }

        if (!
DB::isDbConnected() && !$this->getupdates_without_database) {
            return new 
ServerResponse(
                [
                    
'ok'          => false,
                    
'description' => 'getUpdates needs MySQL connection! (This can be overridden - see documentation)',
                ],
                
$this->bot_username
            
);
        }

        
$offset 0;
        
$limit  null;

        
// By default, get update types sent by Telegram.
        
$allowed_updates = [];

        
// @todo Backwards compatibility for old signature, remove in next version.
        
if (!is_array($data)) {
            
$limit $data;

            @
trigger_error(
                
sprintf('Use of $limit and $timeout parameters in %s is deprecated. Use $data array instead.'__METHOD__),
                
E_USER_DEPRECATED
            
);
        } else {
            
$offset          $data['offset'] ?? $offset;
            
$limit           $data['limit'] ?? $limit;
            
$timeout         $data['timeout'] ?? $timeout;
            
$allowed_updates $data['allowed_updates'] ?? $allowed_updates;
        }

        
// Take custom input into account.
        
if ($custom_input $this->getCustomInput()) {
            try {
                
$input json_decode($this->inputtrue512JSON_THROW_ON_ERROR);
                if (empty(
$input)) {
                    throw new 
TelegramException('Custom input is empty');
                }
                
$response = new ServerResponse($input$this->bot_username);
            } catch (
Throwable $e) {
                throw new 
TelegramException('Invalid custom input JSON: ' $e->getMessage());
            }
        } else {
            if (
DB::isDbConnected() && $last_update DB::selectTelegramUpdate(1)) {
                
// Get last Update id from the database.
                
$last_update          reset($last_update);
                
$this->last_update_id $last_update['id'] ?? null;
            }

            if (
$this->last_update_id !== null) {
                
$offset $this->last_update_id 1// As explained in the telegram bot API documentation.
            
}

            
$response Request::getUpdates(compact('offset''limit''timeout''allowed_updates'));
        }

        if (
$response->isOk()) {
            
// Log update.
            
TelegramLog::update($response->toJson());

            
// Process all updates
            /** @var Update $update */
            
foreach ($response->getResult() as $update) {
                
$this->processUpdate($update);
            }

            if (!
DB::isDbConnected() && !$custom_input && $this->last_update_id !== null && $offset === 0) {
                
// Mark update(s) as read after handling
                
$offset $this->last_update_id 1;
                
$limit  1;

                
Request::getUpdates(compact('offset''limit''timeout''allowed_updates'));
            }
        }

        return 
$response;
    }

    
/**
     * Handle bot request from webhook
     *
     * @return bool
     *
     * @throws TelegramException
     */
    
public function handle(): bool
    
{
        if (
$this->bot_username === '') {
            throw new 
TelegramException('Bot Username is not defined!');
        }

        
$input Request::getInput();
        if (empty(
$input)) {
            throw new 
TelegramException('Input is empty! The webhook must not be called manually, only by Telegram.');
        }

        
// Log update.
        
TelegramLog::update($input);

        
$post json_decode($inputtrue);
        if (empty(
$post)) {
            throw new 
TelegramException('Invalid input JSON! The webhook must not be called manually, only by Telegram.');
        }

        if (
$response $this->processUpdate(new Update($post$this->bot_username))) {
            return 
$response->isOk();
        }

        return 
false;
    }

    
/**
     * Get the command name from the command type
     *
     * @param string $type
     *
     * @return string
     */
    
protected function getCommandFromType(string $type): string
    
{
        return 
$this->ucFirstUnicode(str_replace('_'''$type));
    }

    
/**
     * Process bot Update request
     *
     * @param Update $update
     *
     * @return ServerResponse
     * @throws TelegramException
     */
    
public function processUpdate(Update $update): ServerResponse
    
{
        
$this->update         $update;
        
$this->last_update_id $update->getUpdateId();

        if (
is_callable($this->update_filter)) {
            
$reason 'Update denied by update_filter';
            try {
                
$allowed = (bool) call_user_func_array($this->update_filter, [$update$this, &$reason]);
            } catch (
Exception $e) {
                
$allowed false;
            }

            if (!
$allowed) {
                
TelegramLog::debug($reason);
                return new 
ServerResponse(['ok' => false'description' => 'denied']);
            }
        }

        
//Load admin commands
        
if ($this->isAdmin()) {
            
$this->addCommandsPath(TB_BASE_COMMANDS_PATH '/AdminCommands'false);
        }

        
//Make sure we have an up-to-date command list
        //This is necessary to "require" all the necessary command files!
        
$this->commands_objects $this->getCommandsList();

        
//If all else fails, it's a generic message.
        
$command self::GENERIC_MESSAGE_COMMAND;

        
$update_type $this->update->getUpdateType();
        if (
$update_type === 'message') {
            
$message $this->update->getMessage();
            
$type    $message->getType();

            
// Let's check if the message object has the type field we're looking for...
            
$command_tmp $type === 'command' $message->getCommand() : $this->getCommandFromType($type);
            
// ...and if a fitting command class is available.
            
$command_obj $command_tmp $this->getCommandObject($command_tmp) : null;

            
// Empty usage string denotes a non-executable command.
            // @see https://github.com/php-telegram-bot/core/issues/772#issuecomment-388616072
            
if (
                (
$command_obj === null && $type === 'command')
                || (
$command_obj !== null && $command_obj->getUsage() !== '')
            ) {
                
$command $command_tmp;
            }
        } elseif (
$update_type !== null) {
            
$command $this->getCommandFromType($update_type);
        }

        
//Make sure we don't try to process update that was already processed
        
$last_id DB::selectTelegramUpdate(1$this->update->getUpdateId());
        if (
$last_id && count($last_id) === 1) {
            
TelegramLog::debug('Duplicate update received, processing aborted!');
            return 
Request::emptyResponse();
        }

        
DB::insertRequest($this->update);

        return 
$this->executeCommand($command);
    }

    
/**
     * Execute /command
     *
     * @param string $command
     *
     * @return ServerResponse
     * @throws TelegramException
     */
    
public function executeCommand(string $command): ServerResponse
    
{
        
$command mb_strtolower($command);

        
$command_obj $this->commands_objects[$command] ?? $this->getCommandObject($command);

        if (!
$command_obj || !$command_obj->isEnabled()) {
            
//Failsafe in case the Generic command can't be found
            
if ($command === self::GENERIC_COMMAND) {
                throw new 
TelegramException('Generic command missing!');
            }

            
//Handle a generic command or non existing one
            
$this->last_command_response $this->executeCommand(self::GENERIC_COMMAND);
        } else {
            
//execute() method is executed after preExecute()
            //This is to prevent executing a DB query without a valid connection
            
if ($this->update) {
                
$this->last_command_response $command_obj->setUpdate($this->update)->preExecute();
            } else {
                
$this->last_command_response $command_obj->preExecute();
            }
        }

        return 
$this->last_command_response;
    }

    
/**
     * @deprecated
     *
     * @param string $command
     *
     * @return string
     */
    
protected function sanitizeCommand(string $command): string
    
{
        return 
str_replace(' '''$this->ucWordsUnicode(str_replace('_'' '$command)));
    }

    
/**
     * Enable a single Admin account
     *
     * @param int $admin_id Single admin id
     *
     * @return Telegram
     */
    
public function enableAdmin(int $admin_id): Telegram
    
{
        if (
$admin_id <= 0) {
            
TelegramLog::error('Invalid value "' $admin_id '" for admin.');
        } elseif (!
in_array($admin_id$this->admins_listtrue)) {
            
$this->admins_list[] = $admin_id;
        }

        return 
$this;
    }

    
/**
     * Enable a list of Admin Accounts
     *
     * @param array $admin_ids List of admin ids
     *
     * @return Telegram
     */
    
public function enableAdmins(array $admin_ids): Telegram
    
{
        foreach (
$admin_ids as $admin_id) {
            
$this->enableAdmin($admin_id);
        }

        return 
$this;
    }

    
/**
     * Get list of admins
     *
     * @return array
     */
    
public function getAdminList(): array
    {
        return 
$this->admins_list;
    }

    
/**
     * Check if the passed user is an admin
     *
     * If no user id is passed, the current update is checked for a valid message sender.
     *
     * @param int|null $user_id
     *
     * @return bool
     */
    
public function isAdmin($user_id null): bool
    
{
        if (
$user_id === null && $this->update !== null) {
            
//Try to figure out if the user is an admin
            
$update_methods = [
                
'getMessage',
                
'getEditedMessage',
                
'getChannelPost',
                
'getEditedChannelPost',
                
'getInlineQuery',
                
'getChosenInlineResult',
                
'getCallbackQuery',
            ];
            foreach (
$update_methods as $update_method) {
                
$object call_user_func([$this->update$update_method]);
                if (
$object !== null && $from $object->getFrom()) {
                    
$user_id $from->getId();
                    break;
                }
            }
        }

        return (
$user_id === null) ? false in_array($user_id$this->admins_listtrue);
    }

    
/**
     * Check if user required the db connection
     *
     * @return bool
     */
    
public function isDbEnabled(): bool
    
{
        return 
$this->mysql_enabled;
    }

    
/**
     * Add a single custom command class
     *
     * @param string $command_class Full command class name
     *
     * @return Telegram
     */
    
public function addCommandClass(string $command_class): Telegram
    
{
        if (!
$command_class || !class_exists($command_class)) {
            
$error sprintf('Command class "%s" does not exist.'$command_class);
            
TelegramLog::error($error);
            throw new 
InvalidArgumentException($error);
        }

        if (!
is_a($command_classCommand::class, true)) {
            
$error sprintf('Command class "%s" does not extend "%s".'$command_classCommand::class);
            
TelegramLog::error($error);
            throw new 
InvalidArgumentException($error);
        }

        
// Dummy object to get data from.
        
$command_object = new $command_class($this);

        
$auth null;
        
$command_object->isSystemCommand() && $auth Command::AUTH_SYSTEM;
        
$command_object->isAdminCommand() && $auth Command::AUTH_ADMIN;
        
$command_object->isUserCommand() && $auth Command::AUTH_USER;

        if (
$auth) {
            
$command mb_strtolower($command_object->getName());

            
$this->command_classes[$auth][$command] = $command_class;
        }

        return 
$this;
    }

    
/**
     * Add multiple custom command classes
     *
     * @param array $command_classes List of full command class names
     *
     * @return Telegram
     */
    
public function addCommandClasses(array $command_classes): Telegram
    
{
        foreach (
$command_classes as $command_class) {
            
$this->addCommandClass($command_class);
        }

        return 
$this;
    }

    
/**
     * Set a single custom commands path
     *
     * @param string $path Custom commands path to set
     *
     * @return Telegram
     */
    
public function setCommandsPath(string $path): Telegram
    
{
        
$this->commands_paths = [];

        
$this->addCommandsPath($path);

        return 
$this;
    }

    
/**
     * Add a single custom commands path
     *
     * @param string $path   Custom commands path to add
     * @param bool   $before If the path should be prepended or appended to the list
     *
     * @return Telegram
     */
    
public function addCommandsPath(string $pathbool $before true): Telegram
    
{
        if (!
is_dir($path)) {
            
TelegramLog::error('Commands path "' $path '" does not exist.');
        } elseif (!
in_array($path$this->commands_pathstrue)) {
            if (
$before) {
                
array_unshift($this->commands_paths$path);
            } else {
                
$this->commands_paths[] = $path;
            }
        }

        return 
$this;
    }

    
/**
     * Set multiple custom commands paths
     *
     * @param array $paths Custom commands paths to add
     *
     * @return Telegram
     */
    
public function setCommandsPaths(array $paths): Telegram
    
{
        
$this->commands_paths = [];

        
$this->addCommandsPaths($paths);

        return 
$this;
    }

    
/**
     * Add multiple custom commands paths
     *
     * @param array $paths  Custom commands paths to add
     * @param bool  $before If the paths should be prepended or appended to the list
     *
     * @return Telegram
     */
    
public function addCommandsPaths(array $pathsbool $before true): Telegram
    
{
        foreach (
$paths as $path) {
            
$this->addCommandsPath($path$before);
        }

        return 
$this;
    }

    
/**
     * Return the list of commands paths
     *
     * @return array
     */
    
public function getCommandsPaths(): array
    {
        return 
$this->commands_paths;
    }

    
/**
     * Return the list of command classes
     *
     * @return array
     */
    
public function getCommandClasses(): array
    {
        return 
$this->command_classes;
    }

    
/**
     * Set custom upload path
     *
     * @param string $path Custom upload path
     *
     * @return Telegram
     */
    
public function setUploadPath(string $path): Telegram
    
{
        
$this->upload_path $path;

        return 
$this;
    }

    
/**
     * Get custom upload path
     *
     * @return string
     */
    
public function getUploadPath(): string
    
{
        return 
$this->upload_path;
    }

    
/**
     * Set custom download path
     *
     * @param string $path Custom download path
     *
     * @return Telegram
     */
    
public function setDownloadPath(string $path): Telegram
    
{
        
$this->download_path $path;

        return 
$this;
    }

    
/**
     * Get custom download path
     *
     * @return string
     */
    
public function getDownloadPath(): string
    
{
        return 
$this->download_path;
    }

    
/**
     * Set command config
     *
     * Provide further variables to a particular commands.
     * For example you can add the channel name at the command /sendtochannel
     * Or you can add the api key for external service.
     *
     * @param string $command
     * @param array  $config
     *
     * @return Telegram
     */
    
public function setCommandConfig(string $command, array $config): Telegram
    
{
        
$this->commands_config[$command] = $config;

        return 
$this;
    }

    
/**
     * Get command config
     *
     * @param string $command
     *
     * @return array
     */
    
public function getCommandConfig(string $command): array
    {
        return 
$this->commands_config[$command] ?? [];
    }

    
/**
     * Get API key
     *
     * @return string
     */
    
public function getApiKey(): string
    
{
        return 
$this->api_key;
    }

    
/**
     * Get Bot name
     *
     * @return string
     */
    
public function getBotUsername(): string
    
{
        return 
$this->bot_username;
    }

    
/**
     * Get Bot Id
     *
     * @return int
     */
    
public function getBotId(): int
    
{
        return 
$this->bot_id;
    }

    
/**
     * Get Version
     *
     * @return string
     */
    
public function getVersion(): string
    
{
        return 
$this->version;
    }

    
/**
     * Set Webhook for bot
     *
     * @param string $url
     * @param array  $data Optional parameters.
     *
     * @return ServerResponse
     * @throws TelegramException
     */
    
public function setWebhook(string $url, array $data = []): ServerResponse
    
{
        if (
$url === '') {
            throw new 
TelegramException('Hook url is empty!');
        }

        
$data        array_intersect_key($dataarray_flip([
            
'certificate',
            
'ip_address',
            
'max_connections',
            
'allowed_updates',
            
'drop_pending_updates',
            
'secret_token',
        ]));
        
$data['url'] = $url;

        
// If the certificate is passed as a path, encode and add the file to the data array.
        
if (!empty($data['certificate']) && is_string($data['certificate'])) {
            
$data['certificate'] = Request::encodeFile($data['certificate']);
        }

        
$result Request::setWebhook($data);

        if (!
$result->isOk()) {
            throw new 
TelegramException(
                
'Webhook was not set! Error: ' $result->getErrorCode() . ' ' $result->getDescription()
            );
        }

        return 
$result;
    }

    
/**
     * Delete any assigned webhook
     *
     * @param array $data
     *
     * @return ServerResponse
     * @throws TelegramException
     */
    
public function deleteWebhook(array $data = []): ServerResponse
    
{
        
$result Request::deleteWebhook($data);

        if (!
$result->isOk()) {
            throw new 
TelegramException(
                
'Webhook was not deleted! Error: ' $result->getErrorCode() . ' ' $result->getDescription()
            );
        }

        return 
$result;
    }

    
/**
     * Replace function `ucwords` for UTF-8 characters in the class definition and commands
     *
     * @param string $str
     * @param string $encoding (default = 'UTF-8')
     *
     * @return string
     */
    
protected function ucWordsUnicode(string $strstring $encoding 'UTF-8'): string
    
{
        return 
mb_convert_case($strMB_CASE_TITLE$encoding);
    }

    
/**
     * Replace function `ucfirst` for UTF-8 characters in the class definition and commands
     *
     * @param string $str
     * @param string $encoding (default = 'UTF-8')
     *
     * @return string
     */
    
protected function ucFirstUnicode(string $strstring $encoding 'UTF-8'): string
    
{
        return 
mb_strtoupper(mb_substr($str01$encoding), $encoding)
            . 
mb_strtolower(mb_substr($str1mb_strlen($str), $encoding), $encoding);
    }

    
/**
     * Enable requests limiter
     *
     * @param array $options
     *
     * @return Telegram
     * @throws TelegramException
     */
    
public function enableLimiter(array $options = []): Telegram
    
{
        
Request::setLimiter(true$options);

        return 
$this;
    }

    
/**
     * Run provided commands
     *
     * @param array $commands
     *
     * @return ServerResponse[]
     *
     * @throws TelegramException
     */
    
public function runCommands(array $commands): array
    {
        if (empty(
$commands)) {
            throw new 
TelegramException('No command(s) provided!');
        }

        
$this->run_commands true;

        
// Check if this request has a user Update / comes from Telegram.
        
if ($userUpdate $this->update) {
            
$from $this->update->getMessage()->getFrom();
            
$chat $this->update->getMessage()->getChat();
        } else {
            
// Fall back to the Bot user.
            
$from = new User([
                
'id'         => $this->getBotId(),
                
'first_name' => $this->getBotUsername(),
                
'username'   => $this->getBotUsername(),
            ]);

            
// Try to get "live" Bot info.
            
$response Request::getMe();
            if (
$response->isOk()) {
                
/** @var User $result */
                
$result $response->getResult();

                
$from = new User([
                    
'id'         => $result->getId(),
                    
'first_name' => $result->getFirstName(),
                    
'username'   => $result->getUsername(),
                ]);
            }

            
// Give Bot access to admin commands.
            
$this->enableAdmin($from->getId());

            
// Lock the bot to a private chat context.
            
$chat = new Chat([
                
'id'   => $from->getId(),
                
'type' => 'private',
            ]);
        }

        
$newUpdate = static function ($text '') use ($from$chat) {
            return new 
Update([
                
'update_id' => -1,
                
'message'   => [
                    
'message_id' => -1,
                    
'date'       => time(),
                    
'from'       => json_decode($from->toJson(), true),
                    
'chat'       => json_decode($chat->toJson(), true),
                    
'text'       => $text,
                ],
            ]);
        };

        
$responses = [];

        foreach (
$commands as $command) {
            
$this->update $newUpdate($command);

            
// Refresh commands list for new Update object.
            
$this->commands_objects $this->getCommandsList();

            
$responses[] = $this->executeCommand($this->update->getMessage()->getCommand());
        }

        
// Reset Update to initial context.
        
$this->update $userUpdate;

        return 
$responses;
    }

    
/**
     * Is this session initiated by runCommands()
     *
     * @return bool
     */
    
public function isRunCommands(): bool
    
{
        return 
$this->run_commands;
    }

    
/**
     * Switch to enable running getUpdates without a database
     *
     * @param bool $enable
     *
     * @return Telegram
     */
    
public function useGetUpdatesWithoutDatabase(bool $enable true): Telegram
    
{
        
$this->getupdates_without_database $enable;

        return 
$this;
    }

    
/**
     * Return last update id
     *
     * @return int|null
     */
    
public function getLastUpdateId(): ?int
    
{
        return 
$this->last_update_id;
    }

    
/**
     * Set an update filter callback
     *
     * @param callable $callback
     *
     * @return Telegram
     */
    
public function setUpdateFilter(callable $callback): Telegram
    
{
        
$this->update_filter $callback;

        return 
$this;
    }

    
/**
     * Return update filter callback
     *
     * @return callable|null
     */
    
public function getUpdateFilter(): ?callable
    {
        return 
$this->update_filter;
    }

    
/**
     * Converts the name of a class into the name of a command.
     *
     * @param string $class For example FooBarCommand
     *
     * @return string|null for example foo_bar. In case of errors, returns null.
     */
    
protected function classNameToCommandName(string $class): ?string
    
{
        
// If $class doesn't end with 'Command'
        
if (substr($class, -7) !== 'Command') {
            return 
null;
        }

        return 
mb_strtolower(preg_replace('/(.)(?=[p{Lu}])/u''$1_'substr($class0, -7)));
    }

    
/**
     * Converts a command name into the name of a class.
     *
     * @param string $command For example foo_bar
     *
     * @return string|null for example FooBarCommand. In case of errors, returns null.
     */
    
protected function commandNameToClassName(string $command): ?string
    
{
        if (
trim($command) === '') {
            return 
null;
        }

        return 
str_replace(' '''$this->ucWordsUnicode(str_replace('_'' '$command))) . 'Command';
    }
}
Онлайн: 1
Реклама