From 44e96081c6b493db9972110d811cf8cd5ef30073 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 6 Aug 2022 13:42:35 +0300 Subject: [PATCH] Support file reference repair for bot description photo and animation. --- td/telegram/ContactsManager.cpp | 69 ++++++++++++++++++++++++---- td/telegram/ContactsManager.h | 7 ++- td/telegram/FileReferenceManager.cpp | 9 ++++ td/telegram/FileReferenceManager.h | 13 ++++-- td/telegram/FileReferenceManager.hpp | 8 +++- td/telegram/MessagesManager.cpp | 11 +++-- 6 files changed, 96 insertions(+), 21 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index b01881786..4a76a5c01 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -3401,8 +3401,8 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent ContactsManager::~ContactsManager() { Scheduler::instance()->destroy_on_scheduler( G()->get_gc_scheduler_id(), users_, users_full_, user_photos_, unknown_users_, pending_user_photos_, - user_profile_photo_file_source_ids_, my_photo_file_id_, chats_, chats_full_, unknown_chats_, - chat_full_file_source_ids_, min_channels_, channels_, channels_full_, unknown_channels_, + user_profile_photo_file_source_ids_, my_photo_file_id_, user_full_file_source_ids_, chats_, chats_full_, + unknown_chats_, chat_full_file_source_ids_, min_channels_, channels_, channels_full_, unknown_channels_, invalidated_channels_full_, channel_full_file_source_ids_, secret_chats_, unknown_secret_chats_, secret_chats_with_user_, invite_link_infos_, dialog_access_by_invite_link_, loaded_from_database_users_, unavailable_user_fulls_, loaded_from_database_chats_, unavailable_chat_fulls_, loaded_from_database_channels_, @@ -10562,6 +10562,33 @@ void ContactsManager::update_user_full(UserFull *user_full, UserId user_id, cons td_->messages_manager_->drop_common_dialogs_cache(user_id); user_full->is_common_chat_count_changed = false; } + if (user_full->are_files_changed) { + auto file_ids = photo_get_file_ids(user_full->description_photo); + if (user_full->description_animation_file_id.is_valid()) { + file_ids.push_back(user_full->description_animation_file_id); + } + if (user_full->registered_file_ids != file_ids) { + auto &file_source_id = user_full->file_source_id; + if (!file_source_id.is_valid()) { + file_source_id = user_full_file_source_ids_.get(user_id); + if (file_source_id.is_valid()) { + VLOG(file_references) << "Move " << file_source_id << " inside of " << user_id; + user_full_file_source_ids_.erase(user_id); + } else { + VLOG(file_references) << "Need to create new file source for full " << user_id; + file_source_id = td_->file_reference_manager_->create_user_full_file_source(user_id); + } + } + + for (auto &file_id : user_full->registered_file_ids) { + td_->file_manager_->remove_file_source(file_id, file_source_id); + } + user_full->registered_file_ids = std::move(file_ids); + for (auto &file_id : user_full->registered_file_ids) { + td_->file_manager_->add_file_source(file_id, file_source_id); + } + } + } user_full->need_send_update |= user_full->is_changed; user_full->need_save_to_database |= user_full->is_changed; @@ -10838,11 +10865,15 @@ void ContactsManager::on_get_user_full(tl_object_ptr &&u on_update_user_full_commands(user_full, user_id, std::move(user->bot_info_->commands_)); on_update_user_full_menu_button(user_full, user_id, std::move(user->bot_info_->menu_button_)); } - if (user_full->description != description || user_full->description_photo != description_photo || - user_full->description_animation_file_id != description_animation_file_id) { + if (user_full->description != description) { user_full->description = std::move(description); + user_full->is_changed = true; + } + if (user_full->description_photo != description_photo || + user_full->description_animation_file_id != description_animation_file_id) { user_full->description_photo = std::move(description_photo); user_full->description_animation_file_id = description_animation_file_id; + user_full->are_files_changed = true; user_full->is_changed = true; } @@ -12093,7 +12124,7 @@ void ContactsManager::drop_user_photos(UserId user_id, bool is_empty, bool drop_ user_full->expires_at = 0.0; user_full->need_save_to_database = true; } - reload_user_full(user_id); + reload_user_full(user_id, Auto()); } update_user_full(user_full, user_id, "drop_user_photos"); } @@ -12129,6 +12160,7 @@ void ContactsManager::drop_user_full(UserId user_id) { user_full->broadcast_administrator_rights = {}; user_full->premium_gift_options.clear(); user_full->voice_messages_forbidden = false; + user_full->are_files_changed = true; user_full->is_changed = true; update_user_full(user_full, user_id, "drop_user_full"); @@ -14596,11 +14628,9 @@ void ContactsManager::load_user_full(UserId user_id, bool force, Promise & promise.set_value(Unit()); } -void ContactsManager::reload_user_full(UserId user_id) { - auto r_input_user = get_input_user(user_id); - if (r_input_user.is_ok()) { - send_get_user_full_query(user_id, r_input_user.move_as_ok(), Auto(), "reload_user_full"); - } +void ContactsManager::reload_user_full(UserId user_id, Promise &&promise) { + TRY_RESULT_PROMISE(promise, input_user, get_input_user(user_id)); + send_get_user_full_query(user_id, std::move(input_user), std::move(promise), "reload_user_full"); } void ContactsManager::send_get_user_full_query(UserId user_id, tl_object_ptr &&input_user, @@ -14725,6 +14755,25 @@ FileSourceId ContactsManager::get_user_profile_photo_file_source_id(UserId user_ return source_id; } +FileSourceId ContactsManager::get_user_full_file_source_id(UserId user_id) { + if (!user_id.is_valid()) { + return FileSourceId(); + } + + if (get_user_full(user_id) != nullptr) { + VLOG(file_references) << "Don't need to create file source for full " << user_id; + // user full was already added, source ID was registered and shouldn't be needed + return FileSourceId(); + } + + auto &source_id = user_full_file_source_ids_[user_id]; + if (!source_id.is_valid()) { + source_id = td_->file_reference_manager_->create_user_full_file_source(user_id); + } + VLOG(file_references) << "Return " << source_id << " for full " << user_id; + return source_id; +} + FileSourceId ContactsManager::get_chat_full_file_source_id(ChatId chat_id) { if (!chat_id.is_valid()) { return FileSourceId(); diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index f049de409..835fb843f 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -492,7 +492,8 @@ class ContactsManager final : public Actor { bool get_user(UserId user_id, int left_tries, Promise &&promise); void reload_user(UserId user_id, Promise &&promise); void load_user_full(UserId user_id, bool force, Promise &&promise, const char *source); - void reload_user_full(UserId user_id); + FileSourceId get_user_full_file_source_id(UserId user_id); + void reload_user_full(UserId user_id, Promise &&promise); std::pair> get_user_profile_photos(UserId user_id, int32 offset, int32 limit, Promise &&promise); @@ -717,6 +718,8 @@ class ContactsManager final : public Actor { string description; Photo description_photo; FileId description_animation_file_id; + vector registered_file_ids; + FileSourceId file_source_id; vector premium_gift_options; @@ -736,6 +739,7 @@ class ContactsManager final : public Actor { bool voice_messages_forbidden = false; bool is_common_chat_count_changed = true; + bool are_files_changed = true; bool is_changed = true; // have new changes that need to be sent to the client and database bool need_send_update = true; // have new changes that need only to be sent to the client bool need_save_to_database = true; // have new changes that need only to be saved to the database @@ -1703,6 +1707,7 @@ class ContactsManager final : public Actor { }; WaitFreeHashMap, FileSourceId, UserIdPhotoIdHash> user_profile_photo_file_source_ids_; FlatHashMap my_photo_file_id_; + WaitFreeHashMap user_full_file_source_ids_; WaitFreeHashMap, ChatIdHash> chats_; WaitFreeHashMap, ChatIdHash> chats_full_; diff --git a/td/telegram/FileReferenceManager.cpp b/td/telegram/FileReferenceManager.cpp index f757e6c78..d5785369c 100644 --- a/td/telegram/FileReferenceManager.cpp +++ b/td/telegram/FileReferenceManager.cpp @@ -115,6 +115,11 @@ FileSourceId FileReferenceManager::create_background_file_source(BackgroundId ba return add_file_source_id(source, PSLICE() << background_id); } +FileSourceId FileReferenceManager::create_user_full_file_source(UserId user_id) { + FileSourceUserFull source{user_id}; + return add_file_source_id(source, PSLICE() << "full " << user_id); +} + FileSourceId FileReferenceManager::create_chat_full_file_source(ChatId chat_id) { FileSourceChatFull source{chat_id}; return add_file_source_id(source, PSLICE() << "full " << chat_id); @@ -320,6 +325,10 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source [&](const FileSourceSavedRingtones &source) { send_closure_later(G()->notification_settings_manager(), &NotificationSettingsManager::repair_saved_ringtones, std::move(promise)); + }, + [&](const FileSourceUserFull &source) { + send_closure_later(G()->contacts_manager(), &ContactsManager::reload_user_full, source.user_id, + std::move(promise)); })); } diff --git a/td/telegram/FileReferenceManager.h b/td/telegram/FileReferenceManager.h index e77e70d9e..99c60d84a 100644 --- a/td/telegram/FileReferenceManager.h +++ b/td/telegram/FileReferenceManager.h @@ -57,6 +57,7 @@ class FileReferenceManager final : public Actor { FileSourceId create_recent_stickers_file_source(bool is_attached); FileSourceId create_favorite_stickers_file_source(); FileSourceId create_background_file_source(BackgroundId background_id, int64 access_hash); + FileSourceId create_user_full_file_source(UserId user_id); FileSourceId create_chat_full_file_source(ChatId chat_id); FileSourceId create_channel_full_file_source(ChannelId channel_id); FileSourceId create_app_config_file_source(); @@ -156,12 +157,16 @@ class FileReferenceManager final : public Actor { struct FileSourceSavedRingtones { // empty }; + struct FileSourceUserFull { + UserId user_id; + }; // append only - using FileSource = Variant; + using FileSource = + Variant; WaitFreeVector file_sources_; int64 query_generation_{0}; diff --git a/td/telegram/FileReferenceManager.hpp b/td/telegram/FileReferenceManager.hpp index fc533955a..3821c214f 100644 --- a/td/telegram/FileReferenceManager.hpp +++ b/td/telegram/FileReferenceManager.hpp @@ -51,7 +51,8 @@ void FileReferenceManager::store_file_source(FileSourceId file_source_id, Storer }, [&](const FileSourceChatFull &source) { td::store(source.chat_id, storer); }, [&](const FileSourceChannelFull &source) { td::store(source.channel_id, storer); }, - [&](const FileSourceAppConfig &source) {}, [&](const FileSourceSavedRingtones &source) {})); + [&](const FileSourceAppConfig &source) {}, [&](const FileSourceSavedRingtones &source) {}, + [&](const FileSourceUserFull &source) { td::store(source.user_id, storer); })); } template @@ -117,6 +118,11 @@ FileSourceId FileReferenceManager::parse_file_source(Td *td, ParserT &parser) { return td->stickers_manager_->get_app_config_file_source_id(); case 13: return td->notification_settings_manager_->get_saved_ringtones_file_source_id(); + case 14: { + UserId user_id; + td::parse(user_id, parser); + return td->contacts_manager_->get_user_full_file_source_id(user_id); + } default: parser.set_error("Invalid type in FileSource"); return FileSourceId(); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 81775472e..9896c8231 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8451,7 +8451,7 @@ void MessagesManager::reget_dialog_action_bar(DialogId dialog_id, const char *so LOG(INFO) << "Reget action bar in " << dialog_id << " from " << source; switch (dialog_id.get_type()) { case DialogType::User: - td_->contacts_manager_->reload_user_full(dialog_id.get_user_id()); + td_->contacts_manager_->reload_user_full(dialog_id.get_user_id(), Auto()); return; case DialogType::Chat: case DialogType::Channel: @@ -18453,7 +18453,8 @@ void MessagesManager::reload_dialog_info_full(DialogId dialog_id, const char *so LOG(INFO) << "Reload full info about " << dialog_id << " from " << source; switch (dialog_id.get_type()) { case DialogType::User: - send_closure_later(td_->contacts_manager_actor_, &ContactsManager::reload_user_full, dialog_id.get_user_id()); + send_closure_later(td_->contacts_manager_actor_, &ContactsManager::reload_user_full, dialog_id.get_user_id(), + Promise()); return; case DialogType::Chat: send_closure_later(td_->contacts_manager_actor_, &ContactsManager::reload_chat_full, dialog_id.get_chat_id(), @@ -21106,7 +21107,7 @@ void MessagesManager::open_dialog(Dialog *d) { // to repair dialog action bar auto user_id = td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id()); if (user_id.is_valid()) { - td_->contacts_manager_->reload_user_full(user_id); + td_->contacts_manager_->reload_user_full(user_id, Promise()); } break; } @@ -34958,7 +34959,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq switch (dialog_type) { case DialogType::User: td_->contacts_manager_->invalidate_user_full(dialog_id.get_user_id()); - td_->contacts_manager_->reload_user_full(dialog_id.get_user_id()); + td_->contacts_manager_->reload_user_full(dialog_id.get_user_id(), Promise()); break; case DialogType::Chat: case DialogType::Channel: @@ -34968,7 +34969,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq auto user_id = td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id()); if (user_id.is_valid()) { td_->contacts_manager_->invalidate_user_full(user_id); - td_->contacts_manager_->reload_user_full(user_id); + td_->contacts_manager_->reload_user_full(user_id, Promise()); } break; }