Move chat administrators to DialogParticipantManager.
This commit is contained in:
parent
d1251e47a6
commit
d832d5a70f
@ -3141,78 +3141,6 @@ class GetChannelParticipantsQuery final : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GetChannelAdministratorsQuery final : public Td::ResultHandler {
|
|
||||||
Promise<Unit> promise_;
|
|
||||||
ChannelId channel_id_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GetChannelAdministratorsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(ChannelId channel_id, int64 hash) {
|
|
||||||
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
|
|
||||||
if (input_channel == nullptr) {
|
|
||||||
return promise_.set_error(Status::Error(400, "Supergroup not found"));
|
|
||||||
}
|
|
||||||
|
|
||||||
hash = 0; // to load even only ranks or creator changed
|
|
||||||
|
|
||||||
channel_id_ = channel_id;
|
|
||||||
send_query(G()->net_query_creator().create(telegram_api::channels_getParticipants(
|
|
||||||
std::move(input_channel), telegram_api::make_object<telegram_api::channelParticipantsAdmins>(), 0,
|
|
||||||
std::numeric_limits<int32>::max(), hash)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_result(BufferSlice packet) final {
|
|
||||||
auto result_ptr = fetch_result<telegram_api::channels_getParticipants>(packet);
|
|
||||||
if (result_ptr.is_error()) {
|
|
||||||
return on_error(result_ptr.move_as_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto participants_ptr = result_ptr.move_as_ok();
|
|
||||||
LOG(INFO) << "Receive result for GetChannelAdministratorsQuery: " << to_string(participants_ptr);
|
|
||||||
switch (participants_ptr->get_id()) {
|
|
||||||
case telegram_api::channels_channelParticipants::ID: {
|
|
||||||
auto participants = telegram_api::move_object_as<telegram_api::channels_channelParticipants>(participants_ptr);
|
|
||||||
td_->contacts_manager_->on_get_users(std::move(participants->users_), "GetChannelAdministratorsQuery");
|
|
||||||
td_->contacts_manager_->on_get_chats(std::move(participants->chats_), "GetChannelAdministratorsQuery");
|
|
||||||
|
|
||||||
auto channel_type = td_->contacts_manager_->get_channel_type(channel_id_);
|
|
||||||
vector<DialogAdministrator> administrators;
|
|
||||||
administrators.reserve(participants->participants_.size());
|
|
||||||
for (auto &participant : participants->participants_) {
|
|
||||||
DialogParticipant dialog_participant(std::move(participant), channel_type);
|
|
||||||
if (!dialog_participant.is_valid() || !dialog_participant.status_.is_administrator() ||
|
|
||||||
dialog_participant.dialog_id_.get_type() != DialogType::User) {
|
|
||||||
LOG(ERROR) << "Receive " << dialog_participant << " as an administrator of " << channel_id_;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
administrators.emplace_back(dialog_participant.dialog_id_.get_user_id(),
|
|
||||||
dialog_participant.status_.get_rank(), dialog_participant.status_.is_creator());
|
|
||||||
}
|
|
||||||
|
|
||||||
td_->contacts_manager_->on_update_channel_administrator_count(channel_id_,
|
|
||||||
narrow_cast<int32>(administrators.size()));
|
|
||||||
td_->contacts_manager_->on_update_dialog_administrators(DialogId(channel_id_), std::move(administrators), true,
|
|
||||||
false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case telegram_api::channels_channelParticipantsNotModified::ID:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
promise_.set_value(Unit());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_error(Status status) final {
|
|
||||||
td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelAdministratorsQuery");
|
|
||||||
promise_.set_error(std::move(status));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GetSupportUserQuery final : public Td::ResultHandler {
|
class GetSupportUserQuery final : public Td::ResultHandler {
|
||||||
Promise<UserId> promise_;
|
Promise<UserId> promise_;
|
||||||
|
|
||||||
@ -3393,9 +3321,9 @@ ContactsManager::~ContactsManager() {
|
|||||||
Scheduler::instance()->destroy_on_scheduler(
|
Scheduler::instance()->destroy_on_scheduler(
|
||||||
G()->get_gc_scheduler_id(), loaded_from_database_users_, unavailable_user_fulls_, loaded_from_database_chats_,
|
G()->get_gc_scheduler_id(), loaded_from_database_users_, unavailable_user_fulls_, loaded_from_database_chats_,
|
||||||
unavailable_chat_fulls_, loaded_from_database_channels_, unavailable_channel_fulls_,
|
unavailable_chat_fulls_, loaded_from_database_channels_, unavailable_channel_fulls_,
|
||||||
loaded_from_database_secret_chats_, dialog_administrators_, user_online_member_dialogs_,
|
loaded_from_database_secret_chats_, user_online_member_dialogs_, cached_channel_participants_,
|
||||||
cached_channel_participants_, resolved_phone_numbers_, channel_participants_, all_imported_contacts_,
|
resolved_phone_numbers_, channel_participants_, all_imported_contacts_, linked_channel_ids_, restricted_user_ids_,
|
||||||
linked_channel_ids_, restricted_user_ids_, restricted_channel_ids_);
|
restricted_channel_ids_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::start_up() {
|
void ContactsManager::start_up() {
|
||||||
@ -12174,8 +12102,8 @@ void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, cons
|
|||||||
return !td::contains(bot_user_ids, commands.get_bot_user_id());
|
return !td::contains(bot_user_ids, commands.get_bot_user_id());
|
||||||
});
|
});
|
||||||
|
|
||||||
on_update_dialog_administrators(DialogId(chat_id), std::move(administrators), chat_full->version != -1,
|
td_->dialog_participant_manager_->on_update_dialog_administrators(DialogId(chat_id), std::move(administrators),
|
||||||
from_database);
|
chat_full->version != -1, from_database);
|
||||||
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(chat_id),
|
send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(chat_id),
|
||||||
std::move(bot_user_ids), from_database);
|
std::move(bot_user_ids), from_database);
|
||||||
|
|
||||||
@ -14468,7 +14396,8 @@ void ContactsManager::on_get_channel_participants(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filter.is_administrators() || filter.is_recent()) {
|
if (filter.is_administrators() || filter.is_recent()) {
|
||||||
on_update_dialog_administrators(DialogId(channel_id), std::move(administrators), true, false);
|
td_->dialog_participant_manager_->on_update_dialog_administrators(DialogId(channel_id), std::move(administrators),
|
||||||
|
true, false);
|
||||||
}
|
}
|
||||||
if (filter.is_bots() || is_full_recent) {
|
if (filter.is_bots() || is_full_recent) {
|
||||||
on_update_channel_bot_user_ids(channel_id, std::move(bot_user_ids));
|
on_update_channel_bot_user_ids(channel_id, std::move(bot_user_ids));
|
||||||
@ -14757,41 +14686,8 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId
|
|||||||
update_channel(c, channel_id);
|
update_channel(c, channel_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_status.is_administrator() != old_status.is_administrator() ||
|
td_->dialog_participant_manager_->speculative_update_dialog_administrators(DialogId(channel_id), user_id, new_status,
|
||||||
new_status.get_rank() != old_status.get_rank()) {
|
old_status);
|
||||||
DialogId dialog_id(channel_id);
|
|
||||||
auto administrators_it = dialog_administrators_.find(dialog_id);
|
|
||||||
if (administrators_it != dialog_administrators_.end()) {
|
|
||||||
auto administrators = administrators_it->second;
|
|
||||||
if (new_status.is_administrator()) {
|
|
||||||
bool is_found = false;
|
|
||||||
for (auto &administrator : administrators) {
|
|
||||||
if (administrator.get_user_id() == user_id) {
|
|
||||||
is_found = true;
|
|
||||||
if (administrator.get_rank() != new_status.get_rank() ||
|
|
||||||
administrator.is_creator() != new_status.is_creator()) {
|
|
||||||
administrator = DialogAdministrator(user_id, new_status.get_rank(), new_status.is_creator());
|
|
||||||
on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!is_found) {
|
|
||||||
administrators.emplace_back(user_id, new_status.get_rank(), new_status.is_creator());
|
|
||||||
on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
size_t i = 0;
|
|
||||||
while (i != administrators.size() && administrators[i].get_user_id() != user_id) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i != administrators.size()) {
|
|
||||||
administrators.erase(administrators.begin() + i);
|
|
||||||
on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = cached_channel_participants_.find(channel_id);
|
auto it = cached_channel_participants_.find(channel_id);
|
||||||
if (it != cached_channel_participants_.end()) {
|
if (it != cached_channel_participants_.end()) {
|
||||||
@ -15952,7 +15848,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), {}, Auto());
|
td_->dialog_participant_manager_->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)});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18250,105 +18146,6 @@ void ContactsManager::get_channel_participants(ChannelId channel_id,
|
|||||||
->send(channel_id, participant_filter, offset, limit);
|
->send(channel_id, participant_filter, offset, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
td_api::object_ptr<td_api::chatAdministrators> ContactsManager::get_chat_administrators_object(
|
|
||||||
const vector<DialogAdministrator> &dialog_administrators) {
|
|
||||||
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_->dialog_manager_->have_dialog_force(dialog_id, "get_dialog_administrators")) {
|
|
||||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (dialog_id.get_type()) {
|
|
||||||
case DialogType::User:
|
|
||||||
case DialogType::SecretChat:
|
|
||||||
return promise.set_value(td_api::make_object<td_api::chatAdministrators>());
|
|
||||||
case DialogType::Chat:
|
|
||||||
case DialogType::Channel:
|
|
||||||
break;
|
|
||||||
case DialogType::None:
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = dialog_administrators_.find(dialog_id);
|
|
||||||
if (it != dialog_administrators_.end()) {
|
|
||||||
reload_dialog_administrators(dialog_id, it->second, Auto()); // update administrators cache
|
|
||||||
return promise.set_value(get_chat_administrators_object(it->second));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G()->use_chat_info_database()) {
|
|
||||||
LOG(INFO) << "Load administrators of " << dialog_id << " from database";
|
|
||||||
G()->td_db()->get_sqlite_pmc()->get(get_dialog_administrators_database_key(dialog_id),
|
|
||||||
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id,
|
|
||||||
promise = std::move(promise)](string value) mutable {
|
|
||||||
send_closure(actor_id,
|
|
||||||
&ContactsManager::on_load_dialog_administrators_from_database,
|
|
||||||
dialog_id, std::move(value), std::move(promise));
|
|
||||||
}));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
reload_dialog_administrators(dialog_id, {}, std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
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<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;
|
|
||||||
if (log_event_parse(administrators, value).is_error()) {
|
|
||||||
return reload_dialog_administrators(dialog_id, {}, std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "Successfully loaded " << administrators.size() << " administrators in " << dialog_id
|
|
||||||
<< " from database";
|
|
||||||
|
|
||||||
MultiPromiseActorSafe load_users_multipromise{"LoadUsersMultiPromiseActor"};
|
|
||||||
load_users_multipromise.add_promise(
|
|
||||||
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, administrators,
|
|
||||||
promise = std::move(promise)](Result<Unit> result) mutable {
|
|
||||||
send_closure(actor_id, &ContactsManager::on_load_administrator_users_finished, dialog_id,
|
|
||||||
std::move(administrators), std::move(result), std::move(promise));
|
|
||||||
}));
|
|
||||||
|
|
||||||
auto lock_promise = load_users_multipromise.get_promise();
|
|
||||||
|
|
||||||
for (auto &administrator : administrators) {
|
|
||||||
get_user(administrator.get_user_id(), 3, load_users_multipromise.get_promise());
|
|
||||||
}
|
|
||||||
|
|
||||||
lock_promise.set_value(Unit());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContactsManager::on_load_administrator_users_finished(
|
|
||||||
DialogId dialog_id, vector<DialogAdministrator> administrators, Result<> result,
|
|
||||||
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
|
|
||||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
|
||||||
|
|
||||||
if (result.is_error()) {
|
|
||||||
return reload_dialog_administrators(dialog_id, {}, std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
||||||
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_administrator_count");
|
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_administrator_count");
|
||||||
if (channel_full != nullptr && channel_full->administrator_count != administrator_count) {
|
if (channel_full != nullptr && channel_full->administrator_count != administrator_count) {
|
||||||
@ -18370,89 +18167,6 @@ void ContactsManager::on_update_channel_administrator_count(ChannelId channel_id
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_dialog_administrators(DialogId dialog_id, vector<DialogAdministrator> &&administrators,
|
|
||||||
bool have_access, bool from_database) {
|
|
||||||
LOG(INFO) << "Update administrators in " << dialog_id << " to " << format::as_array(administrators);
|
|
||||||
if (have_access) {
|
|
||||||
CHECK(dialog_id.is_valid());
|
|
||||||
std::sort(administrators.begin(), administrators.end(),
|
|
||||||
[](const DialogAdministrator &lhs, const DialogAdministrator &rhs) {
|
|
||||||
return lhs.get_user_id().get() < rhs.get_user_id().get();
|
|
||||||
});
|
|
||||||
|
|
||||||
auto it = dialog_administrators_.find(dialog_id);
|
|
||||||
if (it != dialog_administrators_.end()) {
|
|
||||||
if (it->second == administrators) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
it->second = std::move(administrators);
|
|
||||||
} else {
|
|
||||||
it = dialog_administrators_.emplace(dialog_id, std::move(administrators)).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G()->use_chat_info_database() && !from_database) {
|
|
||||||
LOG(INFO) << "Save administrators of " << dialog_id << " to database";
|
|
||||||
G()->td_db()->get_sqlite_pmc()->set(get_dialog_administrators_database_key(dialog_id),
|
|
||||||
log_event_store(it->second).as_slice().str(), Auto());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dialog_administrators_.erase(dialog_id);
|
|
||||||
if (G()->use_chat_info_database()) {
|
|
||||||
G()->td_db()->get_sqlite_pmc()->erase(get_dialog_administrators_database_key(dialog_id), Auto());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContactsManager::reload_dialog_administrators(DialogId dialog_id,
|
|
||||||
const vector<DialogAdministrator> &dialog_administrators,
|
|
||||||
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
|
|
||||||
auto dialog_type = dialog_id.get_type();
|
|
||||||
if (dialog_type == DialogType::Chat && !get_chat_permissions(dialog_id.get_chat_id()).is_member()) {
|
|
||||||
return promise.set_value(td_api::make_object<td_api::chatAdministrators>());
|
|
||||||
}
|
|
||||||
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_type) {
|
|
||||||
case DialogType::Chat:
|
|
||||||
load_chat_full(dialog_id.get_chat_id(), false, std::move(query_promise), "reload_dialog_administrators");
|
|
||||||
break;
|
|
||||||
case DialogType::Channel: {
|
|
||||||
auto channel_id = dialog_id.get_channel_id();
|
|
||||||
if (is_broadcast_channel(channel_id) && !get_channel_status(channel_id).is_administrator()) {
|
|
||||||
return query_promise.set_error(Status::Error(400, "Administrator list is inaccessible"));
|
|
||||||
}
|
|
||||||
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(channel_id, hash);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
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_get_chat_empty(telegram_api::chatEmpty &chat, const char *source) {
|
void ContactsManager::on_get_chat_empty(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()) {
|
||||||
|
@ -287,9 +287,6 @@ class ContactsManager final : public Actor {
|
|||||||
|
|
||||||
void on_update_bot_menu_button(UserId bot_user_id, tl_object_ptr<telegram_api::BotMenuButton> &&bot_menu_button);
|
void on_update_bot_menu_button(UserId bot_user_id, tl_object_ptr<telegram_api::BotMenuButton> &&bot_menu_button);
|
||||||
|
|
||||||
void on_update_dialog_administrators(DialogId dialog_id, vector<DialogAdministrator> &&administrators,
|
|
||||||
bool have_access, bool from_database);
|
|
||||||
|
|
||||||
void speculative_add_channel_participants(ChannelId channel_id, const vector<UserId> &added_user_ids,
|
void speculative_add_channel_participants(ChannelId channel_id, const vector<UserId> &added_user_ids,
|
||||||
UserId inviter_user_id, int32 date, bool by_me);
|
UserId inviter_user_id, int32 date, bool by_me);
|
||||||
|
|
||||||
@ -684,8 +681,6 @@ class ContactsManager final : public Actor {
|
|||||||
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantFilter filter,
|
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantFilter filter,
|
||||||
Promise<DialogParticipants> &&promise);
|
Promise<DialogParticipants> &&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,
|
||||||
Promise<DialogParticipants> &&promise);
|
Promise<DialogParticipants> &&promise);
|
||||||
@ -1776,24 +1771,6 @@ 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> get_chat_administrators_object(
|
|
||||||
const vector<DialogAdministrator> &dialog_administrators);
|
|
||||||
|
|
||||||
static string get_dialog_administrators_database_key(DialogId dialog_id);
|
|
||||||
|
|
||||||
void on_load_dialog_administrators_from_database(DialogId dialog_id, string value,
|
|
||||||
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
|
|
||||||
|
|
||||||
void on_load_administrator_users_finished(DialogId dialog_id, vector<DialogAdministrator> administrators,
|
|
||||||
Result<> result,
|
|
||||||
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&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);
|
||||||
|
|
||||||
void on_dismiss_suggested_action(SuggestedAction action, Result<Unit> &&result);
|
void on_dismiss_suggested_action(SuggestedAction action, Result<Unit> &&result);
|
||||||
@ -2022,8 +1999,6 @@ class ContactsManager final : public Actor {
|
|||||||
QueryCombiner get_user_full_queries_{"GetUserFullCombiner", 2.0};
|
QueryCombiner get_user_full_queries_{"GetUserFullCombiner", 2.0};
|
||||||
QueryCombiner get_chat_full_queries_{"GetChatFullCombiner", 2.0};
|
QueryCombiner get_chat_full_queries_{"GetChatFullCombiner", 2.0};
|
||||||
|
|
||||||
FlatHashMap<DialogId, vector<DialogAdministrator>, DialogIdHash> dialog_administrators_;
|
|
||||||
|
|
||||||
FlatHashMap<DialogId, vector<SuggestedAction>, DialogIdHash> dialog_suggested_actions_;
|
FlatHashMap<DialogId, vector<SuggestedAction>, DialogIdHash> dialog_suggested_actions_;
|
||||||
FlatHashMap<DialogId, vector<Promise<Unit>>, DialogIdHash> dismiss_suggested_action_queries_;
|
FlatHashMap<DialogId, vector<Promise<Unit>>, DialogIdHash> dismiss_suggested_action_queries_;
|
||||||
|
|
||||||
|
@ -10,15 +10,23 @@
|
|||||||
#include "td/telegram/ContactsManager.h"
|
#include "td/telegram/ContactsManager.h"
|
||||||
#include "td/telegram/DialogManager.h"
|
#include "td/telegram/DialogManager.h"
|
||||||
#include "td/telegram/Global.h"
|
#include "td/telegram/Global.h"
|
||||||
|
#include "td/telegram/logevent/LogEvent.h"
|
||||||
#include "td/telegram/MessagesManager.h"
|
#include "td/telegram/MessagesManager.h"
|
||||||
|
#include "td/telegram/misc.h"
|
||||||
#include "td/telegram/Td.h"
|
#include "td/telegram/Td.h"
|
||||||
|
#include "td/telegram/TdDb.h"
|
||||||
#include "td/telegram/UpdatesManager.h"
|
#include "td/telegram/UpdatesManager.h"
|
||||||
|
|
||||||
|
#include "td/db/SqliteKeyValueAsync.h"
|
||||||
|
|
||||||
|
#include "td/utils/algorithm.h"
|
||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
#include "td/utils/Time.h"
|
#include "td/utils/Time.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
class GetOnlinesQuery final : public Td::ResultHandler {
|
class GetOnlinesQuery final : public Td::ResultHandler {
|
||||||
@ -220,11 +228,87 @@ class HideAllChatJoinRequestsQuery final : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GetChannelAdministratorsQuery final : public Td::ResultHandler {
|
||||||
|
Promise<Unit> promise_;
|
||||||
|
ChannelId channel_id_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GetChannelAdministratorsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(ChannelId channel_id, int64 hash) {
|
||||||
|
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
|
||||||
|
if (input_channel == nullptr) {
|
||||||
|
return promise_.set_error(Status::Error(400, "Supergroup not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
hash = 0; // to load even only ranks or creator changed
|
||||||
|
|
||||||
|
channel_id_ = channel_id;
|
||||||
|
send_query(G()->net_query_creator().create(telegram_api::channels_getParticipants(
|
||||||
|
std::move(input_channel), telegram_api::make_object<telegram_api::channelParticipantsAdmins>(), 0,
|
||||||
|
std::numeric_limits<int32>::max(), hash)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::channels_getParticipants>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto participants_ptr = result_ptr.move_as_ok();
|
||||||
|
LOG(INFO) << "Receive result for GetChannelAdministratorsQuery: " << to_string(participants_ptr);
|
||||||
|
switch (participants_ptr->get_id()) {
|
||||||
|
case telegram_api::channels_channelParticipants::ID: {
|
||||||
|
auto participants = telegram_api::move_object_as<telegram_api::channels_channelParticipants>(participants_ptr);
|
||||||
|
td_->contacts_manager_->on_get_users(std::move(participants->users_), "GetChannelAdministratorsQuery");
|
||||||
|
td_->contacts_manager_->on_get_chats(std::move(participants->chats_), "GetChannelAdministratorsQuery");
|
||||||
|
|
||||||
|
auto channel_type = td_->contacts_manager_->get_channel_type(channel_id_);
|
||||||
|
vector<DialogAdministrator> administrators;
|
||||||
|
administrators.reserve(participants->participants_.size());
|
||||||
|
for (auto &participant : participants->participants_) {
|
||||||
|
DialogParticipant dialog_participant(std::move(participant), channel_type);
|
||||||
|
if (!dialog_participant.is_valid() || !dialog_participant.status_.is_administrator() ||
|
||||||
|
dialog_participant.dialog_id_.get_type() != DialogType::User) {
|
||||||
|
LOG(ERROR) << "Receive " << dialog_participant << " as an administrator of " << channel_id_;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
administrators.emplace_back(dialog_participant.dialog_id_.get_user_id(),
|
||||||
|
dialog_participant.status_.get_rank(), dialog_participant.status_.is_creator());
|
||||||
|
}
|
||||||
|
|
||||||
|
td_->contacts_manager_->on_update_channel_administrator_count(channel_id_,
|
||||||
|
narrow_cast<int32>(administrators.size()));
|
||||||
|
td_->dialog_participant_manager_->on_update_dialog_administrators(DialogId(channel_id_),
|
||||||
|
std::move(administrators), true, false);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case telegram_api::channels_channelParticipantsNotModified::ID:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_.set_value(Unit());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(Status status) final {
|
||||||
|
td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelAdministratorsQuery");
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
DialogParticipantManager::DialogParticipantManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
DialogParticipantManager::DialogParticipantManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||||
update_dialog_online_member_count_timeout_.set_callback(on_update_dialog_online_member_count_timeout_callback);
|
update_dialog_online_member_count_timeout_.set_callback(on_update_dialog_online_member_count_timeout_callback);
|
||||||
update_dialog_online_member_count_timeout_.set_callback_data(static_cast<void *>(this));
|
update_dialog_online_member_count_timeout_.set_callback_data(static_cast<void *>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DialogParticipantManager::~DialogParticipantManager() {
|
||||||
|
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_administrators_);
|
||||||
|
}
|
||||||
|
|
||||||
void DialogParticipantManager::tear_down() {
|
void DialogParticipantManager::tear_down() {
|
||||||
parent_.reset();
|
parent_.reset();
|
||||||
}
|
}
|
||||||
@ -458,4 +542,232 @@ void DialogParticipantManager::process_dialog_join_requests(DialogId dialog_id,
|
|||||||
td_->create_handler<HideAllChatJoinRequestsQuery>(std::move(promise))->send(dialog_id, invite_link, approve);
|
td_->create_handler<HideAllChatJoinRequestsQuery>(std::move(promise))->send(dialog_id, invite_link, approve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogParticipantManager::speculative_update_dialog_administrators(DialogId dialog_id, UserId user_id,
|
||||||
|
const DialogParticipantStatus &new_status,
|
||||||
|
const DialogParticipantStatus &old_status) {
|
||||||
|
if (new_status.is_administrator() == old_status.is_administrator() &&
|
||||||
|
new_status.get_rank() == old_status.get_rank()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto it = dialog_administrators_.find(dialog_id);
|
||||||
|
if (it == dialog_administrators_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto administrators = it->second;
|
||||||
|
if (new_status.is_administrator()) {
|
||||||
|
bool is_found = false;
|
||||||
|
for (auto &administrator : administrators) {
|
||||||
|
if (administrator.get_user_id() == user_id) {
|
||||||
|
is_found = true;
|
||||||
|
if (administrator.get_rank() != new_status.get_rank() ||
|
||||||
|
administrator.is_creator() != new_status.is_creator()) {
|
||||||
|
administrator = DialogAdministrator(user_id, new_status.get_rank(), new_status.is_creator());
|
||||||
|
on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!is_found) {
|
||||||
|
administrators.emplace_back(user_id, new_status.get_rank(), new_status.is_creator());
|
||||||
|
on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t i = 0;
|
||||||
|
while (i != administrators.size() && administrators[i].get_user_id() != user_id) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i != administrators.size()) {
|
||||||
|
administrators.erase(administrators.begin() + i);
|
||||||
|
on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::chatAdministrators> DialogParticipantManager::get_chat_administrators_object(
|
||||||
|
const vector<DialogAdministrator> &dialog_administrators) {
|
||||||
|
auto administrator_objects = transform(dialog_administrators, [this](const DialogAdministrator &administrator) {
|
||||||
|
return administrator.get_chat_administrator_object(td_->contacts_manager_.get());
|
||||||
|
});
|
||||||
|
return td_api::make_object<td_api::chatAdministrators>(std::move(administrator_objects));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogParticipantManager::get_dialog_administrators(
|
||||||
|
DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
|
||||||
|
if (!td_->dialog_manager_->have_dialog_force(dialog_id, "get_dialog_administrators")) {
|
||||||
|
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dialog_id.get_type()) {
|
||||||
|
case DialogType::User:
|
||||||
|
case DialogType::SecretChat:
|
||||||
|
return promise.set_value(td_api::make_object<td_api::chatAdministrators>());
|
||||||
|
case DialogType::Chat:
|
||||||
|
case DialogType::Channel:
|
||||||
|
break;
|
||||||
|
case DialogType::None:
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = dialog_administrators_.find(dialog_id);
|
||||||
|
if (it != dialog_administrators_.end()) {
|
||||||
|
reload_dialog_administrators(dialog_id, it->second, Auto()); // update administrators cache
|
||||||
|
return promise.set_value(get_chat_administrators_object(it->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G()->use_chat_info_database()) {
|
||||||
|
LOG(INFO) << "Load administrators of " << dialog_id << " from database";
|
||||||
|
G()->td_db()->get_sqlite_pmc()->get(
|
||||||
|
get_dialog_administrators_database_key(dialog_id),
|
||||||
|
PromiseCreator::lambda(
|
||||||
|
[actor_id = actor_id(this), dialog_id, promise = std::move(promise)](string value) mutable {
|
||||||
|
send_closure(actor_id, &DialogParticipantManager::on_load_dialog_administrators_from_database, dialog_id,
|
||||||
|
std::move(value), std::move(promise));
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reload_dialog_administrators(dialog_id, {}, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
string DialogParticipantManager::get_dialog_administrators_database_key(DialogId dialog_id) {
|
||||||
|
return PSTRING() << "adm" << (-dialog_id.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogParticipantManager::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;
|
||||||
|
if (log_event_parse(administrators, value).is_error()) {
|
||||||
|
return reload_dialog_administrators(dialog_id, {}, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Successfully loaded " << administrators.size() << " administrators in " << dialog_id
|
||||||
|
<< " from database";
|
||||||
|
|
||||||
|
MultiPromiseActorSafe load_users_multipromise{"LoadUsersMultiPromiseActor"};
|
||||||
|
load_users_multipromise.add_promise(
|
||||||
|
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, administrators,
|
||||||
|
promise = std::move(promise)](Result<Unit> result) mutable {
|
||||||
|
send_closure(actor_id, &DialogParticipantManager::on_load_administrator_users_finished, dialog_id,
|
||||||
|
std::move(administrators), std::move(result), std::move(promise));
|
||||||
|
}));
|
||||||
|
|
||||||
|
auto lock_promise = load_users_multipromise.get_promise();
|
||||||
|
|
||||||
|
for (auto &administrator : administrators) {
|
||||||
|
td_->contacts_manager_->get_user(administrator.get_user_id(), 3, load_users_multipromise.get_promise());
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_promise.set_value(Unit());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogParticipantManager::on_load_administrator_users_finished(
|
||||||
|
DialogId dialog_id, vector<DialogAdministrator> administrators, Result<> result,
|
||||||
|
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
|
||||||
|
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||||
|
|
||||||
|
if (result.is_error()) {
|
||||||
|
return reload_dialog_administrators(dialog_id, {}, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
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 DialogParticipantManager::on_update_dialog_administrators(DialogId dialog_id,
|
||||||
|
vector<DialogAdministrator> &&administrators,
|
||||||
|
bool have_access, bool from_database) {
|
||||||
|
LOG(INFO) << "Update administrators in " << dialog_id << " to " << format::as_array(administrators);
|
||||||
|
if (have_access) {
|
||||||
|
CHECK(dialog_id.is_valid());
|
||||||
|
std::sort(administrators.begin(), administrators.end(),
|
||||||
|
[](const DialogAdministrator &lhs, const DialogAdministrator &rhs) {
|
||||||
|
return lhs.get_user_id().get() < rhs.get_user_id().get();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto it = dialog_administrators_.find(dialog_id);
|
||||||
|
if (it != dialog_administrators_.end()) {
|
||||||
|
if (it->second == administrators) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
it->second = std::move(administrators);
|
||||||
|
} else {
|
||||||
|
it = dialog_administrators_.emplace(dialog_id, std::move(administrators)).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G()->use_chat_info_database() && !from_database) {
|
||||||
|
LOG(INFO) << "Save administrators of " << dialog_id << " to database";
|
||||||
|
G()->td_db()->get_sqlite_pmc()->set(get_dialog_administrators_database_key(dialog_id),
|
||||||
|
log_event_store(it->second).as_slice().str(), Auto());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dialog_administrators_.erase(dialog_id);
|
||||||
|
if (G()->use_chat_info_database()) {
|
||||||
|
G()->td_db()->get_sqlite_pmc()->erase(get_dialog_administrators_database_key(dialog_id), Auto());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogParticipantManager::reload_dialog_administrators(
|
||||||
|
DialogId dialog_id, const vector<DialogAdministrator> &dialog_administrators,
|
||||||
|
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
|
||||||
|
auto dialog_type = dialog_id.get_type();
|
||||||
|
if (dialog_type == DialogType::Chat &&
|
||||||
|
!td_->contacts_manager_->get_chat_permissions(dialog_id.get_chat_id()).is_member()) {
|
||||||
|
return promise.set_value(td_api::make_object<td_api::chatAdministrators>());
|
||||||
|
}
|
||||||
|
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, &DialogParticipantManager::on_reload_dialog_administrators, dialog_id,
|
||||||
|
std::move(promise));
|
||||||
|
} else {
|
||||||
|
promise.set_error(result.move_as_error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
switch (dialog_type) {
|
||||||
|
case DialogType::Chat:
|
||||||
|
td_->contacts_manager_->load_chat_full(dialog_id.get_chat_id(), false, std::move(query_promise),
|
||||||
|
"reload_dialog_administrators");
|
||||||
|
break;
|
||||||
|
case DialogType::Channel: {
|
||||||
|
auto channel_id = dialog_id.get_channel_id();
|
||||||
|
if (td_->contacts_manager_->is_broadcast_channel(channel_id) &&
|
||||||
|
!td_->contacts_manager_->get_channel_status(channel_id).is_administrator()) {
|
||||||
|
return query_promise.set_error(Status::Error(400, "Administrator list is inaccessible"));
|
||||||
|
}
|
||||||
|
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(channel_id, hash);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogParticipantManager::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"));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/telegram/DialogAdministrator.h"
|
||||||
#include "td/telegram/DialogId.h"
|
#include "td/telegram/DialogId.h"
|
||||||
|
#include "td/telegram/DialogParticipant.h"
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
@ -24,6 +26,11 @@ class Td;
|
|||||||
class DialogParticipantManager final : public Actor {
|
class DialogParticipantManager final : public Actor {
|
||||||
public:
|
public:
|
||||||
DialogParticipantManager(Td *td, ActorShared<> parent);
|
DialogParticipantManager(Td *td, ActorShared<> parent);
|
||||||
|
DialogParticipantManager(const DialogParticipantManager &) = delete;
|
||||||
|
DialogParticipantManager &operator=(const DialogParticipantManager &) = delete;
|
||||||
|
DialogParticipantManager(DialogParticipantManager &&) = delete;
|
||||||
|
DialogParticipantManager &operator=(DialogParticipantManager &&) = delete;
|
||||||
|
~DialogParticipantManager() final;
|
||||||
|
|
||||||
static constexpr int32 ONLINE_MEMBER_COUNT_CACHE_EXPIRE_TIME = 30 * 60;
|
static constexpr int32 ONLINE_MEMBER_COUNT_CACHE_EXPIRE_TIME = 30 * 60;
|
||||||
|
|
||||||
@ -42,6 +49,18 @@ class DialogParticipantManager final : public Actor {
|
|||||||
void process_dialog_join_requests(DialogId dialog_id, const string &invite_link, bool approve,
|
void process_dialog_join_requests(DialogId dialog_id, const string &invite_link, bool approve,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void speculative_update_dialog_administrators(DialogId dialog_id, UserId user_id,
|
||||||
|
const DialogParticipantStatus &new_status,
|
||||||
|
const DialogParticipantStatus &old_status);
|
||||||
|
|
||||||
|
void on_update_dialog_administrators(DialogId dialog_id, vector<DialogAdministrator> &&administrators,
|
||||||
|
bool have_access, bool from_database);
|
||||||
|
|
||||||
|
void get_dialog_administrators(DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
|
||||||
|
|
||||||
|
void reload_dialog_administrators(DialogId dialog_id, const vector<DialogAdministrator> &dialog_administrators,
|
||||||
|
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
|
||||||
|
|
||||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -61,6 +80,21 @@ class DialogParticipantManager final : public Actor {
|
|||||||
|
|
||||||
Status can_manage_dialog_join_requests(DialogId dialog_id);
|
Status can_manage_dialog_join_requests(DialogId dialog_id);
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::chatAdministrators> get_chat_administrators_object(
|
||||||
|
const vector<DialogAdministrator> &dialog_administrators);
|
||||||
|
|
||||||
|
static string get_dialog_administrators_database_key(DialogId dialog_id);
|
||||||
|
|
||||||
|
void on_load_dialog_administrators_from_database(DialogId dialog_id, string value,
|
||||||
|
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
|
||||||
|
|
||||||
|
void on_load_administrator_users_finished(DialogId dialog_id, vector<DialogAdministrator> administrators,
|
||||||
|
Result<Unit> result,
|
||||||
|
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);
|
||||||
|
|
||||||
struct OnlineMemberCountInfo {
|
struct OnlineMemberCountInfo {
|
||||||
int32 online_member_count = 0;
|
int32 online_member_count = 0;
|
||||||
double update_time = 0;
|
double update_time = 0;
|
||||||
@ -70,6 +104,8 @@ class DialogParticipantManager final : public Actor {
|
|||||||
|
|
||||||
MultiTimeout update_dialog_online_member_count_timeout_{"UpdateDialogOnlineMemberCountTimeout"};
|
MultiTimeout update_dialog_online_member_count_timeout_{"UpdateDialogOnlineMemberCountTimeout"};
|
||||||
|
|
||||||
|
FlatHashMap<DialogId, vector<DialogAdministrator>, DialogIdHash> dialog_administrators_;
|
||||||
|
|
||||||
Td *td_;
|
Td *td_;
|
||||||
ActorShared<> parent_;
|
ActorShared<> parent_;
|
||||||
};
|
};
|
||||||
|
@ -7009,7 +7009,7 @@ 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_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
contacts_manager_->get_dialog_administrators(DialogId(request.chat_id_), std::move(promise));
|
dialog_participant_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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user