mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 06:39:01 +01:00
Handle FLOOD_PREMIUM_WAIT during file operations
This commit is contained in:
parent
30d542719f
commit
afc082cc63
@ -31,7 +31,9 @@ use danog\MadelineProto\MTProto;
|
||||
use danog\MadelineProto\MTProto\MTProtoIncomingMessage;
|
||||
use danog\MadelineProto\MTProto\MTProtoOutgoingMessage;
|
||||
use danog\MadelineProto\PTSException;
|
||||
use danog\MadelineProto\RPCError\FloodPremiumWaitError;
|
||||
use danog\MadelineProto\RPCError\FloodWaitError;
|
||||
use danog\MadelineProto\RPCError\RateLimitError;
|
||||
use danog\MadelineProto\RPCErrorException;
|
||||
use danog\MadelineProto\SecretPeerNotInDbException;
|
||||
use danog\MadelineProto\SecurityException;
|
||||
@ -451,9 +453,9 @@ trait ResponseHandler
|
||||
}
|
||||
return static fn () => RPCErrorException::make($response['error_message'], $response['error_code'], $request->constructor);
|
||||
case 420:
|
||||
$seconds = preg_replace('/[^0-9]+/', '', $response['error_message']);
|
||||
$seconds = (int) preg_replace('/[^0-9]+/', '', $response['error_message']);
|
||||
$limit = $request->floodWaitLimit ?? $this->API->settings->getRPC()->getFloodTimeout();
|
||||
if (is_numeric($seconds) && $seconds < $limit) {
|
||||
if ($seconds < $limit) {
|
||||
$this->API->logger("Flood, waiting $seconds seconds before repeating async call of $request...", Logger::NOTICE);
|
||||
$this->gotResponseForOutgoingMessage($request);
|
||||
$msgId = $request->getMsgId();
|
||||
@ -466,9 +468,27 @@ trait ResponseHandler
|
||||
return null;
|
||||
}
|
||||
if (str_starts_with($response['error_message'], 'FLOOD_WAIT_')) {
|
||||
return static fn () => new FloodWaitError($response['error_message'], $response['error_code'], $request->constructor);
|
||||
return static fn () => new FloodWaitError(
|
||||
$response['error_message'],
|
||||
$seconds,
|
||||
$response['error_code'],
|
||||
$request->constructor
|
||||
);
|
||||
}
|
||||
// no break
|
||||
if (str_starts_with($response['error_message'], 'FLOOD_PREMIUM_WAIT_')) {
|
||||
return static fn () => new FloodPremiumWaitError(
|
||||
$response['error_message'],
|
||||
$seconds,
|
||||
$response['error_code'],
|
||||
$request->constructor
|
||||
);
|
||||
}
|
||||
return static fn () => new RateLimitError(
|
||||
$response['error_message'],
|
||||
$seconds,
|
||||
$response['error_code'],
|
||||
$request->constructor
|
||||
);
|
||||
default:
|
||||
return static fn () => RPCErrorException::make($response['error_message'], $response['error_code'], $request->constructor);
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ use danog\MadelineProto\FileRedirect;
|
||||
use danog\MadelineProto\Logger;
|
||||
use danog\MadelineProto\MTProtoTools\Crypt\IGE;
|
||||
use danog\MadelineProto\RPCError\FileTokenInvalidError;
|
||||
use danog\MadelineProto\RPCError\FloodPremiumWaitError;
|
||||
use danog\MadelineProto\RPCError\FloodWaitError;
|
||||
use danog\MadelineProto\RPCErrorException;
|
||||
use danog\MadelineProto\SecurityException;
|
||||
@ -358,6 +359,12 @@ trait Files
|
||||
}
|
||||
$d->complete();
|
||||
return;
|
||||
} catch (FloodPremiumWaitError $e) {
|
||||
$this->logger("Got {$e->rpc} while uploading $part_num: {$datacenter}, retrying...");
|
||||
$writePromise = async(static function () use ($cancellation, $e, $writeCb): void {
|
||||
$e->wait($cancellation);
|
||||
$writeCb();
|
||||
});
|
||||
} catch (FileRedirect $e) {
|
||||
$datacenter = $e->dc;
|
||||
$this->logger("Got redirect while uploading $part_num: {$datacenter}");
|
||||
@ -1210,8 +1217,10 @@ trait Files
|
||||
break;
|
||||
} catch (FileRedirect $e) {
|
||||
$datacenter = $e->dc;
|
||||
} catch (FloodWaitError $e) {
|
||||
} catch (FloodWaitError) {
|
||||
delay(1, cancellation: $cancellation);
|
||||
} catch (FloodPremiumWaitError $e) {
|
||||
$e->wait($cancellation);
|
||||
} catch (FileTokenInvalidError) {
|
||||
$cdn = false;
|
||||
$datacenter = $this->authorized_dc;
|
||||
|
26
src/RPCError/FloodPremiumWaitError.php
Normal file
26
src/RPCError/FloodPremiumWaitError.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* RPCErrorException module.
|
||||
*
|
||||
* This file is part of MadelineProto.
|
||||
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
* MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Affero General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @copyright 2016-2023 Daniil Gentili <daniil@daniil.it>
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
|
||||
* @link https://docs.madelineproto.xyz MadelineProto documentation
|
||||
*/
|
||||
|
||||
namespace danog\MadelineProto\RPCError;
|
||||
|
||||
/**
|
||||
* Represents a FLOOD_PREMIUM_WAIT_ RPC error returned by telegram.
|
||||
*/
|
||||
final class FloodPremiumWaitError extends RateLimitError
|
||||
{
|
||||
}
|
@ -18,40 +18,9 @@
|
||||
|
||||
namespace danog\MadelineProto\RPCError;
|
||||
|
||||
use danog\MadelineProto\RPCErrorException;
|
||||
use Exception;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
/**
|
||||
* Represents a FLOOD_WAIT_ RPC error returned by telegram.
|
||||
*/
|
||||
final class FloodWaitError extends RPCErrorException
|
||||
final class FloodWaitError extends RateLimitError
|
||||
{
|
||||
public readonly int $waitTime;
|
||||
public function __construct(string $message, int $code, string $caller, ?Exception $previous = null)
|
||||
{
|
||||
Assert::true(str_starts_with($message, 'FLOOD_WAIT_'));
|
||||
$seconds = substr($message, 11);
|
||||
Assert::numeric($seconds);
|
||||
$this->waitTime = (int) $seconds;
|
||||
parent::__construct($message, "A rate limit was encountered, please repeat the method call after $seconds seconds", $code, $caller, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required waiting period in seconds before repeating the RPC call.
|
||||
*/
|
||||
public function getWaitTime(): int
|
||||
{
|
||||
return $this->waitTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the required waiting period.
|
||||
*/
|
||||
public function wait(): void
|
||||
{
|
||||
delay($this->waitTime);
|
||||
}
|
||||
}
|
||||
|
53
src/RPCError/RateLimitError.php
Normal file
53
src/RPCError/RateLimitError.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* RPCErrorException module.
|
||||
*
|
||||
* This file is part of MadelineProto.
|
||||
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
* MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Affero General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License along with MadelineProto.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author Daniil Gentili <daniil@daniil.it>
|
||||
* @copyright 2016-2023 Daniil Gentili <daniil@daniil.it>
|
||||
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
|
||||
* @link https://docs.madelineproto.xyz MadelineProto documentation
|
||||
*/
|
||||
|
||||
namespace danog\MadelineProto\RPCError;
|
||||
|
||||
use Amp\Cancellation;
|
||||
use danog\MadelineProto\RPCErrorException;
|
||||
use Exception;
|
||||
|
||||
use function Amp\delay;
|
||||
|
||||
/**
|
||||
* Represents a rate limiting RPC error returned by telegram.
|
||||
*/
|
||||
class RateLimitError extends RPCErrorException
|
||||
{
|
||||
/** @internal */
|
||||
public function __construct(string $message, public readonly int $waitTime, int $code, string $caller, ?Exception $previous = null)
|
||||
{
|
||||
parent::__construct($message, "A rate limit was encountered, please repeat the method call after $waitTime seconds", $code, $caller, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required waiting period in seconds before repeating the RPC call.
|
||||
*/
|
||||
public function getWaitTime(): int
|
||||
{
|
||||
return $this->waitTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the required waiting period.
|
||||
*/
|
||||
public function wait(?Cancellation $cancellation = null): void
|
||||
{
|
||||
delay($this->waitTime, cancellation: $cancellation);
|
||||
}
|
||||
}
|
@ -130,6 +130,7 @@ class RPCErrorException extends \Exception
|
||||
'VOLUME_LOC_NOT_FOUND' => true,
|
||||
'FILE_WRITE_EMPTY' => true,
|
||||
'Internal_Server_Error' => true,
|
||||
'INVITE_HASH_UNSYNC' => true,
|
||||
];
|
||||
|
||||
/** @internal */
|
||||
|
@ -57,6 +57,8 @@ require 'vendor/autoload.php';
|
||||
|
||||
`rm -r src/RPCError/*`;
|
||||
`git checkout src/RPCError/FloodWaitError.php`;
|
||||
`git checkout src/RPCError/FloodPremiumWaitError.php`;
|
||||
`git checkout src/RPCError/RateLimitError.php`;
|
||||
|
||||
$map = [];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user