From bfd08f57449a743d956a1d7bf653c138f3de3ead Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Tue, 23 Jun 2020 20:30:40 +0200 Subject: [PATCH] Fix shutdown loop, automatically inflate stripped photoSizes, improve composer reporter --- composer.json | 3 +- examples/bot.php | 1 + src/danog/MadelineProto/API.php | 2 +- src/danog/MadelineProto/DocsBuilder.php | 2 +- .../Loop/Connection/CheckLoop.php | 111 +++++++++--------- .../Loop/Connection/ReadLoop.php | 1 - src/danog/MadelineProto/MTProto.php | 6 +- .../MadelineProto/MTProtoSession/Session.php | 12 ++ src/danog/MadelineProto/TL/TL.php | 2 + tools/phar.php | 12 +- 10 files changed, 85 insertions(+), 67 deletions(-) diff --git a/composer.json b/composer.json index f83095ca0..1dab7b8df 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,8 @@ "danog/7to70": "^1", "danog/7to5": "^1", "vimeo/psalm": "dev-master", - "phpstan/phpstan": "^0.12.14" + "phpstan/phpstan": "^0.12.14", + "friendsofphp/php-cs-fixer": "^2.16" }, "suggest": { "ext-libtgvoip": "Install the php-libtgvoip extension to make phone calls (https://github.com/danog/php-libtgvoip)" diff --git a/examples/bot.php b/examples/bot.php index d63751dd8..0aba7268b 100755 --- a/examples/bot.php +++ b/examples/bot.php @@ -84,6 +84,7 @@ class MyEventHandler extends EventHandler if (isset($update['message']['media']) && $update['message']['media']['_'] !== 'messageMediaGame') { yield $this->messages->sendMedia(['peer' => $update, 'message' => $update['message']['message'], 'media' => $update]); } + yield $this->ping(['multiple' => true] + \array_map(fn ($v) => ['ping_id' => $v], \range(0, 1020))); } } $settings = [ diff --git a/src/danog/MadelineProto/API.php b/src/danog/MadelineProto/API.php index c2fbc0397..fd0f1e92f 100644 --- a/src/danog/MadelineProto/API.php +++ b/src/danog/MadelineProto/API.php @@ -184,7 +184,7 @@ class API extends InternalDoc $this->API->unreference(); } $this->destructing = true; - Tools::wait($this->wrapper->serialize(), true); + Tools::wait($this->wrapper->serialize()); } else { $this->logger->logger('Shutting down MadelineProto (old deserialized instance of API)'); } diff --git a/src/danog/MadelineProto/DocsBuilder.php b/src/danog/MadelineProto/DocsBuilder.php index 1f68a5e85..d74a4b385 100644 --- a/src/danog/MadelineProto/DocsBuilder.php +++ b/src/danog/MadelineProto/DocsBuilder.php @@ -137,7 +137,7 @@ class DocsBuilder foreach (['string', 'bytes', 'int', 'int53', 'long', 'int128', 'int256', 'int512', 'double', 'Bool', 'DataJSON'] as $type) { \file_put_contents("types/$type.md", $this->templates[$type]); } - foreach (['boolFalse', 'boolTrue', 'null'] as $constructor) { + foreach (['boolFalse', 'boolTrue', 'null', 'photoStrippedSize'] as $constructor) { \file_put_contents("constructors/$constructor.md", $this->templates[$constructor]); } \danog\MadelineProto\Logger::log('Done!', \danog\MadelineProto\Logger::NOTICE); diff --git a/src/danog/MadelineProto/Loop/Connection/CheckLoop.php b/src/danog/MadelineProto/Loop/Connection/CheckLoop.php index 6e8f03f73..cd7ce2962 100644 --- a/src/danog/MadelineProto/Loop/Connection/CheckLoop.php +++ b/src/danog/MadelineProto/Loop/Connection/CheckLoop.php @@ -72,33 +72,37 @@ class CheckLoop extends ResumableSignalLoop return; } } - if ($connection->hasPendingCalls()) { - $last_msgid = $connection->msgIdHandler->getMaxId(true); - $last_chunk = $connection->getLastChunk(); - if ($shared->hasTempAuthKey()) { - $full_message_ids = $connection->getPendingCalls(); - //array_values($connection->new_outgoing); - foreach (\array_chunk($full_message_ids, 8192) as $message_ids) { - $deferred = new Deferred(); - $deferred->promise()->onResolve(function ($e, $result) use ($message_ids, $API, $connection, $datacenter, $timeoutResend) { - if ($e) { - $API->logger("Got exception in check loop for DC {$datacenter}"); - $API->logger((string) $e); - return; + if (!$connection->hasPendingCalls()) { + if (yield $this->waitSignal($this->pause($timeout))) { + return; + } + continue; + } + $last_msgid = $connection->msgIdHandler->getMaxId(true); + $last_chunk = $connection->getLastChunk(); + if ($shared->hasTempAuthKey()) { + $full_message_ids = $connection->getPendingCalls(); + foreach (\array_chunk($full_message_ids, 8192) as $message_ids) { + $deferred = new Deferred(); + $deferred->promise()->onResolve(function ($e, $result) use ($message_ids, $API, $connection, $datacenter, $timeoutResend) { + if ($e) { + $API->logger("Got exception in check loop for DC {$datacenter}"); + $API->logger((string) $e); + return; + } + $reply = []; + foreach (\str_split($result['info']) as $key => $chr) { + $message_id = $message_ids[$key]; + if (!isset($connection->outgoing_messages[$message_id])) { + $API->logger->logger('Already got response for and forgot about message ID '.$message_id); + continue; } - $reply = []; - foreach (\str_split($result['info']) as $key => $chr) { - $message_id = $message_ids[$key]; - if (!isset($connection->outgoing_messages[$message_id])) { - $API->logger->logger('Already got response for and forgot about message ID '.$message_id); - continue; - } - if (!isset($connection->new_outgoing[$message_id])) { - $API->logger->logger('Already got response for '.$connection->outgoing_messages[$message_id]['_'].' with message ID '.$message_id); - continue; - } - $chr = \ord($chr); - switch ($chr & 7) { + if (!isset($connection->new_outgoing[$message_id])) { + $API->logger->logger('Already got response for '.$connection->outgoing_messages[$message_id]['_'].' with message ID '.$message_id); + continue; + } + $chr = \ord($chr); + switch ($chr & 7) { case 0: $API->logger->logger('Wrong message status 0 for '.$connection->outgoing_messages[$message_id]['_'], \danog\MadelineProto\Logger::FATAL_ERROR); break; @@ -131,42 +135,37 @@ class CheckLoop extends ResumableSignalLoop $reply[] = $message_id; } } - } - if ($reply) { - \danog\MadelineProto\Tools::callFork($connection->objectCall('msg_resend_ans_req', ['msg_ids' => $reply], ['postpone' => true])); - } - $connection->flush(); - }); - $list = ''; - // Don't edit this here pls - foreach ($message_ids as $message_id) { - $list .= $connection->outgoing_messages[$message_id]['_'].', '; } - $API->logger->logger("Still missing {$list} on DC {$datacenter}, sending state request", \danog\MadelineProto\Logger::ERROR); - yield from $connection->objectCall('msgs_state_req', ['msg_ids' => $message_ids], ['promise' => $deferred]); - } - } else { - foreach ($connection->new_outgoing as $message_id) { - if (isset($connection->outgoing_messages[$message_id]['sent']) && $connection->outgoing_messages[$message_id]['sent'] + $timeout < \time() && $connection->outgoing_messages[$message_id]['unencrypted']) { - $API->logger->logger('Still missing '.$connection->outgoing_messages[$message_id]['_'].' with message id '.$message_id." on DC {$datacenter}, resending", \danog\MadelineProto\Logger::ERROR); - $connection->methodRecall('', ['message_id' => $message_id, 'postpone' => true]); + if ($reply) { + \danog\MadelineProto\Tools::callFork($connection->objectCall('msg_resend_ans_req', ['msg_ids' => $reply], ['postpone' => true])); } + $connection->flush(); + }); + $list = ''; + // Don't edit this here pls + foreach ($message_ids as $message_id) { + $list .= $connection->outgoing_messages[$message_id]['_'].', '; } - $connection->flush(); - } - if (yield $this->waitSignal($this->pause($timeout))) { - return; - } - if ($connection->msgIdHandler->getMaxId(true) === $last_msgid && $connection->getLastChunk() === $last_chunk) { - $API->logger->logger("We did not receive a response for {$timeout} seconds: reconnecting and exiting check loop on DC {$datacenter}"); - //$this->exitedLoop(); - Tools::callForkDefer($connection->reconnect()); - return; + $API->logger->logger("Still missing {$list} on DC {$datacenter}, sending state request", \danog\MadelineProto\Logger::ERROR); + yield from $connection->objectCall('msgs_state_req', ['msg_ids' => $message_ids], ['promise' => $deferred]); } } else { - if (yield $this->waitSignal($this->pause($timeout))) { - return; + foreach ($connection->new_outgoing as $message_id) { + if (isset($connection->outgoing_messages[$message_id]['sent']) && $connection->outgoing_messages[$message_id]['sent'] + $timeout < \time() && $connection->outgoing_messages[$message_id]['unencrypted']) { + $API->logger->logger('Still missing '.$connection->outgoing_messages[$message_id]['_'].' with message id '.$message_id." on DC {$datacenter}, resending", \danog\MadelineProto\Logger::ERROR); + $connection->methodRecall('', ['message_id' => $message_id, 'postpone' => true]); + } } + $connection->flush(); + } + if (yield $this->waitSignal($this->pause($timeout))) { + return; + } + if ($connection->msgIdHandler->getMaxId(true) === $last_msgid && $connection->getLastChunk() === $last_chunk) { + $API->logger->logger("We did not receive a response for {$timeout} seconds: reconnecting and exiting check loop on DC {$datacenter}"); + //$this->exitedLoop(); + Tools::callForkDefer($connection->reconnect()); + return; } } } diff --git a/src/danog/MadelineProto/Loop/Connection/ReadLoop.php b/src/danog/MadelineProto/Loop/Connection/ReadLoop.php index e5fec3a59..76a39bcb0 100644 --- a/src/danog/MadelineProto/Loop/Connection/ReadLoop.php +++ b/src/danog/MadelineProto/Loop/Connection/ReadLoop.php @@ -223,7 +223,6 @@ class ReadLoop extends SignalLoop $connection->incoming_messages[$message_id]['content'] = $deserialized; $connection->incoming_messages[$message_id]['response'] = -1; $connection->new_incoming[$message_id] = $message_id; - //$connection->last_http_wait = 0; $API->logger->logger('Received payload from DC '.$datacenter, Logger::ULTRA_VERBOSE); } finally { $connection->reading(false); diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index 29d79f15e..bd352528e 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -1870,7 +1870,11 @@ class MTProto extends AsyncConstruct implements TLCallback */ public function getConstructorCallbacks(): array { - return \array_merge(\array_fill_keys(['chat', 'chatEmpty', 'chatForbidden', 'channel', 'channelEmpty', 'channelForbidden'], [[$this, 'addChat']]), \array_fill_keys(['user', 'userEmpty'], [[$this, 'addUser']]), ['help.support' => [[$this, 'addSupport']]]); + return \array_merge( + \array_fill_keys(['chat', 'chatEmpty', 'chatForbidden', 'channel', 'channelEmpty', 'channelForbidden'], [[$this, 'addChat']]), + \array_fill_keys(['user', 'userEmpty'], [[$this, 'addUser']]), + ['help.support' => [[$this, 'addSupport']]] + ); } /** * Called right before deserialization of object. diff --git a/src/danog/MadelineProto/MTProtoSession/Session.php b/src/danog/MadelineProto/MTProtoSession/Session.php index 02d26a132..d98fe0da1 100644 --- a/src/danog/MadelineProto/MTProtoSession/Session.php +++ b/src/danog/MadelineProto/MTProtoSession/Session.php @@ -82,6 +82,18 @@ abstract class Session * @var array */ public $ack_queue = []; + /** + * State request queue. + * + * @var array + */ + public $state_queue = []; + /** + * Resend request queue. + * + * @var array + */ + public $resend_queue = []; /** * Message ID handler. * diff --git a/src/danog/MadelineProto/TL/TL.php b/src/danog/MadelineProto/TL/TL.php index 04d5c468b..cf0edc035 100644 --- a/src/danog/MadelineProto/TL/TL.php +++ b/src/danog/MadelineProto/TL/TL.php @@ -995,6 +995,8 @@ class TL default: return $x['value']; } + } elseif ($x['_'] === 'photoStrippedSize') { + $x['inflated'] = Tools::inflateStripped($x['bytes']); } if (isset($this->callbacks[TLCallback::CONSTRUCTOR_CALLBACK][$x['_']])) { foreach ($this->callbacks[TLCallback::CONSTRUCTOR_CALLBACK][$x['_']] as $callback) { diff --git a/tools/phar.php b/tools/phar.php index 60c9f733d..3ea3172e8 100644 --- a/tools/phar.php +++ b/tools/phar.php @@ -116,7 +116,7 @@ function ___install_madeline() ]; } - if (defined('HHVM_VERSION')) { + if (\defined('HHVM_VERSION')) { $phpVersion = 'HHVM ' . HHVM_VERSION; } else { $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION; @@ -125,15 +125,15 @@ function ___install_madeline() [ 'method' => 'POST', 'header' => [ - 'Content-Type: application/json', - sprintf( + 'Content-Type: application/json', + \sprintf( 'User-Agent: Composer/%s (%s; %s; %s; %s%s)', 'MadelineProto', - function_exists('php_uname') ? @php_uname('s') : 'Unknown', - function_exists('php_uname') ? @php_uname('r') : 'Unknown', + \function_exists('php_uname') ? @\php_uname('s') : 'Unknown', + \function_exists('php_uname') ? @\php_uname('r') : 'Unknown', $phpVersion, 'streams', - getenv('CI') ? '; CI' : '' + \getenv('CI') ? '; CI' : '' ) ], 'content' => \json_encode($postData),