From 0514b5fcf51333588d971acdd84c4a20c4f119ed Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 22 Apr 2021 16:09:36 +0200 Subject: [PATCH] Fix IPC file callbacks --- src/danog/MadelineProto/Ipc/Client.php | 64 +++++++++++++++---- src/danog/MadelineProto/Ipc/Wrapper.php | 13 ++-- .../MadelineProto/MTProtoTools/Files.php | 6 +- .../MadelineProto/MTProtoTools/FilesLogic.php | 10 +-- 4 files changed, 68 insertions(+), 25 deletions(-) diff --git a/src/danog/MadelineProto/Ipc/Client.php b/src/danog/MadelineProto/Ipc/Client.php index b0e5f5b34..30686fe29 100644 --- a/src/danog/MadelineProto/Ipc/Client.php +++ b/src/danog/MadelineProto/Ipc/Client.php @@ -149,7 +149,7 @@ class Client extends ClientAbstract { if (\is_object($url) && $url instanceof FileCallbackInterface) { $cb = $url; - $url = $url->getFile(); + $url = yield $url->getFile(); } $params = [$url, $size, $fileName, &$cb, $encrypted]; $wrapper = yield from Wrapper::create($params, $this->session, $this->logger); @@ -178,7 +178,7 @@ class Client extends ClientAbstract { if (\is_object($callable) && $callable instanceof FileCallbackInterface) { $cb = $callable; - $callable = $callable->getFile(); + $callable = yield $callable->getFile(); } $params = [&$callable, $size, $mime, $fileName, &$cb, $seekable, $encrypted]; $wrapper = yield from Wrapper::create($params, $this->session, $this->logger); @@ -201,13 +201,53 @@ class Client extends ClientAbstract { if (\is_object($media) && $media instanceof FileCallbackInterface) { $cb = $media; - $media = $media->getFile(); + $media = yield $media->getFile(); } $params = [$media, &$cb, $encrypted]; $wrapper = yield from Wrapper::create($params, $this->session, $this->logger); $wrapper->wrap($cb, false); return yield from $this->__call('uploadFromTgfile', $wrapper); } + /** + * Call method and wait asynchronously for response. + * + * If the $aargs['noResponse'] is true, will not wait for a response. + * + * @param string $method Method name + * @param array|\Generator $args Arguments + * @param array $aargs Additional arguments + * + * @psalm-param array|\Generator $args + * + * @return \Generator + */ + public function methodCallAsyncRead(string $method, $args, array $aargs) + { + if (\is_array($args)) { + if (($method === 'messages.editInlineBotMessage' || + $method === 'messages.uploadMedia' || + $method === 'messages.sendMedia' || + $method === 'messages.editMessage') && + isset($args['media']['file']) && + $args['media']['file'] instanceof FileCallbackInterface + ) { + $params = [$method, &$args, $aargs]; + $wrapper = yield from Wrapper::create($params, $this->session, $this->logger); + $wrapper->wrap($args['media']['file'], true); + return yield from $this->__call('methodCallAsyncRead', $wrapper); + } elseif ($method === 'messages.sendMultiMedia' && isset($args['multi_media'])) { + $params = [$method, &$args, $aargs]; + $wrapper = yield from Wrapper::create($params, $this->session, $this->logger); + foreach ($args['multi_media'] as &$media) { + if (isset($media['media']['file']) && $media['media']['file'] instanceof FileCallbackInterface) { + $wrapper->wrap($media['media']['file'], true); + } + } + return yield from $this->__call('methodCallAsyncRead', $wrapper); + } + } + return yield from $this->__call('methodCallAsyncRead', [$method, $args, $aargs]); + } /** * Download file to directory. * @@ -223,7 +263,7 @@ class Client extends ClientAbstract { if (\is_object($dir) && $dir instanceof FileCallbackInterface) { $cb = $dir; - $dir = $dir->getFile(); + $dir = yield $dir->getFile(); } $params = [$messageMedia, $dir, &$cb]; $wrapper = yield from Wrapper::create($params, $this->session, $this->logger); @@ -245,7 +285,7 @@ class Client extends ClientAbstract { if (\is_object($file) && $file instanceof FileCallbackInterface) { $cb = $file; - $file = $file->getFile(); + $file = yield $file->getFile(); } $params = [$messageMedia, $file, &$cb]; $wrapper = yield from Wrapper::create($params, $this->session, $this->logger); @@ -259,12 +299,12 @@ class Client extends ClientAbstract * The callable should return the number of written bytes. * * @param mixed $messageMedia File to download - * @param callable|FileCallbackInterface $callable Chunk callback - * @param callable $cb Status callback (DEPRECATED, use FileCallbackInterface) - * @param bool $seekable Whether the callable can be called out of order - * @param int $offset Offset where to start downloading - * @param int $end Offset where to stop downloading (inclusive) - * @param int $part_size Size of each chunk + * @param callable|FileCallbackInterface $callable Chunk callback + * @param callable $cb Status callback (DEPRECATED, use FileCallbackInterface) + * @param bool $seekable Whether the callable can be called out of order + * @param int $offset Offset where to start downloading + * @param int $end Offset where to stop downloading (inclusive) + * @param int $part_size Size of each chunk * * @return \Generator * @@ -275,7 +315,7 @@ class Client extends ClientAbstract $messageMedia = (yield from $this->getDownloadInfo($messageMedia)); if (\is_object($callable) && $callable instanceof FileCallbackInterface) { $cb = $callable; - $callable = $callable->getFile(); + $callable = yield $callable->getFile(); } $params = [$messageMedia, &$callable, &$cb, $seekable, $offset, $end, $part_size, ]; $wrapper = yield from Wrapper::create($params, $this->session, $this->logger); diff --git a/src/danog/MadelineProto/Ipc/Wrapper.php b/src/danog/MadelineProto/Ipc/Wrapper.php index 0a05c2548..55f294b4e 100644 --- a/src/danog/MadelineProto/Ipc/Wrapper.php +++ b/src/danog/MadelineProto/Ipc/Wrapper.php @@ -7,9 +7,13 @@ use Amp\ByteStream\OutputStream as ByteStreamOutputStream; use Amp\Ipc\Sync\ChannelledSocket; use Amp\Parallel\Sync\ExitFailure; use Amp\Promise; +use danog\MadelineProto\FileCallbackInterface; +use danog\MadelineProto\Ipc\Wrapper\FileCallback; use danog\MadelineProto\Ipc\Wrapper\InputStream; use danog\MadelineProto\Ipc\Wrapper\Obj; use danog\MadelineProto\Ipc\Wrapper\OutputStream; +use danog\MadelineProto\Ipc\Wrapper\SeekableInputStream; +use danog\MadelineProto\Ipc\Wrapper\SeekableOutputStream; use danog\MadelineProto\Logger; use danog\MadelineProto\SessionPaths; use danog\MadelineProto\Tools; @@ -103,12 +107,11 @@ class Wrapper extends ClientAbstract } $class = Obj::class; if ($callback instanceof ByteStreamInputStream) { - $class = InputStream::class; + $class = \method_exists($callback, 'seek') ? InputStream::class : SeekableInputStream::class; } elseif ($callback instanceof ByteStreamOutputStream) { - $class = OutputStream::class; - } - if ($class !== Obj::class && \method_exists($callback, 'seek')) { - $class = "Seekable$class"; + $class = \method_exists($callback, 'seek') ? OutputStream::class : SeekableOutputStream::class; + } elseif ($callback instanceof FileCallbackInterface) { + $class = FileCallback::class; } $callback = [$class, $ids]; // Will be re-filled later $this->callbackIds[] = &$callback; diff --git a/src/danog/MadelineProto/MTProtoTools/Files.php b/src/danog/MadelineProto/MTProtoTools/Files.php index 1e16c2306..912fae1c3 100644 --- a/src/danog/MadelineProto/MTProtoTools/Files.php +++ b/src/danog/MadelineProto/MTProtoTools/Files.php @@ -66,7 +66,7 @@ trait Files { if (\is_object($url) && $url instanceof FileCallbackInterface) { $cb = $url; - $url = $url->getFile(); + $url = yield $url->getFile(); } /** @var $response \Amp\Http\Client\Response */ $request = new Request($url); @@ -116,7 +116,7 @@ trait Files { if (\is_object($callable) && $callable instanceof FileCallbackInterface) { $cb = $callable; - $callable = $callable->getFile(); + $callable = yield $callable->getFile(); } if (!\is_callable($callable)) { throw new Exception('Invalid callable provided'); @@ -244,7 +244,7 @@ trait Files { if (\is_object($media) && $media instanceof FileCallbackInterface) { $cb = $media; - $media = $media->getFile(); + $media = yield $media->getFile(); } $media = (yield from $this->getDownloadInfo($media)); if (!isset($media['size'], $media['mime'])) { diff --git a/src/danog/MadelineProto/MTProtoTools/FilesLogic.php b/src/danog/MadelineProto/MTProtoTools/FilesLogic.php index 1a45e906b..60116b65e 100644 --- a/src/danog/MadelineProto/MTProtoTools/FilesLogic.php +++ b/src/danog/MadelineProto/MTProtoTools/FilesLogic.php @@ -49,7 +49,7 @@ trait FilesLogic { if (\is_object($messageMedia) && $messageMedia instanceof FileCallbackInterface) { $cb = $messageMedia; - $messageMedia = $messageMedia->getFile(); + $messageMedia = yield $messageMedia->getFile(); } $headers = []; @@ -103,7 +103,7 @@ trait FilesLogic $messageMedia = yield from $this->getDownloadInfo($messageMedia); if (\is_object($stream) && $stream instanceof FileCallbackInterface) { $cb = $stream; - $stream = $stream->getFile(); + $stream = yield $stream->getFile(); } /** @var $stream \Amp\ByteStream\OutputStream */ if (!\is_object($stream)) { @@ -148,7 +148,7 @@ trait FilesLogic { if (\is_object($messageMedia) && $messageMedia instanceof FileCallbackInterface) { $cb = $messageMedia; - $messageMedia = $messageMedia->getFile(); + $messageMedia = yield $messageMedia->getFile(); } $messageMedia = yield from $this->getDownloadInfo($messageMedia); @@ -216,7 +216,7 @@ trait FilesLogic { if (\is_object($file) && $file instanceof FileCallbackInterface) { $cb = $file; - $file = $file->getFile(); + $file = yield $file->getFile(); } if (\is_string($file) || \is_object($file) && \method_exists($file, '__toString')) { if (\filter_var($file, FILTER_VALIDATE_URL)) { @@ -272,7 +272,7 @@ trait FilesLogic { if (\is_object($stream) && $stream instanceof FileCallbackInterface) { $cb = $stream; - $stream = $stream->getFile(); + $stream = yield $stream->getFile(); } /* @var $stream \Amp\ByteStream\OutputStream */ if (!\is_object($stream)) {