From 0dd1a4973ad839a0b63455e834e41d71e92c89df Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 28 Mar 2024 13:46:30 +0400 Subject: [PATCH] Handle the new FLOOD_PREMIUM_WAIT errors. --- Telegram/SourceFiles/mtproto/mtp_instance.cpp | 45 +++++++++++++++---- Telegram/SourceFiles/mtproto/mtp_instance.h | 3 ++ .../SourceFiles/mtproto/mtproto_response.h | 3 +- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index 7a9908d99..861d6cd44 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -99,6 +99,9 @@ public: void restartedByTimeout(ShiftedDcId shiftedDcId); [[nodiscard]] rpl::producer restartsByTimeout() const; + [[nodiscard]] auto nonPremiumDelayedRequests() const + -> rpl::producer; + void restart(); void restart(ShiftedDcId shiftedDcId); [[nodiscard]] int32 dcstate(ShiftedDcId shiftedDcId = 0); @@ -283,6 +286,8 @@ private: Fn _stateChangedHandler; Fn _sessionResetHandler; + rpl::event_stream _nonPremiumDelayedRequests; + base::Timer _checkDelayedTimer; Core::SettingsProxy &_proxySettings; @@ -553,6 +558,11 @@ rpl::producer Instance::Private::restartsByTimeout() const { return _restartsByTimeout.events(); } +auto Instance::Private::nonPremiumDelayedRequests() const +-> rpl::producer { + return _nonPremiumDelayedRequests.events(); +} + void Instance::Private::requestConfigIfOld() { const auto timeout = _config->values().blockedMode ? kConfigBecomesOldForBlockedIn @@ -1356,8 +1366,9 @@ bool Instance::Private::onErrorDefault( auto badGuestDc = (code == 400) && (type == u"FILE_ID_INVALID"_q); static const auto MigrateRegExp = QRegularExpression("^(FILE|PHONE|NETWORK|USER)_MIGRATE_(\\d+)$"); static const auto FloodWaitRegExp = QRegularExpression("^FLOOD_WAIT_(\\d+)$"); + static const auto FloodPremiumWaitRegExp = QRegularExpression("^FLOOD_PREMIUM_WAIT_(\\d+)$"); static const auto SlowmodeWaitRegExp = QRegularExpression("^SLOWMODE_WAIT_(\\d+)$"); - QRegularExpressionMatch m1, m2; + QRegularExpressionMatch m1, m2, m3; if ((m1 = MigrateRegExp.match(type)).hasMatch()) { if (!requestId) return false; @@ -1462,13 +1473,17 @@ bool Instance::Private::onErrorDefault( } else if (code < 0 || code >= 500 || (m1 = FloodWaitRegExp.match(type)).hasMatch() - || ((m2 = SlowmodeWaitRegExp.match(type)).hasMatch() - && m2.captured(1).toInt() < 3)) { - if (!requestId) return false; + || (m2 = FloodPremiumWaitRegExp.match(type)).hasMatch() + || ((m3 = SlowmodeWaitRegExp.match(type)).hasMatch() + && m3.captured(1).toInt() < 3)) { + if (!requestId) { + return false; + } - int32 secs = 1; + auto secs = 1; + auto nonPremiumDelay = false; if (code < 0 || code >= 500) { - auto it = _requestsDelays.find(requestId); + const auto it = _requestsDelays.find(requestId); if (it != _requestsDelays.cend()) { secs = (it->second > 60) ? it->second : (it->second *= 2); } else { @@ -1479,17 +1494,27 @@ bool Instance::Private::onErrorDefault( // if (secs >= 60) return false; } else if (m2.hasMatch()) { secs = m2.captured(1).toInt(); + nonPremiumDelay = true; + } else if (m3.hasMatch()) { + secs = m3.captured(1).toInt(); } auto sendAt = crl::now() + secs * 1000 + 10; auto it = _delayedRequests.begin(), e = _delayedRequests.end(); for (; it != e; ++it) { - if (it->first == requestId) return true; - if (it->second > sendAt) break; + if (it->first == requestId) { + return true; + } else if (it->second > sendAt) { + break; + } } _delayedRequests.insert(it, std::make_pair(requestId, sendAt)); checkDelayedRequests(); + if (nonPremiumDelay) { + _nonPremiumDelayedRequests.fire_copy(requestId); + } + return true; } else if ((code == 401 && type != u"AUTH_KEY_PERM_EMPTY"_q) || (badGuestDc && _badGuestDcRequests.find(requestId) == _badGuestDcRequests.cend())) { @@ -1879,6 +1904,10 @@ rpl::producer Instance::restartsByTimeout() const { return _private->restartsByTimeout(); } +rpl::producer Instance::nonPremiumDelayedRequests() const { + return _private->nonPremiumDelayedRequests(); +} + void Instance::requestConfigIfOld() { _private->requestConfigIfOld(); } diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.h b/Telegram/SourceFiles/mtproto/mtp_instance.h index 7dc5be49b..55401065f 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.h +++ b/Telegram/SourceFiles/mtproto/mtp_instance.h @@ -140,6 +140,9 @@ public: void restartedByTimeout(ShiftedDcId shiftedDcId); [[nodiscard]] rpl::producer restartsByTimeout() const; + [[nodiscard]] auto nonPremiumDelayedRequests() const + -> rpl::producer; + void syncHttpUnixtime(); void sendAnything(ShiftedDcId shiftedDcId = 0, crl::time msCanWait = 0); diff --git a/Telegram/SourceFiles/mtproto/mtproto_response.h b/Telegram/SourceFiles/mtproto/mtproto_response.h index 657546fcc..3a810b200 100644 --- a/Telegram/SourceFiles/mtproto/mtproto_response.h +++ b/Telegram/SourceFiles/mtproto/mtproto_response.h @@ -39,7 +39,8 @@ private: }; inline bool IsFloodError(const QString &type) { - return type.startsWith(u"FLOOD_WAIT_"_q); + return type.startsWith(u"FLOOD_WAIT_"_q) + || type.startsWith(u"FLOOD_PREMIUM_WAIT_"_q); } inline bool IsFloodError(const Error &error) {