Support file reference repair for bot description photo and animation.

This commit is contained in:
levlam 2022-08-06 13:42:35 +03:00
parent 14fa1d71d9
commit 44e96081c6
6 changed files with 96 additions and 21 deletions

View File

@ -3401,8 +3401,8 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent
ContactsManager::~ContactsManager() { ContactsManager::~ContactsManager() {
Scheduler::instance()->destroy_on_scheduler( Scheduler::instance()->destroy_on_scheduler(
G()->get_gc_scheduler_id(), users_, users_full_, user_photos_, unknown_users_, pending_user_photos_, 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_, user_profile_photo_file_source_ids_, my_photo_file_id_, user_full_file_source_ids_, chats_, chats_full_,
chat_full_file_source_ids_, min_channels_, channels_, channels_full_, unknown_channels_, 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_, 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_, 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_, 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); td_->messages_manager_->drop_common_dialogs_cache(user_id);
user_full->is_common_chat_count_changed = false; 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_send_update |= user_full->is_changed;
user_full->need_save_to_database |= 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<telegram_api::userFull> &&u
on_update_user_full_commands(user_full, user_id, std::move(user->bot_info_->commands_)); 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_)); 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 || if (user_full->description != description) {
user_full->description_animation_file_id != description_animation_file_id) {
user_full->description = std::move(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_photo = std::move(description_photo);
user_full->description_animation_file_id = description_animation_file_id; user_full->description_animation_file_id = description_animation_file_id;
user_full->are_files_changed = true;
user_full->is_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->expires_at = 0.0;
user_full->need_save_to_database = true; 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"); 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->broadcast_administrator_rights = {};
user_full->premium_gift_options.clear(); user_full->premium_gift_options.clear();
user_full->voice_messages_forbidden = false; user_full->voice_messages_forbidden = false;
user_full->are_files_changed = true;
user_full->is_changed = true; user_full->is_changed = true;
update_user_full(user_full, user_id, "drop_user_full"); 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<Unit> &
promise.set_value(Unit()); promise.set_value(Unit());
} }
void ContactsManager::reload_user_full(UserId user_id) { void ContactsManager::reload_user_full(UserId user_id, Promise<Unit> &&promise) {
auto r_input_user = get_input_user(user_id); TRY_RESULT_PROMISE(promise, input_user, get_input_user(user_id));
if (r_input_user.is_ok()) { send_get_user_full_query(user_id, std::move(input_user), std::move(promise), "reload_user_full");
send_get_user_full_query(user_id, r_input_user.move_as_ok(), Auto(), "reload_user_full");
}
} }
void ContactsManager::send_get_user_full_query(UserId user_id, tl_object_ptr<telegram_api::InputUser> &&input_user, void ContactsManager::send_get_user_full_query(UserId user_id, tl_object_ptr<telegram_api::InputUser> &&input_user,
@ -14725,6 +14755,25 @@ FileSourceId ContactsManager::get_user_profile_photo_file_source_id(UserId user_
return source_id; 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) { FileSourceId ContactsManager::get_chat_full_file_source_id(ChatId chat_id) {
if (!chat_id.is_valid()) { if (!chat_id.is_valid()) {
return FileSourceId(); return FileSourceId();

View File

@ -492,7 +492,8 @@ class ContactsManager final : public Actor {
bool get_user(UserId user_id, int left_tries, Promise<Unit> &&promise); bool get_user(UserId user_id, int left_tries, Promise<Unit> &&promise);
void reload_user(UserId user_id, Promise<Unit> &&promise); void reload_user(UserId user_id, Promise<Unit> &&promise);
void load_user_full(UserId user_id, bool force, Promise<Unit> &&promise, const char *source); void load_user_full(UserId user_id, bool force, Promise<Unit> &&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<Unit> &&promise);
std::pair<int32, vector<const Photo *>> get_user_profile_photos(UserId user_id, int32 offset, int32 limit, std::pair<int32, vector<const Photo *>> get_user_profile_photos(UserId user_id, int32 offset, int32 limit,
Promise<Unit> &&promise); Promise<Unit> &&promise);
@ -717,6 +718,8 @@ class ContactsManager final : public Actor {
string description; string description;
Photo description_photo; Photo description_photo;
FileId description_animation_file_id; FileId description_animation_file_id;
vector<FileId> registered_file_ids;
FileSourceId file_source_id;
vector<PremiumGiftOption> premium_gift_options; vector<PremiumGiftOption> premium_gift_options;
@ -736,6 +739,7 @@ class ContactsManager final : public Actor {
bool voice_messages_forbidden = false; bool voice_messages_forbidden = false;
bool is_common_chat_count_changed = true; 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 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_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 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<std::pair<UserId, int64>, FileSourceId, UserIdPhotoIdHash> user_profile_photo_file_source_ids_; WaitFreeHashMap<std::pair<UserId, int64>, FileSourceId, UserIdPhotoIdHash> user_profile_photo_file_source_ids_;
FlatHashMap<int64, FileId> my_photo_file_id_; FlatHashMap<int64, FileId> my_photo_file_id_;
WaitFreeHashMap<UserId, FileSourceId, UserIdHash> user_full_file_source_ids_;
WaitFreeHashMap<ChatId, unique_ptr<Chat>, ChatIdHash> chats_; WaitFreeHashMap<ChatId, unique_ptr<Chat>, ChatIdHash> chats_;
WaitFreeHashMap<ChatId, unique_ptr<ChatFull>, ChatIdHash> chats_full_; WaitFreeHashMap<ChatId, unique_ptr<ChatFull>, ChatIdHash> chats_full_;

View File

@ -115,6 +115,11 @@ FileSourceId FileReferenceManager::create_background_file_source(BackgroundId ba
return add_file_source_id(source, PSLICE() << background_id); 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) { FileSourceId FileReferenceManager::create_chat_full_file_source(ChatId chat_id) {
FileSourceChatFull source{chat_id}; FileSourceChatFull source{chat_id};
return add_file_source_id(source, PSLICE() << "full " << 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) { [&](const FileSourceSavedRingtones &source) {
send_closure_later(G()->notification_settings_manager(), &NotificationSettingsManager::repair_saved_ringtones, send_closure_later(G()->notification_settings_manager(), &NotificationSettingsManager::repair_saved_ringtones,
std::move(promise)); std::move(promise));
},
[&](const FileSourceUserFull &source) {
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_user_full, source.user_id,
std::move(promise));
})); }));
} }

View File

@ -57,6 +57,7 @@ class FileReferenceManager final : public Actor {
FileSourceId create_recent_stickers_file_source(bool is_attached); FileSourceId create_recent_stickers_file_source(bool is_attached);
FileSourceId create_favorite_stickers_file_source(); FileSourceId create_favorite_stickers_file_source();
FileSourceId create_background_file_source(BackgroundId background_id, int64 access_hash); 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_chat_full_file_source(ChatId chat_id);
FileSourceId create_channel_full_file_source(ChannelId channel_id); FileSourceId create_channel_full_file_source(ChannelId channel_id);
FileSourceId create_app_config_file_source(); FileSourceId create_app_config_file_source();
@ -156,12 +157,16 @@ class FileReferenceManager final : public Actor {
struct FileSourceSavedRingtones { struct FileSourceSavedRingtones {
// empty // empty
}; };
struct FileSourceUserFull {
UserId user_id;
};
// append only // append only
using FileSource = Variant<FileSourceMessage, FileSourceUserPhoto, FileSourceChatPhoto, FileSourceChannelPhoto, using FileSource =
FileSourceWallpapers, FileSourceWebPage, FileSourceSavedAnimations, Variant<FileSourceMessage, FileSourceUserPhoto, FileSourceChatPhoto, FileSourceChannelPhoto, FileSourceWallpapers,
FileSourceRecentStickers, FileSourceFavoriteStickers, FileSourceBackground, FileSourceWebPage, FileSourceSavedAnimations, FileSourceRecentStickers, FileSourceFavoriteStickers,
FileSourceChatFull, FileSourceChannelFull, FileSourceAppConfig, FileSourceSavedRingtones>; FileSourceBackground, FileSourceChatFull, FileSourceChannelFull, FileSourceAppConfig,
FileSourceSavedRingtones, FileSourceUserFull>;
WaitFreeVector<FileSource> file_sources_; WaitFreeVector<FileSource> file_sources_;
int64 query_generation_{0}; int64 query_generation_{0};

View File

@ -51,7 +51,8 @@ void FileReferenceManager::store_file_source(FileSourceId file_source_id, Storer
}, },
[&](const FileSourceChatFull &source) { td::store(source.chat_id, storer); }, [&](const FileSourceChatFull &source) { td::store(source.chat_id, storer); },
[&](const FileSourceChannelFull &source) { td::store(source.channel_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 <class ParserT> template <class ParserT>
@ -117,6 +118,11 @@ FileSourceId FileReferenceManager::parse_file_source(Td *td, ParserT &parser) {
return td->stickers_manager_->get_app_config_file_source_id(); return td->stickers_manager_->get_app_config_file_source_id();
case 13: case 13:
return td->notification_settings_manager_->get_saved_ringtones_file_source_id(); 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: default:
parser.set_error("Invalid type in FileSource"); parser.set_error("Invalid type in FileSource");
return FileSourceId(); return FileSourceId();

View File

@ -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; LOG(INFO) << "Reget action bar in " << dialog_id << " from " << source;
switch (dialog_id.get_type()) { switch (dialog_id.get_type()) {
case DialogType::User: 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; return;
case DialogType::Chat: case DialogType::Chat:
case DialogType::Channel: 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; LOG(INFO) << "Reload full info about " << dialog_id << " from " << source;
switch (dialog_id.get_type()) { switch (dialog_id.get_type()) {
case DialogType::User: 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<Unit>());
return; return;
case DialogType::Chat: case DialogType::Chat:
send_closure_later(td_->contacts_manager_actor_, &ContactsManager::reload_chat_full, dialog_id.get_chat_id(), 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 // to repair dialog action bar
auto user_id = td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id()); auto user_id = td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id());
if (user_id.is_valid()) { if (user_id.is_valid()) {
td_->contacts_manager_->reload_user_full(user_id); td_->contacts_manager_->reload_user_full(user_id, Promise<Unit>());
} }
break; break;
} }
@ -34958,7 +34959,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
switch (dialog_type) { switch (dialog_type) {
case DialogType::User: case DialogType::User:
td_->contacts_manager_->invalidate_user_full(dialog_id.get_user_id()); 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<Unit>());
break; break;
case DialogType::Chat: case DialogType::Chat:
case DialogType::Channel: 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()); auto user_id = td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id());
if (user_id.is_valid()) { if (user_id.is_valid()) {
td_->contacts_manager_->invalidate_user_full(user_id); 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<Unit>());
} }
break; break;
} }