From 88febd4aa07a30203d5f643cd026d199f35a9b58 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 9 May 2019 04:07:21 +0300 Subject: [PATCH] File reference support for backgrounds. GitOrigin-RevId: e4c7f0ee8e6be2341e51f7ef86edfcd264089e3c --- td/telegram/BackgroundManager.cpp | 69 ++++++++++++++++++++++++---- td/telegram/BackgroundManager.h | 18 ++++++-- td/telegram/FileReferenceManager.cpp | 28 +++++++---- td/telegram/FileReferenceManager.h | 16 +++++-- td/telegram/FileReferenceManager.hpp | 13 +++++- 5 files changed, 118 insertions(+), 26 deletions(-) diff --git a/td/telegram/BackgroundManager.cpp b/td/telegram/BackgroundManager.cpp index 7c14e78c1..ba487d6d1 100644 --- a/td/telegram/BackgroundManager.cpp +++ b/td/telegram/BackgroundManager.cpp @@ -188,15 +188,21 @@ Result BackgroundManager::get_background_url(const string &name, } } -void BackgroundManager::reload_background(BackgroundId background_id, - telegram_api::object_ptr &&input_wallpaper, - Promise &&promise) const { +void BackgroundManager::reload_background_from_server( + BackgroundId background_id, telegram_api::object_ptr &&input_wallpaper, + Promise &&promise) const { if (G()->close_flag()) { return promise.set_error(Status::Error(500, "Request aborted")); } td_->create_handler(std::move(promise))->send(background_id, std::move(input_wallpaper)); } +void BackgroundManager::reload_background(BackgroundId background_id, int64 access_hash, Promise &&promise) { + reload_background_from_server( + background_id, telegram_api::make_object(background_id.get(), access_hash), + std::move(promise)); +} + BackgroundId BackgroundManager::search_background(const string &name, Promise &&promise) { auto it = name_to_background_id_.find(name); if (it != name_to_background_id_.end()) { @@ -204,14 +210,31 @@ BackgroundId BackgroundManager::search_background(const string &name, Promisesecond; } - reload_background(BackgroundId(), telegram_api::make_object(name), - std::move(promise)); + reload_background_from_server(BackgroundId(), telegram_api::make_object(name), + std::move(promise)); return BackgroundId(); } BackgroundManager::Background *BackgroundManager::add_background(BackgroundId background_id) { CHECK(background_id.is_valid()); - return &backgrounds_[background_id]; + auto *result = &backgrounds_[background_id]; + if (!result->id.is_valid()) { + auto it = background_id_to_file_source_id_.find(background_id); + if (it != background_id_to_file_source_id_.end()) { + result->file_source_id = it->second.second; + background_id_to_file_source_id_.erase(it); + } + } + return result; +} + +BackgroundManager::Background *BackgroundManager::get_background_ref(BackgroundId background_id) { + auto p = backgrounds_.find(background_id); + if (p == backgrounds_.end()) { + return nullptr; + } else { + return &p->second; + } } const BackgroundManager::Background *BackgroundManager::get_background(BackgroundId background_id) const { @@ -290,7 +313,6 @@ BackgroundId BackgroundManager::on_get_background(BackgroundId expected_backgrou auto *background = add_background(id); background->id = id; background->access_hash = wallpaper->access_hash_; - background->file_id = document.file_id; background->is_creator = (flags & telegram_api::wallPaper::CREATOR_MASK) != 0; background->is_default = (flags & telegram_api::wallPaper::DEFAULT_MASK) != 0; background->is_dark = (flags & telegram_api::wallPaper::DARK_MASK) != 0; @@ -304,7 +326,18 @@ BackgroundId BackgroundManager::on_get_background(BackgroundId expected_backgrou background->name = std::move(wallpaper->slug_); name_to_background_id_.emplace(background->name, id); } - + if (background->file_id != document.file_id) { + LOG_IF(ERROR, background->file_id.is_valid()) + << "Background file has changed from " << background->file_id << " to " << document.file_id; + if (!background->file_source_id.is_valid()) { + background->file_source_id = + td_->file_reference_manager_->create_background_file_source(id, background->access_hash); + } + for (auto file_id : document.get_file_ids(td_)) { + td_->file_manager_->add_file_source(file_id, background->file_source_id); + } + background->file_id = document.file_id; + } return id; } @@ -375,4 +408,24 @@ td_api::object_ptr BackgroundManager::get_backgrounds_objec installed_backgrounds_, [this](BackgroundId background_id) { return get_background_object(background_id); })); } +FileSourceId BackgroundManager::get_background_file_source_id(BackgroundId background_id, int64 access_hash) { + Background *background = get_background_ref(background_id); + if (background != nullptr) { + if (!background->file_source_id.is_valid()) { + background->file_source_id = + td_->file_reference_manager_->create_background_file_source(background_id, background->access_hash); + } + return background->file_source_id; + } + + auto &result = background_id_to_file_source_id_[background_id]; + if (result.first == 0) { + result.first = access_hash; + } + if (!result.second.is_valid()) { + result.second = td_->file_reference_manager_->create_background_file_source(background_id, result.first); + } + return result.second; +} + } // namespace td diff --git a/td/telegram/BackgroundManager.h b/td/telegram/BackgroundManager.h index 41fe42237..f9832b832 100644 --- a/td/telegram/BackgroundManager.h +++ b/td/telegram/BackgroundManager.h @@ -34,6 +34,8 @@ class BackgroundManager : public Actor { Result get_background_url(const string &name, td_api::object_ptr background_type) const; + void reload_background(BackgroundId background_id, int64 access_hash, Promise &&promise); + BackgroundId search_background(const string &name, Promise &&promise); td_api::object_ptr get_background_object(BackgroundId background_id) const; @@ -43,6 +45,8 @@ class BackgroundManager : public Actor { BackgroundId on_get_background(BackgroundId expected_background_id, telegram_api::object_ptr wallpaper); + FileSourceId get_background_file_source_id(BackgroundId background_id, int64 access_hash); + private: struct BackgroundType { enum class Type : int32 { Wallpaper, Pattern, Solid }; @@ -72,16 +76,19 @@ class BackgroundManager : public Actor { bool is_default = false; bool is_dark = false; BackgroundType type; + FileSourceId file_source_id; }; void tear_down() override; - void reload_background(BackgroundId background_id, - telegram_api::object_ptr &&input_wallpaper, - Promise &&promise) const; + void reload_background_from_server(BackgroundId background_id, + telegram_api::object_ptr &&input_wallpaper, + Promise &&promise) const; Background *add_background(BackgroundId background_id); + Background *get_background_ref(BackgroundId background_id); + const Background *get_background(BackgroundId background_id) const; static Result get_background_type(td_api::object_ptr type); @@ -93,7 +100,10 @@ class BackgroundManager : public Actor { static td_api::object_ptr get_background_type_object(const BackgroundType &type); - std::unordered_map backgrounds_; // id -> Background + std::unordered_map backgrounds_; + + std::unordered_map, BackgroundIdHash> + background_id_to_file_source_id_; // id -> [access_hash, file_source_id] std::unordered_map name_to_background_id_; diff --git a/td/telegram/FileReferenceManager.cpp b/td/telegram/FileReferenceManager.cpp index 51f387c08..a0cc3ed44 100644 --- a/td/telegram/FileReferenceManager.cpp +++ b/td/telegram/FileReferenceManager.cpp @@ -40,15 +40,16 @@ size_t FileReferenceManager::get_file_reference_error_pos(const Status &error) { } /* -fileSourceMessage chat_id:int53 message_id:int53 = FileSource; // repaired with get_message_from_server -fileSourceUserProfilePhoto user_id:int32 photo_id:int64 = FileSource; // repaired with photos.getUserPhotos -fileSourceBasicGroupPhoto basic_group_id:int32 = FileSource; // repaired with messages.getChats -fileSourceSupergroupPhoto supergroup_id:int32 = FileSource; // repaired with channels.getChannels -fileSourceWebPage url:string = FileSource; // repaired with messages.getWebPage -fileSourceWallpapers = FileSource; // can't be repaired -fileSourceSavedAnimations = FileSource; // repaired with messages.getSavedGifs -fileSourceRecentStickers is_attached:Bool = FileSource; // repaired with messages.getRecentStickers, not reliable -fileSourceFavoriteStickers = FileSource; // repaired with messages.getFavedStickers, not reliable +fileSourceMessage chat_id:int53 message_id:int53 = FileSource; // repaired with get_message_from_server +fileSourceUserProfilePhoto user_id:int32 photo_id:int64 = FileSource; // repaired with photos.getUserPhotos +fileSourceBasicGroupPhoto basic_group_id:int32 = FileSource; // repaired with messages.getChats +fileSourceSupergroupPhoto supergroup_id:int32 = FileSource; // repaired with channels.getChannels +fileSourceWebPage url:string = FileSource; // repaired with messages.getWebPage +fileSourceWallpapers = FileSource; // can't be repaired +fileSourceSavedAnimations = FileSource; // repaired with messages.getSavedGifs +fileSourceRecentStickers is_attached:Bool = FileSource; // repaired with messages.getRecentStickers, not reliable +fileSourceFavoriteStickers = FileSource; // repaired with messages.getFavedStickers, not reliable +fileSourceBackground background_id:int64 access_hash:int64 = FileSource; // repaired with account.getWallPaper */ FileSourceId FileReferenceManager::get_current_file_source_id() const { @@ -103,6 +104,11 @@ FileSourceId FileReferenceManager::create_favorite_stickers_file_source() { return add_file_source_id(source, PSLICE() << "favorite stickers"); } +FileSourceId FileReferenceManager::create_background_file_source(BackgroundId background_id, int64 access_hash) { + FileSourceBackground source{background_id, access_hash}; + return add_file_source_id(source, PSLICE() << background_id); +} + bool FileReferenceManager::add_file_source(NodeId node_id, FileSourceId file_source_id) { bool is_added = nodes_[node_id].file_source_ids.add(file_source_id); VLOG(file_references) << "Add " << (is_added ? "new" : "old") << ' ' << file_source_id << " for file " << node_id; @@ -273,6 +279,10 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source }, [&](const FileSourceFavoriteStickers &source) { send_closure_later(G()->stickers_manager(), &StickersManager::repair_favorite_stickers, std::move(promise)); + }, + [&](const FileSourceBackground &source) { + send_closure_later(G()->background_manager(), &BackgroundManager::reload_background, source.background_id, + source.access_hash, std::move(promise)); })); } diff --git a/td/telegram/FileReferenceManager.h b/td/telegram/FileReferenceManager.h index 835b4b5ee..258d04d1a 100644 --- a/td/telegram/FileReferenceManager.h +++ b/td/telegram/FileReferenceManager.h @@ -9,6 +9,7 @@ #include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" +#include "td/telegram/BackgroundId.h" #include "td/telegram/ChannelId.h" #include "td/telegram/ChatId.h" #include "td/telegram/files/FileId.h" @@ -44,6 +45,7 @@ class FileReferenceManager : public Actor { FileSourceId create_saved_animations_file_source(); 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); using NodeId = FileId; void repair_file_reference(NodeId node_id, Promise<> promise); @@ -109,12 +111,18 @@ class FileReferenceManager : public Actor { struct FileSourceRecentStickers { bool is_attached; }; - struct FileSourceFavoriteStickers {}; + struct FileSourceFavoriteStickers { + // empty + }; + struct FileSourceBackground { + BackgroundId background_id; + int64 access_hash = 0; + }; // append only - using FileSource = - Variant; + using FileSource = Variant; vector file_sources_; int64 query_generation_{0}; diff --git a/td/telegram/FileReferenceManager.hpp b/td/telegram/FileReferenceManager.hpp index bc914ff69..4409c41fd 100644 --- a/td/telegram/FileReferenceManager.hpp +++ b/td/telegram/FileReferenceManager.hpp @@ -43,7 +43,11 @@ void FileReferenceManager::store_file_source(FileSourceId file_source_id, Storer [&](const FileSourceWebPage &source) { td::store(source.url, storer); }, [&](const FileSourceSavedAnimations &source) {}, [&](const FileSourceRecentStickers &source) { td::store(source.is_attached, storer); }, - [&](const FileSourceFavoriteStickers &source) {})); + [&](const FileSourceFavoriteStickers &source) {}, + [&](const FileSourceBackground &source) { + td::store(source.background_id, storer); + td::store(source.access_hash, storer); + })); } template @@ -88,6 +92,13 @@ FileSourceId FileReferenceManager::parse_file_source(Td *td, ParserT &parser) { } case 8: return td->stickers_manager_->get_favorite_stickers_file_source_id(); + case 9: { + BackgroundId background_id; + int64 access_hash; + td::parse(background_id, parser); + td::parse(access_hash, parser); + return td->background_manager_->get_background_file_source_id(background_id, access_hash); + } default: parser.set_error("Invalid type in FileSource"); return FileSourceId();