Replace GetChatMemberRequest with REQUEST_PROMISE.

This commit is contained in:
levlam 2021-07-19 04:17:29 +03:00
parent 4caf74a86f
commit 13fcffd711
3 changed files with 117 additions and 141 deletions

View File

@ -14658,68 +14658,81 @@ void ContactsManager::ban_dialog_participant(DialogId dialog_id,
} }
} }
DialogParticipant ContactsManager::get_dialog_participant(DialogId dialog_id, void ContactsManager::get_dialog_participant(DialogId dialog_id,
const tl_object_ptr<td_api::MessageSender> &participant_id, const tl_object_ptr<td_api::MessageSender> &participant_id,
int64 &random_id, bool force, Promise<Unit> &&promise) { Promise<td_api::object_ptr<td_api::chatMember>> &&promise) {
// TODO TRY_RESULT_PROMISE(promise, participant_dialog_id, get_participant_dialog_id(participant_id)); 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();
LOG(INFO) << "Receive GetChatMember request to get " << participant_dialog_id << " in " << dialog_id auto new_promise = PromiseCreator::lambda(
<< " with random_id " << random_id; [actor_id = actor_id(this), promise = std::move(promise)](Result<DialogParticipant> &&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<td_api::object_ptr<td_api::chatMember>> &&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<DialogParticipant> &&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")) { if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_participant")) {
promise.set_error(Status::Error(3, "Chat not found")); return promise.set_error(Status::Error(3, "Chat not found"));
return DialogParticipant();
} }
switch (dialog_id.get_type()) { switch (dialog_id.get_type()) {
case DialogType::User: case DialogType::User:
if (participant_dialog_id == DialogId(get_my_id())) { if (participant_dialog_id == DialogId(get_my_id())) {
promise.set_value(Unit()); return promise.set_value(
return {participant_dialog_id, dialog_id.get_user_id(), 0, DialogParticipantStatus::Member()}; DialogParticipant{participant_dialog_id, dialog_id.get_user_id(), 0, DialogParticipantStatus::Member()});
} }
if (participant_dialog_id == dialog_id) { if (participant_dialog_id == dialog_id) {
promise.set_value(Unit()); return promise.set_value(
return {participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}; DialogParticipant{participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()});
} }
promise.set_error(Status::Error(3, "Member not found")); return promise.set_error(Status::Error(3, "Member not found"));
break;
case DialogType::Chat: case DialogType::Chat:
if (participant_dialog_id.get_type() != DialogType::User) { if (participant_dialog_id.get_type() != DialogType::User) {
promise.set_value(Unit()); return promise.set_value(DialogParticipant::left(participant_dialog_id));
return DialogParticipant::left(participant_dialog_id);
} }
return get_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), force, return get_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), std::move(promise));
std::move(promise));
case DialogType::Channel: case DialogType::Channel:
return get_channel_participant(dialog_id.get_channel_id(), participant_dialog_id, random_id, force, return get_channel_participant(dialog_id.get_channel_id(), participant_dialog_id, std::move(promise));
std::move(promise));
case DialogType::SecretChat: { case DialogType::SecretChat: {
auto peer_user_id = get_secret_chat_user_id(dialog_id.get_secret_chat_id()); auto peer_user_id = get_secret_chat_user_id(dialog_id.get_secret_chat_id());
if (participant_dialog_id == DialogId(get_my_id())) { if (participant_dialog_id == DialogId(get_my_id())) {
promise.set_value(Unit()); return promise.set_value(DialogParticipant{participant_dialog_id,
return {participant_dialog_id, peer_user_id.is_valid() ? peer_user_id : get_my_id(), 0, peer_user_id.is_valid() ? peer_user_id : get_my_id(), 0,
DialogParticipantStatus::Member()}; DialogParticipantStatus::Member()});
} }
if (participant_dialog_id == DialogId(peer_user_id)) { if (participant_dialog_id == DialogId(peer_user_id)) {
promise.set_value(Unit()); return promise.set_value(
return {participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}; DialogParticipant{participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()});
} }
promise.set_error(Status::Error(3, "Member not found")); return promise.set_error(Status::Error(3, "Member not found"));
break;
} }
case DialogType::None: case DialogType::None:
default: default:
UNREACHABLE(); 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, 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, void ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, Promise<DialogParticipant> &&promise) {
Promise<Unit> &&promise) {
LOG(INFO) << "Trying to get " << user_id << " as member of " << chat_id; 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); auto c = get_chat(chat_id);
if (result == nullptr) { if (c == nullptr) {
return DialogParticipant::left(DialogId(user_id)); 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<Unit> &&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<DialogParticipant> &&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, 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, void ContactsManager::get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id,
int64 &random_id, bool force, Promise<Unit> &&promise) { Promise<DialogParticipant> &&promise) {
LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_id << " with random_id " LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_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;
}
auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read); auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read);
if (input_peer == nullptr) { if (input_peer == nullptr) {
promise.set_error(Status::Error(6, "User not found")); return promise.set_error(Status::Error(6, "User not found"));
return DialogParticipant();
} }
if (have_channel_participant_cache(channel_id)) { if (have_channel_participant_cache(channel_id)) {
auto *participant = get_channel_participant_from_cache(channel_id, participant_dialog_id); auto *participant = get_channel_participant_from_cache(channel_id, participant_dialog_id);
if (participant != nullptr) { if (participant != nullptr) {
promise.set_value(Unit()); return promise.set_value(DialogParticipant{*participant});
return *participant;
} }
} }
do { auto on_result_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, promise = std::move(promise)](
random_id = Random::secure_int64(); Result<DialogParticipant> r_dialog_participant) mutable {
} while (random_id == 0 || received_channel_participant_.find(random_id) != received_channel_participant_.end()); TRY_RESULT_PROMISE(promise, dialog_participant, std::move(r_dialog_participant));
received_channel_participant_[random_id]; // reserve place for result send_closure(actor_id, &ContactsManager::finish_get_channel_participant, channel_id, std::move(dialog_participant),
std::move(promise));
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<DialogParticipant> 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));
}); });
td_->create_handler<GetChannelParticipantQuery>(std::move(on_result_promise)) td_->create_handler<GetChannelParticipantQuery>(std::move(on_result_promise))
->send(channel_id, participant_dialog_id, std::move(input_peer)); ->send(channel_id, participant_dialog_id, std::move(input_peer));
return DialogParticipant();
} }
void ContactsManager::on_get_channel_participant(ChannelId channel_id, int64 random_id, void ContactsManager::finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant,
Result<DialogParticipant> r_dialog_participant, Promise<DialogParticipant> &&promise) {
Promise<Unit> &&promise) {
if (G()->close_flag()) { if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted")); 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); dialog_participant.status.update_restrictions();
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)) { if (have_channel_participant_cache(channel_id)) {
add_channel_participant_to_cache(channel_id, it->second, false); add_channel_participant_to_cache(channel_id, dialog_participant, false);
}
promise.set_value(Unit());
} }
promise.set_value(std::move(dialog_participant));
} }
void ContactsManager::get_channel_participants(ChannelId channel_id, void ContactsManager::get_channel_participants(ChannelId channel_id,

View File

@ -520,9 +520,8 @@ class ContactsManager final : public Actor {
void ban_dialog_participant(DialogId dialog_id, const tl_object_ptr<td_api::MessageSender> &participant_id, void ban_dialog_participant(DialogId dialog_id, const tl_object_ptr<td_api::MessageSender> &participant_id,
int32 banned_until_date, bool revoke_messages, Promise<Unit> &&promise); int32 banned_until_date, bool revoke_messages, Promise<Unit> &&promise);
DialogParticipant get_dialog_participant(DialogId dialog_id, void get_dialog_participant(DialogId dialog_id, const tl_object_ptr<td_api::MessageSender> &participant_id,
const tl_object_ptr<td_api::MessageSender> &participant_id, int64 &random_id, Promise<td_api::object_ptr<td_api::chatMember>> &&promise);
bool force, Promise<Unit> &&promise);
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter,
Promise<DialogParticipants> &&promise); Promise<DialogParticipants> &&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, DialogParticipants search_private_chat_participants(UserId my_user_id, UserId peer_user_id, const string &query,
int32 limit, DialogParticipantsFilter filter) const; int32 limit, DialogParticipantsFilter filter) const;
DialogParticipant get_chat_participant(ChatId chat_id, UserId user_id, bool force, Promise<Unit> &&promise); void get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, Promise<DialogParticipant> &&promise);
DialogParticipant get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, int64 &random_id, void finish_get_dialog_participant(DialogParticipant &&dialog_participant,
bool force, Promise<Unit> &&promise); Promise<td_api::object_ptr<td_api::chatMember>> &&promise);
void get_chat_participant(ChatId chat_id, UserId user_id, Promise<DialogParticipant> &&promise);
void finish_get_chat_participant(ChatId chat_id, UserId user_id, Promise<DialogParticipant> &&promise);
void get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id,
Promise<DialogParticipant> &&promise);
void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant,
Promise<DialogParticipant> &&promise);
static string get_dialog_administrators_database_key(DialogId dialog_id); 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<Unit> &&promise); void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise<Unit> &&promise);
void on_get_channel_participant(ChannelId channel_id, int64 random_id, Result<DialogParticipant> r_dialog_participant,
Promise<Unit> &&promise);
void search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantsFilter filter, void search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantsFilter filter,
Promise<DialogParticipants> &&promise); Promise<DialogParticipants> &&promise);
@ -1649,8 +1655,6 @@ class ContactsManager final : public Actor {
std::unordered_map<int64, std::pair<vector<UserId>, vector<int32>>> imported_contacts_; std::unordered_map<int64, std::pair<vector<UserId>, vector<int32>>> imported_contacts_;
std::unordered_map<int64, DialogParticipant> received_channel_participant_;
std::unordered_map<ChannelId, vector<DialogParticipant>, ChannelIdHash> cached_channel_participants_; std::unordered_map<ChannelId, vector<DialogParticipant>, ChannelIdHash> cached_channel_participants_;
// bot-administrators only // bot-administrators only

View File

@ -1943,39 +1943,6 @@ class UpgradeGroupChatToSupergroupChatRequest final : public RequestActor<> {
} }
}; };
class GetChatMemberRequest final : public RequestActor<> {
DialogId dialog_id_;
tl_object_ptr<td_api::MessageSender> participant_id_;
int64 random_id_;
DialogParticipant dialog_participant_;
void do_run(Promise<Unit> &&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> td, uint64 request_id, int64 dialog_id,
tl_object_ptr<td_api::MessageSender> 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<> { class GetChatAdministratorsRequest final : public RequestActor<> {
DialogId dialog_id_; 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) { 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) { void Td::on_request(uint64 id, td_api::searchChatMembers &request) {