From 93464ccd2778274405f3c763ad109be57abe8707 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 18 Dec 2021 22:44:25 +0300 Subject: [PATCH] Use request promise in getChatAdministrators. --- td/telegram/ContactsManager.cpp | 128 ++++++++++++++++++-------------- td/telegram/ContactsManager.h | 19 +++-- td/telegram/Td.cpp | 27 +------ 3 files changed, 89 insertions(+), 85 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 00f03f5b1..34105cfd5 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -13399,7 +13399,7 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id c->is_creator_changed = true; send_get_channel_full_query(nullptr, channel_id, Auto(), "update channel owner"); - reload_dialog_administrators(DialogId(channel_id), 0, Auto()); + reload_dialog_administrators(DialogId(channel_id), {}, Auto()); remove_dialog_suggested_action(SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)}); } @@ -15234,60 +15234,39 @@ void ContactsManager::get_channel_participants(ChannelId channel_id, ->send(channel_id, participants_filter, offset, limit); } -vector ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries, - Promise &&promise) { - LOG(INFO) << "Receive GetChatAdministrators request in " << dialog_id << " with " << left_tries << " left tries"; +td_api::object_ptr ContactsManager::get_chat_administrators_object( + const vector &dialog_administrators) { + auto administrator_objects = transform(dialog_administrators, [this](const DialogAdministrator &administrator) { + return administrator.get_chat_administrator_object(this); + }); + return td_api::make_object(std::move(administrator_objects)); +} + +void ContactsManager::get_dialog_administrators(DialogId dialog_id, + Promise> &&promise) { if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_administrators")) { - promise.set_error(Status::Error(400, "Chat not found")); - return {}; + return promise.set_error(Status::Error(400, "Chat not found")); } switch (dialog_id.get_type()) { case DialogType::User: case DialogType::SecretChat: - promise.set_value(Unit()); - return {}; + return promise.set_value(td_api::make_object()); case DialogType::Chat: case DialogType::Channel: break; case DialogType::None: default: UNREACHABLE(); - return {}; + return; } auto it = dialog_administrators_.find(dialog_id); if (it != dialog_administrators_.end()) { - promise.set_value(Unit()); - if (left_tries >= 2) { - auto hash = get_vector_hash(transform(it->second, [](const DialogAdministrator &administrator) { - return static_cast(administrator.get_user_id().get()); - })); - reload_dialog_administrators(dialog_id, hash, Auto()); // update administrators cache - } - return it->second; + reload_dialog_administrators(dialog_id, it->second, Auto()); // update administrators cache + return promise.set_value(get_chat_administrators_object(it->second)); } - if (left_tries >= 3) { - load_dialog_administrators(dialog_id, std::move(promise)); - return {}; - } - - if (left_tries >= 2) { - reload_dialog_administrators(dialog_id, 0, std::move(promise)); - return {}; - } - - LOG(ERROR) << "Have no known administrators in " << dialog_id; - promise.set_value(Unit()); - return {}; -} - -string ContactsManager::get_dialog_administrators_database_key(DialogId dialog_id) { - return PSTRING() << "adm" << (-dialog_id.get()); -} - -void ContactsManager::load_dialog_administrators(DialogId dialog_id, Promise &&promise) { if (G()->parameters().use_chat_info_db) { LOG(INFO) << "Load administrators of " << dialog_id << " from database"; G()->td_db()->get_sqlite_pmc()->get(get_dialog_administrators_database_key(dialog_id), @@ -15297,16 +15276,22 @@ void ContactsManager::load_dialog_administrators(DialogId dialog_id, Promise &&promise) { - if (value.empty() || G()->close_flag()) { - promise.set_value(Unit()); - return; +string ContactsManager::get_dialog_administrators_database_key(DialogId dialog_id) { + return PSTRING() << "adm" << (-dialog_id.get()); +} + +void ContactsManager::on_load_dialog_administrators_from_database( + DialogId dialog_id, string value, Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + if (value.empty()) { + return reload_dialog_administrators(dialog_id, {}, std::move(promise)); } vector administrators; @@ -15332,13 +15317,18 @@ void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialo lock_promise.set_value(Unit()); } -void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id, - vector administrators, Result<> result, - Promise promise) { - if (!G()->close_flag() && result.is_ok()) { - dialog_administrators_.emplace(dialog_id, std::move(administrators)); +void ContactsManager::on_load_administrator_users_finished( + DialogId dialog_id, vector administrators, Result<> result, + Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + if (result.is_error()) { + return reload_dialog_administrators(dialog_id, {}, std::move(promise)); } - promise.set_value(Unit()); + + auto it = dialog_administrators_.emplace(dialog_id, std::move(administrators)).first; + reload_dialog_administrators(dialog_id, it->second, Auto()); // update administrators cache + promise.set_value(get_chat_administrators_object(it->second)); } void ContactsManager::on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count) { @@ -15394,19 +15384,49 @@ void ContactsManager::on_update_dialog_administrators(DialogId dialog_id, vector } } -void ContactsManager::reload_dialog_administrators(DialogId dialog_id, int64 hash, Promise &&promise) { +void ContactsManager::reload_dialog_administrators(DialogId dialog_id, + const vector &dialog_administrators, + Promise> &&promise) { + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), dialog_id, promise = std::move(promise)](Result &&result) mutable { + if (promise) { + if (result.is_ok()) { + send_closure(actor_id, &ContactsManager::on_reload_dialog_administrators, dialog_id, std::move(promise)); + } else { + promise.set_error(result.move_as_error()); + } + } + }); switch (dialog_id.get_type()) { case DialogType::Chat: - load_chat_full(dialog_id.get_chat_id(), false, std::move(promise), "reload_dialog_administrators"); + load_chat_full(dialog_id.get_chat_id(), false, std::move(query_promise), "reload_dialog_administrators"); break; - case DialogType::Channel: - td_->create_handler(std::move(promise))->send(dialog_id.get_channel_id(), hash); + case DialogType::Channel: { + auto hash = get_vector_hash(transform(dialog_administrators, [](const DialogAdministrator &administrator) { + return static_cast(administrator.get_user_id().get()); + })); + td_->create_handler(std::move(query_promise)) + ->send(dialog_id.get_channel_id(), hash); break; + } default: UNREACHABLE(); } } +void ContactsManager::on_reload_dialog_administrators( + DialogId dialog_id, Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + auto it = dialog_administrators_.find(dialog_id); + if (it != dialog_administrators_.end()) { + return promise.set_value(get_chat_administrators_object(it->second)); + } + + LOG(ERROR) << "Failed to load administrators in " << dialog_id; + promise.set_error(Status::Error(500, "Failed to find chat administrators")); +} + void ContactsManager::on_chat_update(telegram_api::chatEmpty &chat, const char *source) { ChatId chat_id(chat.id_); if (!chat_id.is_valid()) { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index fc54082f5..8a30d9efc 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -534,7 +534,7 @@ class ContactsManager final : public Actor { void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, Promise &&promise); - vector get_dialog_administrators(DialogId dialog_id, int left_tries, Promise &&promise); + void get_dialog_administrators(DialogId dialog_id, Promise> &&promise); void get_channel_participants(ChannelId channel_id, tl_object_ptr &&filter, string additional_query, int32 offset, int32 limit, int32 additional_limit, @@ -1476,16 +1476,23 @@ class ContactsManager final : public Actor { void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant, Promise &&promise); + td_api::object_ptr ContactsManager::get_chat_administrators_object( + const vector &dialog_administrators); + static string get_dialog_administrators_database_key(DialogId dialog_id); - void load_dialog_administrators(DialogId dialog_id, Promise &&promise); - - void on_load_dialog_administrators_from_database(DialogId dialog_id, string value, Promise &&promise); + void on_load_dialog_administrators_from_database(DialogId dialog_id, string value, + Promise> &&promise); void on_load_administrator_users_finished(DialogId dialog_id, vector administrators, - Result<> result, Promise promise); + Result<> result, + Promise> &&promise); - void reload_dialog_administrators(DialogId dialog_id, int64 hash, Promise &&promise); + void reload_dialog_administrators(DialogId dialog_id, const vector &dialog_administrators, + Promise> &&promise); + + void on_reload_dialog_administrators(DialogId dialog_id, + Promise> &&promise); void remove_dialog_suggested_action(SuggestedAction action); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 7bc1d69e6..df59dbedd 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1764,30 +1764,6 @@ class UpgradeGroupChatToSupergroupChatRequest final : public RequestActor<> { } }; -class GetChatAdministratorsRequest final : public RequestActor<> { - DialogId dialog_id_; - - vector administrators_; - - void do_run(Promise &&promise) final { - administrators_ = td_->contacts_manager_->get_dialog_administrators(dialog_id_, get_tries(), std::move(promise)); - } - - void do_send_result() final { - auto administrator_objects = transform( - administrators_, [contacts_manager = td_->contacts_manager_.get()](const DialogAdministrator &administrator) { - return administrator.get_chat_administrator_object(contacts_manager); - }); - send_result(td_api::make_object(std::move(administrator_objects))); - } - - public: - GetChatAdministratorsRequest(ActorShared td, uint64 request_id, int64 dialog_id) - : RequestActor(std::move(td), request_id), dialog_id_(dialog_id) { - set_tries(3); - } -}; - class CheckChatInviteLinkRequest final : public RequestActor<> { string invite_link_; @@ -6194,7 +6170,8 @@ void Td::on_request(uint64 id, td_api::searchChatMembers &request) { } void Td::on_request(uint64 id, const td_api::getChatAdministrators &request) { - CREATE_REQUEST(GetChatAdministratorsRequest, request.chat_id_); + CREATE_REQUEST_PROMISE(); + contacts_manager_->get_dialog_administrators(DialogId(request.chat_id_), std::move(promise)); } void Td::on_request(uint64 id, const td_api::replacePrimaryChatInviteLink &request) {