mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 06:18:58 +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\MTProtoIncomingMessage;
|
||||||
use danog\MadelineProto\MTProto\MTProtoOutgoingMessage;
|
use danog\MadelineProto\MTProto\MTProtoOutgoingMessage;
|
||||||
use danog\MadelineProto\PTSException;
|
use danog\MadelineProto\PTSException;
|
||||||
|
use danog\MadelineProto\RPCError\FloodPremiumWaitError;
|
||||||
use danog\MadelineProto\RPCError\FloodWaitError;
|
use danog\MadelineProto\RPCError\FloodWaitError;
|
||||||
|
use danog\MadelineProto\RPCError\RateLimitError;
|
||||||
use danog\MadelineProto\RPCErrorException;
|
use danog\MadelineProto\RPCErrorException;
|
||||||
use danog\MadelineProto\SecretPeerNotInDbException;
|
use danog\MadelineProto\SecretPeerNotInDbException;
|
||||||
use danog\MadelineProto\SecurityException;
|
use danog\MadelineProto\SecurityException;
|
||||||
@ -451,9 +453,9 @@ trait ResponseHandler
|
|||||||
}
|
}
|
||||||
return static fn () => RPCErrorException::make($response['error_message'], $response['error_code'], $request->constructor);
|
return static fn () => RPCErrorException::make($response['error_message'], $response['error_code'], $request->constructor);
|
||||||
case 420:
|
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();
|
$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->API->logger("Flood, waiting $seconds seconds before repeating async call of $request...", Logger::NOTICE);
|
||||||
$this->gotResponseForOutgoingMessage($request);
|
$this->gotResponseForOutgoingMessage($request);
|
||||||
$msgId = $request->getMsgId();
|
$msgId = $request->getMsgId();
|
||||||
@ -466,9 +468,27 @@ trait ResponseHandler
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (str_starts_with($response['error_message'], 'FLOOD_WAIT_')) {
|
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:
|
default:
|
||||||
return static fn () => RPCErrorException::make($response['error_message'], $response['error_code'], $request->constructor);
|
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\Logger;
|
||||||
use danog\MadelineProto\MTProtoTools\Crypt\IGE;
|
use danog\MadelineProto\MTProtoTools\Crypt\IGE;
|
||||||
use danog\MadelineProto\RPCError\FileTokenInvalidError;
|
use danog\MadelineProto\RPCError\FileTokenInvalidError;
|
||||||
|
use danog\MadelineProto\RPCError\FloodPremiumWaitError;
|
||||||
use danog\MadelineProto\RPCError\FloodWaitError;
|
use danog\MadelineProto\RPCError\FloodWaitError;
|
||||||
use danog\MadelineProto\RPCErrorException;
|
use danog\MadelineProto\RPCErrorException;
|
||||||
use danog\MadelineProto\SecurityException;
|
use danog\MadelineProto\SecurityException;
|
||||||
@ -358,6 +359,12 @@ trait Files
|
|||||||
}
|
}
|
||||||
$d->complete();
|
$d->complete();
|
||||||
return;
|
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) {
|
} catch (FileRedirect $e) {
|
||||||
$datacenter = $e->dc;
|
$datacenter = $e->dc;
|
||||||
$this->logger("Got redirect while uploading $part_num: {$datacenter}");
|
$this->logger("Got redirect while uploading $part_num: {$datacenter}");
|
||||||
@ -1210,8 +1217,10 @@ trait Files
|
|||||||
break;
|
break;
|
||||||
} catch (FileRedirect $e) {
|
} catch (FileRedirect $e) {
|
||||||
$datacenter = $e->dc;
|
$datacenter = $e->dc;
|
||||||
} catch (FloodWaitError $e) {
|
} catch (FloodWaitError) {
|
||||||
delay(1, cancellation: $cancellation);
|
delay(1, cancellation: $cancellation);
|
||||||
|
} catch (FloodPremiumWaitError $e) {
|
||||||
|
$e->wait($cancellation);
|
||||||
} catch (FileTokenInvalidError) {
|
} catch (FileTokenInvalidError) {
|
||||||
$cdn = false;
|
$cdn = false;
|
||||||
$datacenter = $this->authorized_dc;
|
$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;
|
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.
|
* 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,
|
'VOLUME_LOC_NOT_FOUND' => true,
|
||||||
'FILE_WRITE_EMPTY' => true,
|
'FILE_WRITE_EMPTY' => true,
|
||||||
'Internal_Server_Error' => true,
|
'Internal_Server_Error' => true,
|
||||||
|
'INVITE_HASH_UNSYNC' => true,
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
|
@ -57,6 +57,8 @@ require 'vendor/autoload.php';
|
|||||||
|
|
||||||
`rm -r src/RPCError/*`;
|
`rm -r src/RPCError/*`;
|
||||||
`git checkout src/RPCError/FloodWaitError.php`;
|
`git checkout src/RPCError/FloodWaitError.php`;
|
||||||
|
`git checkout src/RPCError/FloodPremiumWaitError.php`;
|
||||||
|
`git checkout src/RPCError/RateLimitError.php`;
|
||||||
|
|
||||||
$map = [];
|
$map = [];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user