From 13fcffd711ab1563f30b437ac892bcd29235a7f5 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 19 Jul 2021 04:17:29 +0300 Subject: [PATCH] Replace GetChatMemberRequest with REQUEST_PROMISE. --- td/telegram/ContactsManager.cpp | 195 ++++++++++++++++---------------- td/telegram/ContactsManager.h | 26 +++-- td/telegram/Td.cpp | 37 +----- 3 files changed, 117 insertions(+), 141 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 156bdf11f..871dc1956 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -14658,68 +14658,81 @@ void ContactsManager::ban_dialog_participant(DialogId dialog_id, } } -DialogParticipant ContactsManager::get_dialog_participant(DialogId dialog_id, - const tl_object_ptr &participant_id, - int64 &random_id, bool force, Promise &&promise) { - // TODO TRY_RESULT_PROMISE(promise, participant_dialog_id, get_participant_dialog_id(participant_id)); - auto r_participant_dialog_id = get_participant_dialog_id(participant_id); - if (r_participant_dialog_id.is_error()) { - promise.set_error(r_participant_dialog_id.move_as_error()); - return {}; - } - auto participant_dialog_id = r_participant_dialog_id.move_as_ok(); +void ContactsManager::get_dialog_participant(DialogId dialog_id, + const tl_object_ptr &participant_id, + Promise> &&promise) { + TRY_RESULT_PROMISE(promise, participant_dialog_id, get_participant_dialog_id(participant_id)); - LOG(INFO) << "Receive GetChatMember request to get " << participant_dialog_id << " in " << dialog_id - << " with random_id " << random_id; + auto new_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), promise = std::move(promise)](Result &&result) mutable { + TRY_RESULT_PROMISE(promise, dialog_participant, std::move(result)); + send_closure(actor_id, &ContactsManager::finish_get_dialog_participant, std::move(dialog_participant), + std::move(promise)); + }); + get_dialog_participant(dialog_id, participant_dialog_id, std::move(new_promise)); +} + +void ContactsManager::finish_get_dialog_participant(DialogParticipant &&dialog_participant, + Promise> &&promise) { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + + auto participant_dialog_id = dialog_participant.dialog_id; + bool is_user = participant_dialog_id.get_type() == DialogType::User; + if ((is_user && !have_user(participant_dialog_id.get_user_id())) || + (!is_user && !td_->messages_manager_->have_dialog(participant_dialog_id))) { + return promise.set_error(Status::Error(400, "Member not found")); + } + + promise.set_value(get_chat_member_object(dialog_participant)); +} + +void ContactsManager::get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, + Promise &&promise) { + LOG(INFO) << "Receive GetChatMember request to get " << participant_dialog_id << " in " << dialog_id; if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_participant")) { - promise.set_error(Status::Error(3, "Chat not found")); - return DialogParticipant(); + return promise.set_error(Status::Error(3, "Chat not found")); } switch (dialog_id.get_type()) { case DialogType::User: if (participant_dialog_id == DialogId(get_my_id())) { - promise.set_value(Unit()); - return {participant_dialog_id, dialog_id.get_user_id(), 0, DialogParticipantStatus::Member()}; + return promise.set_value( + DialogParticipant{participant_dialog_id, dialog_id.get_user_id(), 0, DialogParticipantStatus::Member()}); } if (participant_dialog_id == dialog_id) { - promise.set_value(Unit()); - return {participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}; + return promise.set_value( + DialogParticipant{participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}); } - promise.set_error(Status::Error(3, "Member not found")); - break; + return promise.set_error(Status::Error(3, "Member not found")); case DialogType::Chat: if (participant_dialog_id.get_type() != DialogType::User) { - promise.set_value(Unit()); - return DialogParticipant::left(participant_dialog_id); + return promise.set_value(DialogParticipant::left(participant_dialog_id)); } - return get_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), force, - std::move(promise)); + return get_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), std::move(promise)); case DialogType::Channel: - return get_channel_participant(dialog_id.get_channel_id(), participant_dialog_id, random_id, force, - std::move(promise)); + return get_channel_participant(dialog_id.get_channel_id(), participant_dialog_id, std::move(promise)); case DialogType::SecretChat: { auto peer_user_id = get_secret_chat_user_id(dialog_id.get_secret_chat_id()); if (participant_dialog_id == DialogId(get_my_id())) { - promise.set_value(Unit()); - return {participant_dialog_id, peer_user_id.is_valid() ? peer_user_id : get_my_id(), 0, - DialogParticipantStatus::Member()}; + return promise.set_value(DialogParticipant{participant_dialog_id, + peer_user_id.is_valid() ? peer_user_id : get_my_id(), 0, + DialogParticipantStatus::Member()}); } if (participant_dialog_id == DialogId(peer_user_id)) { - promise.set_value(Unit()); - return {participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}; + return promise.set_value( + DialogParticipant{participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}); } - promise.set_error(Status::Error(3, "Member not found")); - break; + return promise.set_error(Status::Error(3, "Member not found")); } case DialogType::None: default: UNREACHABLE(); - promise.set_error(Status::Error(500, "Wrong chat type")); + return promise.set_error(Status::Error(500, "Wrong chat type")); } - return DialogParticipant(); } DialogParticipants ContactsManager::search_private_chat_participants(UserId my_user_id, UserId peer_user_id, @@ -14846,22 +14859,43 @@ void ContactsManager::search_dialog_participants(DialogId dialog_id, const strin } } -DialogParticipant ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, bool force, - Promise &&promise) { +void ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, Promise &&promise) { LOG(INFO) << "Trying to get " << user_id << " as member of " << chat_id; - if (force) { - promise.set_value(Unit()); - } else if (!load_chat_full(chat_id, force, std::move(promise), "get_chat_participant")) { - return DialogParticipant(); - } - // promise is already set - auto result = get_chat_participant(chat_id, user_id); - if (result == nullptr) { - return DialogParticipant::left(DialogId(user_id)); + auto c = get_chat(chat_id); + if (c == nullptr) { + return promise.set_error(Status::Error(6, "Group not found")); } - return *result; + auto chat_full = get_chat_full_force(chat_id, "get_chat_participant"); + if (chat_full == nullptr || (td_->auth_manager_->is_bot() && is_chat_full_outdated(chat_full, c, chat_id))) { + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), chat_id, user_id, promise = std::move(promise)](Result &&result) mutable { + TRY_STATUS_PROMISE(promise, std::move(result)); + send_closure(actor_id, &ContactsManager::finish_get_chat_participant, chat_id, user_id, std::move(promise)); + }); + send_get_chat_full_query(chat_id, std::move(query_promise), "get_chat_participant"); + } + + if (is_chat_full_outdated(chat_full, c, chat_id)) { + send_get_chat_full_query(chat_id, Auto(), "get_chat_participant lazy"); + } + + finish_get_chat_participant(chat_id, user_id, std::move(promise)); +} + +void ContactsManager::finish_get_chat_participant(ChatId chat_id, UserId user_id, + Promise &&promise) { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + + const auto *participant = get_chat_participant(chat_id, user_id); + if (participant == nullptr) { + return promise.set_value(DialogParticipant::left(DialogId(user_id))); + } + + promise.set_value(DialogParticipant(*participant)); } void ContactsManager::search_chat_participants(ChatId chat_id, const string &query, int32 limit, @@ -14931,77 +14965,46 @@ void ContactsManager::do_search_chat_participants(ChatId chat_id, const string & })}); } -DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, - int64 &random_id, bool force, Promise &&promise) { - LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_id << " with random_id " - << random_id; - if (random_id != 0) { - // request has already been sent before - auto it = received_channel_participant_.find(random_id); - CHECK(it != received_channel_participant_.end()); - auto result = std::move(it->second); - result.status.update_restrictions(); - received_channel_participant_.erase(it); - promise.set_value(Unit()); - return result; - } +void ContactsManager::get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, + Promise &&promise) { + LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_id; auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read); if (input_peer == nullptr) { - promise.set_error(Status::Error(6, "User not found")); - return DialogParticipant(); + return promise.set_error(Status::Error(6, "User not found")); } if (have_channel_participant_cache(channel_id)) { auto *participant = get_channel_participant_from_cache(channel_id, participant_dialog_id); if (participant != nullptr) { - promise.set_value(Unit()); - return *participant; + return promise.set_value(DialogParticipant{*participant}); } } - do { - random_id = Random::secure_int64(); - } while (random_id == 0 || received_channel_participant_.find(random_id) != received_channel_participant_.end()); - received_channel_participant_[random_id]; // reserve place for result - - LOG(DEBUG) << "Get info about " << participant_dialog_id << " membership in the " << channel_id << " with random_id " - << random_id; - - auto on_result_promise = - PromiseCreator::lambda([actor_id = actor_id(this), channel_id, random_id, - promise = std::move(promise)](Result r_dialog_participant) mutable { - send_closure(actor_id, &ContactsManager::on_get_channel_participant, channel_id, random_id, - std::move(r_dialog_participant), std::move(promise)); - }); + auto on_result_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, promise = std::move(promise)]( + Result r_dialog_participant) mutable { + TRY_RESULT_PROMISE(promise, dialog_participant, std::move(r_dialog_participant)); + send_closure(actor_id, &ContactsManager::finish_get_channel_participant, channel_id, std::move(dialog_participant), + std::move(promise)); + }); td_->create_handler(std::move(on_result_promise)) ->send(channel_id, participant_dialog_id, std::move(input_peer)); - return DialogParticipant(); } -void ContactsManager::on_get_channel_participant(ChannelId channel_id, int64 random_id, - Result r_dialog_participant, - Promise &&promise) { +void ContactsManager::finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant, + Promise &&promise) { if (G()->close_flag()) { return promise.set_error(Status::Error(500, "Request aborted")); } - LOG(INFO) << "Receive a member of a channel " << channel_id << " with random_id " << random_id; + LOG(INFO) << "Receive a member " << dialog_participant.dialog_id << " of a channel " << channel_id; - auto it = received_channel_participant_.find(random_id); - CHECK(it != received_channel_participant_.end()); - - if (r_dialog_participant.is_error()) { - received_channel_participant_.erase(it); - promise.set_error(r_dialog_participant.move_as_error()); - } else { - it->second = r_dialog_participant.move_as_ok(); - if (have_channel_participant_cache(channel_id)) { - add_channel_participant_to_cache(channel_id, it->second, false); - } - promise.set_value(Unit()); + dialog_participant.status.update_restrictions(); + if (have_channel_participant_cache(channel_id)) { + add_channel_participant_to_cache(channel_id, dialog_participant, false); } + promise.set_value(std::move(dialog_participant)); } void ContactsManager::get_channel_participants(ChannelId channel_id, diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index e939836ab..9a6ad61b4 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -520,9 +520,8 @@ class ContactsManager final : public Actor { void ban_dialog_participant(DialogId dialog_id, const tl_object_ptr &participant_id, int32 banned_until_date, bool revoke_messages, Promise &&promise); - DialogParticipant get_dialog_participant(DialogId dialog_id, - const tl_object_ptr &participant_id, int64 &random_id, - bool force, Promise &&promise); + void get_dialog_participant(DialogId dialog_id, const tl_object_ptr &participant_id, + Promise> &&promise); void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, Promise &&promise); @@ -1408,10 +1407,20 @@ class ContactsManager final : public Actor { DialogParticipants search_private_chat_participants(UserId my_user_id, UserId peer_user_id, const string &query, int32 limit, DialogParticipantsFilter filter) const; - DialogParticipant get_chat_participant(ChatId chat_id, UserId user_id, bool force, Promise &&promise); + void get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, Promise &&promise); - DialogParticipant get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, int64 &random_id, - bool force, Promise &&promise); + void finish_get_dialog_participant(DialogParticipant &&dialog_participant, + Promise> &&promise); + + void get_chat_participant(ChatId chat_id, UserId user_id, Promise &&promise); + + void finish_get_chat_participant(ChatId chat_id, UserId user_id, Promise &&promise); + + void get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, + Promise &&promise); + + void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant, + Promise &&promise); static string get_dialog_administrators_database_key(DialogId dialog_id); @@ -1474,9 +1483,6 @@ class ContactsManager final : public Actor { void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise &&promise); - void on_get_channel_participant(ChannelId channel_id, int64 random_id, Result r_dialog_participant, - Promise &&promise); - void search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantsFilter filter, Promise &&promise); @@ -1649,8 +1655,6 @@ class ContactsManager final : public Actor { std::unordered_map, vector>> imported_contacts_; - std::unordered_map received_channel_participant_; - std::unordered_map, ChannelIdHash> cached_channel_participants_; // bot-administrators only diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index c544f8b72..23d1b76f4 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1943,39 +1943,6 @@ class UpgradeGroupChatToSupergroupChatRequest final : public RequestActor<> { } }; -class GetChatMemberRequest final : public RequestActor<> { - DialogId dialog_id_; - tl_object_ptr participant_id_; - int64 random_id_; - - DialogParticipant dialog_participant_; - - void do_run(Promise &&promise) final { - dialog_participant_ = td->contacts_manager_->get_dialog_participant(dialog_id_, participant_id_, random_id_, - get_tries() < 3, std::move(promise)); - } - - void do_send_result() final { - auto participant_dialog_id = dialog_participant_.dialog_id; - bool is_user = participant_dialog_id.get_type() == DialogType::User; - if ((is_user && !td->contacts_manager_->have_user(participant_dialog_id.get_user_id())) || - (!is_user && !td->messages_manager_->have_dialog(participant_dialog_id))) { - return send_error(Status::Error(3, "Member not found")); - } - send_result(td->contacts_manager_->get_chat_member_object(dialog_participant_)); - } - - public: - GetChatMemberRequest(ActorShared td, uint64 request_id, int64 dialog_id, - tl_object_ptr participant_id) - : RequestActor(std::move(td), request_id) - , dialog_id_(dialog_id) - , participant_id_(std::move(participant_id)) - , random_id_(0) { - set_tries(3); - } -}; - class GetChatAdministratorsRequest final : public RequestActor<> { DialogId dialog_id_; @@ -6491,7 +6458,9 @@ void Td::on_request(uint64 id, td_api::transferChatOwnership &request) { } void Td::on_request(uint64 id, td_api::getChatMember &request) { - CREATE_REQUEST(GetChatMemberRequest, request.chat_id_, std::move(request.member_id_)); + CREATE_REQUEST_PROMISE(); + contacts_manager_->get_dialog_participant(DialogId(request.chat_id_), std::move(request.member_id_), + std::move(promise)); } void Td::on_request(uint64 id, td_api::searchChatMembers &request) {