diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 19b017c6c..656a43af1 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -2942,8 +2942,8 @@ ContactsManager::~ContactsManager() { Scheduler::instance()->destroy_on_scheduler( 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_, - loaded_from_database_secret_chats_, cached_channel_participants_, resolved_phone_numbers_, all_imported_contacts_, - linked_channel_ids_, restricted_user_ids_, restricted_channel_ids_); + loaded_from_database_secret_chats_, resolved_phone_numbers_, all_imported_contacts_, linked_channel_ids_, + restricted_user_ids_, restricted_channel_ids_); } void ContactsManager::start_up() { @@ -13062,27 +13062,6 @@ void ContactsManager::update_chat_online_member_count(const ChatFull *chat_full, is_from_server); } -void ContactsManager::update_channel_online_member_count(ChannelId channel_id, bool is_from_server) { - if (!is_megagroup_channel(channel_id) || - get_channel_effective_has_hidden_participants(channel_id, "update_channel_online_member_count")) { - return; - } - - auto it = cached_channel_participants_.find(channel_id); - if (it == cached_channel_participants_.end()) { - return; - } - td_->dialog_participant_manager_->update_dialog_online_member_count(it->second, DialogId(channel_id), is_from_server); -} - -void ContactsManager::set_cached_channel_participants(ChannelId channel_id, vector participants) { - cached_channel_participants_[channel_id] = std::move(participants); -} - -void ContactsManager::drop_cached_channel_participants(ChannelId channel_id) { - cached_channel_participants_.erase(channel_id); -} - void ContactsManager::on_get_chat_participants(tl_object_ptr &&participants_ptr, bool from_update) { switch (participants_ptr->get_id()) { @@ -13292,9 +13271,8 @@ bool ContactsManager::speculative_add_count(int32 &count, int32 delta_count, int void ContactsManager::speculative_add_channel_participants(ChannelId channel_id, const vector &added_user_ids, UserId inviter_user_id, int32 date, bool by_me) { - auto it = cached_channel_participants_.find(channel_id); + td_->dialog_participant_manager_->add_cached_channel_participants(channel_id, added_user_ids, inviter_user_id, date); auto channel_full = get_channel_full_force(channel_id, true, "speculative_add_channel_participants"); - bool is_participants_cache_changed = false; int32 delta_participant_count = 0; for (auto user_id : added_user_ids) { @@ -13303,22 +13281,6 @@ void ContactsManager::speculative_add_channel_participants(ChannelId channel_id, } delta_participant_count++; - - if (it != cached_channel_participants_.end()) { - auto &participants = it->second; - bool is_found = false; - for (auto &participant : participants) { - if (participant.dialog_id_ == DialogId(user_id)) { - is_found = true; - break; - } - } - if (!is_found) { - is_participants_cache_changed = true; - participants.emplace_back(DialogId(user_id), inviter_user_id, date, DialogParticipantStatus::Member()); - } - } - if (channel_full != nullptr && is_user_bot(user_id) && !td::contains(channel_full->bot_user_ids, user_id)) { channel_full->bot_user_ids.push_back(user_id); channel_full->need_save_to_database = true; @@ -13328,9 +13290,6 @@ void ContactsManager::speculative_add_channel_participants(ChannelId channel_id, channel_full->bot_user_ids, false); } } - if (is_participants_cache_changed) { - update_channel_online_member_count(channel_id, false); - } if (channel_full != nullptr) { if (channel_full->is_changed) { channel_full->speculative_version++; @@ -13349,17 +13308,7 @@ void ContactsManager::speculative_delete_channel_participant(ChannelId channel_i return; } - auto it = cached_channel_participants_.find(channel_id); - if (it != cached_channel_participants_.end()) { - auto &participants = it->second; - for (size_t i = 0; i < participants.size(); i++) { - if (participants[i].dialog_id_ == DialogId(deleted_user_id)) { - participants.erase(participants.begin() + i); - update_channel_online_member_count(channel_id, false); - break; - } - } - } + td_->dialog_participant_manager_->delete_cached_channel_participant(channel_id, deleted_user_id); if (is_user_bot(deleted_user_id)) { auto channel_full = get_channel_full_force(channel_id, true, "speculative_delete_channel_participant"); @@ -13429,27 +13378,7 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId update_channel(c, channel_id); } - auto it = cached_channel_participants_.find(channel_id); - if (it != cached_channel_participants_.end()) { - auto &participants = it->second; - bool is_found = false; - for (size_t i = 0; i < participants.size(); i++) { - if (participants[i].dialog_id_ == DialogId(user_id)) { - if (!new_status.is_member()) { - participants.erase(participants.begin() + i); - update_channel_online_member_count(channel_id, false); - } else { - participants[i].status_ = new_status; - } - is_found = true; - break; - } - } - if (!is_found && new_status.is_member()) { - participants.emplace_back(DialogId(user_id), get_my_id(), G()->unix_time(), new_status); - update_channel_online_member_count(channel_id, false); - } - } + td_->dialog_participant_manager_->update_cached_channel_participant_status(channel_id, user_id, new_status); if (channel_full == nullptr) { return; diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 8f811b2ac..c1045dd29 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -354,14 +354,8 @@ class ContactsManager final : public Actor { void update_chat_online_member_count(ChatId chat_id, bool is_from_server); - void update_channel_online_member_count(ChannelId channel_id, bool is_from_server); - void on_update_channel_bot_user_ids(ChannelId channel_id, vector &&bot_user_ids); - void set_cached_channel_participants(ChannelId channel_id, vector participants); - - void drop_cached_channel_participants(ChannelId channel_id); - void on_update_username_is_active(UserId user_id, string &&username, bool is_active, Promise &&promise); void on_update_active_usernames_order(UserId user_id, vector &&usernames, Promise &&promise); @@ -1930,8 +1924,6 @@ class ContactsManager final : public Actor { FlatHashMap, vector>> imported_contacts_; - FlatHashMap, ChannelIdHash> cached_channel_participants_; - FlatHashMap resolved_phone_numbers_; FlatHashMap, UserIdHash> user_messages_; diff --git a/td/telegram/DialogParticipantManager.cpp b/td/telegram/DialogParticipantManager.cpp index f0dedd2a5..e22bff566 100644 --- a/td/telegram/DialogParticipantManager.cpp +++ b/td/telegram/DialogParticipantManager.cpp @@ -836,7 +836,8 @@ DialogParticipantManager::DialogParticipantManager(Td *td, ActorShared<> parent) DialogParticipantManager::~DialogParticipantManager() { Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), user_online_member_dialogs_, - dialog_administrators_, channel_participants_); + dialog_administrators_, channel_participants_, + cached_channel_participants_); } void DialogParticipantManager::tear_down() { @@ -1022,7 +1023,7 @@ void DialogParticipantManager::update_user_online_member_count(UserId user_id) { td_->contacts_manager_->update_chat_online_member_count(dialog_id.get_chat_id(), false); break; case DialogType::Channel: - td_->contacts_manager_->update_channel_online_member_count(dialog_id.get_channel_id(), false); + update_channel_online_member_count(dialog_id.get_channel_id(), false); break; case DialogType::User: case DialogType::SecretChat: @@ -1034,7 +1035,7 @@ void DialogParticipantManager::update_user_online_member_count(UserId user_id) { for (auto &dialog_id : expired_dialog_ids) { online_member_dialogs.erase(dialog_id); if (dialog_id.get_type() == DialogType::Channel) { - td_->contacts_manager_->drop_cached_channel_participants(dialog_id.get_channel_id()); + drop_cached_channel_participants(dialog_id.get_channel_id()); } } if (online_member_dialogs.empty()) { @@ -1042,6 +1043,20 @@ void DialogParticipantManager::update_user_online_member_count(UserId user_id) { } } +void DialogParticipantManager::update_channel_online_member_count(ChannelId channel_id, bool is_from_server) { + if (!td_->contacts_manager_->is_megagroup_channel(channel_id) || + td_->contacts_manager_->get_channel_effective_has_hidden_participants(channel_id, + "update_channel_online_member_count")) { + return; + } + + auto it = cached_channel_participants_.find(channel_id); + if (it == cached_channel_participants_.end()) { + return; + } + update_dialog_online_member_count(it->second, DialogId(channel_id), is_from_server); +} + void DialogParticipantManager::update_dialog_online_member_count(const vector &participants, DialogId dialog_id, bool is_from_server) { if (td_->auth_manager_->is_bot()) { @@ -1873,8 +1888,8 @@ void DialogParticipantManager::on_get_channel_participants( administrator_count = narrow_cast(administrators.size()); if (is_megagroup && !td_->auth_manager_->is_bot() && is_full_recent) { - td_->contacts_manager_->set_cached_channel_participants(channel_id, result); - td_->contacts_manager_->update_channel_online_member_count(channel_id, true); + set_cached_channel_participants(channel_id, result); + update_channel_online_member_count(channel_id, true); } } else if (filter.is_administrators()) { for (const auto &participant : result) { @@ -2780,6 +2795,91 @@ const DialogParticipant *DialogParticipantManager::get_channel_participant_from_ return nullptr; } +void DialogParticipantManager::set_cached_channel_participants(ChannelId channel_id, + vector participants) { + cached_channel_participants_[channel_id] = std::move(participants); +} + +void DialogParticipantManager::drop_cached_channel_participants(ChannelId channel_id) { + cached_channel_participants_.erase(channel_id); +} + +void DialogParticipantManager::add_cached_channel_participants(ChannelId channel_id, + const vector &added_user_ids, + UserId inviter_user_id, int32 date) { + auto it = cached_channel_participants_.find(channel_id); + if (it == cached_channel_participants_.end()) { + return; + } + auto &participants = it->second; + bool is_participants_cache_changed = false; + for (auto user_id : added_user_ids) { + if (!user_id.is_valid()) { + continue; + } + + bool is_found = false; + for (const auto &participant : participants) { + if (participant.dialog_id_ == DialogId(user_id)) { + is_found = true; + break; + } + } + if (!is_found) { + is_participants_cache_changed = true; + participants.emplace_back(DialogId(user_id), inviter_user_id, date, DialogParticipantStatus::Member()); + } + } + if (is_participants_cache_changed) { + update_channel_online_member_count(channel_id, false); + } +} + +void DialogParticipantManager::delete_cached_channel_participant(ChannelId channel_id, UserId deleted_user_id) { + if (!deleted_user_id.is_valid()) { + return; + } + + auto it = cached_channel_participants_.find(channel_id); + if (it == cached_channel_participants_.end()) { + return; + } + auto &participants = it->second; + for (size_t i = 0; i < participants.size(); i++) { + if (participants[i].dialog_id_ == DialogId(deleted_user_id)) { + participants.erase(participants.begin() + i); + update_channel_online_member_count(channel_id, false); + break; + } + } +} + +void DialogParticipantManager::update_cached_channel_participant_status(ChannelId channel_id, UserId user_id, + const DialogParticipantStatus &status) { + auto it = cached_channel_participants_.find(channel_id); + if (it == cached_channel_participants_.end()) { + return; + } + auto &participants = it->second; + bool is_found = false; + for (size_t i = 0; i < participants.size(); i++) { + if (participants[i].dialog_id_ == DialogId(user_id)) { + if (!status.is_member()) { + participants.erase(participants.begin() + i); + update_channel_online_member_count(channel_id, false); + } else { + participants[i].status_ = status; + } + is_found = true; + break; + } + } + if (!is_found && status.is_member()) { + participants.emplace_back(DialogId(user_id), td_->contacts_manager_->get_my_id(), G()->unix_time(), status); + update_channel_online_member_count(channel_id, false); + } +} + void DialogParticipantManager::can_transfer_ownership(Promise &&promise) { auto request_promise = PromiseCreator::lambda([promise = std::move(promise)](Result r_result) mutable { CHECK(r_result.is_error()); diff --git a/td/telegram/DialogParticipantManager.h b/td/telegram/DialogParticipantManager.h index b28427867..c7b554e1f 100644 --- a/td/telegram/DialogParticipantManager.h +++ b/td/telegram/DialogParticipantManager.h @@ -49,6 +49,14 @@ class DialogParticipantManager final : public Actor { void on_update_dialog_online_member_count(DialogId dialog_id, int32 online_member_count, bool is_from_server); + void add_cached_channel_participants(ChannelId channel_id, const vector &added_user_ids, + UserId inviter_user_id, int32 date); + + void delete_cached_channel_participant(ChannelId channel_id, UserId deleted_user_id); + + void update_cached_channel_participant_status(ChannelId channel_id, UserId user_id, + const DialogParticipantStatus &status); + void on_dialog_opened(DialogId dialog_id); void on_dialog_closed(DialogId dialog_id); @@ -254,6 +262,12 @@ class DialogParticipantManager final : public Actor { void on_channel_participant_cache_timeout(ChannelId channel_id); + void set_cached_channel_participants(ChannelId channel_id, vector participants); + + void drop_cached_channel_participants(ChannelId channel_id); + + void update_channel_online_member_count(ChannelId channel_id, bool is_from_server); + void transfer_channel_ownership(ChannelId channel_id, UserId user_id, tl_object_ptr input_check_password, Promise &&promise); @@ -283,6 +297,8 @@ class DialogParticipantManager final : public Actor { }; FlatHashMap channel_participants_; + FlatHashMap, ChannelIdHash> cached_channel_participants_; + FlatHashMap>, ChannelIdHash> join_channel_queries_; MultiTimeout update_dialog_online_member_count_timeout_{"UpdateDialogOnlineMemberCountTimeout"};