From d31b798df9347022a06026c18a012bc39762537d Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sun, 4 Oct 2020 16:27:22 +0200 Subject: [PATCH] Final fixes, and update to latest version of websocket lib --- composer.json | 5 +- .../MadelineProto/Async/AsyncParameters.php | 65 ------------------- src/danog/MadelineProto/Connection.php | 4 +- src/danog/MadelineProto/DataCenter.php | 8 ++- .../MadelineProto/Db/ArrayCacheTrait.php | 6 +- src/danog/MadelineProto/Db/DriverArray.php | 10 ++- src/danog/MadelineProto/Db/MysqlArray.php | 14 ++++ src/danog/MadelineProto/Db/PostgresArray.php | 13 ++++ src/danog/MadelineProto/Db/RedisArray.php | 14 +++- src/danog/MadelineProto/Db/SqlArray.php | 14 ++-- src/danog/MadelineProto/DoHConnector.php | 4 +- .../MadelineProto/FileCallbackInterface.php | 6 +- src/danog/MadelineProto/InternalDoc.php | 42 ++++++++---- .../Ipc/Wrapper/FileCallback.php | 12 ++-- .../MadelineProto/Loop/Update/SeqLoop.php | 5 ++ src/danog/MadelineProto/MTProto.php | 4 +- .../MTProtoSession/CallHandler.php | 25 ++++--- .../MTProtoTools/AuthKeyHandler.php | 2 + .../MTProtoTools/CallHandler.php | 24 ++++--- .../MadelineProto/MTProtoTools/Files.php | 22 ++++--- .../MadelineProto/MTProtoTools/FilesLogic.php | 3 +- .../MTProtoTools/PeerHandler.php | 2 +- .../MTProtoTools/UpdateHandler.php | 2 +- .../MadelineProto/MyTelegramOrgWrapper.php | 8 ++- src/danog/MadelineProto/SessionPaths.php | 2 +- src/danog/MadelineProto/StrTools.php | 4 +- .../Stream/Common/UdpBufferedStream.php | 7 +- .../Stream/ConnectionContext.php | 6 +- .../Stream/MTProtoTransport/HttpStream.php | 2 +- .../Stream/Transport/WsStream.php | 7 +- .../MadelineProto/TL/Conversion/BotAPI.php | 6 +- .../MadelineProto/TL/Conversion/Extension.php | 9 ++- src/danog/MadelineProto/TL/TL.php | 4 +- src/danog/MadelineProto/TL/Types/Button.php | 4 +- src/danog/MadelineProto/TON/APIFactory.php | 2 +- src/danog/MadelineProto/TON/InternalDoc.php | 57 ++++++++++++++++ 36 files changed, 251 insertions(+), 173 deletions(-) delete mode 100644 src/danog/MadelineProto/Async/AsyncParameters.php diff --git a/composer.json b/composer.json index c2060f4c..5098a089 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,8 @@ "danog/loop": "^0.1.0", "danog/tgseclib": "^3", "amphp/redis": "^1.0", - "symfony/polyfill-php80": "^1.18" + "symfony/polyfill-php80": "^1.18", + "amphp/websocket-client": "^1.0" }, "require-dev": { "vlucas/phpdotenv": "^3", @@ -51,8 +52,6 @@ "haydenpierce/class-finder": "^0.4", "amphp/http-server": "dev-master", "amphp/http": "^1.6", - "amphp/websocket-client": "dev-master as 1", - "amphp/websocket": "dev-master as 1", "ext-ctype": "*", "danog/7to70": "^1", "danog/7to5": "^1", diff --git a/src/danog/MadelineProto/Async/AsyncParameters.php b/src/danog/MadelineProto/Async/AsyncParameters.php deleted file mode 100644 index 75d7d876..00000000 --- a/src/danog/MadelineProto/Async/AsyncParameters.php +++ /dev/null @@ -1,65 +0,0 @@ -. - * - * @author Daniil Gentili - * @copyright 2016-2020 Daniil Gentili - * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3 - * - * @link https://docs.madelineproto.xyz MadelineProto documentation - */ - -namespace danog\MadelineProto\Async; - -/** - * Async parameters class. - * - * Manages asynchronous generation of method parameters - * - * @author Daniil Gentili - */ -class AsyncParameters -{ - /** - * Async callable. - * - * @var callable - */ - private $callable; - /** - * Create async parameters. - * - * @param callable $callable Async callable that will return parameters - */ - public function __construct(callable $callable) - { - $this->callable = $callable; - } - /** - * Create async parameters. - * - * @param callable $callable Async callable that will return parameters - */ - public function setCallable(callable $callable): void - { - $this->callable = $callable; - } - /** - * Get parameters asynchronously. - * - * @return \Generator|\Amp\Promise - */ - public function getParameters() - { - $callable = $this->callable; - return $callable(); - } -} diff --git a/src/danog/MadelineProto/Connection.php b/src/danog/MadelineProto/Connection.php index 28b3d72d..c08cbe15 100644 --- a/src/danog/MadelineProto/Connection.php +++ b/src/danog/MadelineProto/Connection.php @@ -393,7 +393,9 @@ class Connection { $deferred = new Deferred(); if (!isset($message['serialized_body'])) { - $body = \is_object($message['body']) ? yield from $message['body'] : $message['body']; + $body = $message['body'] instanceof \Generator + ? yield from $message['body'] + : $message['body']; $refreshNext = $message['refreshReferences'] ?? false; if ($refreshNext) { $this->API->referenceDatabase->refreshNext(true); diff --git a/src/danog/MadelineProto/DataCenter.php b/src/danog/MadelineProto/DataCenter.php index 87b607e4..d301f403 100644 --- a/src/danog/MadelineProto/DataCenter.php +++ b/src/danog/MadelineProto/DataCenter.php @@ -122,7 +122,7 @@ class DataCenter /** * DoH connector. */ - private Rfc6455Connector $webSocketConnnector; + private Rfc6455Connector $webSocketConnector; public function __sleep() { @@ -238,7 +238,7 @@ class DataCenter $this->dnsConnector = new DnsConnector(new Rfc1035StubResolver()); if (\class_exists(Rfc6455Connector::class)) { - $this->webSocketConnnector = new Rfc6455Connector($this->HTTPClient); + $this->webSocketConnector = new Rfc6455Connector($this->HTTPClient); } } $this->settings->applyChanges(); @@ -420,6 +420,7 @@ class DataCenter if ($stream[0] === DefaultStream::class && $stream[1] === []) { $stream[1] = $useDoH ? new DoHConnector($this, $ctx) : $this->dnsConnector; } + /** @var array{0: class-string, 1: mixed} $stream */ $ctx->addStream(...$stream); } $ctxs[] = $ctx; @@ -480,8 +481,9 @@ class DataCenter if (!\class_exists(Handshake::class)) { throw new Exception('Please install amphp/websocket-client by running "composer require amphp/websocket-client:dev-master"'); } - $stream[1] = $this->webSocketConnnector; + $stream[1] = $this->webSocketConnector; } + /** @var array{0: class-string, 1: mixed} $stream */ $ctx->addStream(...$stream); } $ctxs[] = $ctx; diff --git a/src/danog/MadelineProto/Db/ArrayCacheTrait.php b/src/danog/MadelineProto/Db/ArrayCacheTrait.php index e8837ce4..9481867c 100644 --- a/src/danog/MadelineProto/Db/ArrayCacheTrait.php +++ b/src/danog/MadelineProto/Db/ArrayCacheTrait.php @@ -7,8 +7,6 @@ use danog\MadelineProto\Logger; /** * Array caching trait. - * - * @property string $table */ trait ArrayCacheTrait { @@ -94,8 +92,8 @@ trait ArrayCacheTrait Logger::log( \sprintf( - "cache for table:%s; keys left: %s; keys removed: %s", - $this->table, + "cache for table: %s; keys left: %s; keys removed: %s", + (string) $this, \count($this->cache), $oldCount ), diff --git a/src/danog/MadelineProto/Db/DriverArray.php b/src/danog/MadelineProto/Db/DriverArray.php index 9c8c026a..d79360af 100644 --- a/src/danog/MadelineProto/Db/DriverArray.php +++ b/src/danog/MadelineProto/Db/DriverArray.php @@ -8,8 +8,6 @@ use ReflectionClass; /** * Array caching trait. - * - * @property string $table */ abstract class DriverArray implements DbArray { @@ -20,6 +18,12 @@ abstract class DriverArray implements DbArray $this->stopCacheCleanupLoop(); } + /** + * Get string representation of driver/table. + * + * @return string + */ + abstract public function __toString(): string; public function __wakeup() { @@ -62,7 +66,7 @@ abstract class DriverArray implements DbArray $counter++; if ($counter % 500 === 0) { yield $new->offsetSet($key, $item); - Logger::log("Loading data to table {$new->table}: $counter/$total", Logger::WARNING); + Logger::log("Loading data to table {$new}: $counter/$total", Logger::WARNING); } else { $new->offsetSet($key, $item); } diff --git a/src/danog/MadelineProto/Db/MysqlArray.php b/src/danog/MadelineProto/Db/MysqlArray.php index 5474ec77..bb7bf407 100644 --- a/src/danog/MadelineProto/Db/MysqlArray.php +++ b/src/danog/MadelineProto/Db/MysqlArray.php @@ -22,6 +22,20 @@ class MysqlArray extends SqlArray // Legacy protected array $settings; + /** + * Initialize on startup. + * + * @return \Generator + */ + public function initStartup(): \Generator + { + return $this->initConnection($this->dbSettings); + } + public function __toString(): string + { + return $this->table; + } + public function __sleep(): array { return ['table', 'dbSettings']; diff --git a/src/danog/MadelineProto/Db/PostgresArray.php b/src/danog/MadelineProto/Db/PostgresArray.php index 8784aacb..0dbf2e55 100644 --- a/src/danog/MadelineProto/Db/PostgresArray.php +++ b/src/danog/MadelineProto/Db/PostgresArray.php @@ -22,6 +22,19 @@ class PostgresArray extends SqlArray // Legacy protected array $settings; + /** + * Initialize on startup. + * + * @return \Generator + */ + public function initStartup(): \Generator + { + return $this->initConnection($this->dbSettings); + } + public function __toString(): string + { + return $this->table; + } /** * Initialize connection. * diff --git a/src/danog/MadelineProto/Db/RedisArray.php b/src/danog/MadelineProto/Db/RedisArray.php index 8026d15f..04f09641 100644 --- a/src/danog/MadelineProto/Db/RedisArray.php +++ b/src/danog/MadelineProto/Db/RedisArray.php @@ -15,13 +15,25 @@ use function Amp\call; class RedisArray extends SqlArray { - protected string $table; protected DatabaseRedis $dbSettings; private RedisRedis $db; // Legacy protected array $settings; + /** + * Initialize on startup. + * + * @return \Generator + */ + public function initStartup(): \Generator + { + return $this->initConnection($this->dbSettings); + } + public function __toString(): string + { + return $this->table; + } /** * @return Generator * diff --git a/src/danog/MadelineProto/Db/SqlArray.php b/src/danog/MadelineProto/Db/SqlArray.php index 14cef107..d21aa02c 100644 --- a/src/danog/MadelineProto/Db/SqlArray.php +++ b/src/danog/MadelineProto/Db/SqlArray.php @@ -9,6 +9,8 @@ use function Amp\call; abstract class SqlArray extends DriverArray { + protected string $table; + /** * Create table for property. * @@ -20,15 +22,6 @@ abstract class SqlArray extends DriverArray abstract protected function renameTable(string $from, string $to): \Generator; - /** - * Initialize on startup. - * - * @return \Generator - */ - public function initStartup(): \Generator - { - return $this->initConnection($this->dbSettings); - } /** * @param string $name @@ -37,7 +30,7 @@ abstract class SqlArray extends DriverArray * @param DatabaseAbstract $settings * * @return Promise - * + * * @psalm-return Promise */ public static function getInstance(string $name, $value = null, string $tablePrefix = '', $settings): Promise @@ -50,6 +43,7 @@ abstract class SqlArray extends DriverArray $instance->table = $tableName; } + /** @psalm-suppress UndefinedPropertyAssignment */ $instance->dbSettings = $settings; $instance->ttl = $settings->getCacheTtl(); diff --git a/src/danog/MadelineProto/DoHConnector.php b/src/danog/MadelineProto/DoHConnector.php index c2aa812f..dd60bf75 100644 --- a/src/danog/MadelineProto/DoHConnector.php +++ b/src/danog/MadelineProto/DoHConnector.php @@ -117,13 +117,13 @@ class DoHConnector implements Connector foreach ($uris as $builtUri) { try { $streamContext = \stream_context_create($socketContext->withoutTlsContext()->toStreamContextArray()); - /** @psalm-ignore NullArgument */ + /** @psalm-suppress NullArgument */ if (!($socket = @\stream_socket_client($builtUri, $errno, $errstr, null, $flags, $streamContext))) { throw new ConnectException(\sprintf('Connection to %s failed: [Error #%d] %s%s', $uri, $errno, $errstr, $failures ? '; previous attempts: '.\implode($failures) : ''), $errno); } \stream_set_blocking($socket, false); $deferred = new Deferred(); - /** @psalm-ignore InvalidArgument */ + /** @psalm-suppress InvalidArgument */ $watcher = Loop::onWritable($socket, [$deferred, 'resolve']); $id = $token->subscribe([$deferred, 'fail']); try { diff --git a/src/danog/MadelineProto/FileCallbackInterface.php b/src/danog/MadelineProto/FileCallbackInterface.php index 4d1bd122..eb954c16 100644 --- a/src/danog/MadelineProto/FileCallbackInterface.php +++ b/src/danog/MadelineProto/FileCallbackInterface.php @@ -33,9 +33,9 @@ interface FileCallbackInterface /** * Invoke callback. * - * @param int $percent Percent - * @param int $speed Speed in mbps - * @param int $time Time + * @param float $percent Percent + * @param float $speed Speed in mbps + * @param float $time Time * * @return mixed */ diff --git a/src/danog/MadelineProto/InternalDoc.php b/src/danog/MadelineProto/InternalDoc.php index 0de59578..5ff9acb6 100644 --- a/src/danog/MadelineProto/InternalDoc.php +++ b/src/danog/MadelineProto/InternalDoc.php @@ -5172,7 +5172,7 @@ class InternalDoc extends APIFactory */ public function getExtensionFromLocation($location, string $default): string { - return \danog\MadelineProto\MTProto::getExtensionFromLocation($location, $default); + return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromLocation($location, $default); } /** * Get extension from mime type. @@ -5183,7 +5183,7 @@ class InternalDoc extends APIFactory */ public function getExtensionFromMime(string $mime): string { - return \danog\MadelineProto\MTProto::getExtensionFromMime($mime); + return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromMime($mime); } /** * Get info about file. @@ -5272,7 +5272,21 @@ class InternalDoc extends APIFactory * * @return \Amp\Promise Info object * - * @psalm-return \Amp\Promise + * @psalm-return \Generator|array, mixed, array{ + * InputPeer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}, + * Peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}, + * DialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}}, + * NotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}}, + * InputDialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}}, + * InputNotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}}, + * bot_api_id: int|string, + * user_id?: int, + * chat_id?: int, + * channel_id?: int, + * InputUser?: {_: string, user_id?: int, access_hash?: mixed, min?: bool}, + * InputChannel?: {_: string, channel_id: int, access_hash: mixed, min: bool}, + * type: string + * }> */ public function getInfo($id, $recursive = true, array $extra = []) { @@ -5312,7 +5326,7 @@ class InternalDoc extends APIFactory */ public function getMimeFromBuffer(string $buffer): string { - return \danog\MadelineProto\MTProto::getMimeFromBuffer($buffer); + return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromBuffer($buffer); } /** * Get mime type from file extension. @@ -5324,7 +5338,7 @@ class InternalDoc extends APIFactory */ public function getMimeFromExtension(string $extension, string $default): string { - return \danog\MadelineProto\MTProto::getMimeFromExtension($extension, $default); + return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromExtension($extension, $default); } /** * Get mime type of file. @@ -5335,7 +5349,7 @@ class InternalDoc extends APIFactory */ public function getMimeFromFile(string $file): string { - return \danog\MadelineProto\MTProto::getMimeFromFile($file); + return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromFile($file); } /** * Get download info of the propic of a user @@ -5670,9 +5684,11 @@ class InternalDoc extends APIFactory * * If the $aargs['noResponse'] is true, will not wait for a response. * - * @param string $method Method name - * @param array $args Arguments - * @param array $aargs Additional arguments + * @param string $method Method name + * @param array|\Generator $args Arguments + * @param array $aargs Additional arguments + * + * @psalm-param array|\Generator $args * * @return \Amp\Promise */ @@ -5686,9 +5702,11 @@ class InternalDoc extends APIFactory /** * Call method and make sure it is asynchronously sent. * - * @param string $method Method name - * @param array $args Arguments - * @param array $aargs Additional arguments + * @param string $method Method name + * @param array|\Generator $args Arguments + * @param array $aargs Additional arguments + * + * @psalm-param array|\Generator $args * * @return \Amp\Promise */ diff --git a/src/danog/MadelineProto/Ipc/Wrapper/FileCallback.php b/src/danog/MadelineProto/Ipc/Wrapper/FileCallback.php index 399a96c8..bfe32600 100644 --- a/src/danog/MadelineProto/Ipc/Wrapper/FileCallback.php +++ b/src/danog/MadelineProto/Ipc/Wrapper/FileCallback.php @@ -18,14 +18,16 @@ class FileCallback extends Obj implements FileCallbackInterface /** * Invoke callback. * - * @param int $percent Percent - * @param int $speed Speed in mbps - * @param int $time Time + * @param float $percent Percent + * @param float $speed Speed in mbps + * @param float $time Time + * + * @psalm-suppress MethodSignatureMismatch * * @return mixed */ - public function __invoke(...$args) + public function __invoke($percent, $speed, $time) { - return $this->__call('__invoke', $args); + return $this->__call('__invoke', [$percent, $speed, $time]); } } diff --git a/src/danog/MadelineProto/Loop/Update/SeqLoop.php b/src/danog/MadelineProto/Loop/Update/SeqLoop.php index ed086b7c..3f80565a 100644 --- a/src/danog/MadelineProto/Loop/Update/SeqLoop.php +++ b/src/danog/MadelineProto/Loop/Update/SeqLoop.php @@ -21,6 +21,7 @@ namespace danog\MadelineProto\Loop\Update; use danog\Loop\ResumableSignalLoop; use danog\MadelineProto\Loop\InternalLoop; +use danog\MadelineProto\MTProtoTools\UpdatesState; /** * update feed loop. @@ -42,6 +43,10 @@ class SeqLoop extends ResumableSignalLoop * Pending updates. */ private array $pendingWakeups = []; + /** + * State. + */ + private ?UpdatesState $state = null; /** * Main loop. * diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index b05244a6..5a122acf 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -67,7 +67,6 @@ class MTProto extends AsyncConstruct implements TLCallback use \danog\MadelineProto\SecretChats\SeqNoHandler; use \danog\MadelineProto\TL\Conversion\BotAPI; use \danog\MadelineProto\TL\Conversion\BotAPIFiles; - use \danog\MadelineProto\TL\Conversion\Extension; use \danog\MadelineProto\TL\Conversion\TD; use \danog\MadelineProto\VoIP\AuthKeyHandler; use \danog\MadelineProto\Wrappers\DialogHandler; @@ -1066,6 +1065,7 @@ class MTProto extends AsyncConstruct implements TLCallback // Convert old array settings to new settings object if (\is_array($this->settings)) { if (($this->settings['updates']['callback'] ?? '') === 'getUpdatesUpdateHandler') { + /** @psalm-suppress InvalidPropertyAssignmentValue */ $this->settings['updates']['callback'] = [$this, 'getUpdatesUpdateHandler']; } if (\is_callable($this->settings['updates']['callback'] ?? null)) { @@ -1731,6 +1731,7 @@ class MTProto extends AsyncConstruct implements TLCallback $this->logger("Could not obtain info about report peer $peer: $e", Logger::FATAL_ERROR); } } + /** @var int[] $userOrId */ $this->reportDest = $userOrId; } /** @@ -1881,5 +1882,4 @@ class MTProto extends AsyncConstruct implements TLCallback unset($vars['full_chats'], $vars['chats'], $vars['referenceDatabase'], $vars['minDatabase'], $vars['TL']); return $vars; } - const ALL_MIMES = ['webp' => [0 => 'image/webp'], 'png' => [0 => 'image/png', 1 => 'image/x-png'], 'bmp' => [0 => 'image/bmp', 1 => 'image/x-bmp', 2 => 'image/x-bitmap', 3 => 'image/x-xbitmap', 4 => 'image/x-win-bitmap', 5 => 'image/x-windows-bmp', 6 => 'image/ms-bmp', 7 => 'image/x-ms-bmp', 8 => 'application/bmp', 9 => 'application/x-bmp', 10 => 'application/x-win-bitmap'], 'gif' => [0 => 'image/gif'], 'jpeg' => [0 => 'image/jpeg', 1 => 'image/pjpeg'], 'xspf' => [0 => 'application/xspf+xml'], 'vlc' => [0 => 'application/videolan'], 'wmv' => [0 => 'video/x-ms-wmv', 1 => 'video/x-ms-asf'], 'au' => [0 => 'audio/x-au'], 'ac3' => [0 => 'audio/ac3'], 'flac' => [0 => 'audio/x-flac'], 'ogg' => [0 => 'audio/ogg', 1 => 'video/ogg', 2 => 'application/ogg'], 'kmz' => [0 => 'application/vnd.google-earth.kmz'], 'kml' => [0 => 'application/vnd.google-earth.kml+xml'], 'rtx' => [0 => 'text/richtext'], 'rtf' => [0 => 'text/rtf'], 'jar' => [0 => 'application/java-archive', 1 => 'application/x-java-application', 2 => 'application/x-jar'], 'zip' => [0 => 'application/x-zip', 1 => 'application/zip', 2 => 'application/x-zip-compressed', 3 => 'application/s-compressed', 4 => 'multipart/x-zip'], '7zip' => [0 => 'application/x-compressed'], 'xml' => [0 => 'application/xml', 1 => 'text/xml'], 'svg' => [0 => 'image/svg+xml'], '3g2' => [0 => 'video/3gpp2'], '3gp' => [0 => 'video/3gp', 1 => 'video/3gpp'], 'mp4' => [0 => 'video/mp4'], 'm4a' => [0 => 'audio/x-m4a'], 'f4v' => [0 => 'video/x-f4v'], 'flv' => [0 => 'video/x-flv'], 'webm' => [0 => 'video/webm'], 'aac' => [0 => 'audio/x-acc'], 'm4u' => [0 => 'application/vnd.mpegurl'], 'pdf' => [0 => 'application/pdf', 1 => 'application/octet-stream'], 'pptx' => [0 => 'application/vnd.openxmlformats-officedocument.presentationml.presentation'], 'ppt' => [0 => 'application/powerpoint', 1 => 'application/vnd.ms-powerpoint', 2 => 'application/vnd.ms-office', 3 => 'application/msword'], 'docx' => [0 => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'], 'xlsx' => [0 => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 1 => 'application/vnd.ms-excel'], 'xl' => [0 => 'application/excel'], 'xls' => [0 => 'application/msexcel', 1 => 'application/x-msexcel', 2 => 'application/x-ms-excel', 3 => 'application/x-excel', 4 => 'application/x-dos_ms_excel', 5 => 'application/xls', 6 => 'application/x-xls'], 'xsl' => [0 => 'text/xsl'], 'mpeg' => [0 => 'video/mpeg'], 'mov' => [0 => 'video/quicktime'], 'avi' => [0 => 'video/x-msvideo', 1 => 'video/msvideo', 2 => 'video/avi', 3 => 'application/x-troff-msvideo'], 'movie' => [0 => 'video/x-sgi-movie'], 'log' => [0 => 'text/x-log'], 'txt' => [0 => 'text/plain'], 'css' => [0 => 'text/css'], 'html' => [0 => 'text/html'], 'wav' => [0 => 'audio/x-wav', 1 => 'audio/wave', 2 => 'audio/wav'], 'xhtml' => [0 => 'application/xhtml+xml'], 'tar' => [0 => 'application/x-tar'], 'tgz' => [0 => 'application/x-gzip-compressed'], 'psd' => [0 => 'application/x-photoshop', 1 => 'image/vnd.adobe.photoshop'], 'exe' => [0 => 'application/x-msdownload'], 'js' => [0 => 'application/x-javascript'], 'mp3' => [0 => 'audio/mpeg', 1 => 'audio/mpg', 2 => 'audio/mpeg3', 3 => 'audio/mp3'], 'rar' => [0 => 'application/x-rar', 1 => 'application/rar', 2 => 'application/x-rar-compressed'], 'gzip' => [0 => 'application/x-gzip'], 'hqx' => [0 => 'application/mac-binhex40', 1 => 'application/mac-binhex', 2 => 'application/x-binhex40', 3 => 'application/x-mac-binhex40'], 'cpt' => [0 => 'application/mac-compactpro'], 'bin' => [0 => 'application/macbinary', 1 => 'application/mac-binary', 2 => 'application/x-binary', 3 => 'application/x-macbinary'], 'oda' => [0 => 'application/oda'], 'ai' => [0 => 'application/postscript'], 'smil' => [0 => 'application/smil'], 'mif' => [0 => 'application/vnd.mif'], 'wbxml' => [0 => 'application/wbxml'], 'wmlc' => [0 => 'application/wmlc'], 'dcr' => [0 => 'application/x-director'], 'dvi' => [0 => 'application/x-dvi'], 'gtar' => [0 => 'application/x-gtar'], 'php' => [0 => 'application/x-httpd-php', 1 => 'application/php', 2 => 'application/x-php', 3 => 'text/php', 4 => 'text/x-php', 5 => 'application/x-httpd-php-source'], 'swf' => [0 => 'application/x-shockwave-flash'], 'sit' => [0 => 'application/x-stuffit'], 'z' => [0 => 'application/x-compress'], 'mid' => [0 => 'audio/midi'], 'aif' => [0 => 'audio/x-aiff', 1 => 'audio/aiff'], 'ram' => [0 => 'audio/x-pn-realaudio'], 'rpm' => [0 => 'audio/x-pn-realaudio-plugin'], 'ra' => [0 => 'audio/x-realaudio'], 'rv' => [0 => 'video/vnd.rn-realvideo'], 'jp2' => [0 => 'image/jp2', 1 => 'video/mj2', 2 => 'image/jpx', 3 => 'image/jpm'], 'tiff' => [0 => 'image/tiff'], 'eml' => [0 => 'message/rfc822'], 'pem' => [0 => 'application/x-x509-user-cert', 1 => 'application/x-pem-file'], 'p10' => [0 => 'application/x-pkcs10', 1 => 'application/pkcs10'], 'p12' => [0 => 'application/x-pkcs12'], 'p7a' => [0 => 'application/x-pkcs7-signature'], 'p7c' => [0 => 'application/pkcs7-mime', 1 => 'application/x-pkcs7-mime'], 'p7r' => [0 => 'application/x-pkcs7-certreqresp'], 'p7s' => [0 => 'application/pkcs7-signature'], 'crt' => [0 => 'application/x-x509-ca-cert', 1 => 'application/pkix-cert'], 'crl' => [0 => 'application/pkix-crl', 1 => 'application/pkcs-crl'], 'pgp' => [0 => 'application/pgp'], 'gpg' => [0 => 'application/gpg-keys'], 'rsa' => [0 => 'application/x-pkcs7'], 'ics' => [0 => 'text/calendar'], 'zsh' => [0 => 'text/x-scriptzsh'], 'cdr' => [0 => 'application/cdr', 1 => 'application/coreldraw', 2 => 'application/x-cdr', 3 => 'application/x-coreldraw', 4 => 'image/cdr', 5 => 'image/x-cdr', 6 => 'zz-application/zz-winassoc-cdr'], 'wma' => [0 => 'audio/x-ms-wma'], 'vcf' => [0 => 'text/x-vcard'], 'srt' => [0 => 'text/srt'], 'vtt' => [0 => 'text/vtt'], 'ico' => [0 => 'image/x-icon', 1 => 'image/x-ico', 2 => 'image/vnd.microsoft.icon'], 'csv' => [0 => 'text/x-comma-separated-values', 1 => 'text/comma-separated-values', 2 => 'application/vnd.msexcel'], 'json' => [0 => 'application/json', 1 => 'text/json']]; } diff --git a/src/danog/MadelineProto/MTProtoSession/CallHandler.php b/src/danog/MadelineProto/MTProtoSession/CallHandler.php index d4d9b56e..3e212ef8 100644 --- a/src/danog/MadelineProto/MTProtoSession/CallHandler.php +++ b/src/danog/MadelineProto/MTProtoSession/CallHandler.php @@ -20,7 +20,6 @@ namespace danog\MadelineProto\MTProtoSession; use Amp\Deferred; -use danog\MadelineProto\Async\AsyncParameters; use danog\MadelineProto\TL\Exception; use danog\MadelineProto\Tools; @@ -79,9 +78,11 @@ trait CallHandler * * If the $aargs['noResponse'] is true, will not wait for a response. * - * @param string $method Method name - * @param array $args Arguments - * @param array $aargs Additional arguments + * @param string $method Method name + * @param array|\Generator $args Arguments + * @param array $aargs Additional arguments + * + * @psalm-param array|\Generator $args * * @return \Generator */ @@ -100,9 +101,11 @@ trait CallHandler /** * Call method and make sure it is asynchronously sent (generator). * - * @param string $method Method name - * @param array $args Arguments - * @param array $aargs Additional arguments + * @param string $method Method name + * @param array|\Generator $args Arguments + * @param array $aargs Additional arguments + * + * @psalm-param array|\Generator $args * * @return \Generator */ @@ -160,6 +163,7 @@ trait CallHandler $aargs, [ '_' => $method, + 'body' => $args, 'type' => $methodInfo['type'], 'contentRelated' => $this->contentRelated($method), 'promise' => $deferred, @@ -167,16 +171,11 @@ trait CallHandler 'unencrypted' => !$this->shared->hasTempAuthKey() && \strpos($method, '.') === false ] ); - if (\is_object($args) && $args instanceof AsyncParameters) { - $message['body'] = yield $args->fetchParameters(); - } else { - $message['body'] = $args; - } if ($method === 'users.getUsers' && $args === ['id' => [['_' => 'inputUserSelf']]] || $method === 'auth.exportAuthorization' || $method === 'updates.getDifference') { $message['user_related'] = true; } $aargs['postpone'] = $aargs['postpone'] ?? false; - $deferred = (yield from $this->sendMessage($message, !$aargs['postpone'])); + $deferred = yield from $this->sendMessage($message, !$aargs['postpone']); $this->checker->resume(); return $deferred; } diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php index bcb9d5aa..9a5ff1b1 100644 --- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php @@ -229,6 +229,7 @@ trait AuthKeyHandler * Separate answer and hash */ $answer_hash = \substr($answer_with_hash, 0, 20); + /** @var string */ $answer = \substr($answer_with_hash, 20); /* * *********************************************************************** @@ -553,6 +554,7 @@ trait AuthKeyHandler foreach ($dcs as $id => &$dc) { $dc = $dc(); } + /** @var \Generator[] $dcs */ yield \danog\MadelineProto\Tools::all($dcs); foreach ($postpone as $id => $socket) { yield from $this->initAuthorizationSocket($id, $socket); diff --git a/src/danog/MadelineProto/MTProtoTools/CallHandler.php b/src/danog/MadelineProto/MTProtoTools/CallHandler.php index c91b6b51..b4571f6e 100644 --- a/src/danog/MadelineProto/MTProtoTools/CallHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/CallHandler.php @@ -31,9 +31,11 @@ trait CallHandler /** * Synchronous wrapper for methodCall. * - * @param string $method Method name - * @param array $args Arguments - * @param array $aargs Additional arguments + * @param string $method Method name + * @param array|\Generator $args Arguments + * @param array $aargs Additional arguments + * + * @psalm-param array|\Generator $args * * @return mixed */ @@ -46,9 +48,11 @@ trait CallHandler * * If the $aargs['noResponse'] is true, will not wait for a response. * - * @param string $method Method name - * @param array $args Arguments - * @param array $aargs Additional arguments + * @param string $method Method name + * @param array|\Generator $args Arguments + * @param array $aargs Additional arguments + * + * @psalm-param array|\Generator $args * * @return \Generator */ @@ -59,9 +63,11 @@ trait CallHandler /** * Call method and make sure it is asynchronously sent. * - * @param string $method Method name - * @param array $args Arguments - * @param array $aargs Additional arguments + * @param string $method Method name + * @param array|\Generator $args Arguments + * @param array $aargs Additional arguments + * + * @psalm-param array|\Generator $args * * @return \Generator */ diff --git a/src/danog/MadelineProto/MTProtoTools/Files.php b/src/danog/MadelineProto/MTProtoTools/Files.php index 8a1aac90..098f659f 100644 --- a/src/danog/MadelineProto/MTProtoTools/Files.php +++ b/src/danog/MadelineProto/MTProtoTools/Files.php @@ -172,7 +172,9 @@ trait Files $exception = null; $start = \microtime(true); while ($part_num < $part_total_num) { - $writePromise = Tools::call($this->methodCallAsyncWrite($method, $callable($part_num), ['heavy' => true, 'file' => true, 'datacenter' => &$datacenter])); + $resa = $callable($part_num); + \var_dump($resa); + $writePromise = Tools::call($this->methodCallAsyncWrite($method, $resa, ['heavy' => true, 'file' => true, 'datacenter' => &$datacenter])); if (!$seekable) { yield $writePromise; } @@ -622,10 +624,10 @@ trait Files } } if (!isset($res['ext']) || $res['ext'] === '') { - $res['ext'] = $this->getExtensionFromLocation($res['InputFileLocation'], $this->getExtensionFromMime($res['mime'] ?? 'image/jpeg')); + $res['ext'] = Tools::getExtensionFromLocation($res['InputFileLocation'], Tools::getExtensionFromMime($res['mime'] ?? 'image/jpeg')); } if (!isset($res['mime']) || $res['mime'] === '') { - $res['mime'] = $this->getMimeFromExtension($res['ext'], 'image/jpeg'); + $res['mime'] = Tools::getMimeFromExtension($res['ext'], 'image/jpeg'); } if (!isset($res['name']) || $res['name'] === '') { $res['name'] = Tools::unpackSignedLongString($messageMedia['file']['access_hash']); @@ -680,8 +682,8 @@ trait Files $res['thumb_size'] = $messageMedia['type']; if ($messageMedia['location']['_'] === 'fileLocationUnavailable') { $res['name'] = Tools::unpackSignedLongString($messageMedia['volume_id']).'_'.$messageMedia['local_id']; - $res['mime'] = $this->getMimeFromBuffer($res['data']); - $res['ext'] = $this->getExtensionFromMime($res['mime']); + $res['mime'] = Tools::getMimeFromBuffer($res['data']); + $res['ext'] = TOols::getExtensionFromMime($res['mime']); } else { $res = \array_merge($res, yield from $this->getDownloadInfo($messageMedia['location'])); } @@ -699,13 +701,13 @@ trait Files case 'fileLocation': $res['name'] = Tools::unpackSignedLongString($messageMedia['volume_id']).'_'.$messageMedia['local_id']; $res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $messageMedia['volume_id'], 'local_id' => $messageMedia['local_id'], 'secret' => $messageMedia['secret'], 'dc_id' => $messageMedia['dc_id'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::PHOTO_LOCATION_LOCATION, $messageMedia)]; - $res['ext'] = $this->getExtensionFromLocation($res['InputFileLocation'], '.jpg'); - $res['mime'] = $this->getMimeFromExtension($res['ext'], 'image/jpeg'); + $res['ext'] = Tools::getExtensionFromLocation($res['InputFileLocation'], '.jpg'); + $res['mime'] = Tools::getMimeFromExtension($res['ext'], 'image/jpeg'); return $res; case 'fileLocationToBeDeprecated': $res['name'] = Tools::unpackSignedLongString($messageMedia['volume_id']).'_'.$messageMedia['local_id']; $res['ext'] = '.jpg'; - $res['mime'] = $this->getMimeFromExtension($res['ext'], 'image/jpeg'); + $res['mime'] = Tools::getMimeFromExtension($res['ext'], 'image/jpeg'); $res['InputFileLocation'] = [ '_' => 'inputFileLocationTemp', // Will be overwritten @@ -742,7 +744,7 @@ trait Files } $res['InputFileLocation'] = ['_' => 'inputDocumentFileLocation', 'id' => $messageMedia['document']['id'], 'access_hash' => $messageMedia['document']['access_hash'], 'version' => isset($messageMedia['document']['version']) ? $messageMedia['document']['version'] : 0, 'dc_id' => $messageMedia['document']['dc_id'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::DOCUMENT_LOCATION, $messageMedia['document'])]; if (!isset($res['ext']) || $res['ext'] === '') { - $res['ext'] = $this->getExtensionFromLocation($res['InputFileLocation'], $this->getExtensionFromMime($messageMedia['document']['mime_type'])); + $res['ext'] = Tools::getExtensionFromLocation($res['InputFileLocation'], Tools::getExtensionFromMime($messageMedia['document']['mime_type'])); } if (!isset($res['name']) || $res['name'] === '') { $res['name'] = Tools::unpackSignedLongString($messageMedia['document']['access_hash']); @@ -962,7 +964,7 @@ trait Files * @param array $messageMedia File object * @param bool $cdn Whether this is a CDN file * @param string $datacenter DC ID - * @param string $old_dc Previous DC ID + * @param ?string $old_dc Previous DC ID * @param AES $ige IGE decryptor instance * @param callable $cb Status callback * @param array $offset Offset diff --git a/src/danog/MadelineProto/MTProtoTools/FilesLogic.php b/src/danog/MadelineProto/MTProtoTools/FilesLogic.php index 569e0123..1a45e906 100644 --- a/src/danog/MadelineProto/MTProtoTools/FilesLogic.php +++ b/src/danog/MadelineProto/MTProtoTools/FilesLogic.php @@ -25,6 +25,7 @@ use danog\MadelineProto\Stream\Common\BufferedRawStream; use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream; use danog\MadelineProto\Stream\ConnectionContext; use danog\MadelineProto\Stream\Transport\PremadeStream; +use danog\MadelineProto\TL\Conversion\Extension; use danog\MadelineProto\Tools; @@ -245,7 +246,7 @@ trait FilesLogic throw new \danog\MadelineProto\Exception('Given file is too big!'); } $stream = yield open($file, 'rb'); - $mime = $this->getMimeFromFile($file); + $mime = Extension::getMimeFromFile($file); try { return yield from $this->uploadFromStream($stream, $size, $mime, $fileName, $cb, $encrypted); } finally { diff --git a/src/danog/MadelineProto/MTProtoTools/PeerHandler.php b/src/danog/MadelineProto/MTProtoTools/PeerHandler.php index e279ff13..1a941c7d 100644 --- a/src/danog/MadelineProto/MTProtoTools/PeerHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/PeerHandler.php @@ -432,7 +432,7 @@ trait PeerHandler case 'contact': return $id['user_id']; case 'updatePhoneCall': - return $id->getOtherID(); + return $id['phone_call']->getOtherID(); case 'updateReadHistoryInbox': case 'updateReadHistoryOutbox': return $this->getId($id['peer']); diff --git a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php index ea913f39..d01c2d53 100644 --- a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php @@ -155,7 +155,7 @@ trait UpdateHandler * * @internal * - * @return \Generator + * @return \Generator */ public function loadUpdateState(): \Generator { diff --git a/src/danog/MadelineProto/MyTelegramOrgWrapper.php b/src/danog/MadelineProto/MyTelegramOrgWrapper.php index 4c7d80d8..05ee3ba1 100644 --- a/src/danog/MadelineProto/MyTelegramOrgWrapper.php +++ b/src/danog/MadelineProto/MyTelegramOrgWrapper.php @@ -104,11 +104,17 @@ class MyTelegramOrgWrapper $this->settings = new Settings; } elseif (\is_array($this->settings)) { $this->settings = Settings::parseFromLegacy($this->settings); + if (!$this->settings instanceof Settings) { + $settings = new Settings; + $settings->merge($this->settings); + $this->settings = $settings; + } } if (!$this->jar || !$this->jar instanceof InMemoryCookieJar) { $this->jar = new InMemoryCookieJar(); } $this->datacenter = new DataCenter(new class(new Logger($this->settings->getLogger())) { + public Logger $logger; public function __construct(Logger $logger) { $this->logger = $logger; @@ -347,7 +353,7 @@ class MyTelegramOrgWrapper * @param string $name Function name * @param array $arguments Arguments * - * @return void + * @return mixed */ public function __call(string $name, array $arguments) { diff --git a/src/danog/MadelineProto/SessionPaths.php b/src/danog/MadelineProto/SessionPaths.php index e7faf7cc..f0ca636d 100644 --- a/src/danog/MadelineProto/SessionPaths.php +++ b/src/danog/MadelineProto/SessionPaths.php @@ -106,7 +106,7 @@ class SessionPaths * @param string $path Object path, defaults to session path * * @return \Generator - * + * * @psalm-return \Generator */ public function unserialize(string $path = ''): \Generator diff --git a/src/danog/MadelineProto/StrTools.php b/src/danog/MadelineProto/StrTools.php index c3fc7448..38238a88 100644 --- a/src/danog/MadelineProto/StrTools.php +++ b/src/danog/MadelineProto/StrTools.php @@ -19,10 +19,12 @@ namespace danog\MadelineProto; +use danog\MadelineProto\TL\Conversion\Extension; + /** * Some tools. */ -abstract class StrTools +abstract class StrTools extends Extension { /** * Convert to camelCase. diff --git a/src/danog/MadelineProto/Stream/Common/UdpBufferedStream.php b/src/danog/MadelineProto/Stream/Common/UdpBufferedStream.php index b982bb7f..3a2bf0d3 100644 --- a/src/danog/MadelineProto/Stream/Common/UdpBufferedStream.php +++ b/src/danog/MadelineProto/Stream/Common/UdpBufferedStream.php @@ -42,7 +42,6 @@ use danog\MadelineProto\Stream\WriteBufferInterface; class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface, MTProtoBufferInterface { use BufferedStream; - private RawStreamInterface $stream; /** * Connect to stream. * @@ -72,7 +71,7 @@ class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface * * @psalm-return \Generator|Success> */ - public function getReadBuffer(&$length): \Generator + public function getReadBufferGenerator(&$length): \Generator { if (!$this->stream) { return new Failure(new ClosedException("MadelineProto stream was disconnected")); @@ -185,7 +184,7 @@ class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface */ public function getSocket(): EncryptableSocket { - return $this->stream->getSocket(); + return $this->getSocket(); } /** * {@inheritDoc} @@ -194,7 +193,7 @@ class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface */ public function getStream(): RawStreamInterface { - return $this->stream; + return $this; } public static function getName(): string { diff --git a/src/danog/MadelineProto/Stream/ConnectionContext.php b/src/danog/MadelineProto/Stream/ConnectionContext.php index 5c50870b..9f56a51c 100644 --- a/src/danog/MadelineProto/Stream/ConnectionContext.php +++ b/src/danog/MadelineProto/Stream/ConnectionContext.php @@ -100,7 +100,7 @@ class ConnectionContext /** * An array of arrays containing an array with the stream name and the extra parameter to pass to it. * - * @var array> + * @var array<0: class-string, 1: mixed>[] */ private $nextStreams = []; /** @@ -344,7 +344,9 @@ class ConnectionContext * Add a stream to the stream chain. * * @param string $streamName - * @param mixed $extra + * @param mixed $extra + * + * @psalm-param class-string $streamName * * @return self */ diff --git a/src/danog/MadelineProto/Stream/MTProtoTransport/HttpStream.php b/src/danog/MadelineProto/Stream/MTProtoTransport/HttpStream.php index d7c83648..a2c0d900 100644 --- a/src/danog/MadelineProto/Stream/MTProtoTransport/HttpStream.php +++ b/src/danog/MadelineProto/Stream/MTProtoTransport/HttpStream.php @@ -38,7 +38,7 @@ class HttpStream implements MTProtoBufferInterface, BufferedProxyStreamInterface { use BufferedStream; /** - * Stream + * Stream. * * @var RawStreamInterface */ diff --git a/src/danog/MadelineProto/Stream/Transport/WsStream.php b/src/danog/MadelineProto/Stream/Transport/WsStream.php index 6fbb3931..c274966e 100644 --- a/src/danog/MadelineProto/Stream/Transport/WsStream.php +++ b/src/danog/MadelineProto/Stream/Transport/WsStream.php @@ -19,11 +19,14 @@ namespace danog\MadelineProto\Stream\Transport; +use Amp\Http\Client\HttpClientBuilder; use Amp\Promise; use Amp\Socket\EncryptableSocket; use Amp\Websocket\Client\Connection; use Amp\Websocket\Client\Connector; use Amp\Websocket\Client\Handshake; +use Amp\Websocket\Client\Rfc6455Connector; +use Amp\Websocket\ClosedException; use Amp\Websocket\Message; use danog\MadelineProto\Stream\Async\RawStream; use danog\MadelineProto\Stream\ConnectionContext; @@ -73,7 +76,7 @@ class WsStream implements RawStreamInterface, ProxyStreamInterface $uri = $ctx->getStringUri(); $uri = \str_replace('tcp://', $ctx->isSecure() ? 'wss://' : 'ws://', $uri); $handshake = new Handshake($uri); - $this->stream = yield ($this->connector ?? connector())->connect($handshake, $ctx->getCancellationToken()); + $this->stream = yield ($this->connector ?? new Rfc6455Connector(HttpClientBuilder::buildDefault()))->connect($handshake, $ctx->getCancellationToken()); if (\strlen($header)) { yield $this->write($header); } @@ -100,7 +103,7 @@ class WsStream implements RawStreamInterface, ProxyStreamInterface $this->message = null; } } catch (\Throwable $e) { - if ($e instanceof Amp\Websocket\ClosedException && $e->getReason() !== 'Client closed the underlying TCP connection') { + if ($e instanceof ClosedException && $e->getReason() !== 'Client closed the underlying TCP connection') { throw $e; } return null; diff --git a/src/danog/MadelineProto/TL/Conversion/BotAPI.php b/src/danog/MadelineProto/TL/Conversion/BotAPI.php index 8423242d..b8961598 100644 --- a/src/danog/MadelineProto/TL/Conversion/BotAPI.php +++ b/src/danog/MadelineProto/TL/Conversion/BotAPI.php @@ -22,6 +22,7 @@ namespace danog\MadelineProto\TL\Conversion; use danog\Decoder\FileId; use danog\MadelineProto\Logger; use danog\MadelineProto\MTProtoTools\PeerHandler; +use danog\MadelineProto\Tools; use const danog\Decoder\TYPES_IDS; @@ -387,7 +388,7 @@ trait BotAPI $res['file_name'] .= $res['ext']; unset($res['ext']); } else { - $res['file_name'] .= $this->getExtensionFromMime($data['document']['mime_type']); + $res['file_name'] .= Tools::getExtensionFromMime($data['document']['mime_type']); } $res['file_size'] = $data['document']['size']; $res['mime_type'] = $data['document']['mime_type']; @@ -698,9 +699,8 @@ trait BotAPI $delimOffset = 0; foreach ($initialArray as $item) { $delimOffset += $this->mbStrlen($item); - //if ($this->mbStrlen($item) > 0) { + /** @var int $delimOffset */ $finalArray[] = $item.($delimOffset < $this->mbStrlen($string) ? $string[$delimOffset] : ''); - //} $delimOffset++; } return $finalArray; diff --git a/src/danog/MadelineProto/TL/Conversion/Extension.php b/src/danog/MadelineProto/TL/Conversion/Extension.php index 12ffe0a9..8d2c00ac 100644 --- a/src/danog/MadelineProto/TL/Conversion/Extension.php +++ b/src/danog/MadelineProto/TL/Conversion/Extension.php @@ -14,13 +14,12 @@ If not, see . namespace danog\MadelineProto\TL\Conversion; -use danog\MadelineProto\MTProto; - /** * Manages generation of extensions for files. */ -trait Extension +abstract class Extension { + const ALL_MIMES = ['webp' => [0 => 'image/webp'], 'png' => [0 => 'image/png', 1 => 'image/x-png'], 'bmp' => [0 => 'image/bmp', 1 => 'image/x-bmp', 2 => 'image/x-bitmap', 3 => 'image/x-xbitmap', 4 => 'image/x-win-bitmap', 5 => 'image/x-windows-bmp', 6 => 'image/ms-bmp', 7 => 'image/x-ms-bmp', 8 => 'application/bmp', 9 => 'application/x-bmp', 10 => 'application/x-win-bitmap'], 'gif' => [0 => 'image/gif'], 'jpeg' => [0 => 'image/jpeg', 1 => 'image/pjpeg'], 'xspf' => [0 => 'application/xspf+xml'], 'vlc' => [0 => 'application/videolan'], 'wmv' => [0 => 'video/x-ms-wmv', 1 => 'video/x-ms-asf'], 'au' => [0 => 'audio/x-au'], 'ac3' => [0 => 'audio/ac3'], 'flac' => [0 => 'audio/x-flac'], 'ogg' => [0 => 'audio/ogg', 1 => 'video/ogg', 2 => 'application/ogg'], 'kmz' => [0 => 'application/vnd.google-earth.kmz'], 'kml' => [0 => 'application/vnd.google-earth.kml+xml'], 'rtx' => [0 => 'text/richtext'], 'rtf' => [0 => 'text/rtf'], 'jar' => [0 => 'application/java-archive', 1 => 'application/x-java-application', 2 => 'application/x-jar'], 'zip' => [0 => 'application/x-zip', 1 => 'application/zip', 2 => 'application/x-zip-compressed', 3 => 'application/s-compressed', 4 => 'multipart/x-zip'], '7zip' => [0 => 'application/x-compressed'], 'xml' => [0 => 'application/xml', 1 => 'text/xml'], 'svg' => [0 => 'image/svg+xml'], '3g2' => [0 => 'video/3gpp2'], '3gp' => [0 => 'video/3gp', 1 => 'video/3gpp'], 'mp4' => [0 => 'video/mp4'], 'm4a' => [0 => 'audio/x-m4a'], 'f4v' => [0 => 'video/x-f4v'], 'flv' => [0 => 'video/x-flv'], 'webm' => [0 => 'video/webm'], 'aac' => [0 => 'audio/x-acc'], 'm4u' => [0 => 'application/vnd.mpegurl'], 'pdf' => [0 => 'application/pdf', 1 => 'application/octet-stream'], 'pptx' => [0 => 'application/vnd.openxmlformats-officedocument.presentationml.presentation'], 'ppt' => [0 => 'application/powerpoint', 1 => 'application/vnd.ms-powerpoint', 2 => 'application/vnd.ms-office', 3 => 'application/msword'], 'docx' => [0 => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'], 'xlsx' => [0 => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 1 => 'application/vnd.ms-excel'], 'xl' => [0 => 'application/excel'], 'xls' => [0 => 'application/msexcel', 1 => 'application/x-msexcel', 2 => 'application/x-ms-excel', 3 => 'application/x-excel', 4 => 'application/x-dos_ms_excel', 5 => 'application/xls', 6 => 'application/x-xls'], 'xsl' => [0 => 'text/xsl'], 'mpeg' => [0 => 'video/mpeg'], 'mov' => [0 => 'video/quicktime'], 'avi' => [0 => 'video/x-msvideo', 1 => 'video/msvideo', 2 => 'video/avi', 3 => 'application/x-troff-msvideo'], 'movie' => [0 => 'video/x-sgi-movie'], 'log' => [0 => 'text/x-log'], 'txt' => [0 => 'text/plain'], 'css' => [0 => 'text/css'], 'html' => [0 => 'text/html'], 'wav' => [0 => 'audio/x-wav', 1 => 'audio/wave', 2 => 'audio/wav'], 'xhtml' => [0 => 'application/xhtml+xml'], 'tar' => [0 => 'application/x-tar'], 'tgz' => [0 => 'application/x-gzip-compressed'], 'psd' => [0 => 'application/x-photoshop', 1 => 'image/vnd.adobe.photoshop'], 'exe' => [0 => 'application/x-msdownload'], 'js' => [0 => 'application/x-javascript'], 'mp3' => [0 => 'audio/mpeg', 1 => 'audio/mpg', 2 => 'audio/mpeg3', 3 => 'audio/mp3'], 'rar' => [0 => 'application/x-rar', 1 => 'application/rar', 2 => 'application/x-rar-compressed'], 'gzip' => [0 => 'application/x-gzip'], 'hqx' => [0 => 'application/mac-binhex40', 1 => 'application/mac-binhex', 2 => 'application/x-binhex40', 3 => 'application/x-mac-binhex40'], 'cpt' => [0 => 'application/mac-compactpro'], 'bin' => [0 => 'application/macbinary', 1 => 'application/mac-binary', 2 => 'application/x-binary', 3 => 'application/x-macbinary'], 'oda' => [0 => 'application/oda'], 'ai' => [0 => 'application/postscript'], 'smil' => [0 => 'application/smil'], 'mif' => [0 => 'application/vnd.mif'], 'wbxml' => [0 => 'application/wbxml'], 'wmlc' => [0 => 'application/wmlc'], 'dcr' => [0 => 'application/x-director'], 'dvi' => [0 => 'application/x-dvi'], 'gtar' => [0 => 'application/x-gtar'], 'php' => [0 => 'application/x-httpd-php', 1 => 'application/php', 2 => 'application/x-php', 3 => 'text/php', 4 => 'text/x-php', 5 => 'application/x-httpd-php-source'], 'swf' => [0 => 'application/x-shockwave-flash'], 'sit' => [0 => 'application/x-stuffit'], 'z' => [0 => 'application/x-compress'], 'mid' => [0 => 'audio/midi'], 'aif' => [0 => 'audio/x-aiff', 1 => 'audio/aiff'], 'ram' => [0 => 'audio/x-pn-realaudio'], 'rpm' => [0 => 'audio/x-pn-realaudio-plugin'], 'ra' => [0 => 'audio/x-realaudio'], 'rv' => [0 => 'video/vnd.rn-realvideo'], 'jp2' => [0 => 'image/jp2', 1 => 'video/mj2', 2 => 'image/jpx', 3 => 'image/jpm'], 'tiff' => [0 => 'image/tiff'], 'eml' => [0 => 'message/rfc822'], 'pem' => [0 => 'application/x-x509-user-cert', 1 => 'application/x-pem-file'], 'p10' => [0 => 'application/x-pkcs10', 1 => 'application/pkcs10'], 'p12' => [0 => 'application/x-pkcs12'], 'p7a' => [0 => 'application/x-pkcs7-signature'], 'p7c' => [0 => 'application/pkcs7-mime', 1 => 'application/x-pkcs7-mime'], 'p7r' => [0 => 'application/x-pkcs7-certreqresp'], 'p7s' => [0 => 'application/pkcs7-signature'], 'crt' => [0 => 'application/x-x509-ca-cert', 1 => 'application/pkix-cert'], 'crl' => [0 => 'application/pkix-crl', 1 => 'application/pkcs-crl'], 'pgp' => [0 => 'application/pgp'], 'gpg' => [0 => 'application/gpg-keys'], 'rsa' => [0 => 'application/x-pkcs7'], 'ics' => [0 => 'text/calendar'], 'zsh' => [0 => 'text/x-scriptzsh'], 'cdr' => [0 => 'application/cdr', 1 => 'application/coreldraw', 2 => 'application/x-cdr', 3 => 'application/x-coreldraw', 4 => 'image/cdr', 5 => 'image/x-cdr', 6 => 'zz-application/zz-winassoc-cdr'], 'wma' => [0 => 'audio/x-ms-wma'], 'vcf' => [0 => 'text/x-vcard'], 'srt' => [0 => 'text/srt'], 'vtt' => [0 => 'text/vtt'], 'ico' => [0 => 'image/x-icon', 1 => 'image/x-ico', 2 => 'image/vnd.microsoft.icon'], 'csv' => [0 => 'text/x-comma-separated-values', 1 => 'text/comma-separated-values', 2 => 'application/vnd.msexcel'], 'json' => [0 => 'application/json', 1 => 'text/json']]; /** * Get mime type from file extension. * @@ -32,8 +31,8 @@ trait Extension public static function getMimeFromExtension(string $extension, string $default): string { $ext = \ltrim($extension, '.'); - if (isset(MTProto::ALL_MIMES[$ext])) { - return MTProto::ALL_MIMES[$ext][0]; + if (isset(self::ALL_MIMES[$ext])) { + return self::ALL_MIMES[$ext][0]; } return $default; } diff --git a/src/danog/MadelineProto/TL/TL.php b/src/danog/MadelineProto/TL/TL.php index 4bfc2321..4e2c4db5 100644 --- a/src/danog/MadelineProto/TL/TL.php +++ b/src/danog/MadelineProto/TL/TL.php @@ -787,8 +787,8 @@ class TL /** * Get length of TL payload. * - * @param resource $stream Stream - * @param array $type Type identifier + * @param resource|string $stream Stream + * @param array $type Type identifier * * @return int */ diff --git a/src/danog/MadelineProto/TL/Types/Button.php b/src/danog/MadelineProto/TL/Types/Button.php index 54c44662..ecf2a46e 100644 --- a/src/danog/MadelineProto/TL/Types/Button.php +++ b/src/danog/MadelineProto/TL/Types/Button.php @@ -26,6 +26,8 @@ class Button implements \JsonSerializable, \ArrayAccess { /** * Button data. + * + * @psalm-var non-empty-array */ private array $button; /** @@ -139,7 +141,7 @@ class Button implements \JsonSerializable, \ArrayAccess * * @param $name Field name * - * @return void + * @return mixed */ public function offsetGet($name) { diff --git a/src/danog/MadelineProto/TON/APIFactory.php b/src/danog/MadelineProto/TON/APIFactory.php index c2247557..512f97ad 100644 --- a/src/danog/MadelineProto/TON/APIFactory.php +++ b/src/danog/MadelineProto/TON/APIFactory.php @@ -88,7 +88,7 @@ class APIFactory extends AbstractAPIFactory * * @param string $name Method name * @param array $arguments Arguments - * + * @psalm-suppress UndefinedThisPropertyFetch * @return \Generator */ public function __call_async(string $name, array $arguments): \Generator diff --git a/src/danog/MadelineProto/TON/InternalDoc.php b/src/danog/MadelineProto/TON/InternalDoc.php index d1446850..046997d1 100644 --- a/src/danog/MadelineProto/TON/InternalDoc.php +++ b/src/danog/MadelineProto/TON/InternalDoc.php @@ -1105,6 +1105,29 @@ class InternalDoc extends APIFactory { return \danog\MadelineProto\Tools::genVectorHash($ints); } + /** + * Get extension from file location. + * + * @param mixed $location File location + * @param string $default Default extension + * + * @return string + */ + public function getExtensionFromLocation($location, string $default): string + { + return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromLocation($location, $default); + } + /** + * Get extension from mime type. + * + * @param string $mime MIME type + * + * @return string + */ + public function getExtensionFromMime(string $mime): string + { + return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromMime($mime); + } /** * Get TL method namespaces. * @@ -1114,6 +1137,40 @@ class InternalDoc extends APIFactory { return $this->API->getMethodNamespaces(); } + /** + * Get mime type from buffer. + * + * @param string $buffer Buffer + * + * @return string + */ + public function getMimeFromBuffer(string $buffer): string + { + return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromBuffer($buffer); + } + /** + * Get mime type from file extension. + * + * @param string $extension File extension + * @param string $default Default mime type + * + * @return string + */ + public function getMimeFromExtension(string $extension, string $default): string + { + return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromExtension($extension, $default); + } + /** + * Get mime type of file. + * + * @param string $file File + * + * @return string + */ + public function getMimeFromFile(string $file): string + { + return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromFile($file); + } /** * Accesses a private variable from an object. *