2018-12-05 10:32:31 +01:00
|
|
|
//
|
2022-12-31 22:28:08 +01:00
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
|
2018-12-05 10:32:31 +01:00
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#include "td/telegram/FileReferenceManager.h"
|
|
|
|
|
2019-01-14 19:46:04 +01:00
|
|
|
#include "td/telegram/AnimationsManager.h"
|
2022-08-10 20:12:05 +02:00
|
|
|
#include "td/telegram/AttachMenuManager.h"
|
2019-05-07 04:51:56 +02:00
|
|
|
#include "td/telegram/BackgroundManager.h"
|
2021-10-08 12:41:22 +02:00
|
|
|
#include "td/telegram/ConfigManager.h"
|
2019-01-14 19:46:04 +01:00
|
|
|
#include "td/telegram/ContactsManager.h"
|
2019-01-05 16:13:27 +01:00
|
|
|
#include "td/telegram/files/FileManager.h"
|
2018-12-05 10:32:31 +01:00
|
|
|
#include "td/telegram/Global.h"
|
|
|
|
#include "td/telegram/MessagesManager.h"
|
2022-04-15 15:27:30 +02:00
|
|
|
#include "td/telegram/NotificationSettingsManager.h"
|
2019-09-18 05:55:43 +02:00
|
|
|
#include "td/telegram/StickerSetId.h"
|
2019-02-02 11:30:49 +01:00
|
|
|
#include "td/telegram/StickersManager.h"
|
2023-05-20 00:23:33 +02:00
|
|
|
#include "td/telegram/StoryManager.h"
|
2020-07-04 11:00:14 +02:00
|
|
|
#include "td/telegram/Td.h"
|
2021-10-21 11:51:16 +02:00
|
|
|
#include "td/telegram/WebPageId.h"
|
2019-01-14 19:46:04 +01:00
|
|
|
#include "td/telegram/WebPagesManager.h"
|
2018-12-05 10:32:31 +01:00
|
|
|
|
2021-01-01 13:59:53 +01:00
|
|
|
#include "td/utils/algorithm.h"
|
2019-02-12 22:26:36 +01:00
|
|
|
#include "td/utils/common.h"
|
2019-01-19 18:19:29 +01:00
|
|
|
#include "td/utils/logging.h"
|
2019-01-18 20:10:38 +01:00
|
|
|
#include "td/utils/misc.h"
|
2019-01-14 19:46:04 +01:00
|
|
|
#include "td/utils/overloaded.h"
|
2021-05-17 14:21:11 +02:00
|
|
|
#include "td/utils/SliceBuilder.h"
|
2019-10-22 19:01:15 +02:00
|
|
|
#include "td/utils/Time.h"
|
2018-12-05 10:32:31 +01:00
|
|
|
|
|
|
|
namespace td {
|
|
|
|
|
2019-04-08 18:15:39 +02:00
|
|
|
int VERBOSITY_NAME(file_references) = VERBOSITY_NAME(INFO);
|
2019-01-14 19:46:04 +01:00
|
|
|
|
2022-08-09 16:00:36 +02:00
|
|
|
FileReferenceManager::FileReferenceManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
|
|
|
}
|
|
|
|
|
2022-07-20 12:40:14 +02:00
|
|
|
FileReferenceManager::~FileReferenceManager() {
|
2022-11-17 17:13:36 +01:00
|
|
|
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), file_sources_, nodes_);
|
2022-07-20 12:40:14 +02:00
|
|
|
}
|
|
|
|
|
2022-08-09 16:00:36 +02:00
|
|
|
void FileReferenceManager::tear_down() {
|
|
|
|
parent_.reset();
|
|
|
|
}
|
|
|
|
|
2019-01-23 17:00:56 +01:00
|
|
|
bool FileReferenceManager::is_file_reference_error(const Status &error) {
|
|
|
|
return error.is_error() && error.code() == 400 && begins_with(error.message(), "FILE_REFERENCE_");
|
|
|
|
}
|
|
|
|
|
2019-02-08 15:54:23 +01:00
|
|
|
size_t FileReferenceManager::get_file_reference_error_pos(const Status &error) {
|
|
|
|
if (!is_file_reference_error(error)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
auto offset = Slice("FILE_REFERENCE_").size();
|
|
|
|
if (error.message().size() <= offset || !is_digit(error.message()[offset])) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return to_integer<size_t>(error.message().substr(offset)) + 1;
|
|
|
|
}
|
|
|
|
|
2019-01-14 19:46:04 +01:00
|
|
|
/*
|
2019-05-09 03:07:21 +02:00
|
|
|
fileSourceMessage chat_id:int53 message_id:int53 = FileSource; // repaired with get_message_from_server
|
2023-02-28 12:11:49 +01:00
|
|
|
fileSourceUserProfilePhoto user_id:int53 photo_id:int64 = FileSource; // repaired with photos.getUserPhotos
|
|
|
|
fileSourceBasicGroupPhoto basic_group_id:int53 = FileSource; // no need to repair
|
|
|
|
fileSourceSupergroupPhoto supergroup_id:int53 = FileSource; // no need to repair
|
2019-05-09 03:07:21 +02:00
|
|
|
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
|
2023-02-28 12:11:49 +01:00
|
|
|
fileSourceBasicGroupFull basic_group_id:int53 = FileSource; // repaired with messages.getFullChat
|
|
|
|
fileSourceSupergroupFull supergroup_id:int53 = FileSource; // repaired with messages.getFullChannel
|
2021-10-08 12:41:22 +02:00
|
|
|
fileSourceAppConfig = FileSource; // repaired with help.getAppConfig, not reliable
|
2022-04-15 15:27:30 +02:00
|
|
|
fileSourceSavedRingtones = FileSource; // repaired with account.getSavedRingtones
|
2022-08-10 20:12:05 +02:00
|
|
|
fileSourceUserFull = FileSource; // repaired with users.getFullUser
|
2023-02-28 12:11:49 +01:00
|
|
|
fileSourceAttachmentMenuBot user_id:int53 = FileSource; // repaired with messages.getAttachMenuBot
|
|
|
|
fileSourceWebApp user_id:int53 short_name:string = FileSource; // repaired with messages.getAttachMenuBot
|
2023-05-20 00:23:33 +02:00
|
|
|
fileSourceStory chat_id:int53 story_id:int32 = FileSource; // repaired with stories.getStoriesByID
|
2019-01-14 19:46:04 +01:00
|
|
|
*/
|
|
|
|
|
2019-01-18 20:10:38 +01:00
|
|
|
FileSourceId FileReferenceManager::get_current_file_source_id() const {
|
|
|
|
return FileSourceId(narrow_cast<int32>(file_sources_.size()));
|
|
|
|
}
|
|
|
|
|
2019-01-18 20:36:23 +01:00
|
|
|
template <class T>
|
2023-02-28 12:35:52 +01:00
|
|
|
FileSourceId FileReferenceManager::add_file_source_id(T &source, Slice source_str) {
|
2019-01-18 20:36:23 +01:00
|
|
|
file_sources_.emplace_back(std::move(source));
|
2019-01-21 19:22:56 +01:00
|
|
|
VLOG(file_references) << "Create file source " << file_sources_.size() << " for " << source_str;
|
2019-01-18 20:36:23 +01:00
|
|
|
return get_current_file_source_id();
|
|
|
|
}
|
|
|
|
|
2019-01-14 19:46:04 +01:00
|
|
|
FileSourceId FileReferenceManager::create_message_file_source(FullMessageId full_message_id) {
|
|
|
|
FileSourceMessage source{full_message_id};
|
2019-01-21 19:22:56 +01:00
|
|
|
return add_file_source_id(source, PSLICE() << full_message_id);
|
2019-01-18 20:36:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FileSourceId FileReferenceManager::create_user_photo_file_source(UserId user_id, int64 photo_id) {
|
|
|
|
FileSourceUserPhoto source{photo_id, user_id};
|
2019-01-21 19:22:56 +01:00
|
|
|
return add_file_source_id(source, PSLICE() << "photo " << photo_id << " of " << user_id);
|
2019-01-18 20:36:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FileSourceId FileReferenceManager::create_web_page_file_source(string url) {
|
|
|
|
FileSourceWebPage source{std::move(url)};
|
2019-01-25 16:44:23 +01:00
|
|
|
auto source_str = PSTRING() << "web page of " << source.url;
|
2023-02-28 12:35:52 +01:00
|
|
|
return add_file_source_id(source, source_str);
|
2019-01-18 20:36:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FileSourceId FileReferenceManager::create_saved_animations_file_source() {
|
|
|
|
FileSourceSavedAnimations source;
|
2019-01-21 19:22:56 +01:00
|
|
|
return add_file_source_id(source, "saved animations");
|
2018-12-05 10:32:31 +01:00
|
|
|
}
|
|
|
|
|
2019-02-02 11:30:49 +01:00
|
|
|
FileSourceId FileReferenceManager::create_recent_stickers_file_source(bool is_attached) {
|
|
|
|
FileSourceRecentStickers source{is_attached};
|
|
|
|
return add_file_source_id(source, PSLICE() << "recent " << (is_attached ? "attached " : "") << "stickers");
|
|
|
|
}
|
|
|
|
|
2019-02-02 11:54:40 +01:00
|
|
|
FileSourceId FileReferenceManager::create_favorite_stickers_file_source() {
|
|
|
|
FileSourceFavoriteStickers source;
|
2021-10-06 12:48:29 +02:00
|
|
|
return add_file_source_id(source, "favorite stickers");
|
2019-02-02 11:54:40 +01:00
|
|
|
}
|
|
|
|
|
2019-05-09 03:07:21 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-07-06 14:26:29 +02:00
|
|
|
FileSourceId FileReferenceManager::create_chat_full_file_source(ChatId chat_id) {
|
|
|
|
FileSourceChatFull source{chat_id};
|
|
|
|
return add_file_source_id(source, PSLICE() << "full " << chat_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
FileSourceId FileReferenceManager::create_channel_full_file_source(ChannelId channel_id) {
|
|
|
|
FileSourceChannelFull source{channel_id};
|
|
|
|
return add_file_source_id(source, PSLICE() << "full " << channel_id);
|
|
|
|
}
|
|
|
|
|
2021-10-08 12:41:22 +02:00
|
|
|
FileSourceId FileReferenceManager::create_app_config_file_source() {
|
|
|
|
FileSourceAppConfig source;
|
|
|
|
return add_file_source_id(source, "app config");
|
|
|
|
}
|
|
|
|
|
2022-08-10 20:12:05 +02:00
|
|
|
FileSourceId FileReferenceManager::create_saved_ringtones_file_source() {
|
|
|
|
FileSourceSavedRingtones source;
|
|
|
|
return add_file_source_id(source, "saved notification sounds");
|
|
|
|
}
|
|
|
|
|
|
|
|
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_attach_menu_bot_file_source(UserId user_id) {
|
|
|
|
FileSourceAttachMenuBot source{user_id};
|
|
|
|
return add_file_source_id(source, PSLICE() << "attachment menu bot " << user_id);
|
|
|
|
}
|
|
|
|
|
2023-02-28 12:11:49 +01:00
|
|
|
FileSourceId FileReferenceManager::create_web_app_file_source(UserId user_id, const string &short_name) {
|
|
|
|
FileSourceWebApp source{user_id, short_name};
|
2023-03-06 14:59:18 +01:00
|
|
|
return add_file_source_id(source, PSLICE() << "Web App " << user_id << '/' << short_name);
|
2023-02-28 12:11:49 +01:00
|
|
|
}
|
|
|
|
|
2023-05-20 00:23:33 +02:00
|
|
|
FileSourceId FileReferenceManager::create_story_file_source(StoryFullId story_full_id) {
|
|
|
|
FileSourceStory source{story_full_id};
|
|
|
|
return add_file_source_id(source, PSLICE() << story_full_id);
|
|
|
|
}
|
|
|
|
|
2022-11-17 17:13:36 +01:00
|
|
|
FileReferenceManager::Node &FileReferenceManager::add_node(NodeId node_id) {
|
2022-02-09 22:59:52 +01:00
|
|
|
CHECK(node_id.is_valid());
|
2022-11-17 17:13:36 +01:00
|
|
|
auto &node = nodes_[node_id];
|
|
|
|
if (node == nullptr) {
|
|
|
|
node = make_unique<Node>();
|
|
|
|
}
|
|
|
|
return *node;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FileReferenceManager::add_file_source(NodeId node_id, FileSourceId file_source_id) {
|
|
|
|
auto &node = add_node(node_id);
|
|
|
|
bool is_added = node.file_source_ids.add(file_source_id);
|
2019-02-05 00:54:39 +01:00
|
|
|
VLOG(file_references) << "Add " << (is_added ? "new" : "old") << ' ' << file_source_id << " for file " << node_id;
|
|
|
|
return is_added;
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
2019-01-18 19:24:03 +01:00
|
|
|
|
2019-01-30 22:37:38 +01:00
|
|
|
bool FileReferenceManager::remove_file_source(NodeId node_id, FileSourceId file_source_id) {
|
2022-02-09 22:59:52 +01:00
|
|
|
CHECK(node_id.is_valid());
|
2022-11-17 17:13:36 +01:00
|
|
|
auto *node = nodes_.get_pointer(node_id);
|
|
|
|
bool is_removed = node != nullptr && node->file_source_ids.remove(file_source_id);
|
2019-02-05 00:54:39 +01:00
|
|
|
if (is_removed) {
|
|
|
|
VLOG(file_references) << "Remove " << file_source_id << " from file " << node_id;
|
|
|
|
} else {
|
|
|
|
VLOG(file_references) << "Can't find " << file_source_id << " from file " << node_id << " to remove it";
|
|
|
|
}
|
|
|
|
return is_removed;
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
|
|
|
|
2019-04-28 19:21:44 +02:00
|
|
|
vector<FileSourceId> FileReferenceManager::get_some_file_sources(NodeId node_id) {
|
2022-11-17 17:13:36 +01:00
|
|
|
auto *node = nodes_.get_pointer(node_id);
|
|
|
|
if (node == nullptr) {
|
2019-01-29 12:07:58 +01:00
|
|
|
return {};
|
|
|
|
}
|
2022-11-17 17:13:36 +01:00
|
|
|
return node->file_source_ids.get_some_elements();
|
2019-01-29 12:07:58 +01:00
|
|
|
}
|
|
|
|
|
2019-04-28 19:21:44 +02:00
|
|
|
vector<FullMessageId> FileReferenceManager::get_some_message_file_sources(NodeId node_id) {
|
|
|
|
auto file_source_ids = get_some_file_sources(node_id);
|
|
|
|
|
|
|
|
vector<FullMessageId> result;
|
|
|
|
for (auto file_source_id : file_source_ids) {
|
|
|
|
auto index = static_cast<size_t>(file_source_id.get()) - 1;
|
|
|
|
CHECK(index < file_sources_.size());
|
|
|
|
const auto &file_source = file_sources_[index];
|
|
|
|
if (file_source.get_offset() == 0) {
|
|
|
|
result.push_back(file_source.get<FileSourceMessage>().full_message_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-01-17 21:42:00 +01:00
|
|
|
void FileReferenceManager::merge(NodeId to_node_id, NodeId from_node_id) {
|
2022-11-17 17:13:36 +01:00
|
|
|
auto *from_node_ptr = nodes_.get_pointer(from_node_id);
|
|
|
|
if (from_node_ptr == nullptr) {
|
2019-01-21 18:43:58 +01:00
|
|
|
return;
|
|
|
|
}
|
2022-11-17 17:13:36 +01:00
|
|
|
auto &from = *from_node_ptr;
|
2019-01-21 18:43:58 +01:00
|
|
|
|
2022-11-17 17:13:36 +01:00
|
|
|
auto &to = add_node(to_node_id);
|
2019-01-20 04:34:47 +01:00
|
|
|
VLOG(file_references) << "Merge " << to.file_source_ids.size() << " and " << from.file_source_ids.size()
|
|
|
|
<< " sources of files " << to_node_id << " and " << from_node_id;
|
2021-12-01 18:54:56 +01:00
|
|
|
CHECK(!to.query || to.query->proxy.is_empty());
|
|
|
|
CHECK(!from.query || from.query->proxy.is_empty());
|
2019-01-17 21:42:00 +01:00
|
|
|
if (to.query || from.query) {
|
|
|
|
if (!to.query) {
|
|
|
|
to.query = make_unique<Query>();
|
2019-01-18 20:36:23 +01:00
|
|
|
to.query->generation = ++query_generation_;
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
|
|
|
if (from.query) {
|
2019-01-19 02:09:58 +01:00
|
|
|
combine(to.query->promises, std::move(from.query->promises));
|
2019-01-17 21:42:00 +01:00
|
|
|
to.query->active_queries += from.query->active_queries;
|
2021-12-01 18:54:56 +01:00
|
|
|
from.query->proxy = Destination(to_node_id, to.query->generation);
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
to.file_source_ids.merge(std::move(from.file_source_ids));
|
|
|
|
run_node(to_node_id);
|
|
|
|
run_node(from_node_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FileReferenceManager::run_node(NodeId node_id) {
|
2022-02-09 22:59:52 +01:00
|
|
|
CHECK(node_id.is_valid());
|
2022-11-17 17:13:36 +01:00
|
|
|
auto *node_ptr = nodes_.get_pointer(node_id);
|
|
|
|
if (node_ptr == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Node &node = *node_ptr;
|
2019-01-17 21:42:00 +01:00
|
|
|
if (!node.query) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (node.query->active_queries != 0) {
|
|
|
|
return;
|
|
|
|
}
|
2019-01-23 20:20:48 +01:00
|
|
|
VLOG(file_references) << "Trying to repair file reference for file " << node_id;
|
2019-01-17 21:42:00 +01:00
|
|
|
if (node.query->promises.empty()) {
|
|
|
|
node.query = {};
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!node.file_source_ids.has_next()) {
|
2019-01-23 20:20:48 +01:00
|
|
|
VLOG(file_references) << "Have no more file sources to repair file reference for file " << node_id;
|
2019-01-17 21:42:00 +01:00
|
|
|
for (auto &p : node.query->promises) {
|
2019-01-23 20:20:48 +01:00
|
|
|
if (node.file_source_ids.empty()) {
|
2019-04-19 00:03:33 +02:00
|
|
|
p.set_error(Status::Error(400, "File source is not found"));
|
2019-01-23 20:20:48 +01:00
|
|
|
} else {
|
|
|
|
p.set_error(Status::Error(429, "Too Many Requests: retry after 1"));
|
|
|
|
}
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
|
|
|
node.query = {};
|
|
|
|
return;
|
|
|
|
}
|
2019-10-18 03:30:49 +02:00
|
|
|
if (node.last_successful_repair_time >= Time::now() - 60) {
|
|
|
|
VLOG(file_references) << "Recently repaired file reference for file " << node_id << ", do not try again";
|
|
|
|
for (auto &p : node.query->promises) {
|
|
|
|
p.set_error(Status::Error(429, "Too Many Requests: retry after 60"));
|
|
|
|
}
|
|
|
|
node.query = {};
|
|
|
|
return;
|
|
|
|
}
|
2019-01-17 21:42:00 +01:00
|
|
|
auto file_source_id = node.file_source_ids.next();
|
2021-12-01 18:54:56 +01:00
|
|
|
send_query(Destination(node_id, node.query->generation), file_source_id);
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileReferenceManager::send_query(Destination dest, FileSourceId file_source_id) {
|
2019-10-09 01:59:25 +02:00
|
|
|
VLOG(file_references) << "Send file reference repair query for file " << dest.node_id << " with generation "
|
2019-01-21 19:22:56 +01:00
|
|
|
<< dest.generation << " from " << file_source_id;
|
2022-11-17 17:13:36 +01:00
|
|
|
auto &node = add_node(dest.node_id);
|
2019-01-17 21:42:00 +01:00
|
|
|
node.query->active_queries++;
|
|
|
|
|
2021-10-07 12:38:49 +02:00
|
|
|
auto promise = PromiseCreator::lambda([dest, file_source_id, actor_id = actor_id(this),
|
|
|
|
file_manager_actor_id = G()->file_manager()](Result<Unit> result) {
|
|
|
|
auto new_promise = PromiseCreator::lambda([dest, file_source_id, actor_id](Result<Unit> result) {
|
2019-03-20 19:13:45 +01:00
|
|
|
Status status;
|
|
|
|
if (result.is_error()) {
|
|
|
|
status = result.move_as_error();
|
|
|
|
}
|
2021-10-07 12:38:49 +02:00
|
|
|
send_closure(actor_id, &FileReferenceManager::on_query_result, dest, file_source_id, std::move(status), 0);
|
2019-03-20 19:13:45 +01:00
|
|
|
});
|
2019-01-29 12:07:58 +01:00
|
|
|
|
2021-10-07 12:38:49 +02:00
|
|
|
send_closure(file_manager_actor_id, &FileManager::on_file_reference_repaired, dest.node_id, file_source_id,
|
2020-07-04 11:00:14 +02:00
|
|
|
std::move(result), std::move(new_promise));
|
2019-01-17 21:42:00 +01:00
|
|
|
});
|
|
|
|
auto index = static_cast<size_t>(file_source_id.get()) - 1;
|
|
|
|
CHECK(index < file_sources_.size());
|
|
|
|
file_sources_[index].visit(overloaded(
|
|
|
|
[&](const FileSourceMessage &source) {
|
2019-02-21 20:28:53 +01:00
|
|
|
send_closure_later(G()->messages_manager(), &MessagesManager::get_message_from_server, source.full_message_id,
|
2021-07-08 16:09:16 +02:00
|
|
|
std::move(promise), "FileSourceMessage", nullptr);
|
2019-01-17 21:42:00 +01:00
|
|
|
},
|
|
|
|
[&](const FileSourceUserPhoto &source) {
|
2019-01-20 04:04:40 +01:00
|
|
|
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_user_profile_photo, source.user_id,
|
|
|
|
source.photo_id, std::move(promise));
|
2019-01-17 21:42:00 +01:00
|
|
|
},
|
|
|
|
[&](const FileSourceChatPhoto &source) {
|
2019-01-20 04:04:40 +01:00
|
|
|
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_chat, source.chat_id, std::move(promise));
|
2019-01-17 21:42:00 +01:00
|
|
|
},
|
|
|
|
[&](const FileSourceChannelPhoto &source) {
|
2019-01-20 04:04:40 +01:00
|
|
|
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_channel, source.channel_id,
|
|
|
|
std::move(promise));
|
2019-01-17 21:42:00 +01:00
|
|
|
},
|
2019-05-07 04:51:56 +02:00
|
|
|
[&](const FileSourceWallpapers &source) { promise.set_error(Status::Error("Can't repair old wallpapers")); },
|
2019-01-17 21:42:00 +01:00
|
|
|
[&](const FileSourceWebPage &source) {
|
|
|
|
send_closure_later(G()->web_pages_manager(), &WebPagesManager::reload_web_page_by_url, source.url,
|
2021-10-07 11:49:46 +02:00
|
|
|
PromiseCreator::lambda([promise = std::move(promise)](Result<WebPageId> &&result) mutable {
|
|
|
|
if (result.is_error()) {
|
|
|
|
promise.set_error(result.move_as_error());
|
|
|
|
} else {
|
|
|
|
promise.set_value(Unit());
|
|
|
|
}
|
|
|
|
}));
|
2019-01-17 21:42:00 +01:00
|
|
|
},
|
|
|
|
[&](const FileSourceSavedAnimations &source) {
|
2019-02-02 11:54:40 +01:00
|
|
|
send_closure_later(G()->animations_manager(), &AnimationsManager::repair_saved_animations, std::move(promise));
|
2019-02-02 11:30:49 +01:00
|
|
|
},
|
|
|
|
[&](const FileSourceRecentStickers &source) {
|
2019-02-02 11:54:40 +01:00
|
|
|
send_closure_later(G()->stickers_manager(), &StickersManager::repair_recent_stickers, source.is_attached,
|
2019-02-02 11:30:49 +01:00
|
|
|
std::move(promise));
|
2019-02-02 11:54:40 +01:00
|
|
|
},
|
|
|
|
[&](const FileSourceFavoriteStickers &source) {
|
|
|
|
send_closure_later(G()->stickers_manager(), &StickersManager::repair_favorite_stickers, std::move(promise));
|
2019-05-09 03:07:21 +02:00
|
|
|
},
|
|
|
|
[&](const FileSourceBackground &source) {
|
|
|
|
send_closure_later(G()->background_manager(), &BackgroundManager::reload_background, source.background_id,
|
|
|
|
source.access_hash, std::move(promise));
|
2020-07-06 14:26:29 +02:00
|
|
|
},
|
|
|
|
[&](const FileSourceChatFull &source) {
|
|
|
|
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_chat_full, source.chat_id,
|
|
|
|
std::move(promise));
|
|
|
|
},
|
|
|
|
[&](const FileSourceChannelFull &source) {
|
|
|
|
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_channel_full, source.channel_id,
|
|
|
|
std::move(promise), "repair file reference");
|
2021-10-08 12:41:22 +02:00
|
|
|
},
|
|
|
|
[&](const FileSourceAppConfig &source) {
|
|
|
|
send_closure_later(G()->config_manager(), &ConfigManager::reget_app_config, std::move(promise));
|
2022-04-15 15:27:30 +02:00
|
|
|
},
|
|
|
|
[&](const FileSourceSavedRingtones &source) {
|
|
|
|
send_closure_later(G()->notification_settings_manager(), &NotificationSettingsManager::repair_saved_ringtones,
|
|
|
|
std::move(promise));
|
2022-08-06 12:42:35 +02:00
|
|
|
},
|
|
|
|
[&](const FileSourceUserFull &source) {
|
|
|
|
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_user_full, source.user_id,
|
|
|
|
std::move(promise));
|
2022-08-10 20:12:05 +02:00
|
|
|
},
|
|
|
|
[&](const FileSourceAttachMenuBot &source) {
|
|
|
|
send_closure_later(G()->attach_menu_manager(), &AttachMenuManager::reload_attach_menu_bot, source.user_id,
|
|
|
|
std::move(promise));
|
2023-02-28 12:11:49 +01:00
|
|
|
},
|
|
|
|
[&](const FileSourceWebApp &source) {
|
|
|
|
send_closure_later(G()->attach_menu_manager(), &AttachMenuManager::reload_web_app, source.user_id,
|
|
|
|
source.short_name, std::move(promise));
|
2023-05-20 00:23:33 +02:00
|
|
|
},
|
|
|
|
[&](const FileSourceStory &source) {
|
|
|
|
send_closure_later(G()->story_manager(), &StoryManager::reload_story, source.story_full_id, std::move(promise));
|
2019-01-17 21:42:00 +01:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
FileReferenceManager::Destination FileReferenceManager::on_query_result(Destination dest, FileSourceId file_source_id,
|
|
|
|
Status status, int32 sub) {
|
2021-10-07 14:28:52 +02:00
|
|
|
if (G()->close_flag()) {
|
|
|
|
VLOG(file_references) << "Ignore file reference repair from " << file_source_id << " during closing";
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
2019-10-09 01:59:25 +02:00
|
|
|
VLOG(file_references) << "Receive result of file reference repair query for file " << dest.node_id
|
2019-01-21 19:22:56 +01:00
|
|
|
<< " with generation " << dest.generation << " from " << file_source_id << ": " << status << " "
|
|
|
|
<< sub;
|
2022-11-17 17:13:36 +01:00
|
|
|
auto &node = add_node(dest.node_id);
|
2019-01-17 21:42:00 +01:00
|
|
|
|
|
|
|
auto query = node.query.get();
|
|
|
|
if (!query) {
|
2019-01-18 15:52:49 +01:00
|
|
|
return dest;
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
|
|
|
if (query->generation != dest.generation) {
|
2019-01-18 15:52:49 +01:00
|
|
|
return dest;
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
|
|
|
query->active_queries--;
|
2019-01-18 15:52:49 +01:00
|
|
|
CHECK(query->active_queries >= 0);
|
2019-01-17 21:42:00 +01:00
|
|
|
|
2021-12-01 18:54:56 +01:00
|
|
|
if (!query->proxy.is_empty()) {
|
2019-01-17 21:42:00 +01:00
|
|
|
query->active_queries -= sub;
|
2019-01-18 15:52:49 +01:00
|
|
|
CHECK(query->active_queries >= 0);
|
2019-01-17 21:42:00 +01:00
|
|
|
auto new_proxy = on_query_result(query->proxy, file_source_id, std::move(status), query->active_queries);
|
2019-01-18 15:52:49 +01:00
|
|
|
query->proxy = new_proxy;
|
2019-01-17 21:42:00 +01:00
|
|
|
run_node(dest.node_id);
|
|
|
|
return new_proxy;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status.is_ok()) {
|
2019-10-18 03:30:49 +02:00
|
|
|
node.last_successful_repair_time = Time::now();
|
2019-01-17 21:42:00 +01:00
|
|
|
for (auto &p : query->promises) {
|
|
|
|
p.set_value(Unit());
|
|
|
|
}
|
|
|
|
node.query = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
run_node(dest.node_id);
|
|
|
|
return dest;
|
2018-12-05 10:32:31 +01:00
|
|
|
}
|
|
|
|
|
2019-01-18 21:12:09 +01:00
|
|
|
void FileReferenceManager::repair_file_reference(NodeId node_id, Promise<> promise) {
|
2022-07-03 11:01:08 +02:00
|
|
|
auto main_file_id = G()->td().get_actor_unsafe()->file_manager_->get_file_view(node_id).get_main_file_id();
|
2020-06-28 16:42:19 +02:00
|
|
|
VLOG(file_references) << "Repair file reference for file " << node_id << "/" << main_file_id;
|
|
|
|
node_id = main_file_id;
|
2022-11-17 17:13:36 +01:00
|
|
|
auto &node = add_node(node_id);
|
2019-01-17 21:42:00 +01:00
|
|
|
if (!node.query) {
|
|
|
|
node.query = make_unique<Query>();
|
2019-01-18 20:36:23 +01:00
|
|
|
node.query->generation = ++query_generation_;
|
2019-01-17 21:42:00 +01:00
|
|
|
node.file_source_ids.reset_position();
|
2019-01-30 22:37:38 +01:00
|
|
|
VLOG(file_references) << "Create new file reference repair query with generation " << query_generation_;
|
2019-01-17 21:42:00 +01:00
|
|
|
}
|
2019-01-18 15:52:49 +01:00
|
|
|
node.query->promises.push_back(std::move(promise));
|
2019-01-17 21:42:00 +01:00
|
|
|
run_node(node_id);
|
|
|
|
}
|
2019-01-18 20:36:23 +01:00
|
|
|
|
2019-07-30 16:42:36 +02:00
|
|
|
void FileReferenceManager::reload_photo(PhotoSizeSource source, Promise<Unit> promise) {
|
2021-11-14 08:47:02 +01:00
|
|
|
switch (source.get_type("reload_photo")) {
|
2019-07-30 16:42:36 +02:00
|
|
|
case PhotoSizeSource::Type::DialogPhotoBig:
|
|
|
|
case PhotoSizeSource::Type::DialogPhotoSmall:
|
2021-04-16 16:43:51 +02:00
|
|
|
case PhotoSizeSource::Type::DialogPhotoBigLegacy:
|
|
|
|
case PhotoSizeSource::Type::DialogPhotoSmallLegacy:
|
2019-07-30 17:43:29 +02:00
|
|
|
send_closure(G()->contacts_manager(), &ContactsManager::reload_dialog_info, source.dialog_photo().dialog_id,
|
2019-07-30 16:42:36 +02:00
|
|
|
std::move(promise));
|
|
|
|
break;
|
|
|
|
case PhotoSizeSource::Type::StickerSetThumbnail:
|
2021-04-16 16:43:51 +02:00
|
|
|
case PhotoSizeSource::Type::StickerSetThumbnailLegacy:
|
|
|
|
case PhotoSizeSource::Type::StickerSetThumbnailVersion:
|
2019-07-30 17:43:29 +02:00
|
|
|
send_closure(G()->stickers_manager(), &StickersManager::reload_sticker_set,
|
2019-09-18 05:55:43 +02:00
|
|
|
StickerSetId(source.sticker_set_thumbnail().sticker_set_id),
|
2019-07-30 17:43:29 +02:00
|
|
|
source.sticker_set_thumbnail().sticker_set_access_hash, std::move(promise));
|
|
|
|
break;
|
2021-04-16 16:43:51 +02:00
|
|
|
case PhotoSizeSource::Type::Legacy:
|
|
|
|
case PhotoSizeSource::Type::FullLegacy:
|
|
|
|
case PhotoSizeSource::Type::Thumbnail:
|
2019-07-30 17:43:29 +02:00
|
|
|
promise.set_error(Status::Error("Unexpected PhotoSizeSource type"));
|
2021-04-16 16:43:51 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2019-07-30 16:42:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-01 21:09:40 +01:00
|
|
|
void FileReferenceManager::get_file_search_text(FileSourceId file_source_id, string unique_file_id,
|
|
|
|
Promise<string> promise) {
|
2022-02-26 19:52:14 +01:00
|
|
|
auto index = static_cast<size_t>(file_source_id.get()) - 1;
|
|
|
|
CHECK(index < file_sources_.size());
|
|
|
|
file_sources_[index].visit(overloaded(
|
|
|
|
[&](const FileSourceMessage &source) {
|
2022-03-01 21:09:40 +01:00
|
|
|
send_closure_later(G()->messages_manager(), &MessagesManager::get_message_file_search_text,
|
2022-02-27 16:23:06 +01:00
|
|
|
source.full_message_id, std::move(unique_file_id), std::move(promise));
|
2022-02-26 19:52:14 +01:00
|
|
|
},
|
|
|
|
[&](const auto &source) { promise.set_error(Status::Error(500, "Unsupported file source")); }));
|
|
|
|
}
|
|
|
|
|
2022-02-27 16:23:06 +01:00
|
|
|
td_api::object_ptr<td_api::message> FileReferenceManager::get_message_object(FileSourceId file_source_id) const {
|
|
|
|
auto index = static_cast<size_t>(file_source_id.get()) - 1;
|
|
|
|
CHECK(index < file_sources_.size());
|
|
|
|
td_api::object_ptr<td_api::message> result;
|
|
|
|
file_sources_[index].visit(overloaded(
|
|
|
|
[&](const FileSourceMessage &source) {
|
|
|
|
result = G()->td().get_actor_unsafe()->messages_manager_->get_message_object(source.full_message_id,
|
|
|
|
"FileReferenceManager");
|
|
|
|
},
|
|
|
|
[&](const auto &source) { LOG(ERROR) << "Unsupported file source"; }));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-12-05 10:32:31 +01:00
|
|
|
} // namespace td
|