From e20ce3d9538f0ea6e3eecf01d693f0ab60e3588a Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 23 May 2024 18:28:18 +0200 Subject: [PATCH 01/42] Switch to upstream MadelineProto image --- Dockerfile | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/Dockerfile b/Dockerfile index ce762c3..da59608 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,6 @@ -FROM php:8.3-cli +FROM hub.madelineproto.xyz/danog/madelineproto:latest -RUN apt-get update && apt-get upgrade -y -RUN true \ - # Install main extension - && apt-get install procps git zip vim libzip-dev libgmp-dev libuv1-dev libssl-dev libnghttp2-dev libffi-dev libicu-dev libonig-dev libxml2-dev libpng-dev -y \ - && docker-php-ext-install -j$(nproc) sockets bcmath mysqli pdo_mysql pcntl ffi intl gmp zip gd \ - # Install additional extension - && mkdir -p /usr/src/php/ext/ && cd /usr/src/php/ext/ \ - && pecl bundle uv && pecl bundle igbinary \ - && docker-php-ext-install -j$(nproc) uv igbinary \ - # Install PrimeModule for AuthKey generation speedup - && git clone https://github.com/danog/PrimeModule-ext \ - && cd PrimeModule-ext && make -j$(nproc) \ - && make install \ - && cd ../ \ - && rm -rf PrimeModule-ext/ \ - # Install composer - && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ - # Cleanup - && docker-php-source delete \ - && apt-get autoremove --purge -y && apt-get autoclean -y && apt-get clean -y \ - && rm -rf /usr/src +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer COPY --from=ghcr.io/ufoscout/docker-compose-wait:latest /wait /usr/local/bin/docker-compose-wait From 68ecec704db7c9b65b7c449f7bf7fff43846469f Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 23 May 2024 18:32:21 +0200 Subject: [PATCH 02/42] Fixup --- docker-compose.base.yml | 2 +- entrypoint.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.base.yml b/docker-compose.base.yml index 475d15a..6de8e6d 100644 --- a/docker-compose.base.yml +++ b/docker-compose.base.yml @@ -19,7 +19,7 @@ services: max-size: "1024k" max-file: "2" healthcheck: - test: timeout 15 curl -f http://localhost:9503/system/healthcheck || bash -c 'kill -INT -1 && (sleep 5; kill -s 9 -1)' + test: timeout 15 curl -f http://localhost:9503/system/healthcheck || sh -c 'kill -INT -1 && (sleep 5; kill -s 9 -1)' interval: 60s timeout: 30s retries: 1 diff --git a/entrypoint.sh b/entrypoint.sh index 60fc295..74a8b80 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh docker-compose-wait \ && nice -n 20 php server.php -e=.env.docker --docker "$@" \ No newline at end of file From e050a07d93699859a92a14c45a16ce52e4b11b93 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 23 May 2024 18:34:54 +0200 Subject: [PATCH 03/42] Bump --- composer.json | 10 +++++----- composer.lock | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 3a6da8b..76d2a88 100644 --- a/composer.json +++ b/composer.json @@ -24,16 +24,16 @@ } ], "require": { - "php": "^8.1", + "php": "^8.2", "ext-json": "*", "ext-mbstring": "*", - "amphp/http-server": "^v3", - "amphp/http": "^v2", + "amphp/http-server": "^3.3.1", + "amphp/http": "^2.1.1", "amphp/http-server-router": "^2", "amphp/http-server-form-parser": "^v2", - "amphp/websocket-server": "^v3", + "amphp/websocket-server": "^3.0.1", "amphp/websocket-client": "^v2", - "vlucas/phpdotenv": "^4", + "vlucas/phpdotenv": "^4.3", "danog/madelineproto": "dev-v8_fix_cleanup", "amphp/dns": "2.x-dev" }, diff --git a/composer.lock b/composer.lock index 2b07d24..890ad38 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "09b26d1017fd85d16a9cb71fc6048cdf", + "content-hash": "a2c43abdf6b1714d394368fda29ac6b4", "packages": [ { "name": "amphp/amp", @@ -4518,7 +4518,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.1", + "php": "^8.2", "ext-json": "*", "ext-mbstring": "*" }, From e8d0aa8e6ba3618d0e0f4cd22ff3fc3e8f46384c Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 27 May 2024 17:05:36 +0200 Subject: [PATCH 04/42] Update Dockerfile --- Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index da59608..7ff409a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,6 @@ RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local COPY --from=ghcr.io/ufoscout/docker-compose-wait:latest /wait /usr/local/bin/docker-compose-wait -ADD docker/php/conf.d/. "$PHP_INI_DIR/conf.d/" - EXPOSE 9503 -ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["./entrypoint.sh"] From 0f8ae6131952ec73b369f25c1e15a688d74d45ef Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 27 May 2024 17:07:23 +0200 Subject: [PATCH 05/42] Cleanup --- docker/php/conf.d/common.ini | 1 - docker/php/conf.d/opcache.ini | 11 ----------- 2 files changed, 12 deletions(-) delete mode 100644 docker/php/conf.d/common.ini delete mode 100644 docker/php/conf.d/opcache.ini diff --git a/docker/php/conf.d/common.ini b/docker/php/conf.d/common.ini deleted file mode 100644 index 7fc1f83..0000000 --- a/docker/php/conf.d/common.ini +++ /dev/null @@ -1 +0,0 @@ -zend.assertions=-1 \ No newline at end of file diff --git a/docker/php/conf.d/opcache.ini b/docker/php/conf.d/opcache.ini deleted file mode 100644 index 14ef174..0000000 --- a/docker/php/conf.d/opcache.ini +++ /dev/null @@ -1,11 +0,0 @@ -; Extended PHP.ini file to enable JIT. -; ==================================== -; Place this file under /usr/local/etc/php/conf.d/ -zend_extension=opcache.so -opcache.enable=1 -opcache.enable_cli=1 -opcache.validate_timestamps=1 -opcache.revalidate_freq=0 -opcache.huge_code_pages=1 -opcache.jit_buffer_size=100M -opcache.jit=function \ No newline at end of file From 77df7acbb10ef930b6d69aa31f7630e2f310dd30 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 6 Jun 2024 12:40:11 +0200 Subject: [PATCH 06/42] Fix --- Dockerfile-dev | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Dockerfile-dev b/Dockerfile-dev index edad447..0386dc4 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -1,12 +1,16 @@ FROM xtrime/telegram-api-server:latest -ADD docker/php/conf.d/. "$PHP_INI_DIR/conf.d/" +ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/ -RUN pecl install xdebug \ - && echo "" >> "$PHP_INI_DIR/conf.d/xdebug.ini" \ - && echo "zend_extension=xdebug.so" >> "$PHP_INI_DIR/conf.d/xdebug.ini" +RUN chmod +x /usr/local/bin/install-php-extensions && \ + install-php-extensions xdebug && \ + rm /usr/local/bin/install-php-extensions && \ + echo "" >> "$PHP_INI_DIR/conf.d/xdebug.ini" && \ + echo "zend_extension=xdebug.so" >> "$PHP_INI_DIR/conf.d/xdebug.ini" + +ADD docker/php/conf.d/. "$PHP_INI_DIR/conf.d/" EXPOSE 9503 EXPOSE 9003 -ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["./entrypoint.sh"] From 1266017bd91ddf4bf0b4d274c816b4125dcdc001 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 6 Jun 2024 12:48:15 +0200 Subject: [PATCH 07/42] Cleanup --- Dockerfile-dev | 6 +++--- docker/php/conf.d/xdebug.ini | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Dockerfile-dev b/Dockerfile-dev index 0386dc4..8392f50 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -2,11 +2,11 @@ FROM xtrime/telegram-api-server:latest ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/ +RUN echo "opcache.jit=disable" >> "$PHP_INI_DIR/conf.d/xdebug.ini" + RUN chmod +x /usr/local/bin/install-php-extensions && \ install-php-extensions xdebug && \ - rm /usr/local/bin/install-php-extensions && \ - echo "" >> "$PHP_INI_DIR/conf.d/xdebug.ini" && \ - echo "zend_extension=xdebug.so" >> "$PHP_INI_DIR/conf.d/xdebug.ini" + rm /usr/local/bin/install-php-extensions ADD docker/php/conf.d/. "$PHP_INI_DIR/conf.d/" diff --git a/docker/php/conf.d/xdebug.ini b/docker/php/conf.d/xdebug.ini index 4d11575..2ed9594 100644 --- a/docker/php/conf.d/xdebug.ini +++ b/docker/php/conf.d/xdebug.ini @@ -1,5 +1,8 @@ +opcache.jit=disable +zend_extension=xdebug.so + xdebug.max_nesting_level=512 xdebug.mode=debug xdebug.start_with_request=yes xdebug.client_host=host.docker.internal -xdebug.client_port=9003 \ No newline at end of file +xdebug.client_port=9003 From 888a6d9add6ef22f8eccdbbc8ee8ce9ca11d1485 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 10 Jun 2024 11:32:22 +0200 Subject: [PATCH 08/42] Bump --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7ff409a..e4f98c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM hub.madelineproto.xyz/danog/madelineproto:latest +FROM danog/madelineproto:latest RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer From 8037271a76be7b746b35fff49948804105057a13 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 17 Jun 2024 19:23:36 +0200 Subject: [PATCH 09/42] Add version check --- Dockerfile | 2 ++ entrypoint.sh | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/Dockerfile b/Dockerfile index e4f98c2..1e462e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,8 @@ RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local COPY --from=ghcr.io/ufoscout/docker-compose-wait:latest /wait /usr/local/bin/docker-compose-wait +RUN echo 1.0.0 > /tas_version + EXPOSE 9503 ENTRYPOINT ["./entrypoint.sh"] diff --git a/entrypoint.sh b/entrypoint.sh index 74a8b80..12659ca 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,4 +1,12 @@ #!/usr/bin/env sh +VERSION=1.0.0 +CURRENT_VERSION=$(cat /tas_version) + +if [ "$VERSION" != "$CURRENT_VERSION" ]; then + echo "Wrong docker image version, expected $VERSION, got $CURRENT_VERSION, please run docker compose pull!" + exit 1 +fi + docker-compose-wait \ && nice -n 20 php server.php -e=.env.docker --docker "$@" \ No newline at end of file From fc2face56523404e547e7c43c13a4c7cf8147aa4 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 17 Jun 2024 19:25:51 +0200 Subject: [PATCH 10/42] Bump --- Dockerfile-dev | 2 +- {docker/php/conf.d => dev}/xdebug.ini | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {docker/php/conf.d => dev}/xdebug.ini (100%) diff --git a/Dockerfile-dev b/Dockerfile-dev index 8392f50..5e129db 100644 --- a/Dockerfile-dev +++ b/Dockerfile-dev @@ -8,7 +8,7 @@ RUN chmod +x /usr/local/bin/install-php-extensions && \ install-php-extensions xdebug && \ rm /usr/local/bin/install-php-extensions -ADD docker/php/conf.d/. "$PHP_INI_DIR/conf.d/" +ADD dev/. "$PHP_INI_DIR/conf.d/" EXPOSE 9503 EXPOSE 9003 diff --git a/docker/php/conf.d/xdebug.ini b/dev/xdebug.ini similarity index 100% rename from docker/php/conf.d/xdebug.ini rename to dev/xdebug.ini From e310b235fa2ea954b65f6412187af2f4c893c3f6 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 20 Jun 2024 23:10:51 +0200 Subject: [PATCH 11/42] Async logger --- src/Logger.php | 44 ++++++++++++++++++++++++++++++++++++++++--- src/Server/Server.php | 1 + 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Logger.php b/src/Logger.php index bd0bf58..45a1306 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -11,6 +11,8 @@ namespace TelegramApiServer; +use Amp\ByteStream\Pipe; +use Amp\ByteStream\WritableStream; use danog\MadelineProto; use DateTimeInterface; use Psr\Log\AbstractLogger; @@ -18,6 +20,10 @@ use Psr\Log\InvalidArgumentException; use Psr\Log\LogLevel; use TelegramApiServer\EventObservers\LogObserver; use Throwable; + +use function Amp\async; +use function Amp\ByteStream\getStdout; +use function Amp\ByteStream\pipe; use function get_class; use function gettype; use function is_object; @@ -56,6 +62,12 @@ class Logger extends AbstractLogger public int $minLevelIndex; private array $formatter; + private WritableStream $stdout; + /** + * @var array + */ + private static array $closePromises = []; + protected function __construct(string $minLevel = LogLevel::WARNING, callable $formatter = null) { if (null === $minLevel) { @@ -83,7 +95,18 @@ class Logger extends AbstractLogger } $this->minLevelIndex = self::$levels[$minLevel]; - $this->formatter = $formatter ?: [$this, 'format']; + $this->formatter = $formatter ?: $this->format(...); + $pipe = new Pipe(PHP_INT_MAX); + $this->stdout = $pipe->getSink(); + $source = $pipe->getSource(); + $promise = async(static function () use ($source, &$promise): void { + try { + pipe($source, getStdout()); + } finally { + unset(self::$closePromises[spl_object_id($promise)]); + } + }); + self::$closePromises[spl_object_id($promise)] = [$this->stdout, $promise]; } public static function getInstance(): Logger @@ -114,8 +137,23 @@ class Logger extends AbstractLogger } $formatter = $this->formatter; - /** @see Logger::format */ - echo $formatter($level, $message, $context); + $data = $formatter($level, $message, $context);; + try { + $this->stdout->write($data); + } catch (\Throwable) { + echo $data; + } + } + + /** + * @internal Internal function used to flush the log buffer on shutdown. + */ + public static function finalize(): void + { + foreach (self::$closePromises as [$stdout, $promise]) { + $stdout->close(); + $promise->await(); + } } private function format(string $level, string $message, array $context): string diff --git a/src/Server/Server.php b/src/Server/Server.php index 718c9fd..36eccf8 100644 --- a/src/Server/Server.php +++ b/src/Server/Server.php @@ -70,6 +70,7 @@ class Server info("Stopping http server"); $server->stop(); } + Logger::finalize(); } /** From ed02ae5e7baccbc6173f88f31e7261f6915ff329 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 21 Jun 2024 19:24:10 +0200 Subject: [PATCH 12/42] Tweak levels --- src/Logger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Logger.php b/src/Logger.php index 45a1306..6267286 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -94,7 +94,7 @@ class Logger extends AbstractLogger throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $minLevel)); } - $this->minLevelIndex = self::$levels[$minLevel]; + $this->minLevelIndex = max(self::$levels[$minLevel], self::$levels[self::$madelineLevels[MadelineProto\Logger::VERBOSE]]); $this->formatter = $formatter ?: $this->format(...); $pipe = new Pipe(PHP_INT_MAX); $this->stdout = $pipe->getSink(); From c15162c9b909a4cadaffdec2786f48cc046933c4 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 21 Jun 2024 19:25:04 +0200 Subject: [PATCH 13/42] Tweak levels --- src/Logger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Logger.php b/src/Logger.php index 6267286..24853b7 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -94,7 +94,7 @@ class Logger extends AbstractLogger throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $minLevel)); } - $this->minLevelIndex = max(self::$levels[$minLevel], self::$levels[self::$madelineLevels[MadelineProto\Logger::VERBOSE]]); + $this->minLevelIndex = min(self::$levels[$minLevel], self::$levels[self::$madelineLevels[MadelineProto\Logger::VERBOSE]]); $this->formatter = $formatter ?: $this->format(...); $pipe = new Pipe(PHP_INT_MAX); $this->stdout = $pipe->getSink(); From 3766db022305040a097dbc643f08b5250ca08bf4 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 21 Jun 2024 19:29:12 +0200 Subject: [PATCH 14/42] Fixes --- src/Logger.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Logger.php b/src/Logger.php index 24853b7..5545913 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -60,7 +60,7 @@ class Logger extends AbstractLogger private static string $dateTimeFormat = 'Y-m-d H:i:s'; public int $minLevelIndex; - private array $formatter; + private \Closure $formatter; private WritableStream $stdout; /** @@ -68,7 +68,7 @@ class Logger extends AbstractLogger */ private static array $closePromises = []; - protected function __construct(string $minLevel = LogLevel::WARNING, callable $formatter = null) + protected function __construct(string $minLevel = LogLevel::WARNING, \Closure $formatter = null) { if (null === $minLevel) { if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) { From 7ce856e9c42d735666dbca5abb9b1d7f2f544414 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 21 Jun 2024 19:32:16 +0200 Subject: [PATCH 15/42] Remove redundant bulking --- src/Controllers/ApiController.php | 33 +------------------------------ 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/src/Controllers/ApiController.php b/src/Controllers/ApiController.php index 8bd7969..61814b8 100644 --- a/src/Controllers/ApiController.php +++ b/src/Controllers/ApiController.php @@ -44,37 +44,6 @@ class ApiController extends AbstractApiController return $this->callApiCommon($madelineProto); } - //GROUP REQUESTS IN BULKS - static $futures = []; - - $futures[] = $future = async($this->callApiCommon(...), $madelineProto); - delay($this->waitNextTick()); - - if ($futures) { - awaitAll($futures); - Logger::getInstance()->notice("Executed bulk requests:" . count($futures)); - $futures = []; - } - - return $future->await(); + return $this->callApiCommon($madelineProto); } - - /** - * Sync threads execution via time ticks - * Need to enable madelineProto futures bulk execution - * @param float $tick interval of execution in seconds. - */ - protected function waitNextTick(float $tick = 0.5): float { - $tickMs = $tick * 1000; - $now = (int)(microtime(true) * 1000); - $currentTick = intdiv((int)(microtime(true) * 1000), $tickMs); - $nextTick = ($currentTick + 1); - $nextTickTime = $nextTick * $tickMs; - $wait = round(($nextTickTime - $now)/1000, 3); - - Logger::getInstance()->notice("Waiting $wait seconds before tick"); - - return $wait; - } - } \ No newline at end of file From fa1190c06bc883da4ba2db090991f9d825eab459 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 21 Jun 2024 19:36:11 +0200 Subject: [PATCH 16/42] Bump --- src/Server/AccessLoggerMiddleware.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Server/AccessLoggerMiddleware.php b/src/Server/AccessLoggerMiddleware.php index a31194d..14eb60e 100644 --- a/src/Server/AccessLoggerMiddleware.php +++ b/src/Server/AccessLoggerMiddleware.php @@ -58,7 +58,7 @@ class AccessLoggerMiddleware implements Middleware ], ]; - $level = $status < 400 ? LogLevel::INFO : LogLevel::NOTICE; + $level = $status < 400 ? LogLevel::DEBUG : LogLevel::INFO; $this->logger->log( $level, From 8d321fec31749b96f1a6c85701f522ca2c1366e3 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 24 Jun 2024 12:00:57 +0200 Subject: [PATCH 17/42] Bump --- entrypoint.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/entrypoint.sh b/entrypoint.sh index 12659ca..31278c8 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -8,5 +8,7 @@ if [ "$VERSION" != "$CURRENT_VERSION" ]; then exit 1 fi +composer update + docker-compose-wait \ && nice -n 20 php server.php -e=.env.docker --docker "$@" \ No newline at end of file From b3d8cdd6a4430c1b750c123cb88b8a9eece96c25 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 26 Jun 2024 22:28:58 +0200 Subject: [PATCH 18/42] Bump --- server.php | 3 --- src/Migrations/StartUpFixes.php | 9 --------- 2 files changed, 12 deletions(-) diff --git a/server.php b/server.php index 3f20601..78fbaa1 100644 --- a/server.php +++ b/server.php @@ -83,9 +83,6 @@ foreach ($options['session'] as $session) { } StartUpFixes::fix(); -foreach ($sessions as $session) { - StartUpFixes::removeBrokenIpc($session); -} new TelegramApiServer\Server\Server( $options, diff --git a/src/Migrations/StartUpFixes.php b/src/Migrations/StartUpFixes.php index 8b93fa8..bbd78e7 100644 --- a/src/Migrations/StartUpFixes.php +++ b/src/Migrations/StartUpFixes.php @@ -8,13 +8,4 @@ class StartUpFixes { define('MADELINE_WORKER_TYPE', 'madeline-ipc'); } - - public static function removeBrokenIpc(string $session): void - { - info('Removing ipc sockets from sessions to fix startup' . PHP_EOL); - foreach (glob(ROOT_DIR . "/$session/*ipc") as $file) { - info("removing: $file"); - unlink($file); - } - } } \ No newline at end of file From ba8a8730a505e0e868c94ba1f572acde5cbc829e Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 26 Jun 2024 22:30:15 +0200 Subject: [PATCH 19/42] Bump --- src/Migrations/StartUpFixes.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Migrations/StartUpFixes.php b/src/Migrations/StartUpFixes.php index bbd78e7..f454f57 100644 --- a/src/Migrations/StartUpFixes.php +++ b/src/Migrations/StartUpFixes.php @@ -2,10 +2,13 @@ namespace TelegramApiServer\Migrations; +use danog\MadelineProto\Magic; + class StartUpFixes { public static function fix(): void { define('MADELINE_WORKER_TYPE', 'madeline-ipc'); + Magic::$isIpcWorker = true; } } \ No newline at end of file From 561fec0a12fcd6f6c1c022f3d93ad4226e16babc Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 26 Jun 2024 22:36:58 +0200 Subject: [PATCH 20/42] Add mutex --- src/Client.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Client.php b/src/Client.php index bc6c2a3..a0363bd 100644 --- a/src/Client.php +++ b/src/Client.php @@ -2,6 +2,7 @@ namespace TelegramApiServer; +use Amp\Sync\LocalKeyedMutex; use danog\MadelineProto\API; use danog\MadelineProto\APIWrapper; use danog\MadelineProto\Settings; @@ -47,8 +48,11 @@ class Client ); } + private LocalKeyedMutex $mutex; + public function addSession(string $session, array $settings = []): API { + $lock = $this->mutex->acquire($session); if (isset($this->instances[$session])) { throw new InvalidArgumentException('Session already exists'); } From 40d16c372a6b2aa1201c642d99db47502c0fbcda Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 26 Jun 2024 22:39:03 +0200 Subject: [PATCH 21/42] Add mutex --- src/Client.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Client.php b/src/Client.php index a0363bd..06b9fbf 100644 --- a/src/Client.php +++ b/src/Client.php @@ -52,6 +52,7 @@ class Client public function addSession(string $session, array $settings = []): API { + $this->mutex ??= new LocalKeyedMutex; $lock = $this->mutex->acquire($session); if (isset($this->instances[$session])) { throw new InvalidArgumentException('Session already exists'); From 083c933ad38a33cca979dc58c5be5ae3ca6ab5e8 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 26 Jun 2024 22:39:31 +0200 Subject: [PATCH 22/42] Add mutex --- src/Client.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Client.php b/src/Client.php index 06b9fbf..62f7c33 100644 --- a/src/Client.php +++ b/src/Client.php @@ -48,12 +48,12 @@ class Client ); } - private LocalKeyedMutex $mutex; + private static LocalKeyedMutex $mutex; public function addSession(string $session, array $settings = []): API { - $this->mutex ??= new LocalKeyedMutex; - $lock = $this->mutex->acquire($session); + self::$mutex ??= new LocalKeyedMutex; + $lock = self::$mutex->acquire($session); if (isset($this->instances[$session])) { throw new InvalidArgumentException('Session already exists'); } From 2bb762af76b6bba2a433e51df122ed91b2520a10 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 26 Jun 2024 22:39:51 +0200 Subject: [PATCH 23/42] Bump --- composer.lock | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/composer.lock b/composer.lock index 890ad38..f21aef7 100644 --- a/composer.lock +++ b/composer.lock @@ -2646,12 +2646,12 @@ "source": { "type": "git", "url": "https://github.com/danog/MadelineProto.git", - "reference": "050d934015299689b11f1b14cd0055b07aa03694" + "reference": "d5c1634ecfac473ce91f681c905a812a6ee7b303" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/danog/MadelineProto/zipball/050d934015299689b11f1b14cd0055b07aa03694", - "reference": "050d934015299689b11f1b14cd0055b07aa03694", + "url": "https://api.github.com/repos/danog/MadelineProto/zipball/d5c1634ecfac473ce91f681c905a812a6ee7b303", + "reference": "d5c1634ecfac473ce91f681c905a812a6ee7b303", "shasum": "" }, "require": { @@ -2766,7 +2766,7 @@ "type": "github" } ], - "time": "2024-05-23T15:33:19+00:00" + "time": "2024-06-13T15:22:29+00:00" }, { "name": "danog/primemodule", @@ -3611,24 +3611,24 @@ }, { "name": "paragonie/constant_time_encoding", - "version": "v2.7.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105" + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/52a0d99e69f56b9ec27ace92ba56897fe6993105", - "reference": "52a0d99e69f56b9ec27ace92ba56897fe6993105", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512", + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512", "shasum": "" }, "require": { - "php": "^7|^8" + "php": "^8" }, "require-dev": { - "phpunit/phpunit": "^6|^7|^8|^9", - "vimeo/psalm": "^1|^2|^3|^4" + "phpunit/phpunit": "^9", + "vimeo/psalm": "^4|^5" }, "type": "library", "autoload": { @@ -3674,7 +3674,7 @@ "issues": "https://github.com/paragonie/constant_time_encoding/issues", "source": "https://github.com/paragonie/constant_time_encoding" }, - "time": "2024-05-08T12:18:48+00:00" + "time": "2024-05-08T12:36:18+00:00" }, { "name": "paragonie/random_compat", @@ -3803,20 +3803,20 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.37", + "version": "3.0.39", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8" + "reference": "211ebc399c6e73c225a018435fe5ae209d1d1485" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8", - "reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/211ebc399c6e73c225a018435fe5ae209d1d1485", + "reference": "211ebc399c6e73c225a018435fe5ae209d1d1485", "shasum": "" }, "require": { - "paragonie/constant_time_encoding": "^1|^2", + "paragonie/constant_time_encoding": "^1|^2|^3", "paragonie/random_compat": "^1.4|^2.0|^9.99.99", "php": ">=5.6.1" }, @@ -3893,7 +3893,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.37" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.39" }, "funding": [ { @@ -3909,7 +3909,7 @@ "type": "tidelift" } ], - "time": "2024-03-03T02:14:58+00:00" + "time": "2024-06-24T06:27:33+00:00" }, { "name": "promphp/prometheus_client_php", @@ -4210,16 +4210,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", "shasum": "" }, "require": { @@ -4269,7 +4269,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" }, "funding": [ { @@ -4285,20 +4285,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -4349,7 +4349,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -4365,7 +4365,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "vlucas/phpdotenv", From ab12a696692cf02de427b9943e7046efd2160ee8 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 27 Jun 2024 18:46:38 +0200 Subject: [PATCH 24/42] Bump --- entrypoint.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 31278c8..e985466 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -8,7 +8,7 @@ if [ "$VERSION" != "$CURRENT_VERSION" ]; then exit 1 fi -composer update +composer install docker-compose-wait \ -&& nice -n 20 php server.php -e=.env.docker --docker "$@" \ No newline at end of file +&& nice -n 20 php server.php -e=.env.docker --docker "$@" From a7d760a72b254188cc392d621701d7fe186942bc Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 27 Jun 2024 18:47:45 +0200 Subject: [PATCH 25/42] Bump --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index f21aef7..f8ae9f8 100644 --- a/composer.lock +++ b/composer.lock @@ -2646,12 +2646,12 @@ "source": { "type": "git", "url": "https://github.com/danog/MadelineProto.git", - "reference": "d5c1634ecfac473ce91f681c905a812a6ee7b303" + "reference": "228bb623fea0693a6a904170e03b6f7acfae21fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/danog/MadelineProto/zipball/d5c1634ecfac473ce91f681c905a812a6ee7b303", - "reference": "d5c1634ecfac473ce91f681c905a812a6ee7b303", + "url": "https://api.github.com/repos/danog/MadelineProto/zipball/228bb623fea0693a6a904170e03b6f7acfae21fc", + "reference": "228bb623fea0693a6a904170e03b6f7acfae21fc", "shasum": "" }, "require": { @@ -2766,7 +2766,7 @@ "type": "github" } ], - "time": "2024-06-13T15:22:29+00:00" + "time": "2024-06-27T16:47:08+00:00" }, { "name": "danog/primemodule", From e15017899a660544afc562b4fee1166f1c28e30c Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 27 Jun 2024 18:53:04 +0200 Subject: [PATCH 26/42] bump --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index f8ae9f8..001b63c 100644 --- a/composer.lock +++ b/composer.lock @@ -2646,12 +2646,12 @@ "source": { "type": "git", "url": "https://github.com/danog/MadelineProto.git", - "reference": "228bb623fea0693a6a904170e03b6f7acfae21fc" + "reference": "cb0743446bcddb821ce556d2f8a131f1da26d976" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/danog/MadelineProto/zipball/228bb623fea0693a6a904170e03b6f7acfae21fc", - "reference": "228bb623fea0693a6a904170e03b6f7acfae21fc", + "url": "https://api.github.com/repos/danog/MadelineProto/zipball/cb0743446bcddb821ce556d2f8a131f1da26d976", + "reference": "cb0743446bcddb821ce556d2f8a131f1da26d976", "shasum": "" }, "require": { @@ -2766,7 +2766,7 @@ "type": "github" } ], - "time": "2024-06-27T16:47:08+00:00" + "time": "2024-06-27T16:52:00+00:00" }, { "name": "danog/primemodule", From e0c9f9afe5dbd073c7fac72995295f7ee9ebb752 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 27 Jun 2024 19:19:22 +0200 Subject: [PATCH 27/42] BUmp --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 001b63c..8fb29c5 100644 --- a/composer.lock +++ b/composer.lock @@ -2646,12 +2646,12 @@ "source": { "type": "git", "url": "https://github.com/danog/MadelineProto.git", - "reference": "cb0743446bcddb821ce556d2f8a131f1da26d976" + "reference": "49175f00b4b75d4ba4dd8c91b81a6747e9e0da31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/danog/MadelineProto/zipball/cb0743446bcddb821ce556d2f8a131f1da26d976", - "reference": "cb0743446bcddb821ce556d2f8a131f1da26d976", + "url": "https://api.github.com/repos/danog/MadelineProto/zipball/49175f00b4b75d4ba4dd8c91b81a6747e9e0da31", + "reference": "49175f00b4b75d4ba4dd8c91b81a6747e9e0da31", "shasum": "" }, "require": { @@ -2766,7 +2766,7 @@ "type": "github" } ], - "time": "2024-06-27T16:52:00+00:00" + "time": "2024-06-27T17:14:22+00:00" }, { "name": "danog/primemodule", From 2cf0f8b6e8aceafae846c1ddfc6bab67d884e4da Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 27 Jun 2024 19:49:38 +0200 Subject: [PATCH 28/42] Bump --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 8fb29c5..001b63c 100644 --- a/composer.lock +++ b/composer.lock @@ -2646,12 +2646,12 @@ "source": { "type": "git", "url": "https://github.com/danog/MadelineProto.git", - "reference": "49175f00b4b75d4ba4dd8c91b81a6747e9e0da31" + "reference": "cb0743446bcddb821ce556d2f8a131f1da26d976" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/danog/MadelineProto/zipball/49175f00b4b75d4ba4dd8c91b81a6747e9e0da31", - "reference": "49175f00b4b75d4ba4dd8c91b81a6747e9e0da31", + "url": "https://api.github.com/repos/danog/MadelineProto/zipball/cb0743446bcddb821ce556d2f8a131f1da26d976", + "reference": "cb0743446bcddb821ce556d2f8a131f1da26d976", "shasum": "" }, "require": { @@ -2766,7 +2766,7 @@ "type": "github" } ], - "time": "2024-06-27T17:14:22+00:00" + "time": "2024-06-27T16:52:00+00:00" }, { "name": "danog/primemodule", From 41d37e28c5c27fa42e51ff8e25d5b29b11f71858 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sun, 30 Jun 2024 16:05:29 +0200 Subject: [PATCH 29/42] Use self --- src/Client.php | 6 ++--- src/Config.php | 6 ++--- src/EventObservers/EventHandler.php | 6 ++--- src/EventObservers/EventObserver.php | 24 +++++++++---------- src/EventObservers/LogObserver.php | 2 +- src/EventObservers/ObserverTrait.php | 8 +++---- src/Files.php | 10 ++++---- src/Logger.php | 12 +++++----- src/MadelineProtoExtensions/ApiExtensions.php | 8 +++---- 9 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/Client.php b/src/Client.php index 62f7c33..5959146 100644 --- a/src/Client.php +++ b/src/Client.php @@ -23,10 +23,10 @@ class Client public static function getInstance(): Client { - if (empty(static::$self)) { - static::$self = new static(); + if (empty(self::$self)) { + self::$self = new static(); } - return static::$self; + return self::$self; } public function connect(array $sessionFiles) diff --git a/src/Config.php b/src/Config.php index 27d2ad7..d2e4845 100644 --- a/src/Config.php +++ b/src/Config.php @@ -11,11 +11,11 @@ class Config public static function getInstance(): Config { - if (null === static::$instance) { - static::$instance = new static(); + if (null === self::$instance) { + self::$instance = new static(); } - return static::$instance; + return self::$instance; } /** diff --git a/src/EventObservers/EventHandler.php b/src/EventObservers/EventHandler.php index 7a045d9..9f3565a 100644 --- a/src/EventObservers/EventHandler.php +++ b/src/EventObservers/EventHandler.php @@ -12,8 +12,8 @@ class EventHandler extends \danog\MadelineProto\EventHandler public function onStart() { $this->sessionName = Files::getSessionName($this->wrapper->getSession()->getSessionPath()); - if (empty(static::$instances[$this->sessionName])) { - static::$instances[$this->sessionName] = true; + if (empty(self::$instances[$this->sessionName])) { + self::$instances[$this->sessionName] = true; warning("Event observer CONSTRUCTED: {$this->sessionName}"); } } @@ -23,7 +23,7 @@ class EventHandler extends \danog\MadelineProto\EventHandler if (empty($this->sessionName)) { return; } - unset(static::$instances[$this->sessionName]); + unset(self::$instances[$this->sessionName]); warning("Event observer DESTRUCTED: {$this->sessionName}"); } diff --git a/src/EventObservers/EventObserver.php b/src/EventObservers/EventObserver.php index 47b42bc..70a2112 100644 --- a/src/EventObservers/EventObserver.php +++ b/src/EventObservers/EventObserver.php @@ -18,7 +18,7 @@ class EventObserver public static function notify(array $update, string $sessionName) { - foreach (static::$subscribers as $clientId => $callback) { + foreach (self::$subscribers as $clientId => $callback) { notice("Pass update to callback. ClientId: {$clientId}"); $callback($update, $sessionName); } @@ -26,16 +26,16 @@ class EventObserver private static function addSessionClient(string $session): void { - if (empty(static::$sessionClients[$session])) { - static::$sessionClients[$session] = 0; + if (empty(self::$sessionClients[$session])) { + self::$sessionClients[$session] = 0; } - ++static::$sessionClients[$session]; + ++self::$sessionClients[$session]; } private static function removeSessionClient(string $session): void { - if (!empty(static::$sessionClients[$session])) { - --static::$sessionClients[$session]; + if (!empty(self::$sessionClients[$session])) { + --self::$sessionClients[$session]; } } @@ -49,8 +49,8 @@ class EventObserver } foreach ($sessions as $session) { - static::addSessionClient($session); - if (static::$sessionClients[$session] === 1) { + self::addSessionClient($session); + if (self::$sessionClients[$session] === 1) { warning("Start EventHandler: {$session}"); try { $instance = Client::getInstance()->getSession($session); @@ -60,7 +60,7 @@ class EventObserver EventHandler::cachePlugins(EventHandler::class); $wrapper->getAPI()->setEventHandler(EventHandler::class); } catch (Throwable $e) { - static::removeSessionClient($session); + self::removeSessionClient($session); error('Cant set EventHandler', [ 'session' => $session, 'exception' => Logger::getExceptionAsArray($e), @@ -79,11 +79,11 @@ class EventObserver $sessions[] = $requestedSession; } foreach ($sessions as $session) { - static::removeSessionClient($session); - if (empty(static::$sessionClients[$session]) || $force) { + self::removeSessionClient($session); + if (empty(self::$sessionClients[$session]) || $force) { warning("Stopping EventHandler: {$session}"); Client::getInstance()->instances[$session]->unsetEventHandler(); - unset(EventHandler::$instances[$session], static::$sessionClients[$session]); + unset(EventHandler::$instances[$session], self::$sessionClients[$session]); } } diff --git a/src/EventObservers/LogObserver.php b/src/EventObservers/LogObserver.php index e6b08f3..dd71990 100644 --- a/src/EventObservers/LogObserver.php +++ b/src/EventObservers/LogObserver.php @@ -11,7 +11,7 @@ class LogObserver public static function notify(string $level, string $message, array $context = []): void { - foreach (static::$subscribers as $clientId => $callback) { + foreach (self::$subscribers as $clientId => $callback) { $callback($level, $message, $context); } } diff --git a/src/EventObservers/ObserverTrait.php b/src/EventObservers/ObserverTrait.php index b02b3c5..a595b9e 100644 --- a/src/EventObservers/ObserverTrait.php +++ b/src/EventObservers/ObserverTrait.php @@ -11,17 +11,17 @@ trait ObserverTrait public static function addSubscriber($clientId, callable $callback): void { notice("Add event listener. ClientId: {$clientId}"); - static::$subscribers[$clientId] = $callback; + self::$subscribers[$clientId] = $callback; } public static function removeSubscriber($clientId): void { notice("Removing listener: {$clientId}"); - unset(static::$subscribers[$clientId]); - $listenersCount = count(static::$subscribers); + unset(self::$subscribers[$clientId]); + $listenersCount = count(self::$subscribers); notice("Event listeners left: {$listenersCount}"); if ($listenersCount === 0) { - static::$subscribers = []; + self::$subscribers = []; } } } \ No newline at end of file diff --git a/src/Files.php b/src/Files.php index c98956e..30cfdb4 100644 --- a/src/Files.php +++ b/src/Files.php @@ -29,7 +29,7 @@ class Files } preg_match( - '~' . static::SESSION_FOLDER . "/(?'sessionName'.*?)" . static::SESSION_EXTENSION . '~', + '~' . self::SESSION_FOLDER . "/(?'sessionName'.*?)" . self::SESSION_EXTENSION . '~', $sessionFile, $matches ); @@ -50,14 +50,14 @@ class Files return null; } $session = trim(trim($session), '/'); - $session = static::SESSION_FOLDER . '/' . $session . $extension; + $session = self::SESSION_FOLDER . '/' . $session . $extension; $session = str_replace('//', '/', $session); return $session; } public static function getSessionSettings(string $session): array { - $settingsFile = static::getSessionFile($session, static::SETTINGS_EXTENSION); + $settingsFile = self::getSessionFile($session, self::SETTINGS_EXTENSION); $settings = []; if (file_exists($settingsFile)) { $settings = json_decode( @@ -73,7 +73,7 @@ class Files public static function saveSessionSettings(string $session, array $settings = []): void { - $settingsFile = static::getSessionFile($session, static::SETTINGS_EXTENSION); + $settingsFile = self::getSessionFile($session, self::SETTINGS_EXTENSION); file_put_contents( $settingsFile, json_encode( @@ -91,7 +91,7 @@ class Files { $files = glob($pattern, $flags) ?: []; foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) { - $files = [...$files, ...static::globRecursive($dir . '/' . basename($pattern), $flags)]; + $files = [...$files, ...self::globRecursive($dir . '/' . basename($pattern), $flags)]; } return $files; } diff --git a/src/Logger.php b/src/Logger.php index 5545913..3cfd1f5 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -111,14 +111,14 @@ class Logger extends AbstractLogger public static function getInstance(): Logger { - if (!static::$instanse) { + if (!self::$instanse) { $settings = Config::getInstance()->get('telegram'); - $loggerLevel = static::$madelineLevels[$settings['logger']['level']]; - static::$instanse = new static($loggerLevel); + $loggerLevel = self::$madelineLevels[$settings['logger']['level']]; + self::$instanse = new static($loggerLevel); } - return static::$instanse; + return self::$instanse; } /** @@ -168,7 +168,7 @@ class Logger extends AbstractLogger $replacements["{{$key}}"] = $val; } else { if ($val instanceof DateTimeInterface) { - $replacements["{{$key}}"] = $val->format(static::$dateTimeFormat); + $replacements["{{$key}}"] = $val->format(self::$dateTimeFormat); } else { if (is_object($val)) { $replacements["{{$key}}"] = '[object ' . get_class($val) . ']'; @@ -184,7 +184,7 @@ class Logger extends AbstractLogger return sprintf( '[%s] [%s] %s %s', - date(static::$dateTimeFormat), + date(self::$dateTimeFormat), $level, $message, $context ? diff --git a/src/MadelineProtoExtensions/ApiExtensions.php b/src/MadelineProtoExtensions/ApiExtensions.php index c0c8b73..874bf17 100644 --- a/src/MadelineProtoExtensions/ApiExtensions.php +++ b/src/MadelineProtoExtensions/ApiExtensions.php @@ -96,7 +96,7 @@ class ApiExtensions $textFormated = sprintf($template, $text); } - $message = static::substringReplace($message, $textFormated, $entity['offset'], $entity['length']); + $message = self::substringReplace($message, $textFormated, $entity['offset'], $entity['length']); //Увеличим оффсеты всех следующих entity foreach ($entities as $nextKey => &$nextEntity) { @@ -167,7 +167,7 @@ class ApiExtensions 'peer' => $data['to_peer'], 'entities' => $message['entities'] ?? [], ]; - if (static::hasMedia($message, false)) { + if (self::hasMedia($message, false)) { $messageData['media'] = $message; //MadelineProto сама достанет все media из сообщения. $result[] = $this->madelineProto->messages->sendMedia(...$messageData); } else { @@ -203,7 +203,7 @@ class ApiExtensions throw new NoMediaException('Empty message'); } - if (!static::hasMedia($message, true)) { + if (!self::hasMedia($message, true)) { throw new NoMediaException('Message has no media'); } @@ -246,7 +246,7 @@ class ApiExtensions throw new NoMediaException('Empty message'); } - if (!static::hasMedia($message, true)) { + if (!self::hasMedia($message, true)) { throw new NoMediaException('Message has no media'); } From 2871122256dd8512cbbb4c5ceecdfdad36e9efcb Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sun, 30 Jun 2024 16:06:07 +0200 Subject: [PATCH 30/42] Cleanup --- src/Client.php | 2 +- src/Config.php | 2 +- src/Controllers/ApiController.php | 2 +- src/Controllers/EventsController.php | 2 +- src/Controllers/LogController.php | 2 +- src/Controllers/SystemController.php | 2 +- src/EventObservers/EventHandler.php | 2 +- src/EventObservers/EventObserver.php | 2 +- src/EventObservers/LogObserver.php | 2 +- src/Exceptions/NoMediaException.php | 2 +- src/Exceptions/NoticeException.php | 2 +- src/Files.php | 2 +- src/Logger.php | 2 +- src/MadelineProtoExtensions/ApiExtensions.php | 2 +- src/MadelineProtoExtensions/SystemApiExtensions.php | 2 +- src/Migrations/StartUpFixes.php | 2 +- src/Server/AccessLoggerMiddleware.php | 2 +- src/Server/Authorization.php | 2 +- src/Server/ErrorResponses.php | 2 +- src/Server/Router.php | 2 +- src/Server/Server.php | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Client.php b/src/Client.php index 5959146..4dab926 100644 --- a/src/Client.php +++ b/src/Client.php @@ -15,7 +15,7 @@ use RuntimeException; use TelegramApiServer\EventObservers\EventHandler; use TelegramApiServer\EventObservers\EventObserver; -class Client +final class Client { public static Client $self; /** @var API[] */ diff --git a/src/Config.php b/src/Config.php index d2e4845..024c276 100644 --- a/src/Config.php +++ b/src/Config.php @@ -4,7 +4,7 @@ namespace TelegramApiServer; -class Config +final class Config { private static ?Config $instance = null; private array $config; diff --git a/src/Controllers/ApiController.php b/src/Controllers/ApiController.php index 61814b8..34b038f 100644 --- a/src/Controllers/ApiController.php +++ b/src/Controllers/ApiController.php @@ -15,7 +15,7 @@ use function Amp\async; use function Amp\delay; use function Amp\Future\awaitAll; -class ApiController extends AbstractApiController +final class ApiController extends AbstractApiController { private ?string $session = ''; diff --git a/src/Controllers/EventsController.php b/src/Controllers/EventsController.php index 9d35878..992b3aa 100644 --- a/src/Controllers/EventsController.php +++ b/src/Controllers/EventsController.php @@ -20,7 +20,7 @@ use TelegramApiServer\EventObservers\EventObserver; use TelegramApiServer\Logger; use Throwable; -class EventsController implements WebsocketClientHandler, WebsocketAcceptor +final class EventsController implements WebsocketClientHandler, WebsocketAcceptor { private const PING_INTERVAL_MS = 10_000; private WebsocketClientGateway $gateway; diff --git a/src/Controllers/LogController.php b/src/Controllers/LogController.php index 0f4bb14..1f6dbf6 100644 --- a/src/Controllers/LogController.php +++ b/src/Controllers/LogController.php @@ -17,7 +17,7 @@ use Revolt\EventLoop; use TelegramApiServer\EventObservers\LogObserver; use TelegramApiServer\Logger; -class LogController implements WebsocketClientHandler, WebsocketAcceptor +final class LogController implements WebsocketClientHandler, WebsocketAcceptor { private const PING_INTERVAL_MS = 10_000; private WebsocketClientGateway $gateway; diff --git a/src/Controllers/SystemController.php b/src/Controllers/SystemController.php index 1159b4c..9ea2831 100644 --- a/src/Controllers/SystemController.php +++ b/src/Controllers/SystemController.php @@ -5,7 +5,7 @@ namespace TelegramApiServer\Controllers; use Exception; use TelegramApiServer\Client; -class SystemController extends AbstractApiController +final class SystemController extends AbstractApiController { /** * Получаем параметры из uri diff --git a/src/EventObservers/EventHandler.php b/src/EventObservers/EventHandler.php index 9f3565a..b231d72 100644 --- a/src/EventObservers/EventHandler.php +++ b/src/EventObservers/EventHandler.php @@ -4,7 +4,7 @@ namespace TelegramApiServer\EventObservers; use TelegramApiServer\Files; -class EventHandler extends \danog\MadelineProto\EventHandler +final class EventHandler extends \danog\MadelineProto\EventHandler { public static array $instances = []; private string $sessionName; diff --git a/src/EventObservers/EventObserver.php b/src/EventObservers/EventObserver.php index 70a2112..174c428 100644 --- a/src/EventObservers/EventObserver.php +++ b/src/EventObservers/EventObserver.php @@ -9,7 +9,7 @@ use TelegramApiServer\Client; use TelegramApiServer\Logger; use Throwable; -class EventObserver +final class EventObserver { use ObserverTrait; diff --git a/src/EventObservers/LogObserver.php b/src/EventObservers/LogObserver.php index dd71990..c457deb 100644 --- a/src/EventObservers/LogObserver.php +++ b/src/EventObservers/LogObserver.php @@ -5,7 +5,7 @@ namespace TelegramApiServer\EventObservers; use TelegramApiServer\Logger; use Throwable; -class LogObserver +final class LogObserver { use ObserverTrait; diff --git a/src/Exceptions/NoMediaException.php b/src/Exceptions/NoMediaException.php index 2e17e87..73476ff 100644 --- a/src/Exceptions/NoMediaException.php +++ b/src/Exceptions/NoMediaException.php @@ -2,7 +2,7 @@ namespace TelegramApiServer\Exceptions; -class NoMediaException extends NoticeException +final class NoMediaException extends NoticeException { } \ No newline at end of file diff --git a/src/Exceptions/NoticeException.php b/src/Exceptions/NoticeException.php index 54e8d22..f488fb6 100644 --- a/src/Exceptions/NoticeException.php +++ b/src/Exceptions/NoticeException.php @@ -4,7 +4,7 @@ namespace TelegramApiServer\Exceptions; use Exception; -class NoticeException extends Exception +final class NoticeException extends Exception { } \ No newline at end of file diff --git a/src/Files.php b/src/Files.php index 30cfdb4..e8a6164 100644 --- a/src/Files.php +++ b/src/Files.php @@ -4,7 +4,7 @@ namespace TelegramApiServer; use RuntimeException; -class Files +final class Files { public const SESSION_EXTENSION = '.madeline'; diff --git a/src/Logger.php b/src/Logger.php index 3cfd1f5..7bf2951 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -34,7 +34,7 @@ use const PHP_EOL; * * @author Kévin Dunglas */ -class Logger extends AbstractLogger +final class Logger extends AbstractLogger { private static ?Logger $instanse = null; diff --git a/src/MadelineProtoExtensions/ApiExtensions.php b/src/MadelineProtoExtensions/ApiExtensions.php index 874bf17..074b241 100644 --- a/src/MadelineProtoExtensions/ApiExtensions.php +++ b/src/MadelineProtoExtensions/ApiExtensions.php @@ -15,7 +15,7 @@ use TelegramApiServer\EventObservers\EventHandler; use TelegramApiServer\Exceptions\NoMediaException; use function Amp\delay; -class ApiExtensions +final class ApiExtensions { private MadelineProto\Api $madelineProto; diff --git a/src/MadelineProtoExtensions/SystemApiExtensions.php b/src/MadelineProtoExtensions/SystemApiExtensions.php index a78a223..c119003 100644 --- a/src/MadelineProtoExtensions/SystemApiExtensions.php +++ b/src/MadelineProtoExtensions/SystemApiExtensions.php @@ -13,7 +13,7 @@ use function Amp\async; use function Amp\File\deleteFile; use function Amp\Future\awaitAll; -class SystemApiExtensions +final class SystemApiExtensions { private Client $client; diff --git a/src/Migrations/StartUpFixes.php b/src/Migrations/StartUpFixes.php index f454f57..a443dea 100644 --- a/src/Migrations/StartUpFixes.php +++ b/src/Migrations/StartUpFixes.php @@ -4,7 +4,7 @@ namespace TelegramApiServer\Migrations; use danog\MadelineProto\Magic; -class StartUpFixes +final class StartUpFixes { public static function fix(): void { diff --git a/src/Server/AccessLoggerMiddleware.php b/src/Server/AccessLoggerMiddleware.php index 14eb60e..28ca0db 100644 --- a/src/Server/AccessLoggerMiddleware.php +++ b/src/Server/AccessLoggerMiddleware.php @@ -9,7 +9,7 @@ use Amp\Http\Server\Response; use Psr\Log\LoggerInterface as PsrLogger; use Psr\Log\LogLevel; -class AccessLoggerMiddleware implements Middleware +final class AccessLoggerMiddleware implements Middleware { public function __construct( private readonly PsrLogger $logger, diff --git a/src/Server/Authorization.php b/src/Server/Authorization.php index b4db07e..07c28d3 100644 --- a/src/Server/Authorization.php +++ b/src/Server/Authorization.php @@ -9,7 +9,7 @@ use Amp\Http\Server\RequestHandler; use Amp\Http\Server\Response; use TelegramApiServer\Config; -class Authorization implements Middleware +final class Authorization implements Middleware { private array $ipWhitelist; private int $selfIp; diff --git a/src/Server/ErrorResponses.php b/src/Server/ErrorResponses.php index ba5307d..1ce3b46 100644 --- a/src/Server/ErrorResponses.php +++ b/src/Server/ErrorResponses.php @@ -5,7 +5,7 @@ namespace TelegramApiServer\Server; use Amp\Http\Server\Response; use TelegramApiServer\Controllers\AbstractApiController; -class ErrorResponses +final class ErrorResponses { /** * @param int $status diff --git a/src/Server/Router.php b/src/Server/Router.php index 7e96fb1..82650a3 100644 --- a/src/Server/Router.php +++ b/src/Server/Router.php @@ -16,7 +16,7 @@ use TelegramApiServer\MadelineProtoExtensions\ApiExtensions; use TelegramApiServer\MadelineProtoExtensions\SystemApiExtensions; use function Amp\Http\Server\Middleware\stackMiddleware; -class Router +final class Router { private \Amp\Http\Server\Router $router; private SocketHttpServer $server; diff --git a/src/Server/Server.php b/src/Server/Server.php index 36eccf8..6309dd2 100644 --- a/src/Server/Server.php +++ b/src/Server/Server.php @@ -18,7 +18,7 @@ use function sprintf; use const SIGINT; use const SIGTERM; -class Server +final class Server { /** * Server constructor. From 0580754d6282c090778f5da235f4e03bec771c62 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sun, 30 Jun 2024 16:07:42 +0200 Subject: [PATCH 31/42] cs-fix --- composer.json | 6 + composer.lock | 2385 ++++++++++++++++- examples/websocket-events.php | 7 +- src/Client.php | 34 +- src/Config.php | 14 +- src/Controllers/AbstractApiController.php | 50 +- src/Controllers/ApiController.php | 18 +- src/Controllers/EventsController.php | 10 +- src/Controllers/LogController.php | 8 +- src/Controllers/SystemController.php | 10 +- src/EventObservers/EventHandler.php | 2 +- src/EventObservers/EventObserver.php | 9 +- src/EventObservers/LogObserver.php | 14 +- src/EventObservers/ObserverTrait.php | 7 +- src/Exceptions/NoMediaException.php | 4 +- src/Exceptions/NoticeException.php | 4 +- src/Files.php | 43 +- src/Logger.php | 58 +- src/MadelineProtoExtensions/ApiExtensions.php | 61 +- .../SystemApiExtensions.php | 22 +- src/Migrations/StartUpFixes.php | 6 +- src/Server/AccessLoggerMiddleware.php | 4 +- src/Server/Authorization.php | 24 +- src/Server/ErrorResponses.php | 8 +- src/Server/Router.php | 7 +- src/Server/Server.php | 34 +- 26 files changed, 2583 insertions(+), 266 deletions(-) diff --git a/composer.json b/composer.json index 76d2a88..ca916f8 100644 --- a/composer.json +++ b/composer.json @@ -37,6 +37,9 @@ "danog/madelineproto": "dev-v8_fix_cleanup", "amphp/dns": "2.x-dev" }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2.0.1" + }, "suggest": { "ext-pcntl": "Install pcintl for propper signal handling and healthcheck (enabled in .env)" }, @@ -57,5 +60,8 @@ "allow-plugins": { "symfony/thanks": false } + }, + "scripts": { + "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php -d pcre.jit=0 vendor/bin/php-cs-fixer fix -v" } } diff --git a/composer.lock b/composer.lock index 001b63c..de9b4a4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a2c43abdf6b1714d394368fda29ac6b4", + "content-hash": "b9e9ba3184bce93fe3654528621101f4", "packages": [ { "name": "amphp/amp", @@ -3402,16 +3402,16 @@ }, { "name": "monolog/monolog", - "version": "3.6.0", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654" + "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", - "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f4393b648b78a5408747de94fca38beb5f7e9ef8", + "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8", "shasum": "" }, "require": { @@ -3487,7 +3487,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.6.0" + "source": "https://github.com/Seldaek/monolog/tree/3.7.0" }, "funding": [ { @@ -3499,7 +3499,7 @@ "type": "tidelift" } ], - "time": "2024-04-12T21:02:21+00:00" + "time": "2024-06-28T09:40:51+00:00" }, { "name": "nikic/fast-route", @@ -4508,7 +4508,2376 @@ "time": "2022-06-03T18:03:27+00:00" } ], - "packages-dev": [], + "packages-dev": [ + { + "name": "amphp/php-cs-fixer-config", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/php-cs-fixer-config.git", + "reference": "0fad9ec6a10a0a58fbf8cb77f41da34f80c031d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/php-cs-fixer-config/zipball/0fad9ec6a10a0a58fbf8cb77f41da34f80c031d6", + "reference": "0fad9ec6a10a0a58fbf8cb77f41da34f80c031d6", + "shasum": "" + }, + "require": { + "friendsofphp/php-cs-fixer": "^3.5", + "php": ">=7.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\CodeStyle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Sascha-Oliver Prolic", + "email": "saschaprolic@googlemail.com" + } + ], + "description": "Code style config for AMPHP.", + "support": { + "issues": "https://github.com/amphp/php-cs-fixer-config/issues", + "source": "https://github.com/amphp/php-cs-fixer-config/tree/v2.1.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T02:16:09+00:00" + }, + { + "name": "clue/ndjson-react", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\NDJson\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", + "keywords": [ + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" + ], + "support": { + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-12-23T10:58:28+00:00" + }, + { + "name": "composer/pcre", + "version": "3.1.4", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "04229f163664973f68f38f6f73d917799168ef24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24", + "reference": "04229f163664973f68f38f6f73d917799168ef24", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.4" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-27T13:40:54+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-08-31T09:50:34+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.1.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-02-07T09:43:46+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.59.3", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "30ba9ecc2b0e5205e578fe29973c15653d9bfd29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/30ba9ecc2b0e5205e578fe29973c15653d9bfd29", + "reference": "30ba9ecc2b0e5205e578fe29973c15653d9bfd29", + "shasum": "" + }, + "require": { + "clue/ndjson-react": "^1.0", + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.0", + "php": "^7.4 || ^8.0", + "react/child-process": "^0.6.5", + "react/event-loop": "^1.0", + "react/promise": "^2.0 || ^3.0", + "react/socket": "^1.0", + "react/stream": "^1.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-mbstring": "^1.28", + "symfony/polyfill-php80": "^1.28", + "symfony/polyfill-php81": "^1.28", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3 || ^2.3", + "infection/infection": "^0.29.5", + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^2.1", + "mikey179/vfsstream": "^1.6.11", + "php-coveralls/php-coveralls": "^2.7", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5", + "phpunit/phpunit": "^9.6.19 || ^10.5.21 || ^11.2", + "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "exclude-from-classmap": [ + "src/Fixer/Internal/*" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.59.3" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2024-06-16T14:17:03+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/child-process", + "version": "v0.6.5", + "source": { + "type": "git", + "url": "https://github.com/reactphp/child-process.git", + "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/socket": "^1.8", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\ChildProcess\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven library for executing child processes with ReactPHP.", + "keywords": [ + "event-driven", + "process", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.5" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-16T13:41:56+00:00" + }, + { + "name": "react/dns", + "version": "v1.13.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.13.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-13T14:18:03+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-13T13:48:05+00:00" + }, + { + "name": "react/promise", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-05-24T10:39:05+00:00" + }, + { + "name": "react/socket", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/216d3aec0b87f04a40ca04f481e6af01bdd1d038", + "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.11", + "react/event-loop": "^1.2", + "react/promise": "^3 || ^2.6 || ^1.2.1", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4 || ^3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.15.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-12-15T11:02:10+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ab83243ecc233de5655b76f577711de9f842e712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ab83243ecc233de5655b76f577711de9f842e712", + "reference": "ab83243ecc233de5655b76f577711de9f842e712", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:30:33+00:00" + }, + { + "name": "symfony/console", + "version": "v7.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "0aa29ca177f432ab68533432db0de059f39c92ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/0aa29ca177f432ab68533432db0de059f39c92ae", + "reference": "0aa29ca177f432ab68533432db0de059f39c92ae", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "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": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.1.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T10:03:55+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "92a91985250c251de9b947a14bb2c9390b1a562c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c", + "reference": "92a91985250c251de9b947a14bb2c9390b1a562c", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "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": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.1.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T10:03:55+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/fbb0ba67688b780efbc886c1a0a0948dcf7205d6", + "reference": "fbb0ba67688b780efbc886c1a0a0948dcf7205d6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "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": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/3fb075789fb91f9ad9af537c4012d523085bd5af", + "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-19T12:30:46+00:00" + }, + { + "name": "symfony/process", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "febf90124323a093c7ee06fdb30e765ca3c20028" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/febf90124323a093c7ee06fdb30e765ca3c20028", + "reference": "febf90124323a093c7ee06fdb30e765ca3c20028", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "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": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/string", + "version": "v7.1.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/14221089ac66cf82e3cf3d1c1da65de305587ff8", + "reference": "14221089ac66cf82e3cf3d1c1da65de305587ff8", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.1.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T09:27:18+00:00" + } + ], "aliases": [], "minimum-stability": "dev", "stability-flags": { diff --git a/examples/websocket-events.php b/examples/websocket-events.php index 9682bad..2b54b13 100644 --- a/examples/websocket-events.php +++ b/examples/websocket-events.php @@ -1,7 +1,7 @@ -startNotLoggedInSessions(); - $sessionsCount = count($sessionFiles); + $sessionsCount = \count($sessionFiles); warning( "\nTelegramApiServer ready." . "\nNumber of sessions: {$sessionsCount}." @@ -63,8 +62,8 @@ final class Client if ($settings) { Files::saveSessionSettings($session, $settings); } - $settings = array_replace_recursive( - (array)Config::getInstance()->get('telegram'), + $settings = \array_replace_recursive( + (array) Config::getInstance()->get('telegram'), Files::getSessionSettings($session), ); @@ -92,14 +91,9 @@ final class Client $instance->unsetEventHandler(); } unset($instance); - gc_collect_cycles(); + \gc_collect_cycles(); } - /** - * @param string|null $session - * - * @return API - */ public function getSession(?string $session = null): API { if (!$this->instances) { @@ -109,8 +103,8 @@ final class Client } if (!$session) { - if (count($this->instances) === 1) { - $session = (string)array_key_first($this->instances); + if (\count($this->instances) === 1) { + $session = (string) \array_key_first($this->instances); } else { throw new InvalidArgumentException( 'Multiple sessions detected. Specify which session to use. See README for examples.' @@ -165,9 +159,10 @@ final class Client return $wrapper; } - private static function getSettingsFromArray(string $session, array $settings, SettingsAbstract $settingsObject = new Settings()): SettingsAbstract { + private static function getSettingsFromArray(string $session, array $settings, SettingsAbstract $settingsObject = new Settings()): SettingsAbstract + { foreach ($settings as $key => $value) { - if (is_array($value) && $key !== 'proxies') { + if (\is_array($value) && $key !== 'proxies') { if ($key === 'db' && isset($value['type'])) { $type = match ($value['type']) { 'memory' => new Settings\Database\Memory(), @@ -185,23 +180,22 @@ final class Client } unset($value[$value['type']], $value['type'],); - if (count($value) === 0) { + if (\count($value) === 0) { continue; } } - $method = 'get' . ucfirst(str_replace('_', '', ucwords($key, '_'))); + $method = 'get' . \ucfirst(\str_replace('_', '', \ucwords($key, '_'))); self::getSettingsFromArray($session, $value, $settingsObject->$method()); } else { - if ($key === 'serializer' && is_string($value)) { + if ($key === 'serializer' && \is_string($value)) { $value = SerializerType::from($value); } - $method = 'set' . ucfirst(str_replace('_', '', ucwords($key, '_'))); + $method = 'set' . \ucfirst(\str_replace('_', '', \ucwords($key, '_'))); $settingsObject->$method($value); } } return $settingsObject; } - } diff --git a/src/Config.php b/src/Config.php index 024c276..36b53b3 100644 --- a/src/Config.php +++ b/src/Config.php @@ -1,9 +1,7 @@ -config; foreach ($path as $pathKey) { - if (!is_array($value) || !array_key_exists($pathKey, $value)) { + if (!\is_array($value) || !\array_key_exists($pathKey, $value)) { return null; } $value = &$value[$pathKey]; @@ -53,4 +51,4 @@ final class Config return $value; } -} \ No newline at end of file +} diff --git a/src/Controllers/AbstractApiController.php b/src/Controllers/AbstractApiController.php index ba98cc0..cfa252f 100644 --- a/src/Controllers/AbstractApiController.php +++ b/src/Controllers/AbstractApiController.php @@ -1,4 +1,4 @@ - self::JSON_HEADER, 'success' => false, @@ -83,19 +80,19 @@ abstract class AbstractApiController } /** - * Получаем параметры из GET и POST + * Получаем параметры из GET и POST. * */ private function resolveRequest(): void { $query = $this->request->getUri()->getQuery(); - $contentType = (string)$this->request->getHeader('Content-Type'); + $contentType = (string) $this->request->getHeader('Content-Type'); - parse_str($query, $get); + \parse_str($query, $get); switch (true) { case $contentType === 'application/x-www-form-urlencoded': - case mb_strpos($contentType, 'multipart/form-data') !== false: + case \mb_strpos($contentType, 'multipart/form-data') !== false: $form = (new StreamingFormParser())->parseForm($this->request); $post = []; @@ -107,27 +104,27 @@ abstract class AbstractApiController //We need to break loop without getting file //All other post field will be omitted, hope we dont need them :) break; - } else { - $post[$field->getName()] = $field->buffer(); } + $post[$field->getName()] = $field->buffer(); + } break; case $contentType === 'application/json': $body = $this->request->getBody()->buffer(); - $post = json_decode($body, 1); + $post = \json_decode($body, 1); break; default: $body = $this->request->getBody()->buffer(); - parse_str($body, $post); + \parse_str($body, $post); } - $this->parameters = array_merge((array)$post, $get); - $this->parameters = array_values($this->parameters); + $this->parameters = \array_merge((array) $post, $get); + $this->parameters = \array_values($this->parameters); } /** - * Получает посты для формирования ответа + * Получает посты для формирования ответа. * */ private function generateResponse(): void @@ -159,16 +156,16 @@ abstract class AbstractApiController protected function callApiCommon(API $madelineProto) { - $pathCount = count($this->api); - if ($pathCount === 1 && method_exists($this->extensionClass, $this->api[0])) { + $pathCount = \count($this->api); + if ($pathCount === 1 && \method_exists($this->extensionClass, $this->api[0])) { /** @var ApiExtensions|SystemApiExtensions $madelineProtoExtensions */ $madelineProtoExtensions = new $this->extensionClass($madelineProto, $this->request, $this->file); $result = $madelineProtoExtensions->{$this->api[0]}(...$this->parameters); } else { if ($this->api[0] === 'API') { $madelineProto = Client::getWrapper($madelineProto)->getAPI(); - array_shift($this->api); - $pathCount = count($this->api); + \array_shift($this->api); + $pathCount = \count($this->api); } //Проверяем нет ли в MadilineProto такого метода. switch ($pathCount) { @@ -190,9 +187,7 @@ abstract class AbstractApiController } /** - * @param Throwable $e * - * @return AbstractApiController * @throws Throwable */ private function setError(Throwable $e): self @@ -210,9 +205,8 @@ abstract class AbstractApiController } /** - * Кодирует ответ в нужный формат: json + * Кодирует ответ в нужный формат: json. * - * @return Response|string * @throws JsonException */ private function getResponse(): string|Response @@ -221,7 +215,7 @@ abstract class AbstractApiController return $this->page['response']; } - if (!is_array($this->page['response']) && !is_scalar($this->page['response'])) { + if (!\is_array($this->page['response']) && !\is_scalar($this->page['response'])) { $this->page['response'] = null; } @@ -234,7 +228,7 @@ abstract class AbstractApiController $data['success'] = true; } - $result = json_encode( + $result = \json_encode( $data, JSON_THROW_ON_ERROR | JSON_INVALID_UTF8_SUBSTITUTE | @@ -248,15 +242,13 @@ abstract class AbstractApiController } /** - * Устанавливает http код ответа (200, 400, 404 и тд.) + * Устанавливает http код ответа (200, 400, 404 и тд.). * - * @param int $code * - * @return AbstractApiController */ private function setPageCode(int $code): self { $this->page['code'] = $this->page['code'] === 200 ? $code : $this->page['code']; return $this; } -} \ No newline at end of file +} diff --git a/src/Controllers/ApiController.php b/src/Controllers/ApiController.php index 34b038f..39f75a9 100644 --- a/src/Controllers/ApiController.php +++ b/src/Controllers/ApiController.php @@ -1,19 +1,10 @@ -session = $path['session'] ?? null; - $this->api = explode('.', $path['method'] ?? ''); + $this->api = \explode('.', $path['method'] ?? ''); } /** @@ -46,4 +36,4 @@ final class ApiController extends AbstractApiController return $this->callApiCommon($madelineProto); } -} \ No newline at end of file +} diff --git a/src/Controllers/EventsController.php b/src/Controllers/EventsController.php index 992b3aa..f8110cf 100644 --- a/src/Controllers/EventsController.php +++ b/src/Controllers/EventsController.php @@ -1,11 +1,11 @@ - $client->ping()); + $pingLoop = EventLoop::repeat(self::PING_INTERVAL_MS, static fn () => $client->ping()); $client->onClose(static function () use ($clientId, $requestedSession, $pingLoop) { EventLoop::cancel($pingLoop); @@ -104,7 +104,7 @@ final class EventsController implements WebsocketClientHandler, WebsocketAccepto ]; $this->gateway->multicastText( - json_encode( + \json_encode( $update, JSON_THROW_ON_ERROR | JSON_INVALID_UTF8_SUBSTITUTE | @@ -115,4 +115,4 @@ final class EventsController implements WebsocketClientHandler, WebsocketAccepto ); }); } -} \ No newline at end of file +} diff --git a/src/Controllers/LogController.php b/src/Controllers/LogController.php index 1f6dbf6..f856ef9 100644 --- a/src/Controllers/LogController.php +++ b/src/Controllers/LogController.php @@ -1,4 +1,4 @@ -getId(); - $pingLoop = EventLoop::repeat(self::PING_INTERVAL_MS, static fn() => $client->ping()); + $pingLoop = EventLoop::repeat(self::PING_INTERVAL_MS, static fn () => $client->ping()); $client->onClose(static function () use ($clientId, $pingLoop) { EventLoop::cancel($pingLoop); @@ -90,7 +90,7 @@ final class LogController implements WebsocketClientHandler, WebsocketAcceptor ]; $this->gateway->multicastText( - json_encode( + \json_encode( $update, JSON_THROW_ON_ERROR | JSON_INVALID_UTF8_SUBSTITUTE | @@ -101,4 +101,4 @@ final class LogController implements WebsocketClientHandler, WebsocketAcceptor ); }); } -} \ No newline at end of file +} diff --git a/src/Controllers/SystemController.php b/src/Controllers/SystemController.php index 9ea2831..23bc3e6 100644 --- a/src/Controllers/SystemController.php +++ b/src/Controllers/SystemController.php @@ -1,4 +1,4 @@ -api = explode('.', $path['method'] ?? ''); + $this->api = \explode('.', $path['method'] ?? ''); } /** - * @return mixed * @throws Exception */ protected function callApi() @@ -29,4 +27,4 @@ final class SystemController extends AbstractApiController return $result; } -} \ No newline at end of file +} diff --git a/src/EventObservers/EventHandler.php b/src/EventObservers/EventHandler.php index b231d72..4442de9 100644 --- a/src/EventObservers/EventHandler.php +++ b/src/EventObservers/EventHandler.php @@ -32,4 +32,4 @@ final class EventHandler extends \danog\MadelineProto\EventHandler info("Received update from session: {$this->sessionName}"); EventObserver::notify($update, $this->sessionName); } -} \ No newline at end of file +} diff --git a/src/EventObservers/EventObserver.php b/src/EventObservers/EventObserver.php index 174c428..aa242d9 100644 --- a/src/EventObservers/EventObserver.php +++ b/src/EventObservers/EventObserver.php @@ -1,8 +1,7 @@ -instances); + $sessions = \array_keys(Client::getInstance()->instances); } else { $sessions[] = $requestedSession; } @@ -74,7 +73,7 @@ final class EventObserver { $sessions = []; if ($requestedSession === null) { - $sessions = array_keys(Client::getInstance()->instances); + $sessions = \array_keys(Client::getInstance()->instances); } else { $sessions[] = $requestedSession; } @@ -89,4 +88,4 @@ final class EventObserver } -} \ No newline at end of file +} diff --git a/src/EventObservers/LogObserver.php b/src/EventObservers/LogObserver.php index c457deb..cdbfa9f 100644 --- a/src/EventObservers/LogObserver.php +++ b/src/EventObservers/LogObserver.php @@ -1,4 +1,4 @@ -log(Logger::$madelineLevels[$level], (string)$message); + if (\is_scalar($message)) { + Logger::getInstance()->log(Logger::$madelineLevels[$level], (string) $message); } else { if ($message instanceof Throwable) { $message = Logger::getExceptionAsArray($message); } - if (is_array($message)) { + if (\is_array($message)) { Logger::getInstance()->log(Logger::$madelineLevels[$level], '', $message); } else { Logger::getInstance()->log( Logger::$madelineLevels[$level], - json_encode($message, + \json_encode( + $message, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_INVALID_UTF8_SUBSTITUTE | @@ -43,4 +43,4 @@ final class LogObserver } } } -} \ No newline at end of file +} diff --git a/src/EventObservers/ObserverTrait.php b/src/EventObservers/ObserverTrait.php index a595b9e..463b148 100644 --- a/src/EventObservers/ObserverTrait.php +++ b/src/EventObservers/ObserverTrait.php @@ -1,8 +1,7 @@ -minLevelIndex = min(self::$levels[$minLevel], self::$levels[self::$madelineLevels[MadelineProto\Logger::VERBOSE]]); + $this->minLevelIndex = \min(self::$levels[$minLevel], self::$levels[self::$madelineLevels[MadelineProto\Logger::VERBOSE]]); $this->formatter = $formatter ?: $this->format(...); $pipe = new Pipe(PHP_INT_MAX); $this->stdout = $pipe->getSink(); @@ -103,10 +100,10 @@ final class Logger extends AbstractLogger try { pipe($source, getStdout()); } finally { - unset(self::$closePromises[spl_object_id($promise)]); + unset(self::$closePromises[\spl_object_id($promise)]); } }); - self::$closePromises[spl_object_id($promise)] = [$this->stdout, $promise]; + self::$closePromises[\spl_object_id($promise)] = [$this->stdout, $promise]; } public static function getInstance(): Logger @@ -127,7 +124,7 @@ final class Logger extends AbstractLogger public function log($level, $message, array $context = []): void { if (!isset(self::$levels[$level])) { - throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); + throw new InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $level)); } LogObserver::notify($level, $message, $context); @@ -137,7 +134,8 @@ final class Logger extends AbstractLogger } $formatter = $this->formatter; - $data = $formatter($level, $message, $context);; + $data = $formatter($level, $message, $context); + ; try { $this->stdout->write($data); } catch (\Throwable) { @@ -158,55 +156,55 @@ final class Logger extends AbstractLogger private function format(string $level, string $message, array $context): string { - if (false !== strpos($message, '{')) { + if (false !== \strpos($message, '{')) { $replacements = []; foreach ($context as $key => $val) { if ($val instanceof Throwable) { $context[$key] = self::getExceptionAsArray($val); } - if (null === $val || is_scalar($val) || (is_object($val) && method_exists($val, '__toString'))) { + if (null === $val || \is_scalar($val) || (\is_object($val) && \method_exists($val, '__toString'))) { $replacements["{{$key}}"] = $val; } else { if ($val instanceof DateTimeInterface) { $replacements["{{$key}}"] = $val->format(self::$dateTimeFormat); } else { - if (is_object($val)) { - $replacements["{{$key}}"] = '[object ' . get_class($val) . ']'; + if (\is_object($val)) { + $replacements["{{$key}}"] = '[object ' . \get_class($val) . ']'; } else { - $replacements["{{$key}}"] = '[' . gettype($val) . ']'; + $replacements["{{$key}}"] = '[' . \gettype($val) . ']'; } } } } - $message = strtr($message, $replacements); + $message = \strtr($message, $replacements); } - return sprintf( - '[%s] [%s] %s %s', - date(self::$dateTimeFormat), - $level, - $message, - $context ? + return \sprintf( + '[%s] [%s] %s %s', + \date(self::$dateTimeFormat), + $level, + $message, + $context ? "\n" . - json_encode( + \json_encode( $context, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE | JSON_PRETTY_PRINT | JSON_UNESCAPED_LINE_TERMINATORS | JSON_UNESCAPED_SLASHES ) : '' - ) . PHP_EOL; + ) . PHP_EOL; } public static function getExceptionAsArray(Throwable $exception) { return [ - 'exception' => get_class($exception), + 'exception' => \get_class($exception), 'message' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'code' => $exception->getCode(), - 'backtrace' => array_slice($exception->getTrace(), 0, 3), + 'backtrace' => \array_slice($exception->getTrace(), 0, 3), 'previous exception' => $exception->getPrevious(), ]; } -} \ No newline at end of file +} diff --git a/src/MadelineProtoExtensions/ApiExtensions.php b/src/MadelineProtoExtensions/ApiExtensions.php index 074b241..19480c6 100644 --- a/src/MadelineProtoExtensions/ApiExtensions.php +++ b/src/MadelineProtoExtensions/ApiExtensions.php @@ -1,9 +1,7 @@ -).*<\/.*$~', '$1', $textFormated) + \preg_replace('~(\>).*<\/.*$~', '$1', $textFormated) ); } else { $nextEntity['offset'] += StrTools::mbStrlen($textFormated) - StrTools::mbStrlen($text); @@ -115,7 +110,7 @@ final class ApiExtensions } } unset($entity); - $message = nl2br($message); + $message = \nl2br($message); return $message; } @@ -127,7 +122,7 @@ final class ApiExtensions } /** - * Пересылает сообщения без ссылки на оригинал + * Пересылает сообщения без ссылки на оригинал. * * @param array $data *
@@ -141,7 +136,7 @@ final class ApiExtensions
      */
     public function copyMessages(array $data)
     {
-        $data = array_merge(
+        $data = \array_merge(
             [
                 'from_peer' => '',
                 'to_peer' => '',
@@ -157,7 +152,7 @@ final class ApiExtensions
             ]
         );
         $result = [];
-        if (!$response || !is_array($response) || !array_key_exists('messages', $response)) {
+        if (!$response || !\is_array($response) || !\array_key_exists('messages', $response)) {
             return $result;
         }
 
@@ -174,7 +169,7 @@ final class ApiExtensions
                 $result[] = $this->madelineProto->messages->sendMessage(...$messageData);
             }
             if ($key > 0) {
-                delay(random_int(300, 2000) / 1000);
+                delay(\random_int(300, 2000) / 1000);
             }
         }
 
@@ -182,14 +177,13 @@ final class ApiExtensions
     }
 
     /**
-     * Загружает медиафайл из указанного сообщения в поток
+     * Загружает медиафайл из указанного сообщения в поток.
      *
-     * @param array $data
      *
      */
     public function getMedia(array $data): Response
     {
-        $data = array_merge(
+        $data = \array_merge(
             [
                 'peer' => '',
                 'id' => [0],
@@ -222,17 +216,16 @@ final class ApiExtensions
             }
         }
 
-
         return $this->downloadToResponse($info);
     }
 
     /**
-     * Загружает превью медиафайла из указанного сообщения в поток
+     * Загружает превью медиафайла из указанного сообщения в поток.
      *
      */
     public function getMediaPreview(array $data): Response
     {
-        $data = array_merge(
+        $data = \array_merge(
             [
                 'peer' => '',
                 'id' => [0],
@@ -250,7 +243,7 @@ final class ApiExtensions
             throw new NoMediaException('Message has no media');
         }
 
-        $media = $message['media'][array_key_last($message['media'])];
+        $media = $message['media'][\array_key_last($message['media'])];
         $thumb = null;
         switch (true) {
             case isset($media['sizes']):
@@ -308,15 +301,15 @@ final class ApiExtensions
     public function getMessages(array $data): array
     {
         $peerInfo = $this->madelineProto->getInfo($data['peer']);
-        if (in_array($peerInfo['type'], ['channel', 'supergroup'])) {
+        if (\in_array($peerInfo['type'], ['channel', 'supergroup'])) {
             $response = $this->madelineProto->channels->getMessages(
                 [
                     'channel' => $data['peer'],
-                    'id' => (array)$data['id'],
+                    'id' => (array) $data['id'],
                 ]
             );
         } else {
-            $response = $this->madelineProto->messages->getMessages(['id' => (array)$data['id']]);
+            $response = $this->madelineProto->messages->getMessages(['id' => (array) $data['id']]);
         }
 
         return $response;
@@ -328,7 +321,6 @@ final class ApiExtensions
      * @param array $info
      *      Any downloadable array: message, media etc...
      *
-     * @return Response
      */
     public function downloadToResponse(array $info): Response
     {
@@ -336,7 +328,7 @@ final class ApiExtensions
     }
 
     /**
-     * Адаптер для стандартного метода
+     * Адаптер для стандартного метода.
      *
      */
     public function downloadToBrowser(array $info): Response
@@ -361,7 +353,7 @@ final class ApiExtensions
             $this->file->getMimeType(),
             $this->file->getFilename()
         );
-        $inputFile['id'] = unpack('P', $inputFile['id'])['1'];
+        $inputFile['id'] = \unpack('P', $inputFile['id'])['1'];
         return [
             'media' => [
                 '_' => 'inputMediaUploadedDocument',
@@ -384,7 +376,6 @@ final class ApiExtensions
         Client::getWrapper($this->madelineProto)->serialize();
     }
 
-
     public function getUpdates(array $params): array
     {
         foreach ($params as $key => $value) {
@@ -410,12 +401,13 @@ final class ApiExtensions
         Client::getWrapper($this->madelineProto)->serialize();
     }
 
-    public function unsubscribeFromUpdates(?string $channel = null): array {
+    public function unsubscribeFromUpdates(?string $channel = null): array
+    {
         $inputChannelId = null;
         if ($channel) {
             $id = (string) $this->madelineProto->getId($channel);
 
-            $inputChannelId = (int)str_replace(['-100', '-'], '', $id);
+            $inputChannelId = (int) \str_replace(['-100', '-'], '', $id);
             if (!$inputChannelId) {
                 throw new InvalidArgumentException('Invalid id');
             }
@@ -438,11 +430,10 @@ final class ApiExtensions
             $counter++;
         }
 
-
         return [
             'disabled_update_loops' => $counter,
-            'current_update_loops' => count(Client::getWrapper($this->madelineProto)->getAPI()->feeders),
+            'current_update_loops' => \count(Client::getWrapper($this->madelineProto)->getAPI()->feeders),
         ];
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/MadelineProtoExtensions/SystemApiExtensions.php b/src/MadelineProtoExtensions/SystemApiExtensions.php
index c119003..73c0aa4 100644
--- a/src/MadelineProtoExtensions/SystemApiExtensions.php
+++ b/src/MadelineProtoExtensions/SystemApiExtensions.php
@@ -1,4 +1,4 @@
-client->addSession($session, $settings);
@@ -75,7 +75,7 @@ final class SystemApiExtensions
         foreach ($this->client->instances as $session => $instance) {
             $authorized = $instance->getAuthorization();
             switch ($authorized) {
-                case API::NOT_LOGGED_IN;
+                case API::NOT_LOGGED_IN:
                     $status = 'NOT_LOGGED_IN';
                     break;
                 case API::WAITING_CODE:
@@ -107,7 +107,7 @@ final class SystemApiExtensions
 
         return [
             'sessions' => $sessions,
-            'memory' => $this->bytesToHuman(memory_get_usage(true)),
+            'memory' => $this->bytesToHuman(\memory_get_usage(true)),
         ];
     }
 
@@ -115,10 +115,10 @@ final class SystemApiExtensions
     {
         $file = Files::getSessionFile($session);
 
-        if (is_file($file)) {
+        if (\is_file($file)) {
             $futures = [];
-            foreach (glob("$file*") as $file) {
-                $futures[] = async(fn() => deleteFile($file));
+            foreach (\glob("$file*") as $file) {
+                $futures[] = async(fn () => deleteFile($file));
             }
             awaitAll($futures);
         } else {
@@ -140,7 +140,7 @@ final class SystemApiExtensions
     public function unlinkSessionSettings($session): string
     {
         $settings = Files::getSessionFile($session, Files::SETTINGS_EXTENSION);
-        if (is_file($settings)) {
+        if (\is_file($settings)) {
             deleteFile($settings);
         }
 
@@ -149,7 +149,7 @@ final class SystemApiExtensions
 
     public function exit(): string
     {
-        EventLoop::defer(static fn() => exit());
+        EventLoop::defer(static fn () => exit());
         return 'ok';
     }
 
@@ -159,6 +159,6 @@ final class SystemApiExtensions
         for ($i = 0; $bytes > 1024; $i++) {
             $bytes /= 1024;
         }
-        return round($bytes, 2) . ' ' . $units[$i];
+        return \round($bytes, 2) . ' ' . $units[$i];
     }
-}
\ No newline at end of file
+}
diff --git a/src/Migrations/StartUpFixes.php b/src/Migrations/StartUpFixes.php
index a443dea..6ac2b14 100644
--- a/src/Migrations/StartUpFixes.php
+++ b/src/Migrations/StartUpFixes.php
@@ -1,4 +1,4 @@
-getMethod();
-        $uri = (string)$request->getUri();
+        $uri = (string) $request->getUri();
         $protocolVersion = $request->getProtocolVersion();
         $remote = Server::getClientIp($request);
 
diff --git a/src/Server/Authorization.php b/src/Server/Authorization.php
index 07c28d3..47258ad 100644
--- a/src/Server/Authorization.php
+++ b/src/Server/Authorization.php
@@ -1,4 +1,4 @@
-selfIp = ip2long(getHostByName(php_uname('n')));
-        $this->ipWhitelist = (array)Config::getInstance()->get('api.ip_whitelist', []);
+        $this->selfIp = \ip2long(\getHostByName(\php_uname('n')));
+        $this->ipWhitelist = (array) Config::getInstance()->get('api.ip_whitelist', []);
         $this->passwords = Config::getInstance()->get('api.passwords', []);
         if (!$this->ipWhitelist && !$this->passwords) {
             error('API is unprotected! Please specify IP_WHITELIST or PASSWORD in .env.docker');
@@ -37,11 +37,11 @@ final class Authorization implements Middleware
         }
 
         if ($this->passwords) {
-            $header = (string)$request->getHeader('Authorization');
+            $header = (string) $request->getHeader('Authorization');
             if ($header) {
-                sscanf($header, "Basic %s", $encodedPassword);
-                [$username, $password] = explode(':', base64_decode($encodedPassword), 2);
-                if (array_key_exists($username, $this->passwords) && $this->passwords[$username] === $password) {
+                \sscanf($header, "Basic %s", $encodedPassword);
+                [$username, $password] = \explode(':', \base64_decode($encodedPassword), 2);
+                if (\array_key_exists($username, $this->passwords) && $this->passwords[$username] === $password) {
                     return $requestHandler->handleRequest($request);
                 }
             }
@@ -59,25 +59,25 @@ final class Authorization implements Middleware
     private function isIpAllowed(string $host): bool
     {
 
-
-        if ($this->ipWhitelist && !in_array($host, $this->ipWhitelist, true)) {
+        if ($this->ipWhitelist && !\in_array($host, $this->ipWhitelist, true)) {
             return false;
         }
         return true;
     }
 
-    private function isLocal(string $host): bool {
+    private function isLocal(string $host): bool
+    {
         if ($host === '127.0.0.1' || $host === 'localhost') {
             return true;
         }
 
         global $options;
         if ($options['docker']) {
-            $isSameNetwork = abs(ip2long($host) - $this->selfIp) < 256;
+            $isSameNetwork = \abs(\ip2long($host) - $this->selfIp) < 256;
             if ($isSameNetwork) {
                 return true;
             }
         }
         return false;
     }
-}
\ No newline at end of file
+}
diff --git a/src/Server/ErrorResponses.php b/src/Server/ErrorResponses.php
index 1ce3b46..736ef81 100644
--- a/src/Server/ErrorResponses.php
+++ b/src/Server/ErrorResponses.php
@@ -1,4 +1,4 @@
- false,
                     'errors' => [
@@ -33,4 +31,4 @@ final class ErrorResponses
         );
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/Server/Router.php b/src/Server/Router.php
index 82650a3..f3faa43 100644
--- a/src/Server/Router.php
+++ b/src/Server/Router.php
@@ -1,12 +1,12 @@
-router->addRoute('GET', '/log/{level:.*?[^/]}[/]', $logHandler);
     }
 
-
-}
\ No newline at end of file
+}
diff --git a/src/Server/Server.php b/src/Server/Server.php
index 6309dd2..4d8a0be 100644
--- a/src/Server/Server.php
+++ b/src/Server/Server.php
@@ -1,4 +1,4 @@
-stop();
         } else {
             EventLoop::run();
@@ -74,16 +70,14 @@ final class Server
     }
 
     /**
-     * Установить конфигурацию для http-сервера
+     * Установить конфигурацию для http-сервера.
      *
-     * @param array $config
-     * @return array
      */
     private function getConfig(array $config = []): array
     {
-        $config = array_filter($config);
+        $config = \array_filter($config);
 
-        $config = array_merge(
+        $config = \array_merge(
             Config::getInstance()->get('server', []),
             $config
         );
@@ -97,18 +91,18 @@ final class Server
         if ($realIpHeader) {
             $remote = $request->getHeader($realIpHeader);
             if (!$remote) {
-                GOTO DIRECT;
+                goto DIRECT;
             }
-            $tmp = explode(',', $remote);
-            $remote = trim(end($tmp));
+            $tmp = \explode(',', $remote);
+            $remote = \trim(\end($tmp));
         } else {
             DIRECT:
             $remote = $request->getClient()->getRemoteAddress()->toString();
-            $hostArray = explode(':', $remote);
-            if (count($hostArray) >= 2) {
-                $port = (int)array_pop($hostArray);
+            $hostArray = \explode(':', $remote);
+            if (\count($hostArray) >= 2) {
+                $port = (int) \array_pop($hostArray);
                 if ($port > 0 && $port <= 65353) {
-                    $remote = implode(':', $hostArray);
+                    $remote = \implode(':', $hostArray);
                 }
             }
 
@@ -117,4 +111,4 @@ final class Server
         return $remote;
     }
 
-}
\ No newline at end of file
+}

From 781766f849e1081b4bba969ab7a0b54f5e4cc002 Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Sun, 30 Jun 2024 16:08:55 +0200
Subject: [PATCH 32/42] cs-fix

---
 src/Controllers/AbstractApiController.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Controllers/AbstractApiController.php b/src/Controllers/AbstractApiController.php
index cfa252f..4ff37ef 100644
--- a/src/Controllers/AbstractApiController.php
+++ b/src/Controllers/AbstractApiController.php
@@ -111,7 +111,7 @@ abstract class AbstractApiController
                 break;
             case $contentType === 'application/json':
                 $body = $this->request->getBody()->buffer();
-                $post = \json_decode($body, 1);
+                $post = \json_decode($body, true);
                 break;
             default:
                 $body = $this->request->getBody()->buffer();

From f484ee67a7bd1be75aea6ea82a2e473e3e16b108 Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Sun, 30 Jun 2024 16:12:30 +0200
Subject: [PATCH 33/42] Set up a loop error handler

---
 bootstrap.php | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/bootstrap.php b/bootstrap.php
index 0705a7d..3c92ba2 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -1,5 +1,8 @@
 emergency($message, $context);
     }
 }
+
+EventLoop::setErrorHandler(function (\Throwable $e) {
+    if ($e instanceof UnhandledFutureError) {
+        $e = $e->getPrevious();
+    }
+    if ($e instanceof SecurityException || $e instanceof SignalException) {
+        throw $e;
+    }
+    if (str_starts_with($e->getMessage(), 'Could not connect to DC ')) {
+        throw $e;
+    }
+    emergency((string) $e);
+});
\ No newline at end of file

From 7ad157021a814ab5ad6205d8cee1a2644437a778 Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Sun, 30 Jun 2024 16:13:05 +0200
Subject: [PATCH 34/42] Fix

---
 src/Exceptions/NoticeException.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Exceptions/NoticeException.php b/src/Exceptions/NoticeException.php
index 2d2ec5b..c5765e9 100644
--- a/src/Exceptions/NoticeException.php
+++ b/src/Exceptions/NoticeException.php
@@ -4,7 +4,7 @@ namespace TelegramApiServer\Exceptions;
 
 use Exception;
 
-final class NoticeException extends Exception
+class NoticeException extends Exception
 {
 
 }

From 632da98a33a62174e3805613934ff1520a2855eb Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Sun, 30 Jun 2024 16:15:51 +0200
Subject: [PATCH 35/42] Fix

---
 bootstrap.php  | 3 ++-
 src/Client.php | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/bootstrap.php b/bootstrap.php
index 3c92ba2..e9837cc 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -2,6 +2,7 @@
 
 use Amp\Future\UnhandledFutureError;
 use Amp\SignalException;
+use Amp\Sql\SqlException;
 use danog\MadelineProto\SecurityException;
 use Revolt\EventLoop;
 use TelegramApiServer\Logger;
@@ -121,7 +122,7 @@ EventLoop::setErrorHandler(function (\Throwable $e) {
     if ($e instanceof UnhandledFutureError) {
         $e = $e->getPrevious();
     }
-    if ($e instanceof SecurityException || $e instanceof SignalException) {
+    if ($e instanceof SecurityException || $e instanceof SignalException || $e instanceof SqlException) {
         throw $e;
     }
     if (str_starts_with($e->getMessage(), 'Could not connect to DC ')) {
diff --git a/src/Client.php b/src/Client.php
index 64b9abd..7a278f0 100644
--- a/src/Client.php
+++ b/src/Client.php
@@ -14,6 +14,8 @@ use ReflectionProperty;
 use RuntimeException;
 use TelegramApiServer\EventObservers\EventObserver;
 
+use function Amp\Socket\SocketAddress\fromString;
+
 final class Client
 {
     public static Client $self;

From 6184b5fd65366c00c3b42145569bfe9df77f6da4 Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Sun, 30 Jun 2024 16:18:13 +0200
Subject: [PATCH 36/42] Enable prometheus collection if requested

---
 config.php | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/config.php b/config.php
index 19e886c..6e1db41 100644
--- a/config.php
+++ b/config.php
@@ -3,6 +3,8 @@
 use danog\MadelineProto\Logger;
 use TelegramApiServer\EventObservers\LogObserver;
 
+use function Amp\Socket\SocketAddress\fromString;
+
 $settings = [
     'server' => [
         'address' => (string)getenv('SERVER_ADDRESS'),
@@ -69,6 +71,10 @@ $settings = [
         'passwords' => (array)json_decode((string)getenv('PASSWORDS'), true),
         'bulk_interval' => (float)getenv('REQUESTS_BULK_INTERVAL')
     ],
+    'metrics' => [
+        'enable_prometheus_collection' => (bool)getenv("PROMETHEUS_BIND_TO"),
+        'bind_to' => getenv("PROMETHEUS_BIND_TO") ? fromString(getenv("PROMETHEUS_BIND_TO")) : null
+    ]
 ];
 
 if (empty($settings['telegram']['connection']['proxies']['\danog\MadelineProto\Stream\Proxy\SocksProxy'][0]['address'])) {

From 6518c4bcb4222ac1cba3ab860dc3f13e831deeda Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Sun, 30 Jun 2024 16:24:30 +0200
Subject: [PATCH 37/42] Bump

---
 docker-compose.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docker-compose.yml b/docker-compose.yml
index 3352a94..2ec29a2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,6 +5,7 @@ services:
       service: base-api
     ports:
       - "127.0.0.1:9503:9503"
+      - "127.0.0.1:12345:12345"
     command:
       - "-s=session"
   mysql:

From 14a9fcaf8575becd7c9b8248add65527522dbdf9 Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Mon, 1 Jul 2024 12:56:29 +0300
Subject: [PATCH 38/42] Fix

---
 config.php         | 10 +++++-----
 docker-compose.yml |  4 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/config.php b/config.php
index 6e1db41..5af26f3 100644
--- a/config.php
+++ b/config.php
@@ -60,6 +60,10 @@ $settings = [
             'report_broken_media' => false,
             'download_parallel_chunks' => 20,
         ],
+        'metrics' => [
+            'enable_prometheus_collection' => true, //(bool)getenv("PROMETHEUS_BIND_TO"),
+            'metrics_bind_to' => fromString("0.0.0.0:12345")
+        ]
     ],
     'api' => [
         'ip_whitelist' => array_filter(
@@ -71,10 +75,6 @@ $settings = [
         'passwords' => (array)json_decode((string)getenv('PASSWORDS'), true),
         'bulk_interval' => (float)getenv('REQUESTS_BULK_INTERVAL')
     ],
-    'metrics' => [
-        'enable_prometheus_collection' => (bool)getenv("PROMETHEUS_BIND_TO"),
-        'bind_to' => getenv("PROMETHEUS_BIND_TO") ? fromString(getenv("PROMETHEUS_BIND_TO")) : null
-    ]
 ];
 
 if (empty($settings['telegram']['connection']['proxies']['\danog\MadelineProto\Stream\Proxy\SocksProxy'][0]['address'])) {
@@ -85,4 +85,4 @@ if (empty($settings['telegram']['app_info']['api_id'])) {
     throw new InvalidArgumentException('Need to fill TELEGRAM_API_ID in .env.docker or .env');
 }
 
-return $settings;
\ No newline at end of file
+return $settings;
diff --git a/docker-compose.yml b/docker-compose.yml
index 2ec29a2..74eb406 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,7 +5,7 @@ services:
       service: base-api
     ports:
       - "127.0.0.1:9503:9503"
-      - "127.0.0.1:12345:12345"
+      - "12345:12345"
     command:
       - "-s=session"
   mysql:
@@ -16,4 +16,4 @@ services:
       - "127.0.0.1:9507:3306"
 networks:
   default:
-    name: telegram-api-server
\ No newline at end of file
+    name: telegram-api-server

From c8db204d7f764cc3b8ef838982ca5df099edac06 Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Mon, 1 Jul 2024 12:29:31 +0200
Subject: [PATCH 39/42] Disable io_uring

---
 Dockerfile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Dockerfile b/Dockerfile
index 1e462e8..0c8b88e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,4 +8,6 @@ RUN echo 1.0.0 > /tas_version
 
 EXPOSE 9503
 
+ENV UV_USE_IO_URING=0
+
 ENTRYPOINT ["./entrypoint.sh"]

From cf2dc3197d4849f28c9f892eae66b9fe230b4985 Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Wed, 10 Jul 2024 16:35:47 +0200
Subject: [PATCH 40/42] Bump

---
 composer.lock | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/composer.lock b/composer.lock
index de9b4a4..5fda336 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1274,16 +1274,16 @@
         },
         {
             "name": "amphp/pipeline",
-            "version": "v1.2.0",
+            "version": "v1.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/amphp/pipeline.git",
-                "reference": "f1c2ce35d27ae86ead018adb803eccca7421dd9b"
+                "reference": "66c095673aa5b6e689e63b52d19e577459129ab3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/amphp/pipeline/zipball/f1c2ce35d27ae86ead018adb803eccca7421dd9b",
-                "reference": "f1c2ce35d27ae86ead018adb803eccca7421dd9b",
+                "url": "https://api.github.com/repos/amphp/pipeline/zipball/66c095673aa5b6e689e63b52d19e577459129ab3",
+                "reference": "66c095673aa5b6e689e63b52d19e577459129ab3",
                 "shasum": ""
             },
             "require": {
@@ -1329,7 +1329,7 @@
             ],
             "support": {
                 "issues": "https://github.com/amphp/pipeline/issues",
-                "source": "https://github.com/amphp/pipeline/tree/v1.2.0"
+                "source": "https://github.com/amphp/pipeline/tree/v1.2.1"
             },
             "funding": [
                 {
@@ -1337,7 +1337,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2024-03-10T14:48:16+00:00"
+            "time": "2024-07-04T00:56:47+00:00"
         },
         {
             "name": "amphp/postgres",
@@ -3553,16 +3553,16 @@
         },
         {
             "name": "nikic/php-parser",
-            "version": "v5.0.2",
+            "version": "v5.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13"
+                "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13",
-                "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1",
+                "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1",
                 "shasum": ""
             },
             "require": {
@@ -3573,7 +3573,7 @@
             },
             "require-dev": {
                 "ircmaxell/php-yacc": "^0.0.7",
-                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+                "phpunit/phpunit": "^9.0"
             },
             "bin": [
                 "bin/php-parse"
@@ -3605,9 +3605,9 @@
             ],
             "support": {
                 "issues": "https://github.com/nikic/PHP-Parser/issues",
-                "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2"
+                "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0"
             },
-            "time": "2024-03-05T20:51:40+00:00"
+            "time": "2024-07-01T20:03:41+00:00"
         },
         {
             "name": "paragonie/constant_time_encoding",
@@ -5691,16 +5691,16 @@
         },
         {
             "name": "sebastian/diff",
-            "version": "6.0.1",
+            "version": "6.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/diff.git",
-                "reference": "ab83243ecc233de5655b76f577711de9f842e712"
+                "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ab83243ecc233de5655b76f577711de9f842e712",
-                "reference": "ab83243ecc233de5655b76f577711de9f842e712",
+                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544",
+                "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544",
                 "shasum": ""
             },
             "require": {
@@ -5746,7 +5746,7 @@
             "support": {
                 "issues": "https://github.com/sebastianbergmann/diff/issues",
                 "security": "https://github.com/sebastianbergmann/diff/security/policy",
-                "source": "https://github.com/sebastianbergmann/diff/tree/6.0.1"
+                "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2"
             },
             "funding": [
                 {
@@ -5754,7 +5754,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2024-03-02T07:30:33+00:00"
+            "time": "2024-07-03T04:53:05+00:00"
         },
         {
             "name": "symfony/console",

From fb55db2e236a446169349d32c995169a61bbf7ef Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Wed, 10 Jul 2024 17:08:40 +0200
Subject: [PATCH 41/42] Bump

---
 composer.lock | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/composer.lock b/composer.lock
index 5fda336..125eade 100644
--- a/composer.lock
+++ b/composer.lock
@@ -2646,12 +2646,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/danog/MadelineProto.git",
-                "reference": "cb0743446bcddb821ce556d2f8a131f1da26d976"
+                "reference": "ddb2bb5a2358cc62cb8d0f847710e2cccb106390"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/danog/MadelineProto/zipball/cb0743446bcddb821ce556d2f8a131f1da26d976",
-                "reference": "cb0743446bcddb821ce556d2f8a131f1da26d976",
+                "url": "https://api.github.com/repos/danog/MadelineProto/zipball/ddb2bb5a2358cc62cb8d0f847710e2cccb106390",
+                "reference": "ddb2bb5a2358cc62cb8d0f847710e2cccb106390",
                 "shasum": ""
             },
             "require": {
@@ -2766,7 +2766,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2024-06-27T16:52:00+00:00"
+            "time": "2024-07-10T14:36:36+00:00"
         },
         {
             "name": "danog/primemodule",

From c005d86a477a6fd2997a72a65957bf99727731b7 Mon Sep 17 00:00:00 2001
From: Daniil Gentili 
Date: Sat, 13 Jul 2024 15:26:17 +0200
Subject: [PATCH 42/42] BUmp

---
 src/Client.php                            | 2 --
 src/Controllers/AbstractApiController.php | 2 +-
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/Client.php b/src/Client.php
index 7a278f0..64b9abd 100644
--- a/src/Client.php
+++ b/src/Client.php
@@ -14,8 +14,6 @@ use ReflectionProperty;
 use RuntimeException;
 use TelegramApiServer\EventObservers\EventObserver;
 
-use function Amp\Socket\SocketAddress\fromString;
-
 final class Client
 {
     public static Client $self;
diff --git a/src/Controllers/AbstractApiController.php b/src/Controllers/AbstractApiController.php
index d07ffae..e7a40f2 100644
--- a/src/Controllers/AbstractApiController.php
+++ b/src/Controllers/AbstractApiController.php
@@ -92,7 +92,7 @@ abstract class AbstractApiController
 
         switch (true) {
             case $contentType === 'application/x-www-form-urlencoded':
-            case \mb_strpos($contentType, 'multipart/form-data') !== false:
+            case \str_contains($contentType, 'multipart/form-data'):
                 $form = (new StreamingFormParser())->parseForm($this->request);
                 $post = [];