diff --git a/.gitignore b/.gitignore index c0546a714..5776d8103 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ .idea .phpintel composer.phar +composer.lock # Local System Files (i.e. cache, logs, etc.) # /cache diff --git a/.travis.yml b/.travis.yml index 5aaf587c6..2a2e57815 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ cache: - "$HOME/.composer/cache" php: - - 5.5 - 5.6 - 7.0 - 7.1 diff --git a/README.md b/README.md index 54414b0ef..87d9f9d40 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Latest Stable Version](https://img.shields.io/packagist/v/Longman/telegram-bot.svg)](https://packagist.org/packages/longman/telegram-bot) [![Total Downloads](https://img.shields.io/packagist/dt/Longman/telegram-bot.svg)](https://packagist.org/packages/longman/telegram-bot) [![Downloads Month](https://img.shields.io/packagist/dm/Longman/telegram-bot.svg)](https://packagist.org/packages/longman/telegram-bot) -[![Minimum PHP Version](http://img.shields.io/badge/php-%3E%3D5.6-8892BF.svg)](https://php.net/) +[![Minimum PHP Version](http://img.shields.io/badge/php-%3E%3D5.6.4-8892BF.svg)](https://php.net/) [![License](https://img.shields.io/packagist/l/Longman/telegram-bot.svg)](https://github.com/php-telegram-bot/core/LICENSE.md) diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/build/.gitkeep b/build/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/composer.json b/composer.json index bc8055478..5d0f1395c 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,11 @@ "name": "longman/telegram-bot", "type": "library", "description": "PHP Telegram bot", - "keywords": ["telegram", "bot", "api"], + "keywords": [ + "telegram", + "bot", + "api" + ], "license": "MIT", "homepage": "https://github.com/php-telegram-bot/core", "support": { @@ -18,16 +22,22 @@ } ], "require": { - "php": "^5.5|^7.0", + "php": ">=5.6.4|^7.0", "ext-pdo": "*", "ext-curl": "*", "ext-mbstring": "*", "monolog/monolog": "^1.23", + "illuminate/container": "5.4.*|5.5.*|5.6.*", + "illuminate/support": "5.4.*|5.5.*|5.6.*", + "illuminate/http": "5.4.*|5.5.*|5.6.*", + "illuminate/config": "5.4.*|5.5.*|5.6.*", "guzzlehttp/guzzle": "^6.3" }, "require-dev": { "phpunit/phpunit": "^4.8|^5.7|^6.5|^7.0", - "squizlabs/php_codesniffer": "^3.2" + "symfony/var-dumper": "3.4.*|~4.0", + "squizlabs/php_codesniffer": "^3.2", + "longman/php-code-style": "^1.0" }, "autoload": { "psr-4": { @@ -43,14 +53,26 @@ "check-code": [ "\"vendor/bin/phpcs\" --standard=phpcs.xml -snp --encoding=utf-8 src/ tests/ --report-width=150" ], + "fix-code": [ + "\"vendor/bin/phpcbf\" --standard=phpcs.xml -snp --encoding=utf-8 src/ tests/ --report-width=150" + ], "test": [ "\"vendor/bin/phpunit\"" ], "test-cov": [ "\"vendor/bin/phpunit\" --coverage-clover build/logs/clover.xml" ], + "test-cov-html": [ + "\"vendor/bin/phpunit\" --coverage-html build/html" + ], "test-cov-upload": [ "wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml" ] + }, + "config": { + "preferred-install": "dist", + "sort-packages": true, + "optimize-autoloader": true, + "process-timeout": 3600 } } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index f58e0d2cb..000000000 --- a/composer.lock +++ /dev/null @@ -1,1550 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "content-hash": "c7d1725771953f0ab9ce92df1e3cc9b3", - "packages": [ - { - "name": "guzzlehttp/guzzle", - "version": "6.3.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/68d0ea14d5a3f42a20e87632a5f84931e2709c90", - "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2018-03-26T16:33:04+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "request", - "response", - "stream", - "uri", - "url" - ], - "time": "2017-03-20T17:10:46+00:00" - }, - { - "name": "monolog/monolog", - "version": "1.23.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4", - "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "psr/log": "~1.0" - }, - "provide": { - "psr/log-implementation": "1.0.0" - }, - "require-dev": { - "aws/aws-sdk-php": "^2.4.9 || ^3.0", - "doctrine/couchdb": "~1.0@dev", - "graylog2/gelf-php": "~1.0", - "jakub-onderka/php-parallel-lint": "0.9", - "php-amqplib/php-amqplib": "~2.4", - "php-console/php-console": "^3.1.3", - "phpunit/phpunit": "~4.5", - "phpunit/phpunit-mock-objects": "2.3.0", - "ruflin/elastica": ">=0.90 <3.0", - "sentry/sentry": "^0.13", - "swiftmailer/swiftmailer": "^5.3|^6.0" - }, - "suggest": { - "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", - "doctrine/couchdb": "Allow sending log messages to a CouchDB server", - "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-mongo": "Allow sending log messages to a MongoDB server", - "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", - "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "php-console/php-console": "Allow sending log messages to Google Chrome", - "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "sentry/sentry": "Allow sending log messages to a Sentry server" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Monolog\\": "src/Monolog" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", - "keywords": [ - "log", - "logging", - "psr-3" - ], - "time": "2017-06-19T01:22:40+00:00" - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2016-08-06T14:39:51+00:00" - }, - { - "name": "psr/log", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2016-10-10T12:19:37+00:00" - } - ], - "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2015-06-14T21:17:01+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2017-09-11T18:02:19+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "3.2.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", - "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", - "shasum": "" - }, - "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.3.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-08-08T06:39:58+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773", - "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "time": "2017-06-03T08:32:36+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.7.5", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2018-02-19T10:16:54+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2015-10-06T15:47:00+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2017-11-27T13:52:08+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2017-02-26T11:10:40+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.12", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2017-12-04T08:55:13+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "4.8.36", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.8.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2017-06-21T08:07:12+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2015-10-02T06:51:40+00:00" - }, - { - "name": "sebastian/comparator", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-01-29T09:50:25+00:00" - }, - { - "name": "sebastian/diff", - "version": "1.4.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2017-05-22T07:24:03+00:00" - }, - { - "name": "sebastian/environment", - "version": "1.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2016-08-18T05:49:44+00:00" - }, - { - "name": "sebastian/exporter", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2016-06-17T09:04:28+00:00" - }, - { - "name": "sebastian/global-state", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2015-10-12T03:26:01+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03T07:41:43+00:00" - }, - { - "name": "sebastian/version", - "version": "1.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21T13:59:46+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.2.3", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "4842476c434e375f9d3182ff7b89059583aa8b27" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4842476c434e375f9d3182ff7b89059583aa8b27", - "reference": "4842476c434e375f9d3182ff7b89059583aa8b27", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2018-02-20T21:35:23+00:00" - }, - { - "name": "symfony/yaml", - "version": "v3.4.6", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "6af42631dcf89e9c616242c900d6c52bd53bd1bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/6af42631dcf89e9c616242c900d6c52bd53bd1bb", - "reference": "6af42631dcf89e9c616242c900d6c52bd53bd1bb", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2018-02-16T09:50:28+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2018-01-29T19:49:41+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^5.5|^7.0", - "ext-pdo": "*", - "ext-curl": "*", - "ext-mbstring": "*" - }, - "platform-dev": [] -} diff --git a/phpcs.xml b/phpcs.xml index 69b989102..9ca0df1b0 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,117 +1,8 @@ - + PHP Code Sniffer - - - - - - - - - - - - - - - - - - - warning - - - - - - - - - - - - - - - - - warning - - - warning - - - - - - - - - - - - - - - - - - - Please review this TODO comment: %s - warning - - - Please review this FIXME comment: %s - warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - warning - - - - - - - diff --git a/src/Commands/AdminCommands/ChatsCommand.php b/src/Commands/AdminCommands/ChatsCommand.php index b5c02d1c7..c25709759 100644 --- a/src/Commands/AdminCommands/ChatsCommand.php +++ b/src/Commands/AdminCommands/ChatsCommand.php @@ -13,7 +13,7 @@ use Longman\TelegramBot\Commands\AdminCommand; use Longman\TelegramBot\DB; use Longman\TelegramBot\Entities\Chat; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; class ChatsCommand extends AdminCommand { @@ -45,7 +45,7 @@ class ChatsCommand extends AdminCommand /** * Command execute method * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ public function execute() @@ -53,7 +53,7 @@ public function execute() $message = $this->getMessage(); $chat_id = $message->getChat()->getId(); - $text = trim($message->getText(true)); + $text = trim($message->getText(true)); $results = DB::selectChats([ 'groups' => true, @@ -63,14 +63,14 @@ public function execute() 'text' => ($text === '' || $text === '*') ? null : $text //Text to search in user/group name ]); - $user_chats = 0; - $group_chats = 0; + $user_chats = 0; + $group_chats = 0; $supergroup_chats = 0; - $channel_chats = 0; + $channel_chats = 0; if ($text === '') { $text_back = ''; - } elseif ($text === '*') { + } else if ($text === '*') { $text_back = 'List of all bot chats:' . PHP_EOL; } else { $text_back = 'Chat search results:' . PHP_EOL; @@ -80,10 +80,10 @@ public function execute() foreach ($results as $result) { //Initialize a chat object $result['id'] = $result['chat_id']; - $chat = new Chat($result); + $chat = new Chat($result); $whois = $chat->getId(); - if ($this->telegram->getCommandObject('whois')) { + if ($this->telegram->createCommandObject('whois')) { // We can't use '-' in command because part of it will become unclickable $whois = '/whois' . str_replace('-', 'g', $chat->getId()); } @@ -94,19 +94,19 @@ public function execute() } ++$user_chats; - } elseif ($chat->isSuperGroup()) { + } else if ($chat->isSuperGroup()) { if ($text !== '') { $text_back .= '- S ' . $chat->getTitle() . ' [' . $whois . ']' . PHP_EOL; } ++$supergroup_chats; - } elseif ($chat->isGroupChat()) { + } else if ($chat->isGroupChat()) { if ($text !== '') { $text_back .= '- G ' . $chat->getTitle() . ' [' . $whois . ']' . PHP_EOL; } ++$group_chats; - } elseif ($chat->isChannel()) { + } else if ($chat->isChannel()) { if ($text !== '') { $text_back .= '- C ' . $chat->getTitle() . ' [' . $whois . ']' . PHP_EOL; } @@ -135,6 +135,6 @@ public function execute() 'text' => $text_back, ]; - return Request::sendMessage($data); + return Client::sendMessage($data); } } diff --git a/src/Commands/AdminCommands/CleanupCommand.php b/src/Commands/AdminCommands/CleanupCommand.php index 171da4d83..d8d60a2f8 100644 --- a/src/Commands/AdminCommands/CleanupCommand.php +++ b/src/Commands/AdminCommands/CleanupCommand.php @@ -13,8 +13,8 @@ use Longman\TelegramBot\Commands\AdminCommand; use Longman\TelegramBot\DB; use Longman\TelegramBot\Exception\TelegramException; -use Longman\TelegramBot\Request; -use Longman\TelegramBot\TelegramLog; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Logger; use PDOException; /** @@ -108,13 +108,13 @@ class CleanupCommand extends AdminCommand */ private function getSettings($custom_time = '') { - $tables_to_clean = self::$default_tables_to_clean; + $tables_to_clean = self::$default_tables_to_clean; $user_tables_to_clean = $this->getConfig('tables_to_clean'); if (is_array($user_tables_to_clean)) { $tables_to_clean = $user_tables_to_clean; } - $clean_older_than = self::$default_clean_older_than; + $clean_older_than = self::$default_clean_older_than; $user_clean_older_than = $this->getConfig('clean_older_than'); if (is_array($user_clean_older_than)) { $clean_older_than = array_merge($clean_older_than, $user_clean_older_than); @@ -122,7 +122,7 @@ private function getSettings($custom_time = '') // Convert numeric-only values to days. array_walk($clean_older_than, function (&$time) use ($custom_time) { - if (!empty($custom_time)) { + if (! empty($custom_time)) { $time = $custom_time; } if (is_numeric($time)) { @@ -143,7 +143,7 @@ private function getSettings($custom_time = '') */ private function getQueries($settings) { - if (empty($settings) || !is_array($settings)) { + if (empty($settings) || ! is_array($settings)) { throw new TelegramException('Settings variable is not an array or is empty!'); } @@ -326,7 +326,7 @@ private function getQueries($settings) /** * Execution if MySQL is required but not available * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response */ public function executeNoDb() { @@ -339,20 +339,20 @@ public function executeNoDb() 'text' => '*No database connection!*', ]; - return Request::sendMessage($data); + return Client::sendMessage($data); } /** * Command execute method * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ public function execute() { $message = $this->getMessage(); $user_id = $message->getFrom()->getId(); - $text = $message->getText(true); + $text = $message->getText(true); $data = [ 'chat_id' => $user_id, @@ -360,7 +360,7 @@ public function execute() ]; $settings = $this->getSettings($text); - $queries = $this->getQueries($settings); + $queries = $this->getQueries($settings); $infos = []; foreach ($settings['tables_to_clean'] as $table) { @@ -375,10 +375,10 @@ public function execute() $data['text'] = 'Cleaning up tables:' . PHP_EOL . implode(PHP_EOL, $infos); - Request::sendMessage($data); + Client::sendMessage($data); $rows = 0; - $pdo = DB::getPdo(); + $pdo = DB::getPdo(); try { $pdo->beginTransaction(); @@ -386,7 +386,7 @@ public function execute() if ($dbq = $pdo->query($query)) { $rows += $dbq->rowCount(); } else { - TelegramLog::error('Error while executing query: ' . $query); + Logger::error('Error while executing query: ' . $query); } } @@ -395,7 +395,7 @@ public function execute() $pdo->rollBack(); // rollback changes on exception (useful if you want to track down error - you can't replicate it when some of the data is already deleted...) $data['text'] = '*Database cleanup failed!* _(check your error logs)_'; - Request::sendMessage($data); + Client::sendMessage($data); throw new TelegramException($e->getMessage()); } @@ -406,6 +406,6 @@ public function execute() $data['text'] = '*No data to clean!*'; } - return Request::sendMessage($data); + return Client::sendMessage($data); } } diff --git a/src/Commands/AdminCommands/DebugCommand.php b/src/Commands/AdminCommands/DebugCommand.php index ec9b0d831..3dc33ce3b 100644 --- a/src/Commands/AdminCommands/DebugCommand.php +++ b/src/Commands/AdminCommands/DebugCommand.php @@ -10,9 +10,11 @@ namespace Longman\TelegramBot\Commands\AdminCommands; +use Exception; use Longman\TelegramBot\Commands\AdminCommand; use Longman\TelegramBot\DB; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Http\Request; /** * Admin "/debug" command @@ -54,10 +56,10 @@ public function execute() $data = ['chat_id' => $chat->getId()]; - if ($text !== 'glasnost' && !$chat->isPrivateChat()) { + if ($text !== 'glasnost' && ! $chat->isPrivateChat()) { $data['text'] = 'Only available in a private chat.'; - return Request::sendMessage($data); + return Client::sendMessage($data); } $debug_info = []; @@ -66,6 +68,8 @@ public function execute() $debug_info[] = sprintf('*Download path:* `%s`', $this->telegram->getDownloadPath() ?: '`_Not set_`'); $debug_info[] = sprintf('*Upload path:* `%s`', $this->telegram->getUploadPath() ?: '`_Not set_`'); + $config = $this->telegram->getConfig(); + // Commands paths. $debug_info[] = '*Commands paths:*'; $debug_info[] = sprintf( @@ -94,30 +98,39 @@ public function execute() $webhook_info_title = '*Webhook Info:*'; try { + /** @var \Longman\TelegramBot\Http\Request $request */ + $request = $this->getTelegram()->getContainer()->make(Request::class); + // Check if we're actually using the Webhook method. - if (Request::getInput() === '') { + if (empty($request->json()->all())) { $debug_info[] = $webhook_info_title . ' `Using getUpdates method, not Webhook.`'; } else { - $webhook_info_result = json_decode(Request::getWebhookInfo(), true)['result']; + /** @var \Longman\TelegramBot\Http\Response $response */ + $response = Client::getWebhookInfo(); + + /** @var \Longman\TelegramBot\Entities\WebhookInfo $result */ + $result = $response->getResult(); + + $webhook_info_result = $result->getRawData(); // Add a human-readable error date string if necessary. if (isset($webhook_info_result['last_error_date'])) { $webhook_info_result['last_error_date_string'] = date('Y-m-d H:i:s', $webhook_info_result['last_error_date']); } - $webhook_info_result_str = json_encode($webhook_info_result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + $webhook_info_result_str = json_encode($webhook_info_result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $debug_info[] = $webhook_info_title; $debug_info[] = sprintf( '```' . PHP_EOL . '%s```', $webhook_info_result_str ); } - } catch (\Exception $e) { + } catch (Exception $e) { $debug_info[] = $webhook_info_title . sprintf(' `Failed to get webhook info! (%s)`', $e->getMessage()); } $data['parse_mode'] = 'Markdown'; $data['text'] = implode(PHP_EOL, $debug_info); - return Request::sendMessage($data); + return Client::sendMessage($data); } } diff --git a/src/Commands/AdminCommands/SendtoallCommand.php b/src/Commands/AdminCommands/SendtoallCommand.php index a05a56658..2f5d6d80b 100644 --- a/src/Commands/AdminCommands/SendtoallCommand.php +++ b/src/Commands/AdminCommands/SendtoallCommand.php @@ -12,8 +12,8 @@ use Longman\TelegramBot\Commands\AdminCommand; use Longman\TelegramBot\Entities\Message; -use Longman\TelegramBot\Entities\ServerResponse; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Response; +use Longman\TelegramBot\Http\Client; /** * Admin "/sendtoall" command @@ -48,7 +48,7 @@ class SendtoallCommand extends AdminCommand /** * Execute command * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ public function execute() @@ -59,8 +59,8 @@ public function execute() return $this->replyToChat('Usage: ' . $this->getUsage()); } - /** @var ServerResponse[] $results */ - $results = Request::sendToActiveChats( + /** @var Response[] $results */ + $results = Client::sendToActiveChats( 'sendMessage', //callback function to execute (see Request.php methods) ['text' => $text], //Param to evaluate the request [ @@ -75,7 +75,7 @@ public function execute() return $this->replyToChat('No users or chats found.'); } - $total = 0; + $total = 0; $failed = 0; $text = 'Message sent to:' . PHP_EOL; @@ -88,7 +88,7 @@ public function execute() /** @var Message $message */ $message = $result->getResult(); - $chat = $message->getChat(); + $chat = $message->getChat(); if ($chat->isPrivateChat()) { $name = $chat->getFirstName(); $type = 'user'; diff --git a/src/Commands/AdminCommands/SendtochannelCommand.php b/src/Commands/AdminCommands/SendtochannelCommand.php index d8d3de78e..608edec76 100644 --- a/src/Commands/AdminCommands/SendtochannelCommand.php +++ b/src/Commands/AdminCommands/SendtochannelCommand.php @@ -15,7 +15,7 @@ use Longman\TelegramBot\Entities\Chat; use Longman\TelegramBot\Entities\Keyboard; use Longman\TelegramBot\Entities\Message; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; class SendtochannelCommand extends AdminCommand { @@ -54,7 +54,7 @@ class SendtochannelCommand extends AdminCommand /** * Command execute method * - * @return \Longman\TelegramBot\Entities\ServerResponse|mixed + * @return \Longman\TelegramBot\Http\Response|mixed * @throws \Longman\TelegramBot\Exception\TelegramException */ public function execute() @@ -68,7 +68,7 @@ public function execute() // if the command is recalled when the conversation is already started in_array($type, ['command', 'text'], true) && $type = 'message'; - $text = trim($message->getText(true)); + $text = trim($message->getText(true)); $text_yes_or_no = ($text === 'Yes' || $text === 'No'); $data = [ @@ -79,13 +79,13 @@ public function execute() $this->conversation = new Conversation($user_id, $chat_id, $this->getName()); $notes = &$this->conversation->notes; - !is_array($notes) && $notes = []; + ! is_array($notes) && $notes = []; $channels = (array) $this->getConfig('your_channel'); if (isset($notes['state'])) { $state = $notes['state']; } else { - $state = (count($channels) === 0) ? -1 : 0; + $state = (count($channels) === 0) ? -1 : 0; $notes['last_message_id'] = $message->getMessageId(); } @@ -115,7 +115,7 @@ public function execute() break; } - $notes['channel'] = $text; + $notes['channel'] = $text; $notes['last_message_id'] = $message->getMessageId(); // Jump to state 1 goto insert; @@ -149,7 +149,7 @@ public function execute() ); break; } - $notes['channel'] = $text; + $notes['channel'] = $text; $notes['last_message_id'] = $message->getMessageId(); // no break @@ -166,21 +166,21 @@ public function execute() break; } $notes['last_message_id'] = $message->getMessageId(); - $notes['message'] = $message->getRawData(); - $notes['message_type'] = $type; + $notes['message'] = $message->getRawData(); + $notes['message_type'] = $type; // no break case 2: - if (!$text_yes_or_no || $notes['last_message_id'] === $message->getMessageId()) { + if (! $text_yes_or_no || $notes['last_message_id'] === $message->getMessageId()) { $notes['state'] = 2; $this->conversation->update(); // Grab any existing caption. if ($caption = $message->getCaption()) { $notes['caption'] = $caption; - $text = 'No'; - } elseif (in_array($notes['message_type'], ['video', 'photo'], true)) { + $text = 'No'; + } else if (in_array($notes['message_type'], ['video', 'photo'], true)) { $text = 'Would you like to insert a caption?'; - if (!$text_yes_or_no && $notes['last_message_id'] !== $message->getMessageId()) { + if (! $text_yes_or_no && $notes['last_message_id'] !== $message->getMessageId()) { $text .= PHP_EOL . 'Type Yes or No'; } @@ -191,7 +191,7 @@ public function execute() break; } } - $notes['set_caption'] = ($text === 'Yes'); + $notes['set_caption'] = ($text === 'Yes'); $notes['last_message_id'] = $message->getMessageId(); // no break case 3: @@ -214,7 +214,7 @@ public function execute() } // no break case 4: - if (!$text_yes_or_no || $notes['last_message_id'] === $message->getMessageId()) { + if (! $text_yes_or_no || $notes['last_message_id'] === $message->getMessageId()) { $notes['state'] = 4; $this->conversation->update(); @@ -229,15 +229,15 @@ public function execute() $data['reply_markup'] = $yes_no_keyboard; $data['text'] = 'Would you like to post it?'; - if (!$text_yes_or_no && $notes['last_message_id'] !== $message->getMessageId()) { + if (! $text_yes_or_no && $notes['last_message_id'] !== $message->getMessageId()) { $data['text'] .= PHP_EOL . 'Type Yes or No'; } - $result = Request::sendMessage($data); + $result = Client::sendMessage($data); } break; } - $notes['post_message'] = ($text === 'Yes'); + $notes['post_message'] = ($text === 'Yes'); $notes['last_message_id'] = $message->getMessageId(); // no break case 5: @@ -245,7 +245,7 @@ public function execute() if ($notes['post_message']) { $data['parse_mode'] = 'markdown'; - $data['text'] = $this->publish( + $data['text'] = $this->publish( new Message($notes['message'], $this->telegram->getBotUsername()), $notes['channel'], $notes['caption'] @@ -255,7 +255,7 @@ public function execute() } $this->conversation->stop(); - $result = Request::sendMessage($data); + $result = Client::sendMessage($data); } return $result; @@ -273,9 +273,9 @@ public function execute() * @todo Looking for a more significant name * * @param \Longman\TelegramBot\Entities\Message $message - * @param array $data + * @param array $data * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ protected function sendBack(Message $message, array $data) @@ -285,35 +285,35 @@ protected function sendBack(Message $message, array $data) if ($type === 'message') { $data['text'] = $message->getText(true); - } elseif ($type === 'audio') { - $data['audio'] = $message->getAudio()->getFileId(); - $data['duration'] = $message->getAudio()->getDuration(); + } else if ($type === 'audio') { + $data['audio'] = $message->getAudio()->getFileId(); + $data['duration'] = $message->getAudio()->getDuration(); $data['performer'] = $message->getAudio()->getPerformer(); - $data['title'] = $message->getAudio()->getTitle(); - } elseif ($type === 'document') { + $data['title'] = $message->getAudio()->getTitle(); + } else if ($type === 'document') { $data['document'] = $message->getDocument()->getFileId(); - } elseif ($type === 'photo') { + } else if ($type === 'photo') { $data['photo'] = $message->getPhoto()[0]->getFileId(); - } elseif ($type === 'sticker') { + } else if ($type === 'sticker') { $data['sticker'] = $message->getSticker()->getFileId(); - } elseif ($type === 'video') { + } else if ($type === 'video') { $data['video'] = $message->getVideo()->getFileId(); - } elseif ($type === 'voice') { + } else if ($type === 'voice') { $data['voice'] = $message->getVoice()->getFileId(); - } elseif ($type === 'location') { - $data['latitude'] = $message->getLocation()->getLatitude(); + } else if ($type === 'location') { + $data['latitude'] = $message->getLocation()->getLatitude(); $data['longitude'] = $message->getLocation()->getLongitude(); } - return Request::send('send' . ucfirst($type), $data); + return Client::send('send' . ucfirst($type), $data); } /** * Publish a message to a channel and return success or failure message in markdown format * * @param \Longman\TelegramBot\Entities\Message $message - * @param string|int $channel_id - * @param string|null $caption + * @param string|int $channel_id + * @param string|null $caption * * @return string * @throws \Longman\TelegramBot\Exception\TelegramException @@ -327,7 +327,7 @@ protected function publish(Message $message, $channel_id, $caption = null) if ($res->isOk()) { /** @var Chat $channel */ - $channel = $res->getResult()->getChat(); + $channel = $res->getResult()->getChat(); $escaped_username = $channel->getUsername() ? $this->getMessage()->escapeMarkdown($channel->getUsername()) : ''; $response = sprintf( @@ -337,9 +337,9 @@ protected function publish(Message $message, $channel_id, $caption = null) ); } else { $escaped_username = $this->getMessage()->escapeMarkdown($channel_id); - $response = "Message not sent to *{$escaped_username}*" . PHP_EOL . - '- Does the channel exist?' . PHP_EOL . - '- Is the bot an admin of the channel?'; + $response = "Message not sent to *{$escaped_username}*" . PHP_EOL . + '- Does the channel exist?' . PHP_EOL . + '- Is the bot an admin of the channel?'; } return $response; @@ -356,7 +356,7 @@ protected function publish(Message $message, $channel_id, $caption = null) public function executeNoDb() { $message = $this->getMessage(); - $text = trim($message->getText(true)); + $text = trim($message->getText(true)); if ($text === '') { return $this->replyToChat('Usage: ' . $this->getUsage()); diff --git a/src/Commands/AdminCommands/WhoisCommand.php b/src/Commands/AdminCommands/WhoisCommand.php index ad5e26155..2090eea63 100644 --- a/src/Commands/AdminCommands/WhoisCommand.php +++ b/src/Commands/AdminCommands/WhoisCommand.php @@ -17,7 +17,7 @@ use Longman\TelegramBot\Entities\Chat; use Longman\TelegramBot\Entities\PhotoSize; use Longman\TelegramBot\Entities\UserProfilePhotos; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; /** * Admin "/whois" command @@ -52,7 +52,7 @@ class WhoisCommand extends AdminCommand /** * Command execute method * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ public function execute() @@ -141,7 +141,7 @@ public function execute() //Code from Whoami command $limit = 10; $offset = null; - $response = Request::getUserProfilePhotos( + $response = Client::getUserProfilePhotos( [ 'user_id' => $user_id, 'limit' => $limit, @@ -163,7 +163,7 @@ public function execute() $data['photo'] = $file_id; $data['caption'] = $text; - return Request::sendPhoto($data); + return Client::sendPhoto($data); } } } elseif ($chat->isGroupChat()) { @@ -182,6 +182,6 @@ public function execute() $data['text'] = $text; - return Request::sendMessage($data); + return Client::sendMessage($data); } } diff --git a/src/Commands/Command.php b/src/Commands/Command.php index cd99cf469..2aec66e69 100644 --- a/src/Commands/Command.php +++ b/src/Commands/Command.php @@ -16,7 +16,8 @@ use Longman\TelegramBot\Entities\InlineQuery; use Longman\TelegramBot\Entities\Message; use Longman\TelegramBot\Entities\Update; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Http\Response; use Longman\TelegramBot\Telegram; /** @@ -143,12 +144,12 @@ public function setUpdate(Update $update = null) /** * Pre-execute command * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ public function preExecute() { - if ($this->need_mysql && !($this->telegram->isDbEnabled() && DB::isDbConnected())) { + if ($this->need_mysql && !(DB::isEnabled() && DB::isDbConnected())) { return $this->executeNoDb(); } @@ -156,7 +157,7 @@ public function preExecute() $message = $this->getMessage(); if ($user = $message->getFrom()) { - return Request::sendMessage([ + return Client::sendMessage([ 'chat_id' => $user->getId(), 'parse_mode' => 'Markdown', 'text' => sprintf( @@ -167,7 +168,7 @@ public function preExecute() ]); } - return Request::emptyResponse(); + return new Response(['ok' => true, 'result' => true]); } return $this->execute(); @@ -176,7 +177,7 @@ public function preExecute() /** * Execute command * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ abstract public function execute(); @@ -184,7 +185,7 @@ abstract public function execute(); /** * Execution if MySQL is required but not available * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ public function executeNoDb() @@ -198,7 +199,7 @@ public function executeNoDb() 'text' => 'Sorry no database connection, unable to execute "' . $this->name . '" command.', ]; - return Request::sendMessage($data); + return Client::sendMessage($data); } /** @@ -375,7 +376,7 @@ protected function removeNonPrivateMessage() if (!$chat->isPrivateChat()) { // Delete the falsely called command message. - Request::deleteMessage([ + Client::deleteMessage([ 'chat_id' => $chat->getId(), 'message_id' => $message->getMessageId(), ]); @@ -393,18 +394,18 @@ protected function removeNonPrivateMessage() * @param string $text * @param array $data * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response */ public function replyToChat($text, array $data = []) { if ($message = $this->getMessage() ?: $this->getEditedMessage() ?: $this->getChannelPost() ?: $this->getEditedChannelPost()) { - return Request::sendMessage(array_merge([ + return Client::sendMessage(array_merge([ 'chat_id' => $message->getChat()->getId(), 'text' => $text, ], $data)); } - return Request::emptyResponse(); + return new Response(['ok' => true, 'result' => true]); } /** @@ -413,17 +414,17 @@ public function replyToChat($text, array $data = []) * @param string $text * @param array $data * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response */ public function replyToUser($text, array $data = []) { if ($message = $this->getMessage() ?: $this->getEditedMessage()) { - return Request::sendMessage(array_merge([ + return Client::sendMessage(array_merge([ 'chat_id' => $message->getFrom()->getId(), 'text' => $text, ], $data)); } - return Request::emptyResponse(); + return new Response(['ok' => true, 'result' => true]); } } diff --git a/src/Commands/CommandContract.php b/src/Commands/CommandContract.php new file mode 100644 index 000000000..2b28679c2 --- /dev/null +++ b/src/Commands/CommandContract.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Commands; + +/** + * Command contract class + * + * Interface for commands + */ +interface CommandContract +{ + +} diff --git a/src/Commands/SystemCommand.php b/src/Commands/SystemCommand.php index e604ba473..9d9774470 100644 --- a/src/Commands/SystemCommand.php +++ b/src/Commands/SystemCommand.php @@ -10,7 +10,8 @@ namespace Longman\TelegramBot\Commands; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Http\Response; abstract class SystemCommand extends Command { @@ -20,11 +21,11 @@ abstract class SystemCommand extends Command * Although system commands should just work and return a successful ServerResponse, * each system command can override this method to add custom functionality. * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response */ public function execute() { //System command, return empty ServerResponse by default - return Request::emptyResponse(); + return new Response(['ok' => true, 'result' => true]); } } diff --git a/src/Commands/SystemCommands/CallbackqueryCommand.php b/src/Commands/SystemCommands/CallbackqueryCommand.php index c92894755..bc831c65e 100644 --- a/src/Commands/SystemCommands/CallbackqueryCommand.php +++ b/src/Commands/SystemCommands/CallbackqueryCommand.php @@ -11,7 +11,7 @@ namespace Longman\TelegramBot\Commands\SystemCommands; use Longman\TelegramBot\Commands\SystemCommand; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; /** * Callback query command @@ -56,7 +56,7 @@ public function execute() $callback($this->getUpdate()->getCallbackQuery()); } - return Request::answerCallbackQuery(['callback_query_id' => $this->getUpdate()->getCallbackQuery()->getId()]); + return Client::answerCallbackQuery(['callback_query_id' => $this->getUpdate()->getCallbackQuery()->getId()]); } /** diff --git a/src/Commands/SystemCommands/GenericCommand.php b/src/Commands/SystemCommands/GenericCommand.php index ff11fd3de..b024949a4 100644 --- a/src/Commands/SystemCommands/GenericCommand.php +++ b/src/Commands/SystemCommands/GenericCommand.php @@ -11,7 +11,6 @@ namespace Longman\TelegramBot\Commands\SystemCommands; use Longman\TelegramBot\Commands\SystemCommand; -use Longman\TelegramBot\Request; /** * Generic command diff --git a/src/Commands/SystemCommands/GenericmessageCommand.php b/src/Commands/SystemCommands/GenericmessageCommand.php index 8d362fb42..885cac1f1 100644 --- a/src/Commands/SystemCommands/GenericmessageCommand.php +++ b/src/Commands/SystemCommands/GenericmessageCommand.php @@ -10,9 +10,10 @@ namespace Longman\TelegramBot\Commands\SystemCommands; -use Longman\TelegramBot\Conversation; -use Longman\TelegramBot\Request; use Longman\TelegramBot\Commands\SystemCommand; +use Longman\TelegramBot\Conversation; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Http\Response; /** * Generic message command @@ -42,18 +43,18 @@ class GenericmessageCommand extends SystemCommand /** * Execution if MySQL is required but not available * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response */ public function executeNoDb() { //Do nothing - return Request::emptyResponse(); + return new Response(['ok' => true, 'result' => true]); } /** * Execute command * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ public function execute() @@ -69,6 +70,6 @@ public function execute() return $this->telegram->executeCommand($command); } - return Request::emptyResponse(); + return new Response(['ok' => true, 'result' => true]); } } diff --git a/src/Commands/SystemCommands/InlinequeryCommand.php b/src/Commands/SystemCommands/InlinequeryCommand.php index 8b6714f18..68753ef5b 100644 --- a/src/Commands/SystemCommands/InlinequeryCommand.php +++ b/src/Commands/SystemCommands/InlinequeryCommand.php @@ -11,9 +11,7 @@ namespace Longman\TelegramBot\Commands\SystemCommands; use Longman\TelegramBot\Commands\SystemCommand; -use Longman\TelegramBot\Entities\InlineQuery\InlineQueryResultArticle; -use Longman\TelegramBot\Entities\InputMessageContent\InputTextMessageContent; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; /** * Inline query command @@ -47,6 +45,6 @@ public function execute() //$user_id = $inline_query->getFrom()->getId(); //$query = $inline_query->getQuery(); - return Request::answerInlineQuery(['inline_query_id' => $this->getUpdate()->getInlineQuery()->getId()]); + return Client::answerInlineQuery(['inline_query_id' => $this->getUpdate()->getInlineQuery()->getId()]); } } diff --git a/src/Commands/SystemCommands/StartCommand.php b/src/Commands/SystemCommands/StartCommand.php index b471a7410..a7322d32c 100644 --- a/src/Commands/SystemCommands/StartCommand.php +++ b/src/Commands/SystemCommands/StartCommand.php @@ -11,7 +11,6 @@ namespace Longman\TelegramBot\Commands\SystemCommands; use Longman\TelegramBot\Commands\SystemCommand; -use Longman\TelegramBot\Request; /** * Start command diff --git a/src/Config.php b/src/Config.php new file mode 100644 index 000000000..bfb6690e5 --- /dev/null +++ b/src/Config.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot; + +use Illuminate\Config\Repository; + +class Config extends Repository +{ + /** + * 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 void + */ + public function addCommandsPath($path, $before = true) + { + $paths = $this->get('commands.paths', []); + + if (! is_dir($path)) { + Logger::error('Commands path "%s" does not exist.', $path); + } else if (! in_array($path, $paths, true)) { + if ($before) { + array_unshift($paths, $path); + } else { + $paths[] = $path; + } + } + + $this->set('commands.paths', $paths); + } + + /** + * 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 void + */ + public function addCommandsPaths(array $paths, $before = true) + { + foreach ($paths as $path) { + $this->addCommandsPath($path, $before); + } + } + + /** + * Return the list of commands paths + * + * @return array + */ + public function getCommandsPaths() + { + return $this->get('commands.paths', []); + } + + /** + * Enable a single Admin account + * + * @param integer $admin_id Single admin id + * + * @return void + */ + public function addAdmin($admin_id) + { + $admins = $this->get('admins', []); + + if (! is_int($admin_id) || $admin_id <= 0) { + Logger::error('Invalid value "%s" for admin.', $admin_id); + } else if (! in_array($admin_id, $admins, true)) { + $admins[] = $admin_id; + } + + $this->set('admins', $admins); + } + + /** + * Enable a list of Admin Accounts + * + * @param array $admin_ids List of admin ids + * + * @return void + */ + public function addAdmins(array $admin_ids) + { + foreach ($admin_ids as $admin_id) { + $this->addAdmin($admin_id); + } + } + + /** + * Get list of admins + * + * @return array + */ + public function getAdmins() + { + return $this->get('admins', []); + } + + /** + * Set custom upload path + * + * @param string $path Custom upload path + * + * @return void + */ + public function setUploadPath($path) + { + $this->set('upload_path', $path); + } + + /** + * Get custom upload path + * + * @return string + */ + public function getUploadPath() + { + return $this->get('upload_path', ''); + } + + /** + * Set custom download path + * + * @param string $path Custom download path + * + * @return void + */ + public function setDownloadPath($path) + { + $this->set('download_path', $path); + } + + /** + * Get custom download path + * + * @return string + */ + public function getDownloadPath() + { + return $this->get('download_path', ''); + } +} diff --git a/src/Console/Kernel.php b/src/Console/Kernel.php new file mode 100644 index 000000000..fc6753005 --- /dev/null +++ b/src/Console/Kernel.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Console; + +use Longman\TelegramBot\DB; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Http\Request; +use Longman\TelegramBot\Http\Response; +use Longman\TelegramBot\Telegram; + +class Kernel +{ + /** + * The application implementation. + * + * @var \Longman\TelegramBot\Telegram + */ + protected $app; + + /** + * Create a new HTTP kernel instance. + * + * @param \Longman\TelegramBot\Telegram $app + * + * @return void + */ + public function __construct(Telegram $app) + { + $this->app = $app; + } + + /** + * Handle an incoming HTTP request. + * + * @param \Longman\TelegramBot\Http\Request $request + * + * @param null $limit + * @param null $timeout + * @return \Longman\TelegramBot\Http\Response + * + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public function handle(Request $request, $limit = null, $timeout = null) + { + if (! DB::isDbConnected() && ! $this->app->getupdates_without_database) { + return new Response( + [ + 'ok' => false, + 'description' => 'getUpdates needs MySQL connection! (This can be overridden - see documentation)', + ], + $this->app->getBotUsername() + ); + } + + $offset = 0; + + if (DB::isDbConnected()) { + // Get last update id from the database + $last_update = DB::selectTelegramUpdate(1); + $last_update = reset($last_update); + + $this->app->last_update_id = isset($last_update['id']) ? $last_update['id'] : null; + } + + if ($this->app->last_update_id !== null) { + $offset = $this->app->last_update_id + 1; // As explained in the telegram bot API documentation + } + + $response = Client::getUpdates( + [ + 'offset' => $offset, + 'limit' => $limit, + 'timeout' => $timeout, + ] + ); + + if ($response->isOk()) { + $results = $response->getResult(); + + // Process all updates + /** @var \Longman\TelegramBot\Entities\Update $result */ + foreach ($results as $result) { + $this->app->processUpdate($result); + } + + if (! DB::isDbConnected() && $this->app->last_update_id !== null && $offset === 0) { + // Mark update(s) as read after handling + Client::getUpdates( + [ + 'offset' => $this->app->last_update_id + 1, + 'limit' => 1, + 'timeout' => $timeout, + ] + ); + } + } + + return $response; + } +} diff --git a/src/DB.php b/src/DB.php index ebf2a2ead..d1a0707f2 100644 --- a/src/DB.php +++ b/src/DB.php @@ -31,36 +31,43 @@ class DB * * @var array */ - static protected $mysql_credentials = []; + protected static $mysql_credentials = []; /** * PDO object * * @var PDO */ - static protected $pdo; + protected static $pdo; /** * Table prefix * * @var string */ - static protected $table_prefix; + protected static $table_prefix; /** * Telegram class object * * @var Telegram */ - static protected $telegram; + protected static $telegram; + + /** + * Enabled + * + * @var bool + */ + protected static $enabled = false; /** * Initialize * - * @param array $credentials Database connection details - * @param Telegram $telegram Telegram object to connect with this object - * @param string $table_prefix Table prefix - * @param string $encoding Database character encoding + * @param array $credentials Database connection details + * @param Telegram $telegram Telegram object to connect with this object + * @param string $table_prefix Table prefix + * @param string $encoding Database character encoding * * @return PDO PDO database object * @throws TelegramException @@ -75,7 +82,7 @@ public static function initialize( throw new TelegramException('MySQL credentials not provided!'); } - $dsn = 'mysql:host=' . $credentials['host'] . ';dbname=' . $credentials['database']; + $dsn = 'mysql:host=' . $credentials['host'] . ';dbname=' . $credentials['database']; $options = [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $encoding]; try { $pdo = new PDO($dsn, $credentials['user'], $credentials['password'], $options); @@ -84,10 +91,10 @@ public static function initialize( throw new TelegramException($e->getMessage()); } - self::$pdo = $pdo; - self::$telegram = $telegram; + self::$pdo = $pdo; + self::$telegram = $telegram; self::$mysql_credentials = $credentials; - self::$table_prefix = $table_prefix; + self::$table_prefix = $table_prefix; self::defineTables(); @@ -99,9 +106,9 @@ public static function initialize( * * Let you use the class with an external already existing Pdo Mysql connection. * - * @param PDO $external_pdo_connection PDO database object - * @param Telegram $telegram Telegram object to connect with this object - * @param string $table_prefix Table prefix + * @param PDO $external_pdo_connection PDO database object + * @param Telegram $telegram Telegram object to connect with this object + * @param string $table_prefix Table prefix * * @return PDO PDO database object * @throws TelegramException @@ -115,10 +122,10 @@ public static function externalInitialize( throw new TelegramException('MySQL external connection not provided!'); } - self::$pdo = $external_pdo_connection; - self::$telegram = $telegram; + self::$pdo = $external_pdo_connection; + self::$telegram = $telegram; self::$mysql_credentials = []; - self::$table_prefix = $table_prefix; + self::$table_prefix = $table_prefix; self::defineTables(); @@ -144,7 +151,7 @@ protected static function defineTables() ]; foreach ($tables as $table) { $table_name = 'TB_' . strtoupper($table); - if (!defined($table_name)) { + if (! defined($table_name)) { define($table_name, self::$table_prefix . $table); } } @@ -173,15 +180,15 @@ public static function getPdo() /** * Fetch update(s) from DB * - * @param int $limit Limit the number of updates to fetch - * @param string $id Check for unique update id + * @param int $limit Limit the number of updates to fetch + * @param string $id Check for unique update id * * @return array|bool Fetched data or false if not connected * @throws TelegramException */ public static function selectTelegramUpdate($limit = null, $id = null) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -228,7 +235,7 @@ public static function selectTelegramUpdate($limit = null, $id = null) */ public static function selectMessages($limit = null) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -275,13 +282,13 @@ protected static function getTimestamp($time = null) * @todo Find a better way, as json_* functions are very heavy * * @param array|null $entities - * @param mixed $default + * @param mixed $default * * @return mixed */ public static function entitiesArrayToJson($entities, $default = null) { - if (!is_array($entities)) { + if (! is_array($entities)) { return $default; } @@ -322,7 +329,7 @@ public static function insertTelegramUpdate( throw new TelegramException('message_id, inline_query_id, chosen_inline_result_id, callback_query_id, edited_message_id are all null'); } - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -351,16 +358,16 @@ public static function insertTelegramUpdate( /** * Insert users and save their connection to chats * - * @param User $user + * @param User $user * @param string $date - * @param Chat $chat + * @param Chat $chat * * @return bool If the insert was successful * @throws TelegramException */ public static function insertUser(User $user, $date = null, Chat $chat = null) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -419,7 +426,7 @@ public static function insertUser(User $user, $date = null, Chat $chat = null) /** * Insert chat * - * @param Chat $chat + * @param Chat $chat * @param string $date * @param string $migrate_to_chat_id * @@ -428,7 +435,7 @@ public static function insertUser(User $user, $date = null, Chat $chat = null) */ public static function insertChat(Chat $chat, $date = null, $migrate_to_chat_id = null) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -446,7 +453,7 @@ public static function insertChat(Chat $chat, $date = null, $migrate_to_chat_id `updated_at` = VALUES(`updated_at`) '); - $chat_id = $chat->getId(); + $chat_id = $chat->getId(); $chat_type = $chat->getType(); if ($migrate_to_chat_id !== null) { @@ -485,11 +492,11 @@ public static function insertChat(Chat $chat, $date = null, $migrate_to_chat_id */ public static function insertRequest(Update $update) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } - $update_id = $update->getUpdateId(); + $update_id = $update->getUpdateId(); $update_type = $update->getUpdateType(); // @todo Make this simpler: if ($message = $update->getMessage()) ... @@ -498,7 +505,7 @@ public static function insertRequest(Update $update) if (self::insertMessageRequest($message)) { $message_id = $message->getMessageId(); - $chat_id = $message->getChat()->getId(); + $chat_id = $message->getChat()->getId(); return self::insertTelegramUpdate( $update_id, @@ -506,12 +513,12 @@ public static function insertRequest(Update $update) $message_id ); } - } elseif ($update_type === 'edited_message') { + } else if ($update_type === 'edited_message') { $edited_message = $update->getEditedMessage(); if (self::insertEditedMessageRequest($edited_message)) { $edited_message_local_id = self::$pdo->lastInsertId(); - $chat_id = $edited_message->getChat()->getId(); + $chat_id = $edited_message->getChat()->getId(); return self::insertTelegramUpdate( $update_id, @@ -523,12 +530,12 @@ public static function insertRequest(Update $update) $edited_message_local_id ); } - } elseif ($update_type === 'channel_post') { + } else if ($update_type === 'channel_post') { $channel_post = $update->getChannelPost(); if (self::insertMessageRequest($channel_post)) { $message_id = $channel_post->getMessageId(); - $chat_id = $channel_post->getChat()->getId(); + $chat_id = $channel_post->getChat()->getId(); return self::insertTelegramUpdate( $update_id, @@ -536,12 +543,12 @@ public static function insertRequest(Update $update) $message_id ); } - } elseif ($update_type === 'edited_channel_post') { + } else if ($update_type === 'edited_channel_post') { $edited_channel_post = $update->getEditedChannelPost(); if (self::insertEditedMessageRequest($edited_channel_post)) { $edited_channel_post_local_id = self::$pdo->lastInsertId(); - $chat_id = $edited_channel_post->getChat()->getId(); + $chat_id = $edited_channel_post->getChat()->getId(); return self::insertTelegramUpdate( $update_id, @@ -553,7 +560,7 @@ public static function insertRequest(Update $update) $edited_channel_post_local_id ); } - } elseif ($update_type === 'inline_query') { + } else if ($update_type === 'inline_query') { $inline_query = $update->getInlineQuery(); if (self::insertInlineQueryRequest($inline_query)) { @@ -566,7 +573,7 @@ public static function insertRequest(Update $update) $inline_query_id ); } - } elseif ($update_type === 'chosen_inline_result') { + } else if ($update_type === 'chosen_inline_result') { $chosen_inline_result = $update->getChosenInlineResult(); if (self::insertChosenInlineResultRequest($chosen_inline_result)) { @@ -580,7 +587,7 @@ public static function insertRequest(Update $update) $chosen_inline_result_local_id ); } - } elseif ($update_type === 'callback_query') { + } else if ($update_type === 'callback_query') { $callback_query = $update->getCallbackQuery(); if (self::insertCallbackQueryRequest($callback_query)) { @@ -610,7 +617,7 @@ public static function insertRequest(Update $update) */ public static function insertInlineQueryRequest(InlineQuery $inline_query) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -622,7 +629,7 @@ public static function insertInlineQueryRequest(InlineQuery $inline_query) (:id, :user_id, :location, :query, :offset, :created_at) '); - $date = self::getTimestamp(); + $date = self::getTimestamp(); $user_id = null; $user = $inline_query->getFrom(); @@ -654,7 +661,7 @@ public static function insertInlineQueryRequest(InlineQuery $inline_query) */ public static function insertChosenInlineResultRequest(ChosenInlineResult $chosen_inline_result) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -666,7 +673,7 @@ public static function insertChosenInlineResultRequest(ChosenInlineResult $chose (:result_id, :user_id, :location, :inline_message_id, :query, :created_at) '); - $date = self::getTimestamp(); + $date = self::getTimestamp(); $user_id = null; $user = $chosen_inline_result->getFrom(); @@ -698,7 +705,7 @@ public static function insertChosenInlineResultRequest(ChosenInlineResult $chose */ public static function insertCallbackQueryRequest(CallbackQuery $callback_query) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -710,7 +717,7 @@ public static function insertCallbackQueryRequest(CallbackQuery $callback_query) (:id, :user_id, :chat_id, :message_id, :inline_message_id, :data, :created_at) '); - $date = self::getTimestamp(); + $date = self::getTimestamp(); $user_id = null; $user = $callback_query->getFrom(); @@ -719,11 +726,11 @@ public static function insertCallbackQueryRequest(CallbackQuery $callback_query) self::insertUser($user, $date); } - $message = $callback_query->getMessage(); - $chat_id = null; + $message = $callback_query->getMessage(); + $chat_id = null; $message_id = null; if ($message instanceof Message) { - $chat_id = $message->getChat()->getId(); + $chat_id = $message->getChat()->getId(); $message_id = $message->getMessageId(); $is_message = self::$pdo->query(' @@ -767,7 +774,7 @@ public static function insertCallbackQueryRequest(CallbackQuery $callback_query) */ public static function insertMessageRequest(Message $message) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -795,16 +802,16 @@ public static function insertMessageRequest(Message $message) if ($forward_from_chat instanceof Chat) { self::insertChat($forward_from_chat, $forward_date); $forward_from_chat = $forward_from_chat->getId(); - $forward_date = self::getTimestamp($message->getForwardDate()); + $forward_date = self::getTimestamp($message->getForwardDate()); } // New and left chat member $new_chat_members_ids = null; - $left_chat_member_id = null; + $left_chat_member_id = null; $new_chat_members = $message->getNewChatMembers(); $left_chat_member = $message->getLeftChatMember(); - if (!empty($new_chat_members)) { + if (! empty($new_chat_members)) { foreach ($new_chat_members as $new_chat_member) { if ($new_chat_member instanceof User) { // Insert the new chat user @@ -813,7 +820,7 @@ public static function insertMessageRequest(Message $message) } } $new_chat_members_ids = implode(',', $new_chat_members_ids); - } elseif ($left_chat_member instanceof User) { + } else if ($left_chat_member instanceof User) { // Insert the left chat user self::insertUser($left_chat_member, $date, $chat); $left_chat_member_id = $left_chat_member->getId(); @@ -847,7 +854,7 @@ public static function insertMessageRequest(Message $message) } $chat_id = $chat->getId(); - $reply_to_message = $message->getReplyToMessage(); + $reply_to_message = $message->getReplyToMessage(); $reply_to_message_id = null; if ($reply_to_message instanceof ReplyToMessage) { $reply_to_message_id = $reply_to_message->getMessageId(); @@ -915,7 +922,7 @@ public static function insertMessageRequest(Message $message) */ public static function insertEditedMessageRequest(Message $edited_message) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -968,7 +975,7 @@ public static function insertEditedMessageRequest(Message $edited_message) */ public static function selectChats($select_chats_params) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -984,7 +991,7 @@ public static function selectChats($select_chats_params) 'text' => null, ], $select_chats_params); - if (!$select['groups'] && !$select['users'] && !$select['supergroups'] && !$select['channels']) { + if (! $select['groups'] && ! $select['users'] && ! $select['supergroups'] && ! $select['channels']) { return false; } @@ -1008,10 +1015,10 @@ public static function selectChats($select_chats_params) } // Building parts of query - $where = []; + $where = []; $tokens = []; - if (!$select['groups'] || !$select['users'] || !$select['supergroups'] || !$select['channels']) { + if (! $select['groups'] || ! $select['users'] || ! $select['supergroups'] || ! $select['channels']) { $chat_or_user = []; $select['groups'] && $chat_or_user[] = TB_CHAT . '.`type` = "group"'; @@ -1023,24 +1030,24 @@ public static function selectChats($select_chats_params) } if (null !== $select['date_from']) { - $where[] = TB_CHAT . '.`updated_at` >= :date_from'; + $where[] = TB_CHAT . '.`updated_at` >= :date_from'; $tokens[':date_from'] = $select['date_from']; } if (null !== $select['date_to']) { - $where[] = TB_CHAT . '.`updated_at` <= :date_to'; + $where[] = TB_CHAT . '.`updated_at` <= :date_to'; $tokens[':date_to'] = $select['date_to']; } if (null !== $select['chat_id']) { - $where[] = TB_CHAT . '.`id` = :chat_id'; + $where[] = TB_CHAT . '.`id` = :chat_id'; $tokens[':chat_id'] = $select['chat_id']; } if (null !== $select['text']) { $text_like = '%' . strtolower($select['text']) . '%'; if ($select['users']) { - $where[] = '( + $where[] = '( LOWER(' . TB_CHAT . '.`title`) LIKE :text1 OR LOWER(' . TB_USER . '.`first_name`) LIKE :text2 OR LOWER(' . TB_USER . '.`last_name`) LIKE :text3 @@ -1051,12 +1058,12 @@ public static function selectChats($select_chats_params) $tokens[':text3'] = $text_like; $tokens[':text4'] = $text_like; } else { - $where[] = 'LOWER(' . TB_CHAT . '.`title`) LIKE :text'; + $where[] = 'LOWER(' . TB_CHAT . '.`title`) LIKE :text'; $tokens[':text'] = $text_like; } } - if (!empty($where)) { + if (! empty($where)) { $query .= ' WHERE ' . implode(' AND ', $where); } @@ -1075,14 +1082,14 @@ public static function selectChats($select_chats_params) * Get Telegram API request count for current chat / message * * @param integer $chat_id - * @param string $inline_message_id + * @param string $inline_message_id * * @return array|bool Array containing TOTAL and CURRENT fields or false on invalid arguments * @throws TelegramException */ public static function getTelegramRequestCount($chat_id = null, $inline_message_id = null) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -1093,7 +1100,7 @@ public static function getTelegramRequestCount($chat_id = null, $inline_message_ (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_minute AND `chat_id` = :chat_id_2) AS LIMIT_PER_MINUTE '); - $date = self::getTimestamp(); + $date = self::getTimestamp(); $date_minute = self::getTimestamp(strtotime('-1 minute')); $sth->bindValue(':chat_id_1', $chat_id); @@ -1115,14 +1122,14 @@ public static function getTelegramRequestCount($chat_id = null, $inline_message_ * Insert Telegram API request in db * * @param string $method - * @param array $data + * @param array $data * * @return bool If the insert was successful * @throws TelegramException */ public static function insertTelegramRequest($method, $data) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -1133,7 +1140,7 @@ public static function insertTelegramRequest($method, $data) (:method, :chat_id, :inline_message_id, :created_at); '); - $chat_id = isset($data['chat_id']) ? $data['chat_id'] : null; + $chat_id = isset($data['chat_id']) ? $data['chat_id'] : null; $inline_message_id = isset($data['inline_message_id']) ? $data['inline_message_id'] : null; $sth->bindValue(':chat_id', $chat_id); @@ -1151,15 +1158,15 @@ public static function insertTelegramRequest($method, $data) * Bulk update the entries of any table * * @param string $table - * @param array $fields_values - * @param array $where_fields_values + * @param array $fields_values + * @param array $where_fields_values * * @return bool * @throws TelegramException */ public static function update($table, array $fields_values, array $where_fields_values) { - if (empty($fields_values) || !self::isDbConnected()) { + if (empty($fields_values) || ! self::isDbConnected()) { return false; } @@ -1169,15 +1176,15 @@ public static function update($table, array $fields_values, array $where_fields_ // Fields with values to update foreach ($fields_values as $field => $value) { - $token = ':' . count($tokens); - $fields[] = "`{$field}` = {$token}"; + $token = ':' . count($tokens); + $fields[] = "`{$field}` = {$token}"; $tokens[$token] = $value; } // Where conditions foreach ($where_fields_values as $field => $value) { - $token = ':' . count($tokens); - $where[] = "`{$field}` = {$token}"; + $token = ':' . count($tokens); + $where[] = "`{$field}` = {$token}"; $tokens[$token] = $value; } @@ -1189,4 +1196,25 @@ public static function update($table, array $fields_values, array $where_fields_ throw new TelegramException($e->getMessage()); } } + + /** + * Return enabled status + * + * @return bool + */ + public static function isEnabled() + { + return self::$enabled; + } + + /** + * Set enabled status + * + * @param $enabled bool + * @return void + */ + public static function setEnabled($enabled) + { + self::$enabled = $enabled; + } } diff --git a/src/Entities/CallbackQuery.php b/src/Entities/CallbackQuery.php index 37cbed0e2..b38eb0ed0 100644 --- a/src/Entities/CallbackQuery.php +++ b/src/Entities/CallbackQuery.php @@ -10,7 +10,7 @@ namespace Longman\TelegramBot\Entities; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; /** * Class CallbackQuery. @@ -19,7 +19,8 @@ * * @method string getId() Unique identifier for this query * @method User getFrom() Sender - * @method Message getMessage() Optional. Message with the callback button that originated the query. Note that message content and message date will not be available if the message is too old + * @method Message getMessage() Optional. Message with the callback button that originated the query. Note that message content and message date will + * not be available if the message is too old * @method string getInlineMessageId() Optional. Identifier of the message sent via the bot in inline mode, that originated the query * @method string getData() Data associated with the callback button. Be aware that a bad client can send arbitrary data in this field */ @@ -45,7 +46,7 @@ public function subEntities() */ public function answer(array $data = []) { - return Request::answerCallbackQuery(array_merge([ + return Client::answerCallbackQuery(array_merge([ 'callback_query_id' => $this->getId(), ], $data)); } diff --git a/src/Entities/Entity.php b/src/Entities/Entity.php index 23e95a153..b40298900 100644 --- a/src/Entities/Entity.php +++ b/src/Entities/Entity.php @@ -12,7 +12,7 @@ use Exception; use Longman\TelegramBot\Entities\InlineQuery\InlineEntity; -use Longman\TelegramBot\TelegramLog; +use Longman\TelegramBot\Logger; /** * Class Entity @@ -38,7 +38,7 @@ abstract class Entity */ public function __construct($data, $bot_username = '') { - //Make sure we're not raw_data inception-ing + // Make sure we're not raw_data inception-ing if (array_key_exists('raw_data', $data)) { if ($data['raw_data'] === null) { unset($data['raw_data']); @@ -48,6 +48,7 @@ public function __construct($data, $bot_username = '') } $data['bot_username'] = $bot_username; + $this->assignMemberVariables($data); $this->validate(); } diff --git a/src/Entities/InlineQuery.php b/src/Entities/InlineQuery.php index b90c0bfd8..78bdcebff 100644 --- a/src/Entities/InlineQuery.php +++ b/src/Entities/InlineQuery.php @@ -11,7 +11,7 @@ namespace Longman\TelegramBot\Entities; use Longman\TelegramBot\Entities\InlineQuery\InlineQueryResult; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; /** * Class InlineQuery @@ -41,13 +41,13 @@ protected function subEntities() * Answer this inline query with the passed results. * * @param InlineQueryResult[] $results - * @param array $data + * @param array $data * * @return ServerResponse */ public function answer(array $results, array $data = []) { - return Request::answerCallbackQuery(array_merge([ + return Client::answerCallbackQuery(array_merge([ 'callback_query_id' => $this->getId(), 'results' => $results, ], $data)); diff --git a/src/Entities/Message.php b/src/Entities/Message.php index 0e592dc68..4ce8af13d 100644 --- a/src/Entities/Message.php +++ b/src/Entities/Message.php @@ -27,7 +27,8 @@ * @method int getForwardFromMessageId() Optional. For forwarded channel posts, identifier of the original message in the channel * @method string getForwardSignature() Optional. For messages forwarded from channels, signature of the post author if present * @method int getForwardDate() Optional. For forwarded messages, date the original message was sent in Unix time - * @method Message getReplyToMessage() Optional. For replies, the original message. Note that the Message object in this field will not contain further reply_to_message fields even if it itself is a reply. + * @method Message getReplyToMessage() Optional. For replies, the original message. Note that the Message object in this field will not + * contain further reply_to_message fields even if it itself is a reply. * @method int getEditDate() Optional. Date the message was last edited in Unix time * @method string getMediaGroupId() Optional. The unique identifier of a media message group this message belongs to * @method string getAuthorSignature() Optional. Signature of the post author for messages in channels @@ -41,15 +42,25 @@ * @method Contact getContact() Optional. Message is a shared contact, information about the contact * @method Location getLocation() Optional. Message is a shared location, information about the location * @method Venue getVenue() Optional. Message is a venue, information about the venue - * @method User getLeftChatMember() Optional. A member was removed from the group, information about them (this member may be the bot itself) + * @method User getLeftChatMember() Optional. A member was removed from the group, information about them (this member may be the bot + * itself) * @method string getNewChatTitle() Optional. A chat title was changed to this value * @method bool getDeleteChatPhoto() Optional. Service message: the chat photo was deleted * @method bool getGroupChatCreated() Optional. Service message: the group has been created - * @method bool getSupergroupChatCreated() Optional. Service message: the supergroup has been created. This field can't be received in a message coming through updates, because bot can’t be a member of a supergroup when it is created. It can only be found in reply_to_message if someone replies to a very first message in a directly created supergroup. - * @method bool getChannelChatCreated() Optional. Service message: the channel has been created. This field can't be received in a message coming through updates, because bot can’t be a member of a channel when it is created. It can only be found in reply_to_message if someone replies to a very first message in a channel. - * @method int getMigrateToChatId() Optional. The group has been migrated to a supergroup with the specified identifier. This number may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. - * @method int getMigrateFromChatId() Optional. The supergroup has been migrated from a group with the specified identifier. This number may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. - * @method Message getPinnedMessage() Optional. Specified message was pinned. Note that the Message object in this field will not contain further reply_to_message fields even if it is itself a reply. + * @method bool getSupergroupChatCreated() Optional. Service message: the supergroup has been created. This field can't be received in a message + * coming through updates, because bot can’t be a member of a supergroup when it is created. It can only be found in reply_to_message if someone replies to + * a very first message in a directly created supergroup. + * @method bool getChannelChatCreated() Optional. Service message: the channel has been created. This field can't be received in a message + * coming through updates, because bot can’t be a member of a channel when it is created. It can only be found in reply_to_message if someone replies to a + * very first message in a channel. + * @method int getMigrateToChatId() Optional. The group has been migrated to a supergroup with the specified identifier. This number may be + * greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it smaller than 52 bits, so a signed 64 + * bit integer or double-precision float type are safe for storing this identifier. + * @method int getMigrateFromChatId() Optional. The supergroup has been migrated from a group with the specified identifier. This number may + * be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it smaller than 52 bits, so a signed + * 64 bit integer or double-precision float type are safe for storing this identifier. + * @method Message getPinnedMessage() Optional. Specified message was pinned. Note that the Message object in this field will not contain + * further reply_to_message fields even if it is itself a reply. * @method Invoice getInvoice() Optional. Message is an invoice for a payment, information about the invoice. * @method SuccessfulPayment getSuccessfulPayment() Optional. Message is a service message about a successful payment, information about the payment. * @method string getConnectedWebsite() Optional. The domain name of the website on which the user has logged in. @@ -91,7 +102,7 @@ protected function subEntities() /** * Message constructor * - * @param array $data + * @param array $data * @param string $bot_username * * @throws \Longman\TelegramBot\Exception\TelegramException @@ -188,7 +199,7 @@ public function getFullCommand() return null; } - $no_EOL = strtok($text, PHP_EOL); + $no_EOL = strtok($text, PHP_EOL); $no_space = strtok($text, ' '); //try to understand which separator \n or space divide /command from text @@ -214,7 +225,7 @@ public function getCommand() //check if command is followed by bot username $split_cmd = explode('@', $full_command); - if (!isset($split_cmd[1])) { + if (! isset($split_cmd[1])) { //command is not followed by name return $full_command; } diff --git a/src/Entities/Payments/PreCheckoutQuery.php b/src/Entities/Payments/PreCheckoutQuery.php index b86e7647a..dce13c925 100644 --- a/src/Entities/Payments/PreCheckoutQuery.php +++ b/src/Entities/Payments/PreCheckoutQuery.php @@ -12,7 +12,7 @@ use Longman\TelegramBot\Entities\Entity; use Longman\TelegramBot\Entities\User; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; /** * Class PreCheckoutQuery @@ -45,14 +45,14 @@ public function subEntities() /** * Answer this pre-checkout query. * - * @param bool $ok + * @param bool $ok * @param array $data * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response */ public function answer($ok, array $data = []) { - return Request::answerPreCheckoutQuery(array_merge([ + return Client::answerPreCheckoutQuery(array_merge([ 'pre_checkout_query_id' => $this->getId(), 'ok' => $ok, ], $data)); diff --git a/src/Entities/Payments/ShippingQuery.php b/src/Entities/Payments/ShippingQuery.php index 0425254d9..927a5763d 100644 --- a/src/Entities/Payments/ShippingQuery.php +++ b/src/Entities/Payments/ShippingQuery.php @@ -12,7 +12,7 @@ use Longman\TelegramBot\Entities\Entity; use Longman\TelegramBot\Entities\User; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; /** * Class ShippingQuery @@ -42,14 +42,14 @@ public function subEntities() /** * Answer this shipping query. * - * @param bool $ok + * @param bool $ok * @param array $data * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response */ public function answer($ok, array $data = []) { - return Request::answerShippingQuery(array_merge([ + return Client::answerShippingQuery(array_merge([ 'shipping_query_id' => $this->getId(), 'ok' => $ok, ], $data)); diff --git a/src/Entities/ServerResponse.php b/src/Entities/ServerResponse.php deleted file mode 100644 index b573e9f80..000000000 --- a/src/Entities/ServerResponse.php +++ /dev/null @@ -1,165 +0,0 @@ - - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Longman\TelegramBot\Entities; - -/** - * Class ServerResponse - * - * @link https://core.telegram.org/bots/api#making-requests - * - * @method bool getOk() If the request was successful - * @method mixed getResult() The result of the query - * @method int getErrorCode() Error code of the unsuccessful request - * @method string getDescription() Human-readable description of the result / unsuccessful request - * - * @todo method ResponseParameters getParameters() Field which can help to automatically handle the error - */ -class ServerResponse extends Entity -{ - /** - * ServerResponse constructor. - * - * @param array $data - * @param string $bot_username - * - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public function __construct(array $data, $bot_username) - { - // Make sure we don't double-save the raw_data - unset($data['raw_data']); - $data['raw_data'] = $data; - - $is_ok = isset($data['ok']) ? (bool) $data['ok'] : false; - $result = isset($data['result']) ? $data['result'] : null; - - if ($is_ok && is_array($result)) { - if ($this->isAssoc($result)) { - $data['result'] = $this->createResultObject($result, $bot_username); - } else { - $data['result'] = $this->createResultObjects($result, $bot_username); - } - } - - parent::__construct($data, $bot_username); - } - - /** - * Check if array is associative - * - * @link https://stackoverflow.com/a/4254008 - * - * @param array $array - * - * @return bool - */ - protected function isAssoc(array $array) - { - return count(array_filter(array_keys($array), 'is_string')) > 0; - } - - /** - * If response is ok - * - * @return bool - */ - public function isOk() - { - return (bool) $this->getOk(); - } - - /** - * Print error - * - * @see https://secure.php.net/manual/en/function.print-r.php - * - * @param bool $return - * - * @return bool|string - */ - public function printError($return = false) - { - $error = sprintf('Error N: %s, Description: %s', $this->getErrorCode(), $this->getDescription()); - - if ($return) { - return $error; - } - - echo $error; - - return true; - } - - /** - * Create and return the object of the received result - * - * @param array $result - * @param string $bot_username - * - * @return \Longman\TelegramBot\Entities\Chat|\Longman\TelegramBot\Entities\ChatMember|\Longman\TelegramBot\Entities\File|\Longman\TelegramBot\Entities\Message|\Longman\TelegramBot\Entities\User|\Longman\TelegramBot\Entities\UserProfilePhotos|\Longman\TelegramBot\Entities\WebhookInfo - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - private function createResultObject($result, $bot_username) - { - // We don't need to save the raw_data of the response object! - $result['raw_data'] = null; - - $result_object_types = [ - 'total_count' => 'UserProfilePhotos', //Response from getUserProfilePhotos - 'file_id' => 'File', //Response from getFile - 'title' => 'Chat', //Response from getChat - 'username' => 'User', //Response from getMe - 'user' => 'ChatMember', //Response from getChatMember - 'url' => 'WebhookInfo', //Response from getWebhookInfo - ]; - foreach ($result_object_types as $type => $object_class) { - if (isset($result[$type])) { - $object_class = __NAMESPACE__ . '\\' . $object_class; - - return new $object_class($result); - } - } - - //Response from sendMessage - return new Message($result, $bot_username); - } - - /** - * Create and return the objects array of the received result - * - * @param array $result - * @param string $bot_username - * - * @return null|\Longman\TelegramBot\Entities\ChatMember[]|\Longman\TelegramBot\Entities\Update[] - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - private function createResultObjects($result, $bot_username) - { - $results = []; - if (isset($result[0]['user'])) { - //Response from getChatAdministrators - foreach ($result as $user) { - // We don't need to save the raw_data of the response object! - $user['raw_data'] = null; - - $results[] = new ChatMember($user); - } - } else { - //Get Update - foreach ($result as $update) { - // We don't need to save the raw_data of the response object! - $update['raw_data'] = null; - - $results[] = new Update($update, $bot_username); - } - } - - return $results; - } -} diff --git a/src/Entities/Update.php b/src/Entities/Update.php index 4ddb64bf7..98417d5f4 100644 --- a/src/Entities/Update.php +++ b/src/Entities/Update.php @@ -18,7 +18,9 @@ * * @link https://core.telegram.org/bots/api#update * - * @method int getUpdateId() The update's unique identifier. Update identifiers start from a certain positive number and increase sequentially. This ID becomes especially handy if you’re using Webhooks, since it allows you to ignore repeated updates or to restore the correct update sequence, should they get out of order. + * @method int getUpdateId() The update's unique identifier. Update identifiers start from a certain positive number and increase + * sequentially. This ID becomes especially handy if you’re using Webhooks, since it allows you to ignore repeated updates or to restore the correct update + * sequence, should they get out of order. * @method Message getMessage() Optional. New incoming message of any kind — text, photo, sticker, etc. * @method Message getEditedMessage() Optional. New version of a message that is known to the bot and was edited * @method Message getChannelPost() Optional. New post in the channel, can be any kind — text, photo, sticker, etc. @@ -31,21 +33,31 @@ */ class Update extends Entity { + const TYPE_MESSAGE = 'message'; + const TYPE_EDITED_MESSAGE = 'edited_message'; + const TYPE_CHANNEL_POST = 'channel_post'; + const TYPE_EDITED_CHANNEL_POST = 'edited_channel_post'; + const TYPE_INLINE_QUERY = 'inline_query'; + const TYPE_CHOSEN_INLINE_QUERY = 'chosen_inline_result'; + const TYPE_CALLBACK_QUERY = 'callback_query'; + const TYPE_SHIPPING_QUERY = 'shipping_query'; + const TYPE_PRE_CHECKOUT_QUERY = 'pre_checkout_query'; + /** * {@inheritdoc} */ protected function subEntities() { return [ - 'message' => Message::class, - 'edited_message' => EditedMessage::class, - 'channel_post' => ChannelPost::class, - 'edited_channel_post' => EditedChannelPost::class, - 'inline_query' => InlineQuery::class, - 'chosen_inline_result' => ChosenInlineResult::class, - 'callback_query' => CallbackQuery::class, - 'shipping_query' => ShippingQuery::class, - 'pre_checkout_query' => PreCheckoutQuery::class, + self::TYPE_MESSAGE => Message::class, + self::TYPE_EDITED_MESSAGE => EditedMessage::class, + self::TYPE_CHANNEL_POST => ChannelPost::class, + self::TYPE_EDITED_CHANNEL_POST => EditedChannelPost::class, + self::TYPE_INLINE_QUERY => InlineQuery::class, + self::TYPE_CHOSEN_INLINE_QUERY => ChosenInlineResult::class, + self::TYPE_CALLBACK_QUERY => CallbackQuery::class, + self::TYPE_SHIPPING_QUERY => ShippingQuery::class, + self::TYPE_PRE_CHECKOUT_QUERY => PreCheckoutQuery::class, ]; } @@ -56,17 +68,8 @@ protected function subEntities() */ public function getUpdateType() { - $types = [ - 'message', - 'edited_message', - 'channel_post', - 'edited_channel_post', - 'inline_query', - 'chosen_inline_result', - 'callback_query', - 'shipping_query', - 'pre_checkout_query', - ]; + $types = array_keys($this->subEntities()); + foreach ($types as $type) { if ($this->getProperty($type)) { return $type; @@ -90,6 +93,7 @@ public function getUpdateContent() // Instead of just getting the property as an array, // use the __call method to get the correct Entity object. $method = 'get' . str_replace('_', '', ucwords($update_type, '_')); + return $this->$method(); } diff --git a/src/Botan.php b/src/Extensions/Botan/Botan.php similarity index 84% rename from src/Botan.php rename to src/Extensions/Botan/Botan.php index 03cc7201f..bbb899a06 100644 --- a/src/Botan.php +++ b/src/Extensions/Botan/Botan.php @@ -8,12 +8,13 @@ * file that was distributed with this source code. */ -namespace Longman\TelegramBot; +namespace Longman\TelegramBot\Extensions\Botan; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; use Longman\TelegramBot\Entities\Update; use Longman\TelegramBot\Exception\TelegramException; +use Longman\TelegramBot\Logger; /** * Class Botan @@ -54,11 +55,18 @@ class Botan */ public static $command = ''; + /** + * Enabled + * + * @var bool + */ + protected static $enabled = false; + /** * Initialize Botan * * @param string $token - * @param array $options + * @param array $options * * @throws \Longman\TelegramBot\Exception\TelegramException */ @@ -74,7 +82,7 @@ public static function initializeBotan($token, array $options = []) $options = array_merge($options_default, $options); - if (!is_numeric($options['timeout'])) { + if (! is_numeric($options['timeout'])) { throw new TelegramException('Timeout must be a number!'); } @@ -102,7 +110,7 @@ public static function lock($command = '') * Track function * * @param \Longman\TelegramBot\Entities\Update $update - * @param string $command + * @param string $command * * @return bool|string * @throws \Longman\TelegramBot\Exception\TelegramException @@ -145,7 +153,7 @@ public static function track(Update $update, $command = '') if ($entity->getType() === 'bot_command' && $entity->getOffset() === 0) { if ($command === 'generic') { $command = 'Generic'; - } elseif ($command === 'genericmessage') { // This should not happen as it equals normal message but leaving it as a fail-safe + } else if ($command === 'genericmessage') { // This should not happen as it equals normal message but leaving it as a fail-safe $command = 'Generic Message'; } else { $command = '/' . $command; @@ -159,7 +167,7 @@ public static function track(Update $update, $command = '') } if (empty($event_name)) { - TelegramLog::error('Botan.io stats report failed, no suitable update object found!'); + Logger::error('Botan.io stats report failed, no suitable update object found!'); return false; } @@ -190,8 +198,8 @@ public static function track(Update $update, $command = '') $responseData = json_decode($result, true); - if (!$responseData || $responseData['status'] !== 'accepted') { - TelegramLog::debug('Botan.io stats report failed: %s', $result ?: 'empty response'); + if (! $responseData || $responseData['status'] !== 'accepted') { + Logger::debug('Botan.io stats report failed: %s', $result ?: 'empty response'); return false; } @@ -202,7 +210,7 @@ public static function track(Update $update, $command = '') /** * Url Shortener function * - * @param string $url + * @param string $url * @param integer $user_id * * @return string @@ -238,7 +246,7 @@ public static function shortenUrl($url, $user_id) } if (filter_var($result, FILTER_VALIDATE_URL) === false) { - TelegramLog::debug('Botan.io URL shortening failed for "%s": %s', $url, $result ?: 'empty response'); + Logger::debug('Botan.io URL shortening failed for "%s": %s', $url, $result ?: 'empty response'); return $url; } @@ -247,4 +255,25 @@ public static function shortenUrl($url, $user_id) return $result; } + + /** + * Return enabled status + * + * @return bool + */ + public static function isEnabled() + { + return self::$enabled; + } + + /** + * Set enabled status + * + * @param $enabled bool + * @return void + */ + public static function setEnabled($enabled) + { + self::$enabled = $enabled; + } } diff --git a/src/BotanDB.php b/src/Extensions/Botan/BotanDB.php similarity index 92% rename from src/BotanDB.php rename to src/Extensions/Botan/BotanDB.php index 6e0093044..20f17afa7 100644 --- a/src/BotanDB.php +++ b/src/Extensions/Botan/BotanDB.php @@ -8,9 +8,10 @@ * file that was distributed with this source code. */ -namespace Longman\TelegramBot; +namespace Longman\TelegramBot\Extensions\Botan; use Exception; +use Longman\TelegramBot\DB; use Longman\TelegramBot\Exception\TelegramException; /** @@ -23,7 +24,7 @@ class BotanDB extends DB */ public static function initializeBotanDb() { - if (!defined('TB_BOTAN_SHORTENER')) { + if (! defined('TB_BOTAN_SHORTENER')) { define('TB_BOTAN_SHORTENER', self::$table_prefix . 'botan_shortener'); } } @@ -39,7 +40,7 @@ public static function initializeBotanDb() */ public static function selectShortUrl($url, $user_id) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } @@ -75,7 +76,7 @@ public static function selectShortUrl($url, $user_id) */ public static function insertShortUrl($url, $user_id, $short_url) { - if (!self::isDbConnected()) { + if (! self::isDbConnected()) { return false; } diff --git a/src/Http/Client.php b/src/Http/Client.php new file mode 100644 index 000000000..76d4ea909 --- /dev/null +++ b/src/Http/Client.php @@ -0,0 +1,726 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Http; + +use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\Exception\RequestException; +use Longman\TelegramBot\DB; +use Longman\TelegramBot\Entities\File; +use Longman\TelegramBot\Exception\TelegramException; +use Longman\TelegramBot\Telegram; +use Longman\TelegramBot\Logger; + +/** + * Class Client + * + * @method static Response getUpdates(array $data) Use this method to receive incoming updates using long polling (wiki). An Array of Update + * objects is returned. + * @method static Response setWebhook(array $data) Use this method to specify a url and receive incoming updates via an outgoing webhook. + * Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url, containing a JSON-serialized Update. In case of an + * unsuccessful request, we will give up after a reasonable amount of attempts. Returns true. + * @method static Response deleteWebhook() Use this method to remove webhook integration if you decide to switch back to getUpdates. + * Returns True on success. Requires no parameters. + * @method static Response getWebhookInfo() Use this method to get current webhook status. Requires no parameters. On success, + * returns a WebhookInfo object. If the bot is using getUpdates, will return an object with the url field empty. + * @method static Response getMe() A simple method for testing your bot's auth token. Requires no parameters. Returns basic + * information about the bot in form of a User object. + * @method static Response forwardMessage(array $data) Use this method to forward messages of any kind. On success, the sent Message is + * returned. + * @method static Response sendPhoto(array $data) Use this method to send photos. On success, the sent Message is returned. + * @method static Response sendAudio(array $data) Use this method to send audio files, if you want Telegram clients to display them in the + * music player. Your audio must be in the .mp3 format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in + * size, this limit may be changed in the future. + * @method static Response sendDocument(array $data) Use this method to send general files. On success, the sent Message is returned. Bots can + * currently send files of any type of up to 50 MB in size, this limit may be changed in the future. + * @method static Response sendSticker(array $data) Use this method to send .webp stickers. On success, the sent Message is returned. + * @method static Response sendVideo(array $data) Use this method to send video files, Telegram clients support mp4 videos (other formats + * may be sent as Document). On success, the sent Message is returned. Bots can currently send video files of up to 50 MB in size, this limit may be + * changed in the future. + * @method static Response sendVoice(array $data) Use this method to send audio files, if you want Telegram clients to display the file as + * a playable voice message. For this to work, your audio must be in an .ogg file encoded with OPUS (other formats may be sent as Audio or Document). On + * success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. + * @method static Response sendVideoNote(array $data) Use this method to send video messages. On success, the sent Message is returned. + * @method static Response sendMediaGroup(array $data) Use this method to send a group of photos or videos as an album. On success, an array of + * the sent Messages is returned. + * @method static Response sendLocation(array $data) Use this method to send point on the map. On success, the sent Message is returned. + * @method static Response editMessageLiveLocation(array $data) Use this method to edit live location messages sent by the bot or via the bot (for inline + * bots). A location can be edited until its live_period expires or editing is explicitly disabled by a call to stopMessageLiveLocation. On success, if the + * edited message was sent by the bot, the edited Message is returned, otherwise True is returned. + * @method static Response stopMessageLiveLocation(array $data) Use this method to stop updating a live location message sent by the bot or via the bot + * (for inline bots) before live_period expires. On success, if the message was sent by the bot, the sent Message is returned, otherwise True is returned. + * @method static Response sendVenue(array $data) Use this method to send information about a venue. On success, the sent Message is + * returned. + * @method static Response sendContact(array $data) Use this method to send phone contacts. On success, the sent Message is returned. + * @method static Response sendChatAction(array $data) Use this method when you need to tell the user that something is happening on the bot's + * side. The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). Returns True on success. + * @method static Response getUserProfilePhotos(array $data) Use this method to get a list of profile pictures for a user. Returns a UserProfilePhotos + * object. + * @method static Response getFile(array $data) Use this method to get basic info about a file and prepare it for downloading. For the + * moment, bots can download files of up to 20MB in size. On success, a File object is returned. The file can then be downloaded via the link + * https://api.telegram.org/file/bot/, where is taken from the response. It is guaranteed that the link will be valid for at + * least 1 hour. When the link expires, a new one can be requested by calling getFile again. + * @method static Response kickChatMember(array $data) Use this method to kick a user from a group, a supergroup or a channel. In the case of + * supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first. The bot must be + * an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + * @method static Response unbanChatMember(array $data) Use this method to unban a previously kicked user in a supergroup or channel. The user + * will not return to the group or channel automatically, but will be able to join via link, etc. The bot must be an administrator for this to work. + * Returns True on success. + * @method static Response restrictChatMember(array $data) Use this method to restrict a user in a supergroup. The bot must be an administrator in + * the supergroup for this to work and must have the appropriate admin rights. Pass True for all boolean parameters to lift restrictions from a user. + * Returns True on success. + * @method static Response promoteChatMember(array $data) Use this method to promote or demote a user in a supergroup or a channel. The bot must be + * an administrator in the chat for this to work and must have the appropriate admin rights. Pass False for all boolean parameters to demote a user. + * Returns True on success. + * @method static Response exportChatInviteLink(array $data) Use this method to export an invite link to a supergroup or a channel. The bot must be an + * administrator in the chat for this to work and must have the appropriate admin rights. Returns exported invite link as String on success. + * @method static Response setChatPhoto(array $data) Use this method to set a new profile photo for the chat. Photos can't be changed for + * private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + * @method static Response deleteChatPhoto(array $data) Use this method to delete a chat photo. Photos can't be changed for private chats. The + * bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + * @method static Response setChatTitle(array $data) Use this method to change the title of a chat. Titles can't be changed for private chats. + * The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + * @method static Response setChatDescription(array $data) Use this method to change the description of a supergroup or a channel. The bot must be + * an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + * @method static Response pinChatMessage(array $data) Use this method to pin a message in a supergroup or a channel. The bot must be an + * administrator in the chat for this to work and must have the ‘can_pin_messages’ admin right in the supergroup or ‘can_edit_messages’ admin right in the + * channel. Returns True on success. + * @method static Response unpinChatMessage(array $data) Use this method to unpin a message in a supergroup or a channel. The bot must be an + * administrator in the chat for this to work and must have the ‘can_pin_messages’ admin right in the supergroup or ‘can_edit_messages’ admin right in the + * channel. Returns True on success. + * @method static Response leaveChat(array $data) Use this method for your bot to leave a group, supergroup or channel. Returns True on + * success. + * @method static Response getChat(array $data) Use this method to get up to date information about the chat (current name of the user + * for one-on-one conversations, current username of a user, group or channel, etc.). Returns a Chat object on success. + * @method static Response getChatAdministrators(array $data) Use this method to get a list of administrators in a chat. On success, returns an Array + * of ChatMember objects that contains information about all chat administrators except other bots. If the chat is a group or a supergroup and no + * administrators were appointed, only the creator will be returned. + * @method static Response getChatMembersCount(array $data) Use this method to get the number of members in a chat. Returns Int on success. + * @method static Response getChatMember(array $data) Use this method to get information about a member of a chat. Returns a ChatMember object + * on success. + * @method static Response setChatStickerSet(array $data) Use this method to set a new group sticker set for a supergroup. The bot must be an + * administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat + * requests to check if the bot can use this method. Returns True on success. + * @method static Response deleteChatStickerSet(array $data) Use this method to delete a group sticker set from a supergroup. The bot must be an + * administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat + * requests to check if the bot can use this method. Returns True on success. + * @method static Response answerCallbackQuery(array $data) Use this method to send answers to callback queries sent from inline keyboards. The + * answer will be displayed to the user as a notification at the top of the chat screen or as an alert. On success, True is returned. + * @method static Response answerInlineQuery(array $data) Use this method to send answers to an inline query. On success, True is returned. + * @method static Response editMessageText(array $data) Use this method to edit text and game messages sent by the bot or via the bot (for inline + * bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. + * @method static Response editMessageCaption(array $data) Use this method to edit captions of messages sent by the bot or via the bot (for inline + * bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. + * @method static Response editMessageReplyMarkup(array $data) Use this method to edit only the reply markup of messages sent by the bot or via the bot + * (for inline bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. + * @method static Response deleteMessage(array $data) Use this method to delete a message, including service messages, with certain + * limitations. Returns True on success. + * @method static Response getStickerSet(array $data) Use this method to get a sticker set. On success, a StickerSet object is returned. + * @method static Response uploadStickerFile(array $data) Use this method to upload a .png file with a sticker for later use in createNewStickerSet + * and addStickerToSet methods (can be used multiple times). Returns the uploaded File on success. + * @method static Response createNewStickerSet(array $data) Use this method to create new sticker set owned by a user. The bot will be able to edit + * the created sticker set. Returns True on success. + * @method static Response addStickerToSet(array $data) Use this method to add a new sticker to a set created by the bot. Returns True on + * success. + * @method static Response setStickerPositionInSet(array $data) Use this method to move a sticker in a set created by the bot to a specific position. + * Returns True on success. + * @method static Response deleteStickerFromSet(array $data) Use this method to delete a sticker from a set created by the bot. Returns True on + * success. + * @method static Response sendInvoice(array $data) Use this method to send invoices. On success, the sent Message is returned. + * @method static Response answerShippingQuery(array $data) If you sent an invoice requesting a shipping address and the parameter is_flexible was + * specified, the Bot API will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries. On success, True is + * returned. + * @method static Response answerPreCheckoutQuery(array $data) Once the user has confirmed their payment and shipping details, the Bot API sends the + * final confirmation in the form of an Update with the field pre_checkout_query. Use this method to respond to such pre-checkout queries. On success, True + * is returned. + */ +class Client +{ + /** + * Telegram object + * + * @var \Longman\TelegramBot\Telegram + */ + private static $telegram; + + /** + * URI of the Telegram API + * + * @var string + */ + private static $api_base_uri = 'https://api.telegram.org'; + + /** + * Guzzle Client object + * + * @var \GuzzleHttp\Client + */ + private static $client; + + /** + * Request limiter + * + * @var boolean + */ + private static $limiter_enabled; + + /** + * Request limiter's interval between checks + * + * @var float + */ + private static $limiter_interval; + + /** + * Available actions to send + * + * This is basically the list of all methods listed on the official API documentation. + * + * @link https://core.telegram.org/bots/api + * + * @var array + */ + private static $actions = [ + 'getUpdates', + 'setWebhook', + 'deleteWebhook', + 'getWebhookInfo', + 'getMe', + 'sendMessage', + 'forwardMessage', + 'sendPhoto', + 'sendAudio', + 'sendDocument', + 'sendSticker', + 'sendVideo', + 'sendVoice', + 'sendVideoNote', + 'sendMediaGroup', + 'sendLocation', + 'editMessageLiveLocation', + 'stopMessageLiveLocation', + 'sendVenue', + 'sendContact', + 'sendChatAction', + 'getUserProfilePhotos', + 'getFile', + 'kickChatMember', + 'unbanChatMember', + 'restrictChatMember', + 'promoteChatMember', + 'exportChatInviteLink', + 'setChatPhoto', + 'deleteChatPhoto', + 'setChatTitle', + 'setChatDescription', + 'pinChatMessage', + 'unpinChatMessage', + 'leaveChat', + 'getChat', + 'getChatAdministrators', + 'getChatMembersCount', + 'getChatMember', + 'setChatStickerSet', + 'deleteChatStickerSet', + 'answerCallbackQuery', + 'answerInlineQuery', + 'editMessageText', + 'editMessageCaption', + 'editMessageReplyMarkup', + 'deleteMessage', + 'getStickerSet', + 'uploadStickerFile', + 'createNewStickerSet', + 'addStickerToSet', + 'setStickerPositionInSet', + 'deleteStickerFromSet', + 'sendInvoice', + 'answerShippingQuery', + 'answerPreCheckoutQuery', + ]; + + /** + * Some methods need a dummy param due to certain cURL issues. + * + * @see Client::addDummyParamIfNecessary() + * + * @var array + */ + private static $actions_need_dummy_param = [ + 'deleteWebhook', + 'getWebhookInfo', + 'getMe', + ]; + + /** + * Initialize + * + * @param \Longman\TelegramBot\Telegram $telegram + * + * @throws TelegramException + */ + public static function initialize(Telegram $telegram) + { + if (! ($telegram instanceof Telegram)) { + throw new TelegramException('Invalid Telegram pointer!'); + } + + self::$telegram = $telegram; + self::setClient(new GuzzleClient(['base_uri' => self::$api_base_uri])); + } + + /** + * Set a custom Guzzle HTTP Client object + * + * @param Client $client + * + * @throws TelegramException + */ + public static function setClient(GuzzleClient $client) + { + if (! ($client instanceof GuzzleClient)) { + throw new TelegramException('Invalid GuzzleHttp\Client pointer!'); + } + + self::$client = $client; + } + + /** + * Generate general fake server response + * + * @param array $data Data to add to fake response + * + * @return array Fake response data + */ + public static function generateGeneralFakeServerResponse(array $data = []) + { + // PARAM BINDED IN PHPUNIT TEST FOR TestServerResponse.php + // Maybe this is not the best possible implementation + + // No value set in $data ie testing setWebhook + // Provided $data['chat_id'] ie testing sendMessage + + $fake_response = ['ok' => true]; // :) + + if ($data === []) { + $fake_response['result'] = true; + } + + //some data to let iniatilize the class method SendMessage + if (isset($data['chat_id'])) { + $data['message_id'] = '1234'; + $data['date'] = '1441378360'; + $data['from'] = [ + 'id' => 123456789, + 'first_name' => 'botname', + 'username' => 'namebot', + ]; + $data['chat'] = ['id' => $data['chat_id']]; + + $fake_response['result'] = $data; + } + + return $fake_response; + } + + /** + * Properly set up the request params + * + * If any item of the array is a resource, reformat it to a multipart request. + * Else, just return the passed data as form params. + * + * @param array $data + * + * @return array + */ + private static function setUpRequestParams(array $data) + { + $has_resource = false; + $multipart = []; + + // Convert any nested arrays into JSON strings. + array_walk($data, function (&$item) { + is_array($item) && $item = json_encode($item); + }); + + //Reformat data array in multipart way if it contains a resource + foreach ($data as $key => $item) { + $has_resource |= (is_resource($item) || $item instanceof \GuzzleHttp\Psr7\Stream); + $multipart[] = ['name' => $key, 'contents' => $item]; + } + if ($has_resource) { + return ['multipart' => $multipart]; + } + + return ['form_params' => $data]; + } + + /** + * Execute HTTP Request + * + * @param string $action Action to execute + * @param array $data Data to attach to the execution + * + * @return string Result of the HTTP Request + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public static function execute($action, array $data = []) + { + //Fix so that the keyboard markup is a string, not an object + if (isset($data['reply_markup'])) { + $data['reply_markup'] = json_encode($data['reply_markup']); + } + + $result = null; + $request_params = self::setUpRequestParams($data); + $request_params['debug'] = Logger::getDebugLogTempStream(); + + try { + $response = self::$client->post( + '/bot' . self::$telegram->getApiKey() . '/' . $action, + $request_params + ); + $result = (string) $response->getBody(); + + // Logging getUpdates Update + if ($action === 'getUpdates') { + Logger::update($result); + } + } catch (RequestException $e) { + $result = ($e->getResponse()) ? (string) $e->getResponse()->getBody() : ''; + } finally { + // Logging verbose debug output + Logger::endDebugLogTempStream('Verbose HTTP Request output:' . PHP_EOL . '%s' . PHP_EOL); + } + + return $result; + } + + /** + * Download file + * + * @param \Longman\TelegramBot\Entities\File $file + * + * @return boolean + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public static function downloadFile(File $file) + { + if (empty($download_path = self::$telegram->getDownloadPath())) { + throw new TelegramException('Download path not set!'); + } + + $tg_file_path = $file->getFilePath(); + $file_path = $download_path . '/' . $tg_file_path; + + $file_dir = dirname($file_path); + //For safety reasons, first try to create the directory, then check that it exists. + //This is in case some other process has created the folder in the meantime. + if (! @mkdir($file_dir, 0755, true) && ! is_dir($file_dir)) { + throw new TelegramException('Directory ' . $file_dir . ' can\'t be created'); + } + + $debug_handle = Logger::getDebugLogTempStream(); + + try { + self::$client->get( + '/file/bot' . self::$telegram->getApiKey() . '/' . $tg_file_path, + ['debug' => $debug_handle, 'sink' => $file_path] + ); + + return filesize($file_path) > 0; + } catch (RequestException $e) { + return ($e->getResponse()) ? (string) $e->getResponse()->getBody() : ''; + } finally { + //Logging verbose debug output + Logger::endDebugLogTempStream('Verbose HTTP File Download Request output:' . PHP_EOL . '%s' . PHP_EOL); + } + } + + /** + * Encode file + * + * @param string $file + * + * @return resource + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public static function encodeFile($file) + { + $fp = fopen($file, 'rb'); + if ($fp === false) { + throw new TelegramException('Cannot open "' . $file . '" for reading'); + } + + return $fp; + } + + /** + * Send command + * + * @todo Fake response doesn't need json encoding? + * @todo Write debug entry on failure + * + * @param string $action + * @param array $data + * + * @return \Longman\TelegramBot\Http\Response + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public static function send($action, array $data = []) + { + self::ensureValidAction($action); + self::addDummyParamIfNecessary($action, $data); + + $bot_username = self::$telegram->getBotUsername(); + + // @TODO: Refactor testing and remove this + if (defined('PHPUNIT_TESTSUITE')) { + $fake_response = self::generateGeneralFakeServerResponse($data); + + return new Response($fake_response, $bot_username); + } + + self::ensureNonEmptyData($data); + + self::limitTelegramRequests($action, $data); + + $result = self::execute($action, $data); + + $response = json_decode($result, true); + + if (null === $response) { + throw new TelegramException('Telegram returned an invalid response! Please review your bot name and API key.'); + } + + return new Response($response, $bot_username); + } + + /** + * Add a dummy parameter if the passed action requires it. + * + * If a method doesn't require parameters, we need to add a dummy one anyway, + * because of some cURL version failed POST request without parameters. + * + * @link https://github.com/php-telegram-bot/core/pull/228 + * + * @todo Would be nice to find a better solution for this! + * + * @param string $action + * @param array $data + */ + protected static function addDummyParamIfNecessary($action, array &$data) + { + if (in_array($action, self::$actions_need_dummy_param, true)) { + // Can be anything, using a single letter to minimise request size. + $data = ['d']; + } + } + + /** + * Make sure the data isn't empty, else throw an exception + * + * @param array $data + * + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + private static function ensureNonEmptyData(array $data) + { + if (count($data) === 0) { + throw new TelegramException('Data is empty!'); + } + } + + /** + * Make sure the action is valid, else throw an exception + * + * @param string $action + * + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + private static function ensureValidAction($action) + { + if (! in_array($action, self::$actions, true)) { + throw new TelegramException('The action "' . $action . '" doesn\'t exist!'); + } + } + + /** + * Use this method to send text messages. On success, the sent Message is returned + * + * @link https://core.telegram.org/bots/api#sendmessage + * + * @param array $data + * + * @return \Longman\TelegramBot\Http\Response + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public static function sendMessage(array $data) + { + $text = $data['text']; + + do { + // Chop off and send the first message + $data['text'] = mb_substr($text, 0, 4096); + $response = self::send('sendMessage', $data); + + // Prepare the next message + $text = mb_substr($text, 4096); + } while (mb_strlen($text, 'UTF-8') > 0); + + return $response; + } + + /** + * Any statically called method should be relayed to the `send` method. + * + * @param string $action + * @param array $data + * + * @return \Longman\TelegramBot\Http\Response + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public static function __callStatic($action, array $data) + { + // Make sure to add the action being called as the first parameter to be passed. + array_unshift($data, $action); + + // @todo Use splat operator for unpacking when we move to PHP 5.6+ + return call_user_func_array('static::send', $data); + } + + /** + * Send message to all active chats + * + * @param string $callback_function + * @param array $data + * @param array $select_chats_params + * + * @return array + * @throws TelegramException + */ + public static function sendToActiveChats( + $callback_function, + array $data, + array $select_chats_params + ) { + if (! method_exists(Client::class, $callback_function)) { + throw new TelegramException('Method "' . $callback_function . '" not found in class Request.'); + } + + $chats = DB::selectChats($select_chats_params); + + $results = []; + if (is_array($chats)) { + foreach ($chats as $row) { + $data['chat_id'] = $row['chat_id']; + $results[] = call_user_func(Client::class . '::' . $callback_function, $data); + } + } + + return $results; + } + + /** + * Enable request limiter + * + * @param boolean $enable + * @param array $options + * + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public static function setLimiter($enable = true, array $options = []) + { + if (DB::isDbConnected()) { + $options_default = [ + 'interval' => 1, + ]; + + $options = array_merge($options_default, $options); + + if (! is_numeric($options['interval']) || $options['interval'] <= 0) { + throw new TelegramException('Interval must be a number and must be greater than zero!'); + } + + self::$limiter_interval = $options['interval']; + self::$limiter_enabled = $enable; + } + } + + /** + * This functions delays API requests to prevent reaching Telegram API limits + * Can be disabled while in execution by 'Request::setLimiter(false)' + * + * @link https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this + * + * @param string $action + * @param array $data + * + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + private static function limitTelegramRequests($action, array $data = []) + { + if (self::$limiter_enabled) { + $limited_methods = [ + 'sendMessage', + 'forwardMessage', + 'sendPhoto', + 'sendAudio', + 'sendDocument', + 'sendSticker', + 'sendVideo', + 'sendVoice', + 'sendVideoNote', + 'sendMediaGroup', + 'sendLocation', + 'editMessageLiveLocation', + 'stopMessageLiveLocation', + 'sendVenue', + 'sendContact', + 'sendInvoice', + 'editMessageText', + 'editMessageCaption', + 'editMessageReplyMarkup', + 'setChatTitle', + 'setChatDescription', + 'setChatStickerSet', + 'deleteChatStickerSet', + ]; + + $chat_id = isset($data['chat_id']) ? $data['chat_id'] : null; + $inline_message_id = isset($data['inline_message_id']) ? $data['inline_message_id'] : null; + + if (($chat_id || $inline_message_id) && in_array($action, $limited_methods)) { + $timeout = 60; + + while (true) { + if ($timeout <= 0) { + throw new TelegramException('Timed out while waiting for a request spot!'); + } + + $requests = DB::getTelegramRequestCount($chat_id, $inline_message_id); + + $chat_per_second = ($requests['LIMIT_PER_SEC'] == 0); // No more than one message per second inside a particular chat + $global_per_second = ($requests['LIMIT_PER_SEC_ALL'] < 30); // No more than 30 messages per second to different chats + $groups_per_minute = (((is_numeric($chat_id) && $chat_id > 0) || ! is_null($inline_message_id)) || ((! is_numeric($chat_id) || $chat_id < 0) && $requests['LIMIT_PER_MINUTE'] < 20)); // No more than 20 messages per minute in groups and channels + + if ($chat_per_second && $global_per_second && $groups_per_minute) { + break; + } + + $timeout--; + usleep(self::$limiter_interval * 1000000); + } + + DB::insertTelegramRequest($action, $data); + } + } + } +} diff --git a/src/Http/Kernel.php b/src/Http/Kernel.php new file mode 100644 index 000000000..3e57579d1 --- /dev/null +++ b/src/Http/Kernel.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Http; + +use Longman\TelegramBot\Entities\Update; +use Longman\TelegramBot\Telegram; + +class Kernel +{ + /** + * The application implementation. + * + * @var \Longman\TelegramBot\Telegram + */ + protected $app; + + /** + * Create a new HTTP kernel instance. + * + * @param \Longman\TelegramBot\Telegram $app + * + * @return void + */ + public function __construct(Telegram $app) + { + $this->app = $app; + } + + /** + * Handle an incoming HTTP request. + * + * @param \Longman\TelegramBot\Http\Request $request + * + * @return \Longman\TelegramBot\Http\Response + * + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public function handle(Request $request) + { + $params = $request->json(); + + $update = new Update($params->all(), $this->app->getBotUsername()); + + return $this->app->processUpdate($update); + } +} diff --git a/src/Http/Request.php b/src/Http/Request.php new file mode 100644 index 000000000..823063095 --- /dev/null +++ b/src/Http/Request.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Http; + +use Illuminate\Http\Request as LaravelRequest; + +class Request extends LaravelRequest +{ + + +} diff --git a/src/Http/Response.php b/src/Http/Response.php new file mode 100644 index 000000000..927a81b3f --- /dev/null +++ b/src/Http/Response.php @@ -0,0 +1,217 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Http; + +use Longman\TelegramBot\Entities\Chat; +use Longman\TelegramBot\Entities\ChatMember; +use Longman\TelegramBot\Entities\File; +use Longman\TelegramBot\Entities\Message; +use Longman\TelegramBot\Entities\Update; +use Longman\TelegramBot\Entities\User; +use Longman\TelegramBot\Entities\UserProfilePhotos; +use Longman\TelegramBot\Entities\WebhookInfo; + +/** + * Class Response + * + * @link https://core.telegram.org/bots/api#making-requests + * + * @todo method ResponseParameters getParameters() Field which can help to automatically handle the error + */ +class Response +{ + /** @var bool */ + protected $ok = false; + + /** @var string */ + protected $description; + + /** @var array */ + protected $result; + + /** @var int */ + protected $error_code; + + /** @var array */ + protected $parameters; + + /** @var array */ + protected $raw_data; + + /** @var string */ + protected $bot_username; + + /** + * Response constructor. + * + * @param array $data + * @param string $bot_username + * + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + public function __construct(array $data, $bot_username = '') + { + $this->raw_data = $data; + + $this->ok = $data['ok']; + + if (isset($data['description'])) { + $this->description = $data['description']; + } + + if (isset($data['error_code'])) { + $this->error_code = $data['error_code']; + } + + if (isset($data['parameters'])) { + $this->parameters = $data['parameters']; + } + + $this->bot_username = $bot_username; + + $result = isset($data['result']) ? $data['result'] : null; + if ($this->ok && is_array($result)) { + if ($this->isAssoc($result)) { + $this->result = $this->createResultObject($result, $bot_username); + } else { + $this->result = $this->createResultObjects($result, $bot_username); + } + } + } + + /** + * Check if array is associative + * + * @link https://stackoverflow.com/a/4254008 + * + * @param array $array + * + * @return bool + */ + protected function isAssoc(array $array) + { + return count(array_filter(array_keys($array), 'is_string')) > 0; + } + + /** + * If response is ok + * + * @return bool + */ + public function isOk() + { + return $this->ok; + } + + /** + * Return result + * + * @return array + */ + public function getResult() + { + return ! empty($this->result) ? $this->result : []; + } + + /** + * Return error code + * + * @return int + */ + public function getErrorCode() + { + return ! empty($this->error_code) ? $this->error_code : null; + } + + /** + * Return human-readable description of the result / unsuccessful request + * + * @return string + */ + public function getDescription() + { + return ! empty($this->description) ? $this->description : null; + } + + /** + * Get error + * + * @see https://secure.php.net/manual/en/function.print-r.php + * + * @return string + */ + public function getError() + { + $error = sprintf('Error N: %s, Description: %s', $this->getErrorCode(), $this->getDescription()); + + return $error; + } + + /** + * Create and return the object of the received result + * + * @param array $result + * @param string $bot_username + * + * @return \Longman\TelegramBot\Entities\Chat|\Longman\TelegramBot\Entities\ChatMember|\Longman\TelegramBot\Entities\File|\Longman\TelegramBot\Entities\Message|\Longman\TelegramBot\Entities\User|\Longman\TelegramBot\Entities\UserProfilePhotos|\Longman\TelegramBot\Entities\WebhookInfo + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + protected function createResultObject($result, $bot_username) + { + $result_object_types = [ + 'total_count' => UserProfilePhotos::class, // Response from getUserProfilePhotos + 'file_id' => File::class, // Response from getFile + 'title' => Chat::class, // Response from getChat + 'username' => User::class, // Response from getMe + 'user' => ChatMember::class, // Response from getChatMember + 'url' => WebhookInfo::class, // Response from getWebhookInfo + ]; + foreach ($result_object_types as $type => $object_class) { + if (isset($result[$type])) { + return new $object_class($result, $bot_username); + } + } + + // Response from sendMessage + return new Message($result, $bot_username); + } + + /** + * Create and return the objects array of the received result + * + * @param array $result + * @param string $bot_username + * + * @return null|\Longman\TelegramBot\Entities\ChatMember[]|\Longman\TelegramBot\Entities\Update[] + * @throws \Longman\TelegramBot\Exception\TelegramException + */ + protected function createResultObjects($result, $bot_username) + { + $results = []; + if (isset($result[0]['user'])) { + // Response from getChatAdministrators + foreach ($result as $user) { + // We don't need to save the raw_data of the response object! + $user['raw_data'] = null; + + $results[] = new ChatMember($user); + } + } else { + // Get Update + foreach ($result as $update) { + // We don't need to save the raw_data of the response object! + $update['raw_data'] = null; + + $results[] = new Update($update, $bot_username); + } + } + + return $results; + } +} diff --git a/src/TelegramLog.php b/src/Logger.php similarity index 93% rename from src/TelegramLog.php rename to src/Logger.php index 57880711b..fe3830332 100644 --- a/src/TelegramLog.php +++ b/src/Logger.php @@ -13,9 +13,9 @@ use Longman\TelegramBot\Exception\TelegramLogException; use Monolog\Formatter\LineFormatter; use Monolog\Handler\StreamHandler; -use Monolog\Logger; +use Monolog\Logger as MonologLogger; -class TelegramLog +class Logger { /** * Monolog instance @@ -66,7 +66,7 @@ class TelegramLog * * @return \Monolog\Logger */ - public static function initialize(Logger $external_monolog = null) + public static function initialize(MonologLogger $external_monolog = null) { if (self::$monolog === null) { if ($external_monolog !== null) { @@ -81,7 +81,7 @@ public static function initialize(Logger $external_monolog = null) } } } else { - self::$monolog = new Logger('bot_log'); + self::$monolog = new MonologLogger('bot_log'); } } @@ -107,7 +107,7 @@ public static function initErrorLog($path) self::$error_log_path = $path; return self::$monolog->pushHandler( - (new StreamHandler(self::$error_log_path, Logger::ERROR)) + (new StreamHandler(self::$error_log_path, MonologLogger::ERROR)) ->setFormatter(new LineFormatter(null, null, true)) ); } @@ -131,7 +131,7 @@ public static function initDebugLog($path) self::$debug_log_path = $path; return self::$monolog->pushHandler( - (new StreamHandler(self::$debug_log_path, Logger::DEBUG)) + (new StreamHandler(self::$debug_log_path, MonologLogger::DEBUG)) ->setFormatter(new LineFormatter(null, null, true)) ); } @@ -186,10 +186,10 @@ public static function initUpdateLog($path) self::$update_log_path = $path; if (self::$monolog_update === null) { - self::$monolog_update = new Logger('bot_update_log'); + self::$monolog_update = new MonologLogger('bot_update_log'); self::$monolog_update->pushHandler( - (new StreamHandler(self::$update_log_path, Logger::INFO)) + (new StreamHandler(self::$update_log_path, MonologLogger::INFO)) ->setFormatter(new LineFormatter('%message%' . PHP_EOL)) ); } diff --git a/src/Request.php b/src/Request.php deleted file mode 100644 index a6ba4a530..000000000 --- a/src/Request.php +++ /dev/null @@ -1,703 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Longman\TelegramBot; - -use GuzzleHttp\Client; -use GuzzleHttp\Exception\RequestException; -use Longman\TelegramBot\Entities\File; -use Longman\TelegramBot\Entities\ServerResponse; -use Longman\TelegramBot\Exception\TelegramException; - -/** - * Class Request - * - * @method static ServerResponse getUpdates(array $data) Use this method to receive incoming updates using long polling (wiki). An Array of Update objects is returned. - * @method static ServerResponse setWebhook(array $data) Use this method to specify a url and receive incoming updates via an outgoing webhook. Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url, containing a JSON-serialized Update. In case of an unsuccessful request, we will give up after a reasonable amount of attempts. Returns true. - * @method static ServerResponse deleteWebhook() Use this method to remove webhook integration if you decide to switch back to getUpdates. Returns True on success. Requires no parameters. - * @method static ServerResponse getWebhookInfo() Use this method to get current webhook status. Requires no parameters. On success, returns a WebhookInfo object. If the bot is using getUpdates, will return an object with the url field empty. - * @method static ServerResponse getMe() A simple method for testing your bot's auth token. Requires no parameters. Returns basic information about the bot in form of a User object. - * @method static ServerResponse forwardMessage(array $data) Use this method to forward messages of any kind. On success, the sent Message is returned. - * @method static ServerResponse sendPhoto(array $data) Use this method to send photos. On success, the sent Message is returned. - * @method static ServerResponse sendAudio(array $data) Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .mp3 format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, this limit may be changed in the future. - * @method static ServerResponse sendDocument(array $data) Use this method to send general files. On success, the sent Message is returned. Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future. - * @method static ServerResponse sendSticker(array $data) Use this method to send .webp stickers. On success, the sent Message is returned. - * @method static ServerResponse sendVideo(array $data) Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). On success, the sent Message is returned. Bots can currently send video files of up to 50 MB in size, this limit may be changed in the future. - * @method static ServerResponse sendVoice(array $data) Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .ogg file encoded with OPUS (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. - * @method static ServerResponse sendVideoNote(array $data) Use this method to send video messages. On success, the sent Message is returned. - * @method static ServerResponse sendMediaGroup(array $data) Use this method to send a group of photos or videos as an album. On success, an array of the sent Messages is returned. - * @method static ServerResponse sendLocation(array $data) Use this method to send point on the map. On success, the sent Message is returned. - * @method static ServerResponse editMessageLiveLocation(array $data) Use this method to edit live location messages sent by the bot or via the bot (for inline bots). A location can be edited until its live_period expires or editing is explicitly disabled by a call to stopMessageLiveLocation. On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned. - * @method static ServerResponse stopMessageLiveLocation(array $data) Use this method to stop updating a live location message sent by the bot or via the bot (for inline bots) before live_period expires. On success, if the message was sent by the bot, the sent Message is returned, otherwise True is returned. - * @method static ServerResponse sendVenue(array $data) Use this method to send information about a venue. On success, the sent Message is returned. - * @method static ServerResponse sendContact(array $data) Use this method to send phone contacts. On success, the sent Message is returned. - * @method static ServerResponse sendChatAction(array $data) Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). Returns True on success. - * @method static ServerResponse getUserProfilePhotos(array $data) Use this method to get a list of profile pictures for a user. Returns a UserProfilePhotos object. - * @method static ServerResponse getFile(array $data) Use this method to get basic info about a file and prepare it for downloading. For the moment, bots can download files of up to 20MB in size. On success, a File object is returned. The file can then be downloaded via the link https://api.telegram.org/file/bot/, where is taken from the response. It is guaranteed that the link will be valid for at least 1 hour. When the link expires, a new one can be requested by calling getFile again. - * @method static ServerResponse kickChatMember(array $data) Use this method to kick a user from a group, a supergroup or a channel. In the case of supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. - * @method static ServerResponse unbanChatMember(array $data) Use this method to unban a previously kicked user in a supergroup or channel. The user will not return to the group or channel automatically, but will be able to join via link, etc. The bot must be an administrator for this to work. Returns True on success. - * @method static ServerResponse restrictChatMember(array $data) Use this method to restrict a user in a supergroup. The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights. Pass True for all boolean parameters to lift restrictions from a user. Returns True on success. - * @method static ServerResponse promoteChatMember(array $data) Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Pass False for all boolean parameters to demote a user. Returns True on success. - * @method static ServerResponse exportChatInviteLink(array $data) Use this method to export an invite link to a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns exported invite link as String on success. - * @method static ServerResponse setChatPhoto(array $data) Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. - * @method static ServerResponse deleteChatPhoto(array $data) Use this method to delete a chat photo. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. - * @method static ServerResponse setChatTitle(array $data) Use this method to change the title of a chat. Titles can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. - * @method static ServerResponse setChatDescription(array $data) Use this method to change the description of a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. - * @method static ServerResponse pinChatMessage(array $data) Use this method to pin a message in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the ‘can_pin_messages’ admin right in the supergroup or ‘can_edit_messages’ admin right in the channel. Returns True on success. - * @method static ServerResponse unpinChatMessage(array $data) Use this method to unpin a message in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the ‘can_pin_messages’ admin right in the supergroup or ‘can_edit_messages’ admin right in the channel. Returns True on success. - * @method static ServerResponse leaveChat(array $data) Use this method for your bot to leave a group, supergroup or channel. Returns True on success. - * @method static ServerResponse getChat(array $data) Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). Returns a Chat object on success. - * @method static ServerResponse getChatAdministrators(array $data) Use this method to get a list of administrators in a chat. On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned. - * @method static ServerResponse getChatMembersCount(array $data) Use this method to get the number of members in a chat. Returns Int on success. - * @method static ServerResponse getChatMember(array $data) Use this method to get information about a member of a chat. Returns a ChatMember object on success. - * @method static ServerResponse setChatStickerSet(array $data) Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. - * @method static ServerResponse deleteChatStickerSet(array $data) Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. - * @method static ServerResponse answerCallbackQuery(array $data) Use this method to send answers to callback queries sent from inline keyboards. The answer will be displayed to the user as a notification at the top of the chat screen or as an alert. On success, True is returned. - * @method static ServerResponse answerInlineQuery(array $data) Use this method to send answers to an inline query. On success, True is returned. - * @method static ServerResponse editMessageText(array $data) Use this method to edit text and game messages sent by the bot or via the bot (for inline bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. - * @method static ServerResponse editMessageCaption(array $data) Use this method to edit captions of messages sent by the bot or via the bot (for inline bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. - * @method static ServerResponse editMessageReplyMarkup(array $data) Use this method to edit only the reply markup of messages sent by the bot or via the bot (for inline bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. - * @method static ServerResponse deleteMessage(array $data) Use this method to delete a message, including service messages, with certain limitations. Returns True on success. - * @method static ServerResponse getStickerSet(array $data) Use this method to get a sticker set. On success, a StickerSet object is returned. - * @method static ServerResponse uploadStickerFile(array $data) Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods (can be used multiple times). Returns the uploaded File on success. - * @method static ServerResponse createNewStickerSet(array $data) Use this method to create new sticker set owned by a user. The bot will be able to edit the created sticker set. Returns True on success. - * @method static ServerResponse addStickerToSet(array $data) Use this method to add a new sticker to a set created by the bot. Returns True on success. - * @method static ServerResponse setStickerPositionInSet(array $data) Use this method to move a sticker in a set created by the bot to a specific position. Returns True on success. - * @method static ServerResponse deleteStickerFromSet(array $data) Use this method to delete a sticker from a set created by the bot. Returns True on success. - * @method static ServerResponse sendInvoice(array $data) Use this method to send invoices. On success, the sent Message is returned. - * @method static ServerResponse answerShippingQuery(array $data) If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API will send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries. On success, True is returned. - * @method static ServerResponse answerPreCheckoutQuery(array $data) Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the field pre_checkout_query. Use this method to respond to such pre-checkout queries. On success, True is returned. - */ -class Request -{ - /** - * Telegram object - * - * @var \Longman\TelegramBot\Telegram - */ - private static $telegram; - - /** - * URI of the Telegram API - * - * @var string - */ - private static $api_base_uri = 'https://api.telegram.org'; - - /** - * Guzzle Client object - * - * @var \GuzzleHttp\Client - */ - private static $client; - - /** - * Input value of the request - * - * @var string - */ - private static $input; - - /** - * Request limiter - * - * @var boolean - */ - private static $limiter_enabled; - - /** - * Request limiter's interval between checks - * - * @var float - */ - private static $limiter_interval; - - /** - * Available actions to send - * - * This is basically the list of all methods listed on the official API documentation. - * - * @link https://core.telegram.org/bots/api - * - * @var array - */ - private static $actions = [ - 'getUpdates', - 'setWebhook', - 'deleteWebhook', - 'getWebhookInfo', - 'getMe', - 'sendMessage', - 'forwardMessage', - 'sendPhoto', - 'sendAudio', - 'sendDocument', - 'sendSticker', - 'sendVideo', - 'sendVoice', - 'sendVideoNote', - 'sendMediaGroup', - 'sendLocation', - 'editMessageLiveLocation', - 'stopMessageLiveLocation', - 'sendVenue', - 'sendContact', - 'sendChatAction', - 'getUserProfilePhotos', - 'getFile', - 'kickChatMember', - 'unbanChatMember', - 'restrictChatMember', - 'promoteChatMember', - 'exportChatInviteLink', - 'setChatPhoto', - 'deleteChatPhoto', - 'setChatTitle', - 'setChatDescription', - 'pinChatMessage', - 'unpinChatMessage', - 'leaveChat', - 'getChat', - 'getChatAdministrators', - 'getChatMembersCount', - 'getChatMember', - 'setChatStickerSet', - 'deleteChatStickerSet', - 'answerCallbackQuery', - 'answerInlineQuery', - 'editMessageText', - 'editMessageCaption', - 'editMessageReplyMarkup', - 'deleteMessage', - 'getStickerSet', - 'uploadStickerFile', - 'createNewStickerSet', - 'addStickerToSet', - 'setStickerPositionInSet', - 'deleteStickerFromSet', - 'sendInvoice', - 'answerShippingQuery', - 'answerPreCheckoutQuery', - ]; - - /** - * Some methods need a dummy param due to certain cURL issues. - * - * @see Request::addDummyParamIfNecessary() - * - * @var array - */ - private static $actions_need_dummy_param = [ - 'deleteWebhook', - 'getWebhookInfo', - 'getMe', - ]; - - /** - * Initialize - * - * @param \Longman\TelegramBot\Telegram $telegram - * - * @throws TelegramException - */ - public static function initialize(Telegram $telegram) - { - if (!($telegram instanceof Telegram)) { - throw new TelegramException('Invalid Telegram pointer!'); - } - - self::$telegram = $telegram; - self::setClient(new Client(['base_uri' => self::$api_base_uri])); - } - - /** - * Set a custom Guzzle HTTP Client object - * - * @param Client $client - * - * @throws TelegramException - */ - public static function setClient(Client $client) - { - if (!($client instanceof Client)) { - throw new TelegramException('Invalid GuzzleHttp\Client pointer!'); - } - - self::$client = $client; - } - - /** - * Set input from custom input or stdin and return it - * - * @return string - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function getInput() - { - // First check if a custom input has been set, else get the PHP input. - if (!($input = self::$telegram->getCustomInput())) { - $input = file_get_contents('php://input'); - } - - // Make sure we have a string to work with. - if (!is_string($input)) { - throw new TelegramException('Input must be a string!'); - } - - self::$input = $input; - - TelegramLog::update(self::$input); - - return self::$input; - } - - /** - * Generate general fake server response - * - * @param array $data Data to add to fake response - * - * @return array Fake response data - */ - public static function generateGeneralFakeServerResponse(array $data = []) - { - //PARAM BINDED IN PHPUNIT TEST FOR TestServerResponse.php - //Maybe this is not the best possible implementation - - //No value set in $data ie testing setWebhook - //Provided $data['chat_id'] ie testing sendMessage - - $fake_response = ['ok' => true]; // :) - - if ($data === []) { - $fake_response['result'] = true; - } - - //some data to let iniatilize the class method SendMessage - if (isset($data['chat_id'])) { - $data['message_id'] = '1234'; - $data['date'] = '1441378360'; - $data['from'] = [ - 'id' => 123456789, - 'first_name' => 'botname', - 'username' => 'namebot', - ]; - $data['chat'] = ['id' => $data['chat_id']]; - - $fake_response['result'] = $data; - } - - return $fake_response; - } - - /** - * Properly set up the request params - * - * If any item of the array is a resource, reformat it to a multipart request. - * Else, just return the passed data as form params. - * - * @param array $data - * - * @return array - */ - private static function setUpRequestParams(array $data) - { - $has_resource = false; - $multipart = []; - - // Convert any nested arrays into JSON strings. - array_walk($data, function (&$item) { - is_array($item) && $item = json_encode($item); - }); - - //Reformat data array in multipart way if it contains a resource - foreach ($data as $key => $item) { - $has_resource |= (is_resource($item) || $item instanceof \GuzzleHttp\Psr7\Stream); - $multipart[] = ['name' => $key, 'contents' => $item]; - } - if ($has_resource) { - return ['multipart' => $multipart]; - } - - return ['form_params' => $data]; - } - - /** - * Execute HTTP Request - * - * @param string $action Action to execute - * @param array $data Data to attach to the execution - * - * @return string Result of the HTTP Request - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function execute($action, array $data = []) - { - //Fix so that the keyboard markup is a string, not an object - if (isset($data['reply_markup'])) { - $data['reply_markup'] = json_encode($data['reply_markup']); - } - - $result = null; - $request_params = self::setUpRequestParams($data); - $request_params['debug'] = TelegramLog::getDebugLogTempStream(); - - try { - $response = self::$client->post( - '/bot' . self::$telegram->getApiKey() . '/' . $action, - $request_params - ); - $result = (string) $response->getBody(); - - //Logging getUpdates Update - if ($action === 'getUpdates') { - TelegramLog::update($result); - } - } catch (RequestException $e) { - $result = ($e->getResponse()) ? (string) $e->getResponse()->getBody() : ''; - } finally { - //Logging verbose debug output - TelegramLog::endDebugLogTempStream('Verbose HTTP Request output:' . PHP_EOL . '%s' . PHP_EOL); - } - - return $result; - } - - /** - * Download file - * - * @param \Longman\TelegramBot\Entities\File $file - * - * @return boolean - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function downloadFile(File $file) - { - if (empty($download_path = self::$telegram->getDownloadPath())) { - throw new TelegramException('Download path not set!'); - } - - $tg_file_path = $file->getFilePath(); - $file_path = $download_path . '/' . $tg_file_path; - - $file_dir = dirname($file_path); - //For safety reasons, first try to create the directory, then check that it exists. - //This is in case some other process has created the folder in the meantime. - if (!@mkdir($file_dir, 0755, true) && !is_dir($file_dir)) { - throw new TelegramException('Directory ' . $file_dir . ' can\'t be created'); - } - - $debug_handle = TelegramLog::getDebugLogTempStream(); - - try { - self::$client->get( - '/file/bot' . self::$telegram->getApiKey() . '/' . $tg_file_path, - ['debug' => $debug_handle, 'sink' => $file_path] - ); - - return filesize($file_path) > 0; - } catch (RequestException $e) { - return ($e->getResponse()) ? (string) $e->getResponse()->getBody() : ''; - } finally { - //Logging verbose debug output - TelegramLog::endDebugLogTempStream('Verbose HTTP File Download Request output:' . PHP_EOL . '%s' . PHP_EOL); - } - } - - /** - * Encode file - * - * @param string $file - * - * @return resource - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function encodeFile($file) - { - $fp = fopen($file, 'rb'); - if ($fp === false) { - throw new TelegramException('Cannot open "' . $file . '" for reading'); - } - - return $fp; - } - - /** - * Send command - * - * @todo Fake response doesn't need json encoding? - * @todo Write debug entry on failure - * - * @param string $action - * @param array $data - * - * @return \Longman\TelegramBot\Entities\ServerResponse - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function send($action, array $data = []) - { - self::ensureValidAction($action); - self::addDummyParamIfNecessary($action, $data); - - $bot_username = self::$telegram->getBotUsername(); - - if (defined('PHPUNIT_TESTSUITE')) { - $fake_response = self::generateGeneralFakeServerResponse($data); - - return new ServerResponse($fake_response, $bot_username); - } - - self::ensureNonEmptyData($data); - - self::limitTelegramRequests($action, $data); - - $response = json_decode(self::execute($action, $data), true); - - if (null === $response) { - throw new TelegramException('Telegram returned an invalid response! Please review your bot name and API key.'); - } - - return new ServerResponse($response, $bot_username); - } - - /** - * Add a dummy parameter if the passed action requires it. - * - * If a method doesn't require parameters, we need to add a dummy one anyway, - * because of some cURL version failed POST request without parameters. - * - * @link https://github.com/php-telegram-bot/core/pull/228 - * - * @todo Would be nice to find a better solution for this! - * - * @param string $action - * @param array $data - */ - protected static function addDummyParamIfNecessary($action, array &$data) - { - if (in_array($action, self::$actions_need_dummy_param, true)) { - // Can be anything, using a single letter to minimise request size. - $data = ['d']; - } - } - - /** - * Make sure the data isn't empty, else throw an exception - * - * @param array $data - * - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - private static function ensureNonEmptyData(array $data) - { - if (count($data) === 0) { - throw new TelegramException('Data is empty!'); - } - } - - /** - * Make sure the action is valid, else throw an exception - * - * @param string $action - * - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - private static function ensureValidAction($action) - { - if (!in_array($action, self::$actions, true)) { - throw new TelegramException('The action "' . $action . '" doesn\'t exist!'); - } - } - - /** - * Use this method to send text messages. On success, the sent Message is returned - * - * @link https://core.telegram.org/bots/api#sendmessage - * - * @param array $data - * - * @return \Longman\TelegramBot\Entities\ServerResponse - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function sendMessage(array $data) - { - $text = $data['text']; - - do { - //Chop off and send the first message - $data['text'] = mb_substr($text, 0, 4096); - $response = self::send('sendMessage', $data); - - //Prepare the next message - $text = mb_substr($text, 4096); - } while (mb_strlen($text, 'UTF-8') > 0); - - return $response; - } - - /** - * Any statically called method should be relayed to the `send` method. - * - * @param string $action - * @param array $data - * - * @return \Longman\TelegramBot\Entities\ServerResponse - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function __callStatic($action, array $data) - { - // Make sure to add the action being called as the first parameter to be passed. - array_unshift($data, $action); - - // @todo Use splat operator for unpacking when we move to PHP 5.6+ - return call_user_func_array('static::send', $data); - } - - /** - * Return an empty Server Response - * - * No request to telegram are sent, this function is used in commands that - * don't need to fire a message after execution - * - * @return \Longman\TelegramBot\Entities\ServerResponse - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function emptyResponse() - { - return new ServerResponse(['ok' => true, 'result' => true], null); - } - - /** - * Send message to all active chats - * - * @param string $callback_function - * @param array $data - * @param array $select_chats_params - * - * @return array - * @throws TelegramException - */ - public static function sendToActiveChats( - $callback_function, - array $data, - array $select_chats_params - ) { - if (!method_exists(Request::class, $callback_function)) { - throw new TelegramException('Method "' . $callback_function . '" not found in class Request.'); - } - - $chats = DB::selectChats($select_chats_params); - - $results = []; - if (is_array($chats)) { - foreach ($chats as $row) { - $data['chat_id'] = $row['chat_id']; - $results[] = call_user_func(Request::class . '::' . $callback_function, $data); - } - } - - return $results; - } - - /** - * Enable request limiter - * - * @param boolean $enable - * @param array $options - * - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - public static function setLimiter($enable = true, array $options = []) - { - if (DB::isDbConnected()) { - $options_default = [ - 'interval' => 1, - ]; - - $options = array_merge($options_default, $options); - - if (!is_numeric($options['interval']) || $options['interval'] <= 0) { - throw new TelegramException('Interval must be a number and must be greater than zero!'); - } - - self::$limiter_interval = $options['interval']; - self::$limiter_enabled = $enable; - } - } - - /** - * This functions delays API requests to prevent reaching Telegram API limits - * Can be disabled while in execution by 'Request::setLimiter(false)' - * - * @link https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this - * - * @param string $action - * @param array $data - * - * @throws \Longman\TelegramBot\Exception\TelegramException - */ - private static function limitTelegramRequests($action, array $data = []) - { - if (self::$limiter_enabled) { - $limited_methods = [ - 'sendMessage', - 'forwardMessage', - 'sendPhoto', - 'sendAudio', - 'sendDocument', - 'sendSticker', - 'sendVideo', - 'sendVoice', - 'sendVideoNote', - 'sendMediaGroup', - 'sendLocation', - 'editMessageLiveLocation', - 'stopMessageLiveLocation', - 'sendVenue', - 'sendContact', - 'sendInvoice', - 'editMessageText', - 'editMessageCaption', - 'editMessageReplyMarkup', - 'setChatTitle', - 'setChatDescription', - 'setChatStickerSet', - 'deleteChatStickerSet', - ]; - - $chat_id = isset($data['chat_id']) ? $data['chat_id'] : null; - $inline_message_id = isset($data['inline_message_id']) ? $data['inline_message_id'] : null; - - if (($chat_id || $inline_message_id) && in_array($action, $limited_methods)) { - $timeout = 60; - - while (true) { - if ($timeout <= 0) { - throw new TelegramException('Timed out while waiting for a request spot!'); - } - - $requests = DB::getTelegramRequestCount($chat_id, $inline_message_id); - - $chat_per_second = ($requests['LIMIT_PER_SEC'] == 0); // No more than one message per second inside a particular chat - $global_per_second = ($requests['LIMIT_PER_SEC_ALL'] < 30); // No more than 30 messages per second to different chats - $groups_per_minute = (((is_numeric($chat_id) && $chat_id > 0) || !is_null($inline_message_id)) || ((!is_numeric($chat_id) || $chat_id < 0) && $requests['LIMIT_PER_MINUTE'] < 20)); // No more than 20 messages per minute in groups and channels - - if ($chat_per_second && $global_per_second && $groups_per_minute) { - break; - } - - $timeout--; - usleep(self::$limiter_interval * 1000000); - } - - DB::insertTelegramRequest($action, $data); - } - } - } -} diff --git a/src/Telegram.php b/src/Telegram.php index 10d2a5087..2bb53774c 100644 --- a/src/Telegram.php +++ b/src/Telegram.php @@ -14,10 +14,16 @@ defined('TB_BASE_COMMANDS_PATH') || define('TB_BASE_COMMANDS_PATH', TB_BASE_PATH . '/Commands'); use Exception; +use Illuminate\Container\Container; use Longman\TelegramBot\Commands\Command; -use Longman\TelegramBot\Entities\ServerResponse; +use Longman\TelegramBot\Console\Kernel as ConsoleKernel; use Longman\TelegramBot\Entities\Update; use Longman\TelegramBot\Exception\TelegramException; +use Longman\TelegramBot\Extensions\Botan\Botan; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Http\Kernel; +use Longman\TelegramBot\Http\Request; +use Longman\TelegramBot\Http\Response; use PDO; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; @@ -30,7 +36,7 @@ class Telegram * * @var string */ - protected $version = '0.53.0'; + const VERSION = '0.53.0'; /** * Telegram API key @@ -54,18 +60,11 @@ class Telegram protected $bot_id = ''; /** - * Raw request data (json) for webhook methods + * Container * - * @var string - */ - protected $input; - - /** - * Custom commands paths - * - * @var array + * @var \Illuminate\Contracts\Container\Container */ - protected $commands_paths = []; + protected $container; /** * Current Update object @@ -74,27 +73,6 @@ class Telegram */ protected $update; - /** - * Upload path - * - * @var string - */ - protected $upload_path; - - /** - * Download path - * - * @var string - */ - protected $download_path; - - /** - * MySQL integration - * - * @var boolean - */ - protected $mysql_enabled = false; - /** * PDO object * @@ -109,27 +87,13 @@ class Telegram */ protected $commands_config = []; - /** - * Admins list - * - * @var array - */ - protected $admins_list = []; - /** * ServerResponse of the last Command execution * - * @var \Longman\TelegramBot\Entities\ServerResponse + * @var \Longman\TelegramBot\Http\Response */ protected $last_command_response; - /** - * Botan.io integration - * - * @var boolean - */ - protected $botan_enabled = false; - /** * Check if runCommands() is running in this session * @@ -142,7 +106,7 @@ class Telegram * * @var bool */ - protected $getupdates_without_database = false; + public $getupdates_without_database = false; /** * Last update ID @@ -150,7 +114,7 @@ class Telegram * * @var integer */ - protected $last_update_id = null; + public $last_update_id = null; /** * Telegram constructor. @@ -166,26 +130,74 @@ public function __construct($api_key, $bot_username = '') throw new TelegramException('API KEY not defined!'); } preg_match('/(\d+)\:[\w\-]+/', $api_key, $matches); - if (!isset($matches[1])) { + if (! isset($matches[1])) { throw new TelegramException('Invalid API KEY defined!'); } - $this->bot_id = $matches[1]; + $this->bot_id = $matches[1]; $this->api_key = $api_key; - if (!empty($bot_username)) { + if (! empty($bot_username)) { $this->bot_username = $bot_username; } - //Add default system commands path + $this->registerContainer(); + + $this->initializeConfig(); + + // Add default system commands path $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/SystemCommands'); - Request::initialize($this); + Client::initialize($this); + } + + /** + * Register the container. + * + * @return void + */ + protected function registerContainer() + { + $this->container = Container::getInstance(); + + $this->container->instance(Telegram::class, $this); + } + + /** + * Initialize config. + * + * @return void + */ + protected function initializeConfig() + { + $config = new Config(); + + $this->container->instance(Config::class, $config); + } + + /** + * Get config. + * + * @return \Longman\TelegramBot\Config + */ + public function getConfig() + { + return $this->container->make(Config::class); + } + + /** + * Get container instance. + * + * @return \Illuminate\Container\Container + */ + public function getContainer() + { + return $this->container; } /** * Initialize Database connection * - * @param array $credential + * @param array $credential * @param string $table_prefix * @param string $encoding * @@ -195,8 +207,8 @@ public function __construct($api_key, $bot_username = '') public function enableMySql(array $credential, $table_prefix = null, $encoding = 'utf8mb4') { $this->pdo = DB::initialize($credential, $this, $table_prefix, $encoding); + DB::setEnabled(true); ConversationDB::initializeConversation(); - $this->mysql_enabled = true; return $this; } @@ -204,7 +216,7 @@ public function enableMySql(array $credential, $table_prefix = null, $encoding = /** * Initialize Database external connection * - * @param PDO $external_pdo_connection PDO database object + * @param PDO $external_pdo_connection PDO database object * @param string $table_prefix * * @return \Longman\TelegramBot\Telegram @@ -213,8 +225,8 @@ public function enableMySql(array $credential, $table_prefix = null, $encoding = public function enableExternalMySql($external_pdo_connection, $table_prefix = null) { $this->pdo = DB::externalInitialize($external_pdo_connection, $this, $table_prefix); + DB::setEnabled(true); ConversationDB::initializeConversation(); - $this->mysql_enabled = true; return $this; } @@ -229,9 +241,10 @@ public function getCommandsList() { $commands = []; - foreach ($this->commands_paths as $path) { + $command_paths = $this->getConfig()->getCommandsPaths(); + foreach ($command_paths as $path) { try { - //Get all "*Command.php" files + // Get all "*Command.php" files $files = new RegexIterator( new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path) @@ -241,7 +254,7 @@ public function getCommandsList() foreach ($files as $file) { //Remove "Command.php" from filename - $command = $this->sanitizeCommand(substr($file->getFilename(), 0, -11)); + $command = $this->sanitizeCommand(substr($file->getFilename(), 0, -11)); $command_name = strtolower($command); if (array_key_exists($command_name, $commands)) { @@ -250,7 +263,7 @@ public function getCommandsList() require_once $file->getPathname(); - $command_obj = $this->getCommandObject($command); + $command_obj = $this->createCommandObject($command); if ($command_obj instanceof Command) { $commands[$command_name] = $command_obj; } @@ -270,14 +283,18 @@ public function getCommandsList() * * @return \Longman\TelegramBot\Commands\Command|null */ - public function getCommandObject($command) + public function createCommandObject($command) { $which = ['System']; - $this->isAdmin() && $which[] = 'Admin'; + if ($this->isAdmin()) { + $which[] = 'Admin'; + } $which[] = 'User'; + $command_name = $this->ucfirstUnicode($command); foreach ($which as $auth) { - $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $this->ucfirstUnicode($command) . 'Command'; + $command_namespace = __NAMESPACE__ . '\\Commands\\' . $auth . 'Commands\\' . $command_name . 'Command'; + if (class_exists($command_namespace)) { return new $command_namespace($this, $this->update); } @@ -286,34 +303,10 @@ public function getCommandObject($command) return null; } - /** - * Set custom input string for debug purposes - * - * @param string $input (json format) - * - * @return \Longman\TelegramBot\Telegram - */ - public function setCustomInput($input) - { - $this->input = $input; - - return $this; - } - - /** - * Get custom input string for debug purposes - * - * @return string - */ - public function getCustomInput() - { - return $this->input; - } - /** * Get the ServerResponse of the last Command execution * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response */ public function getLastCommandResponse() { @@ -323,75 +316,29 @@ public function getLastCommandResponse() /** * Handle getUpdates method * + * @param \Longman\TelegramBot\Http\Request|null $request * @param int|null $limit * @param int|null $timeout * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ - public function handleGetUpdates($limit = null, $timeout = null) + public function handleGetUpdates(Request $request = null, $limit = null, $timeout = null) { 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; + /** @var \Longman\TelegramBot\Console\Kernel $kernel */ + $kernel = $this->getContainer()->make(ConsoleKernel::class); - //Take custom input into account. - if ($custom_input = $this->getCustomInput()) { - $response = new ServerResponse(json_decode($custom_input, true), $this->bot_username); - } else { - if (DB::isDbConnected()) { - //Get last update id from the database - $last_update = DB::selectTelegramUpdate(1); - $last_update = reset($last_update); - - $this->last_update_id = isset($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( - [ - 'offset' => $offset, - 'limit' => $limit, - 'timeout' => $timeout, - ] - ); + if (is_null($request)) { + $request = Request::capture(); } - if ($response->isOk()) { - $results = $response->getResult(); - - //Process all updates - /** @var Update $result */ - foreach ($results as $result) { - $this->processUpdate($result); - } + $this->container->instance(Request::class, $request); - if (!DB::isDbConnected() && !$custom_input && $this->last_update_id !== null && $offset === 0) { - //Mark update(s) as read after handling - Request::getUpdates( - [ - 'offset' => $this->last_update_id + 1, - 'limit' => 1, - 'timeout' => $timeout, - ] - ); - } - } + $response = $kernel->handle($request, $limit, $timeout); return $response; } @@ -399,32 +346,29 @@ public function handleGetUpdates($limit = null, $timeout = null) /** * Handle bot request from webhook * - * @return bool + * @param \Longman\TelegramBot\Http\Request|null $request + * @return \Longman\TelegramBot\Http\Response * * @throws \Longman\TelegramBot\Exception\TelegramException */ - public function handle() + public function handle(Request $request = null) { - if (empty($this->bot_username)) { + if (empty($this->getBotUsername())) { throw new TelegramException('Bot Username is not defined!'); } - $this->input = Request::getInput(); + /** @var \Longman\TelegramBot\Http\Kernel $kernel */ + $kernel = $this->getContainer()->make(Kernel::class); - if (empty($this->input)) { - throw new TelegramException('Input is empty!'); + if (is_null($request)) { + $request = Request::capture(); } - $post = json_decode($this->input, true); - if (empty($post)) { - throw new TelegramException('Invalid JSON!'); - } + $this->container->instance(Request::class, $request); - if ($response = $this->processUpdate(new Update($post, $this->bot_username))) { - return $response->isOk(); - } + $response = $kernel->handle($request); - return false; + return $response; } /** @@ -444,7 +388,7 @@ protected function getCommandFromType($type) * * @param \Longman\TelegramBot\Entities\Update $update * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ public function processUpdate(Update $update) @@ -452,14 +396,14 @@ public function processUpdate(Update $update) $this->update = $update; $this->last_update_id = $update->getUpdateId(); - //If all else fails, it's a generic message. + // If all else fails, it's a generic message. $command = 'genericmessage'; - $update_type = $this->update->getUpdateType(); - if ($update_type === 'message') { - $message = $this->update->getMessage(); + $update_type = $update->getUpdateType(); + if ($update_type === Update::TYPE_MESSAGE) { + $message = $update->getMessage(); - //Load admin commands + // Load admin commands if ($this->isAdmin()) { $this->addCommandsPath(TB_BASE_COMMANDS_PATH . '/AdminCommands', false); } @@ -467,7 +411,7 @@ public function processUpdate(Update $update) $type = $message->getType(); if ($type === 'command') { $command = $message->getCommand(); - } elseif (in_array($type, [ + } else if (in_array($type, [ 'new_chat_members', 'left_chat_member', 'new_chat_title', @@ -489,18 +433,19 @@ public function processUpdate(Update $update) $command = $this->getCommandFromType($update_type); } - //Make sure we have an up-to-date command list - //This is necessary to "require" all the necessary command files! + // Make sure we have an up-to-date command list + // This is necessary to "require" all the necessary command files! $this->getCommandsList(); - //Make sure we don't try to process update that was already processed - $last_id = DB::selectTelegramUpdate(1, $this->update->getUpdateId()); + // Make sure we don't try to process update that was already processed + $last_id = DB::selectTelegramUpdate(1, $update->getUpdateId()); if ($last_id && count($last_id) === 1) { - TelegramLog::debug('Duplicate update received, processing aborted!'); - return Request::emptyResponse(); + Logger::debug('Duplicate update received, processing aborted!'); + + return new Response(['ok' => true, 'result' => true]); } - DB::insertRequest($this->update); + DB::insertRequest($update); return $this->executeCommand($command); } @@ -515,29 +460,29 @@ public function processUpdate(Update $update) */ public function executeCommand($command) { - $command = strtolower($command); - $command_obj = $this->getCommandObject($command); + $command = strtolower($command); + $command_obj = $this->createCommandObject($command); - if (!$command_obj || !$command_obj->isEnabled()) { - //Failsafe in case the Generic command can't be found + if (! $command_obj || ! $command_obj->isEnabled()) { + // Failsafe in case the Generic command can't be found if ($command === 'generic') { throw new TelegramException('Generic command missing!'); } - //Handle a generic command or non existing one + // Handle a generic command or non existing one $this->last_command_response = $this->executeCommand('generic'); } else { - //Botan.io integration, make sure only the actual command user executed is reported - if ($this->botan_enabled) { + // Botan.io integration, make sure only the actual command user executed is reported + if (Botan::isEnabled()) { Botan::lock($command); } - //execute() method is executed after preExecute() - //This is to prevent executing a DB query without a valid connection + // execute() method is executed after preExecute() + // This is to prevent executing a DB query without a valid connection $this->last_command_response = $command_obj->preExecute(); - //Botan.io integration, send report after executing the command - if ($this->botan_enabled) { + // Botan.io integration, send report after executing the command + if (Botan::isEnabled()) { Botan::track($this->update, $command); } } @@ -566,11 +511,7 @@ protected function sanitizeCommand($command) */ public function enableAdmin($admin_id) { - if (!is_int($admin_id) || $admin_id <= 0) { - TelegramLog::error('Invalid value "%s" for admin.', $admin_id); - } elseif (!in_array($admin_id, $this->admins_list, true)) { - $this->admins_list[] = $admin_id; - } + $this->getConfig()->addAdmin($admin_id); return $this; } @@ -584,9 +525,7 @@ public function enableAdmin($admin_id) */ public function enableAdmins(array $admin_ids) { - foreach ($admin_ids as $admin_id) { - $this->enableAdmin($admin_id); - } + $this->getConfig()->addAdmins($admin_ids); return $this; } @@ -598,7 +537,7 @@ public function enableAdmins(array $admin_ids) */ public function getAdminList() { - return $this->admins_list; + return $this->getConfig()->getAdmins(); } /** @@ -632,42 +571,21 @@ public function isAdmin($user_id = null) } } - return ($user_id === null) ? false : in_array($user_id, $this->admins_list, true); - } - - /** - * Check if user required the db connection - * - * @return bool - */ - public function isDbEnabled() - { - if ($this->mysql_enabled) { - return true; - } else { - return false; - } + $admins = $this->getConfig()->getAdmins(); + return ($user_id === null) ? false : in_array($user_id, $admins, true); } /** * 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 + * @param string $path Custom commands path to add + * @param bool $before If the path should be prepended or appended to the list * * @return \Longman\TelegramBot\Telegram */ public function addCommandsPath($path, $before = true) { - if (!is_dir($path)) { - TelegramLog::error('Commands path "%s" does not exist.', $path); - } elseif (!in_array($path, $this->commands_paths, true)) { - if ($before) { - array_unshift($this->commands_paths, $path); - } else { - $this->commands_paths[] = $path; - } - } + $this->getConfig()->addCommandsPath($path, $before); return $this; } @@ -675,16 +593,14 @@ public function addCommandsPath($path, $before = true) /** * 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 + * @param array $paths Custom commands paths to add + * @param bool $before If the paths should be prepended or appended to the list * * @return \Longman\TelegramBot\Telegram */ public function addCommandsPaths(array $paths, $before = true) { - foreach ($paths as $path) { - $this->addCommandsPath($path, $before); - } + $this->getConfig()->addCommandsPaths($paths, $before); return $this; } @@ -696,7 +612,8 @@ public function addCommandsPaths(array $paths, $before = true) */ public function getCommandsPaths() { - return $this->commands_paths; + + return $this->getConfig()->getCommandsPaths(); } /** @@ -708,7 +625,7 @@ public function getCommandsPaths() */ public function setUploadPath($path) { - $this->upload_path = $path; + $this->getConfig()->setUploadPath($path); return $this; } @@ -720,7 +637,7 @@ public function setUploadPath($path) */ public function getUploadPath() { - return $this->upload_path; + return $this->getConfig()->getUploadPath(); } /** @@ -732,7 +649,7 @@ public function getUploadPath() */ public function setDownloadPath($path) { - $this->download_path = $path; + $this->getConfig()->setDownloadPath($path); return $this; } @@ -744,7 +661,7 @@ public function setDownloadPath($path) */ public function getDownloadPath() { - return $this->download_path; + return $this->getConfig()->getDownloadPath(); } /** @@ -755,7 +672,7 @@ public function getDownloadPath() * Or you can add the api key for external service. * * @param string $command - * @param array $config + * @param array $config * * @return \Longman\TelegramBot\Telegram */ @@ -815,39 +732,39 @@ public function getBotId() */ public function getVersion() { - return $this->version; + return self::VERSION; } /** * Set Webhook for bot * * @param string $url - * @param array $data Optional parameters. + * @param array $parameters Optional parameters. * - * @return \Longman\TelegramBot\Entities\ServerResponse + * @return \Longman\TelegramBot\Http\Response * @throws \Longman\TelegramBot\Exception\TelegramException */ - public function setWebhook($url, array $data = []) + public function setWebhook($url, array $parameters = []) { if (empty($url)) { throw new TelegramException('Hook url is empty!'); } - $data = array_intersect_key($data, array_flip([ + $parameters = array_intersect_key($parameters, array_flip([ 'certificate', 'max_connections', 'allowed_updates', ])); - $data['url'] = $url; + $parameters['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']); + if (! empty($parameters['certificate']) && is_string($parameters['certificate'])) { + $parameters['certificate'] = Client::encodeFile($parameters['certificate']); } - $result = Request::setWebhook($data); + $result = Client::setWebhook($parameters); - if (!$result->isOk()) { + if (! $result->isOk()) { throw new TelegramException( 'Webhook was not set! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription() ); @@ -864,9 +781,9 @@ public function setWebhook($url, array $data = []) */ public function deleteWebhook() { - $result = Request::deleteWebhook(); + $result = Client::deleteWebhook(); - if (!$result->isOk()) { + if (! $result->isOk()) { throw new TelegramException( 'Webhook was not deleted! Error: ' . $result->getErrorCode() . ' ' . $result->getDescription() ); @@ -899,14 +816,14 @@ protected function ucwordsUnicode($str, $encoding = 'UTF-8') protected function ucfirstUnicode($str, $encoding = 'UTF-8') { return mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding) - . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding); + . mb_strtolower(mb_substr($str, 1, mb_strlen($str), $encoding), $encoding); } /** * Enable Botan.io integration * * @param string $token - * @param array $options + * @param array $options * * @return \Longman\TelegramBot\Telegram * @throws \Longman\TelegramBot\Exception\TelegramException @@ -914,7 +831,7 @@ protected function ucfirstUnicode($str, $encoding = 'UTF-8') public function enableBotan($token, array $options = []) { Botan::initializeBotan($token, $options); - $this->botan_enabled = true; + Botan::setEnabled(true); return $this; } @@ -928,7 +845,7 @@ public function enableBotan($token, array $options = []) */ public function enableLimiter(array $options = []) { - Request::setLimiter(true, $options); + Client::setLimiter(true, $options); return $this; } @@ -942,28 +859,27 @@ public function enableLimiter(array $options = []) */ public function runCommands($commands) { - if (!is_array($commands) || empty($commands)) { + if (! is_array($commands) || empty($commands)) { throw new TelegramException('No command(s) provided!'); } - $this->run_commands = true; - $this->botan_enabled = false; // Force disable Botan.io integration, we don't want to track self-executed commands! + $this->run_commands = true; + Botan::setEnabled(false); // Force disable Botan.io integration, we don't want to track self-executed commands! - $result = Request::getMe(); + $result = Client::getMe(); if ($result->isOk()) { $result = $result->getResult(); - $bot_id = $result->getId(); - $bot_name = $result->getFirstName(); + $bot_id = $result->getId(); + $bot_name = $result->getFirstName(); $bot_username = $result->getUsername(); } else { - $bot_id = $this->getBotId(); - $bot_name = $this->getBotUsername(); + $bot_id = $this->getBotId(); + $bot_name = $this->getBotUsername(); $bot_username = $this->getBotUsername(); } - $this->enableAdmin($bot_id); // Give bot access to admin commands $this->getCommandsList(); // Load full commands list diff --git a/tests/unit/Commands/CustomTestCommands/HiddenCommand.php b/tests/unit/Commands/CustomTestCommands/HiddenCommand.php index acc82a13b..c8c0489d1 100644 --- a/tests/unit/Commands/CustomTestCommands/HiddenCommand.php +++ b/tests/unit/Commands/CustomTestCommands/HiddenCommand.php @@ -11,7 +11,8 @@ namespace Longman\TelegramBot\Commands\UserCommands; use Longman\TelegramBot\Commands\UserCommand; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Http\Response; /** * Test "/hidden" command to test $show_in_help @@ -51,6 +52,6 @@ class HiddenCommand extends UserCommand */ public function execute() { - return Request::emptyResponse(); + return new Response(['ok' => true, 'result' => true]); } } diff --git a/tests/unit/Commands/CustomTestCommands/VisibleCommand.php b/tests/unit/Commands/CustomTestCommands/VisibleCommand.php index 6d800e896..ad009f6a7 100644 --- a/tests/unit/Commands/CustomTestCommands/VisibleCommand.php +++ b/tests/unit/Commands/CustomTestCommands/VisibleCommand.php @@ -11,7 +11,8 @@ namespace Longman\TelegramBot\Commands\UserCommands; use Longman\TelegramBot\Commands\UserCommand; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Client; +use Longman\TelegramBot\Http\Response; /** * Test "/visible" command to test $show_in_help @@ -51,6 +52,6 @@ class VisibleCommand extends UserCommand */ public function execute() { - return Request::emptyResponse(); + return new Response(['ok' => true, 'result' => true]); } } diff --git a/tests/unit/ConfigTest.php b/tests/unit/ConfigTest.php new file mode 100644 index 000000000..d283ea737 --- /dev/null +++ b/tests/unit/ConfigTest.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Tests\Unit; + +use Longman\TelegramBot\Config; + +class ConfigTest extends TestCase +{ + public function testAddCommandsPathsBefore() + { + $config = new Config(); + + $paths = [ + '/tmp/php-telegram-bot-custom-commands-config-1', + '/tmp/php-telegram-bot-custom-commands-config-2', + '/tmp/php-telegram-bot-custom-commands-config-3', + ]; + foreach ($paths as $path) { + mkdir($path); + } + + $config->addCommandsPaths($paths); + foreach ($paths as $path) { + rmdir($path); + } + + $this->assertEquals(array_reverse($paths), $config->getCommandsPaths()); + } + + public function testAddCommandsPathsAfter() + { + $config = new Config(); + + $paths = [ + '/tmp/php-telegram-bot-custom-commands-config-1', + '/tmp/php-telegram-bot-custom-commands-config-2', + '/tmp/php-telegram-bot-custom-commands-config-3', + ]; + foreach ($paths as $path) { + mkdir($path); + } + + $config->addCommandsPaths($paths, false); + foreach ($paths as $path) { + rmdir($path); + } + + $this->assertEquals($paths, $config->getCommandsPaths()); + } + + public function testAdmins() + { + $config = new Config(); + + $admins = [1, 2, 3]; + + $config->addAdmins($admins); + + $this->assertEquals($admins, $config->getAdmins()); + } + + public function testUploadPath() + { + $config = new Config(); + + $path = '/some/path'; + + $config->setUploadPath($path); + + $this->assertEquals($path, $config->getUploadPath()); + } + + public function testDownloadPath() + { + $config = new Config(); + + $path = '/some/path'; + + $config->setDownloadPath($path); + + $this->assertEquals($path, $config->getDownloadPath()); + } +} diff --git a/tests/unit/Entities/InlineKeyboardButtonTest.php b/tests/unit/Entities/InlineKeyboardButtonTest.php index fc0cb0747..9c44a02ce 100644 --- a/tests/unit/Entities/InlineKeyboardButtonTest.php +++ b/tests/unit/Entities/InlineKeyboardButtonTest.php @@ -95,6 +95,8 @@ public function testInlineKeyboardButtonSuccess() new InlineKeyboardButton(['text' => 'message', 'switch_inline_query_current_chat' => 'switch_inline_query_current_chat_value']); new InlineKeyboardButton(['text' => 'message', 'switch_inline_query_current_chat' => '']); // Allow empty string. new InlineKeyboardButton(['text' => 'message', 'pay' => true]); + + $this->assertTrue(true); } public function testInlineKeyboardButtonCouldBe() diff --git a/tests/unit/Entities/KeyboardButtonTest.php b/tests/unit/Entities/KeyboardButtonTest.php index 018164a3c..097ed8d92 100644 --- a/tests/unit/Entities/KeyboardButtonTest.php +++ b/tests/unit/Entities/KeyboardButtonTest.php @@ -44,6 +44,8 @@ public function testKeyboardButtonSuccess() new KeyboardButton(['text' => 'message']); new KeyboardButton(['text' => 'message', 'request_contact' => true]); new KeyboardButton(['text' => 'message', 'request_location' => true]); + + $this->assertTrue(true); } public function testInlineKeyboardButtonCouldBe() diff --git a/tests/unit/Entities/ServerResponseTest.php b/tests/unit/Entities/ResponseTest.php similarity index 87% rename from tests/unit/Entities/ServerResponseTest.php rename to tests/unit/Entities/ResponseTest.php index c321ac4a1..d39a1edc1 100644 --- a/tests/unit/Entities/ServerResponseTest.php +++ b/tests/unit/Entities/ResponseTest.php @@ -13,8 +13,8 @@ namespace Longman\TelegramBot\Tests\Unit; use Longman\TelegramBot\Entities\Message; -use Longman\TelegramBot\Entities\ServerResponse; -use Longman\TelegramBot\Request; +use Longman\TelegramBot\Http\Response; +use Longman\TelegramBot\Http\Client; /** * @package TelegramTest @@ -23,7 +23,7 @@ * @license http://opensource.org/licenses/mit-license.php The MIT License (MIT) * @link https://github.com/php-telegram-bot/core */ -class ServerResponseTest extends TestCase +class ResponseTest extends TestCase { public function sendMessageOk() { @@ -41,8 +41,8 @@ public function sendMessageOk() public function testSendMessageOk() { - $result = $this->sendMessageOk(); - $server = new ServerResponse(json_decode($result, true), 'testbot'); + $result = $this->sendMessageOk(); + $server = new Response(json_decode($result, true), 'testbot'); $server_result = $server->getResult(); self::assertTrue($server->isOk()); @@ -76,10 +76,10 @@ public function sendMessageFail() public function testSendMessageFail() { $result = $this->sendMessageFail(); - $server = new ServerResponse(json_decode($result, true), 'testbot'); + $server = new Response(json_decode($result, true), 'testbot'); self::assertFalse($server->isOk()); - self::assertNull($server->getResult()); + self::assertEquals([], $server->getResult()); self::assertEquals('400', $server->getErrorCode()); self::assertEquals('Error: Bad Request: wrong chat id', $server->getDescription()); } @@ -92,10 +92,10 @@ public function setWebhookOk() public function testSetWebhookOk() { $result = $this->setWebhookOk(); - $server = new ServerResponse(json_decode($result, true), 'testbot'); + $server = new Response(json_decode($result, true), 'testbot'); self::assertTrue($server->isOk()); - self::assertTrue($server->getResult()); + self::assertEquals([], $server->getResult()); self::assertNull($server->getErrorCode()); self::assertEquals('Webhook was set', $server->getDescription()); } @@ -112,10 +112,10 @@ public function setWebhookFail() public function testSetWebhookFail() { $result = $this->setWebhookFail(); - $server = new ServerResponse(json_decode($result, true), 'testbot'); + $server = new Response(json_decode($result, true), 'testbot'); self::assertFalse($server->isOk()); - self::assertNull($server->getResult()); + self::assertEquals([], $server->getResult()); self::assertEquals(400, $server->getErrorCode()); self::assertEquals('Error: Bad request: htttps://domain.host.org/dir/hook.php', $server->getDescription()); } @@ -172,7 +172,7 @@ public function getUpdatesArray() public function testGetUpdatesArray() { $result = $this->getUpdatesArray(); - $server = new ServerResponse(json_decode($result, true), 'testbot'); + $server = new Response(json_decode($result, true), 'testbot'); self::assertCount(4, $server->getResult()); self::assertInstanceOf('\Longman\TelegramBot\Entities\Update', $server->getResult()[0]); @@ -186,7 +186,7 @@ public function getUpdatesEmpty() public function testGetUpdatesEmpty() { $result = $this->getUpdatesEmpty(); - $server = new ServerResponse(json_decode($result, true), 'testbot'); + $server = new Response(json_decode($result, true), 'testbot'); self::assertEmpty($server->getResult()); } @@ -220,8 +220,8 @@ public function getUserProfilePhotos() public function testGetUserProfilePhotos() { - $result = $this->getUserProfilePhotos(); - $server = new ServerResponse(json_decode($result, true), 'testbot'); + $result = $this->getUserProfilePhotos(); + $server = new Response(json_decode($result, true), 'testbot'); $server_result = $server->getResult(); $photos = $server_result->getPhotos(); @@ -251,7 +251,7 @@ public function getFile() public function testGetFile() { $result = $this->getFile(); - $server = new ServerResponse(json_decode($result, true), 'testbot'); + $server = new Response(json_decode($result, true), 'testbot'); self::assertInstanceOf('\Longman\TelegramBot\Entities\File', $server->getResult()); } @@ -259,19 +259,19 @@ public function testGetFile() public function testSetGeneralTestFakeResponse() { //setWebhook ok - $fake_response = Request::generateGeneralFakeServerResponse(); + $fake_response = Client::generateGeneralFakeServerResponse(); - $server = new ServerResponse($fake_response, 'testbot'); + $server = new Response($fake_response, 'testbot'); self::assertTrue($server->isOk()); - self::assertTrue($server->getResult()); + self::assertEquals([], $server->getResult()); self::assertNull($server->getErrorCode()); self::assertEquals('', $server->getDescription()); //sendMessage ok - $fake_response = Request::generateGeneralFakeServerResponse(['chat_id' => 123456789, 'text' => 'hello']); + $fake_response = Client::generateGeneralFakeServerResponse(['chat_id' => 123456789, 'text' => 'hello']); - $server = new ServerResponse($fake_response, 'testbot'); + $server = new Response($fake_response, 'testbot'); /** @var Message $server_result */ $server_result = $server->getResult(); diff --git a/tests/unit/TelegramLogTest.php b/tests/unit/LoggerTest.php similarity index 75% rename from tests/unit/TelegramLogTest.php rename to tests/unit/LoggerTest.php index 069e9dabd..78fedb3ac 100644 --- a/tests/unit/TelegramLogTest.php +++ b/tests/unit/LoggerTest.php @@ -10,9 +10,9 @@ namespace Longman\TelegramBot\Tests\Unit; -use Longman\TelegramBot\TelegramLog; +use Longman\TelegramBot\Logger; use Monolog\Handler\StreamHandler; -use Monolog\Logger; +use Monolog\Logger as MonologLogger; /** * @package TelegramTest @@ -21,7 +21,7 @@ * @license http://opensource.org/licenses/mit-license.php The MIT License (MIT) * @link https://github.com/php-telegram-bot/core */ -class TelegramLogTest extends TestCase +class LoggerTest extends TestCase { /** * @var array Dummy logfile paths @@ -36,7 +36,7 @@ class TelegramLogTest extends TestCase protected function setUp() { // Make sure no monolog instance is set before each test. - TestHelpers::setStaticProperty('Longman\TelegramBot\TelegramLog', 'monolog', null); + TestHelpers::setStaticProperty('Longman\TelegramBot\Logger', 'monolog', null); } protected function tearDown() @@ -52,7 +52,7 @@ protected function tearDown() */ public function testNewInstanceWithoutErrorPath() { - TelegramLog::initErrorLog(''); + Logger::initErrorLog(''); } /** @@ -60,7 +60,7 @@ public function testNewInstanceWithoutErrorPath() */ public function testNewInstanceWithoutDebugPath() { - TelegramLog::initDebugLog(''); + Logger::initDebugLog(''); } /** @@ -68,17 +68,17 @@ public function testNewInstanceWithoutDebugPath() */ public function testNewInstanceWithoutUpdatePath() { - TelegramLog::initUpdateLog(''); + Logger::initUpdateLog(''); } public function testErrorStream() { $file = self::$logfiles['error']; $this->assertFileNotExists($file); - TelegramLog::initErrorLog($file); - TelegramLog::error('my error'); - TelegramLog::error('my 50% error'); - TelegramLog::error('my %s error', 'placeholder'); + Logger::initErrorLog($file); + Logger::error('my error'); + Logger::error('my 50% error'); + Logger::error('my %s error', 'placeholder'); $this->assertFileExists($file); $error_log = file_get_contents($file); $this->assertContains('bot_log.ERROR: my error', $error_log); @@ -90,10 +90,10 @@ public function testDebugStream() { $file = self::$logfiles['debug']; $this->assertFileNotExists($file); - TelegramLog::initDebugLog($file); - TelegramLog::debug('my debug'); - TelegramLog::debug('my 50% debug'); - TelegramLog::debug('my %s debug', 'placeholder'); + Logger::initDebugLog($file); + Logger::debug('my debug'); + Logger::debug('my 50% debug'); + Logger::debug('my %s debug', 'placeholder'); $this->assertFileExists($file); $debug_log = file_get_contents($file); $this->assertContains('bot_log.DEBUG: my debug', $debug_log); @@ -105,10 +105,10 @@ public function testUpdateStream() { $file = self::$logfiles['update']; $this->assertFileNotExists($file); - TelegramLog::initUpdateLog($file); - TelegramLog::update('my update'); - TelegramLog::update('my 50% update'); - TelegramLog::update('my %s update', 'placeholder'); + Logger::initUpdateLog($file); + Logger::update('my update'); + Logger::update('my 50% update'); + Logger::update('my %s update', 'placeholder'); $this->assertFileExists($file); $debug_log = file_get_contents($file); $this->assertContains('my update', $debug_log); @@ -121,17 +121,17 @@ public function testExternalStream() $file = self::$logfiles['external']; $this->assertFileNotExists($file); - $external_monolog = new Logger('bot_update_log'); - $external_monolog->pushHandler(new StreamHandler($file, Logger::ERROR)); - $external_monolog->pushHandler(new StreamHandler($file, Logger::DEBUG)); + $external_monolog = new MonologLogger('bot_update_log'); + $external_monolog->pushHandler(new StreamHandler($file, MonologLogger::ERROR)); + $external_monolog->pushHandler(new StreamHandler($file, MonologLogger::DEBUG)); - TelegramLog::initialize($external_monolog); - TelegramLog::error('my error'); - TelegramLog::error('my 50% error'); - TelegramLog::error('my %s error', 'placeholder'); - TelegramLog::debug('my debug'); - TelegramLog::debug('my 50% debug'); - TelegramLog::debug('my %s debug', 'placeholder'); + Logger::initialize($external_monolog); + Logger::error('my error'); + Logger::error('my 50% error'); + Logger::error('my %s error', 'placeholder'); + Logger::debug('my debug'); + Logger::debug('my 50% debug'); + Logger::debug('my %s debug', 'placeholder'); $this->assertFileExists($file); $file_contents = file_get_contents($file); diff --git a/tests/unit/TelegramTest.php b/tests/unit/TelegramTest.php index e219c7512..2c8326f36 100644 --- a/tests/unit/TelegramTest.php +++ b/tests/unit/TelegramTest.php @@ -41,7 +41,7 @@ protected function setUp() // Create a few dummy custom commands paths. foreach ($this->custom_commands_paths as $custom_path) { - mkdir($custom_path); + @mkdir($custom_path); } } @@ -49,7 +49,7 @@ protected function tearDown() { // Clean up the custom commands paths. foreach ($this->custom_commands_paths as $custom_path) { - rmdir($custom_path); + @rmdir($custom_path); } } @@ -144,4 +144,38 @@ public function testGetCommandsList() $this->assertInternalType('array', $commands); $this->assertNotCount(0, $commands); } + + public function testContainer() + { + $telegram = new Telegram(self::$dummy_api_key, 'testbot'); + + $this->assertInstanceOf(\Illuminate\Container\Container::class, $telegram->getContainer()); + } + + public function testHandleResponse() + { + $telegram = new Telegram(self::$dummy_api_key, 'testbot'); + + $response = $telegram->handle(); + + $this->assertInstanceOf(\Longman\TelegramBot\Http\Response::class, $response); + } + + public function testHandleUpdatedResponse() + { + $telegram = new Telegram(self::$dummy_api_key, 'testbot'); + + $response = $telegram->handleGetUpdates(); + + $this->assertInstanceOf(\Longman\TelegramBot\Http\Response::class, $response); + } + + public function testCustom() + { + $telegram = new Telegram(self::$dummy_api_key, 'testbot'); + + $telegram->handle(); + + $this->assertTrue(true); + } }