Use request promise in getChatAdministrators.

This commit is contained in:
levlam 2021-12-18 22:44:25 +03:00
parent 28d65e42e6
commit 93464ccd27
3 changed files with 89 additions and 85 deletions

View File

@ -13399,7 +13399,7 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id
c->is_creator_changed = true; c->is_creator_changed = true;
send_get_channel_full_query(nullptr, channel_id, Auto(), "update channel owner"); 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)}); 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); ->send(channel_id, participants_filter, offset, limit);
} }
vector<DialogAdministrator> ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries, td_api::object_ptr<td_api::chatAdministrators> ContactsManager::get_chat_administrators_object(
Promise<Unit> &&promise) { const vector<DialogAdministrator> &dialog_administrators) {
LOG(INFO) << "Receive GetChatAdministrators request in " << dialog_id << " with " << left_tries << " left tries"; auto administrator_objects = transform(dialog_administrators, [this](const DialogAdministrator &administrator) {
return administrator.get_chat_administrator_object(this);
});
return td_api::make_object<td_api::chatAdministrators>(std::move(administrator_objects));
}
void ContactsManager::get_dialog_administrators(DialogId dialog_id,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_administrators")) { if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_administrators")) {
promise.set_error(Status::Error(400, "Chat not found")); return promise.set_error(Status::Error(400, "Chat not found"));
return {};
} }
switch (dialog_id.get_type()) { switch (dialog_id.get_type()) {
case DialogType::User: case DialogType::User:
case DialogType::SecretChat: case DialogType::SecretChat:
promise.set_value(Unit()); return promise.set_value(td_api::make_object<td_api::chatAdministrators>());
return {};
case DialogType::Chat: case DialogType::Chat:
case DialogType::Channel: case DialogType::Channel:
break; break;
case DialogType::None: case DialogType::None:
default: default:
UNREACHABLE(); UNREACHABLE();
return {}; return;
} }
auto it = dialog_administrators_.find(dialog_id); auto it = dialog_administrators_.find(dialog_id);
if (it != dialog_administrators_.end()) { if (it != dialog_administrators_.end()) {
promise.set_value(Unit()); reload_dialog_administrators(dialog_id, it->second, Auto()); // update administrators cache
if (left_tries >= 2) { return promise.set_value(get_chat_administrators_object(it->second));
auto hash = get_vector_hash(transform(it->second, [](const DialogAdministrator &administrator) {
return static_cast<uint64>(administrator.get_user_id().get());
}));
reload_dialog_administrators(dialog_id, hash, Auto()); // update administrators cache
}
return 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<Unit> &&promise) {
if (G()->parameters().use_chat_info_db) { if (G()->parameters().use_chat_info_db) {
LOG(INFO) << "Load administrators of " << dialog_id << " from database"; LOG(INFO) << "Load administrators of " << dialog_id << " from database";
G()->td_db()->get_sqlite_pmc()->get(get_dialog_administrators_database_key(dialog_id), 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<Uni
&ContactsManager::on_load_dialog_administrators_from_database, &ContactsManager::on_load_dialog_administrators_from_database,
dialog_id, std::move(value), std::move(promise)); dialog_id, std::move(value), std::move(promise));
})); }));
} else { return;
promise.set_value(Unit());
}
} }
void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialog_id, string value, reload_dialog_administrators(dialog_id, {}, std::move(promise));
Promise<Unit> &&promise) { }
if (value.empty() || G()->close_flag()) {
promise.set_value(Unit()); string ContactsManager::get_dialog_administrators_database_key(DialogId dialog_id) {
return; return PSTRING() << "adm" << (-dialog_id.get());
}
void ContactsManager::on_load_dialog_administrators_from_database(
DialogId dialog_id, string value, Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
if (value.empty()) {
return reload_dialog_administrators(dialog_id, {}, std::move(promise));
} }
vector<DialogAdministrator> administrators; vector<DialogAdministrator> administrators;
@ -15332,13 +15317,18 @@ void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialo
lock_promise.set_value(Unit()); lock_promise.set_value(Unit());
} }
void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id, void ContactsManager::on_load_administrator_users_finished(
vector<DialogAdministrator> administrators, Result<> result, DialogId dialog_id, vector<DialogAdministrator> administrators, Result<> result,
Promise<Unit> promise) { Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
if (!G()->close_flag() && result.is_ok()) { TRY_STATUS_PROMISE(promise, G()->close_status());
dialog_administrators_.emplace(dialog_id, std::move(administrators));
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) { 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<Unit> &&promise) { void ContactsManager::reload_dialog_administrators(DialogId dialog_id,
const vector<DialogAdministrator> &dialog_administrators,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
auto query_promise = PromiseCreator::lambda(
[actor_id = actor_id(this), dialog_id, promise = std::move(promise)](Result<Unit> &&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()) { switch (dialog_id.get_type()) {
case DialogType::Chat: 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; break;
case DialogType::Channel: case DialogType::Channel: {
td_->create_handler<GetChannelAdministratorsQuery>(std::move(promise))->send(dialog_id.get_channel_id(), hash); auto hash = get_vector_hash(transform(dialog_administrators, [](const DialogAdministrator &administrator) {
return static_cast<uint64>(administrator.get_user_id().get());
}));
td_->create_handler<GetChannelAdministratorsQuery>(std::move(query_promise))
->send(dialog_id.get_channel_id(), hash);
break; break;
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
} }
void ContactsManager::on_reload_dialog_administrators(
DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatAdministrators>> &&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) { void ContactsManager::on_chat_update(telegram_api::chatEmpty &chat, const char *source) {
ChatId chat_id(chat.id_); ChatId chat_id(chat.id_);
if (!chat_id.is_valid()) { if (!chat_id.is_valid()) {

View File

@ -534,7 +534,7 @@ class ContactsManager final : public Actor {
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);
vector<DialogAdministrator> get_dialog_administrators(DialogId dialog_id, int left_tries, Promise<Unit> &&promise); void get_dialog_administrators(DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void get_channel_participants(ChannelId channel_id, tl_object_ptr<td_api::SupergroupMembersFilter> &&filter, void get_channel_participants(ChannelId channel_id, tl_object_ptr<td_api::SupergroupMembersFilter> &&filter,
string additional_query, int32 offset, int32 limit, int32 additional_limit, 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, void finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant,
Promise<DialogParticipant> &&promise); Promise<DialogParticipant> &&promise);
td_api::object_ptr<td_api::chatAdministrators> ContactsManager::get_chat_administrators_object(
const vector<DialogAdministrator> &dialog_administrators);
static string get_dialog_administrators_database_key(DialogId dialog_id); static string get_dialog_administrators_database_key(DialogId dialog_id);
void load_dialog_administrators(DialogId dialog_id, Promise<Unit> &&promise); void on_load_dialog_administrators_from_database(DialogId dialog_id, string value,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void on_load_dialog_administrators_from_database(DialogId dialog_id, string value, Promise<Unit> &&promise);
void on_load_administrator_users_finished(DialogId dialog_id, vector<DialogAdministrator> administrators, void on_load_administrator_users_finished(DialogId dialog_id, vector<DialogAdministrator> administrators,
Result<> result, Promise<Unit> promise); Result<> result,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void reload_dialog_administrators(DialogId dialog_id, int64 hash, Promise<Unit> &&promise); void reload_dialog_administrators(DialogId dialog_id, const vector<DialogAdministrator> &dialog_administrators,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void on_reload_dialog_administrators(DialogId dialog_id,
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
void remove_dialog_suggested_action(SuggestedAction action); void remove_dialog_suggested_action(SuggestedAction action);

View File

@ -1764,30 +1764,6 @@ class UpgradeGroupChatToSupergroupChatRequest final : public RequestActor<> {
} }
}; };
class GetChatAdministratorsRequest final : public RequestActor<> {
DialogId dialog_id_;
vector<DialogAdministrator> administrators_;
void do_run(Promise<Unit> &&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<td_api::chatAdministrators>(std::move(administrator_objects)));
}
public:
GetChatAdministratorsRequest(ActorShared<Td> 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<> { class CheckChatInviteLinkRequest final : public RequestActor<> {
string invite_link_; 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) { 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) { void Td::on_request(uint64 id, const td_api::replacePrimaryChatInviteLink &request) {