From a874e617dcb89805a2561174eaba9f7725b1f6c8 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 11 Sep 2023 22:03:01 +0300 Subject: [PATCH] Add updateUnconfirmedSession. --- td/generate/scheme/td_api.tl | 10 +++ td/telegram/AccountManager.cpp | 119 +++++++++++++++++++++++++++++++++ td/telegram/AccountManager.h | 18 +++++ td/telegram/UpdatesManager.cpp | 11 ++- td/telegram/UpdatesManager.h | 4 +- 5 files changed, 158 insertions(+), 4 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index b2b6a59d5..8650464d7 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4899,6 +4899,13 @@ session id:int64 is_current:Bool is_password_pending:Bool is_unconfirmed:Bool ca //@description Contains a list of sessions @sessions List of sessions @inactive_session_ttl_days Number of days of inactivity before sessions will automatically be terminated; 1-366 days sessions sessions:vector inactive_session_ttl_days:int32 = Sessions; +//@description Contains information about an unconfirmed session +//@id Session identifier +//@log_in_date Point in time (Unix timestamp) when the user has logged in +//@device_model Model of the device that was used for the session creation, as provided by the application +//@location Description of the location used for the session creation +unconfirmedSession id:int64 log_in_date:int32 device_model:string location:string = UnconfirmedSession; + //@description Contains information about one website the current user is logged in with Telegram //@id Website identifier @@ -5998,6 +6005,9 @@ updateTermsOfService terms_of_service_id:string terms_of_service:termsOfService //@description The list of users nearby has changed. The update is guaranteed to be sent only 60 seconds after a successful searchChatsNearby request @users_nearby The new list of users nearby updateUsersNearby users_nearby:vector = Update; +//@description The first unconfirmed session has changed @session The unconfirmed session; may be null if none +updateUnconfirmedSession session:unconfirmedSession = Update; + //@description The list of bots added to attachment or side menu has changed @bots The new list of bots. The bots must not be shown on scheduled messages screen updateAttachmentMenuBots bots:vector = Update; diff --git a/td/telegram/AccountManager.cpp b/td/telegram/AccountManager.cpp index 2edf1ca7a..4decb8465 100644 --- a/td/telegram/AccountManager.cpp +++ b/td/telegram/AccountManager.cpp @@ -6,6 +6,7 @@ // #include "td/telegram/AccountManager.h" +#include "td/telegram/AuthManager.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/DeviceTokenManager.h" #include "td/telegram/Global.h" @@ -602,9 +603,81 @@ class InvalidateSignInCodesQuery final : public Td::ResultHandler { } }; +class AccountManager::UnconfirmedAuthorization { + int64 hash_; + int32 date_; + string device_; + string location_; + + public: + UnconfirmedAuthorization(int64 hash, int32 date, string &&device, string &&location) + : hash_(hash), date_(date), device_(std::move(device)), location_(std::move(location)) { + } + + int64 get_hash() const { + return hash_; + } + + int32 get_date() const { + return date_; + } + + td_api::object_ptr get_unconfirmed_session_object() const { + return td_api::make_object(hash_, date_, device_, location_); + } +}; + +class AccountManager::UnconfirmedAuthorizations { + vector authorizations_; + + public: + bool is_empty() const { + return authorizations_.empty(); + } + + bool add_authorization(UnconfirmedAuthorization &&unconfirmed_authorization, bool &is_first_changed) { + if (unconfirmed_authorization.get_hash() == 0) { + LOG(ERROR) << "Receive empty unconfirmed authorization"; + return false; + } + for (const auto &authorization : authorizations_) { + if (authorization.get_hash() == unconfirmed_authorization.get_hash()) { + return false; + } + } + auto it = authorizations_.begin(); + while (it != authorizations_.end() && it->get_date() <= unconfirmed_authorization.get_date()) { + ++it; + } + is_first_changed = it == authorizations_.begin(); + authorizations_.insert(it, std::move(unconfirmed_authorization)); + return true; + } + + bool delete_authorization(int64 hash, bool &is_first_changed) { + auto it = authorizations_.begin(); + while (it != authorizations_.end() && it->get_hash() != hash) { + ++it; + } + if (it == authorizations_.end()) { + return false; + } + is_first_changed = it == authorizations_.begin(); + authorizations_.erase(it); + return true; + } + + td_api::object_ptr get_first_unconfirmed_session_object() const { + CHECK(!authorizations_.empty()); + return authorizations_[0].get_unconfirmed_session_object(); + } +}; + AccountManager::AccountManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { } +AccountManager::~AccountManager() = default; + void AccountManager::tear_down() { parent_.reset(); } @@ -706,7 +779,53 @@ void AccountManager::invalidate_authentication_codes(vector &&authentica td_->create_handler()->send(std::move(authentication_codes)); } +void AccountManager::on_new_unconfirmed_authorization(int64 hash, int32 date, string &&device, string &&location) { + if (td_->auth_manager_->is_bot()) { + LOG(ERROR) << "Receive unconfirmed authorization by a bot"; + return; + } + if (unconfirmed_authorizations_ == nullptr) { + unconfirmed_authorizations_ = make_unique(); + } + bool is_first_changed = false; + if (unconfirmed_authorizations_->add_authorization({hash, date, std::move(device), std::move(location)}, + is_first_changed)) { + CHECK(!unconfirmed_authorizations_->is_empty()); + if (is_first_changed) { + send_update_unconfirmed_session(); + } + } +} + +void AccountManager::on_confirm_authorization(int64 hash) { + bool is_first_changed = false; + if (unconfirmed_authorizations_ != nullptr && + unconfirmed_authorizations_->delete_authorization(hash, is_first_changed)) { + if (unconfirmed_authorizations_->is_empty()) { + unconfirmed_authorizations_ = nullptr; + } + if (is_first_changed) { + send_update_unconfirmed_session(); + } + } +} + +td_api::object_ptr AccountManager::get_update_unconfirmed_session() const { + if (unconfirmed_authorizations_ == nullptr) { + return td_api::object_ptr(nullptr); + } + return td_api::make_object( + unconfirmed_authorizations_->get_first_unconfirmed_session_object()); +} + +void AccountManager::send_update_unconfirmed_session() const { + send_closure(G()->td(), &Td::send_update, get_update_unconfirmed_session()); +} + void AccountManager::get_current_state(vector> &updates) const { + if (unconfirmed_authorizations_ != nullptr) { + updates.push_back(get_update_unconfirmed_session()); + } } } // namespace td diff --git a/td/telegram/AccountManager.h b/td/telegram/AccountManager.h index 22d227800..cb99064ea 100644 --- a/td/telegram/AccountManager.h +++ b/td/telegram/AccountManager.h @@ -20,6 +20,11 @@ class Td; class AccountManager final : public Actor { public: AccountManager(Td *td, ActorShared<> parent); + AccountManager(const AccountManager &) = delete; + AccountManager &operator=(const AccountManager &) = delete; + AccountManager(AccountManager &&) = delete; + AccountManager &operator=(AccountManager &&) = delete; + ~AccountManager() final; void set_default_message_ttl(int32 message_ttl, Promise &&promise); @@ -55,15 +60,28 @@ class AccountManager final : public Actor { void invalidate_authentication_codes(vector &&authentication_codes); + void on_new_unconfirmed_authorization(int64 hash, int32 date, string &&device, string &&location); + + void on_confirm_authorization(int64 hash); + void get_current_state(vector> &updates) const; private: + class UnconfirmedAuthorization; + class UnconfirmedAuthorizations; + void tear_down() final; void get_user_link_impl(Promise> &&promise); + td_api::object_ptr get_update_unconfirmed_session() const; + + void send_update_unconfirmed_session() const; + Td *td_; ActorShared<> parent_; + + unique_ptr unconfirmed_authorizations_; }; } // namespace td diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 25736f2c6..a71268f21 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -6,6 +6,7 @@ // #include "td/telegram/UpdatesManager.h" +#include "td/telegram/AccountManager.h" #include "td/telegram/AnimationsManager.h" #include "td/telegram/AttachMenuManager.h" #include "td/telegram/AuthManager.h" @@ -4341,10 +4342,16 @@ void UpdatesManager::on_update(tl_object_ptr update promise.set_value(Unit()); } -// unsupported updates - void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) { + if (update->unconfirmed_) { + td_->account_manager_->on_new_unconfirmed_authorization(update->hash_, update->date_, std::move(update->device_), + std::move(update->location_)); + } else { + td_->account_manager_->on_confirm_authorization(update->hash_); + } promise.set_value(Unit()); } +// unsupported updates + } // namespace td diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 316e96c18..c68126320 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -630,9 +630,9 @@ class UpdatesManager final : public Actor { void on_update(tl_object_ptr update, Promise &&promise); - // unsupported updates - void on_update(tl_object_ptr update, Promise &&promise); + + // unsupported updates }; } // namespace td