1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #pragma once
8 
9 #include "td/telegram/BackgroundId.h"
10 #include "td/telegram/ChannelId.h"
11 #include "td/telegram/ChatId.h"
12 #include "td/telegram/files/FileId.h"
13 #include "td/telegram/files/FileSourceId.h"
14 #include "td/telegram/FullMessageId.h"
15 #include "td/telegram/PhotoSizeSource.h"
16 #include "td/telegram/SetWithPosition.h"
17 #include "td/telegram/UserId.h"
18 
19 #include "td/actor/actor.h"
20 #include "td/actor/PromiseFuture.h"
21 
22 #include "td/utils/common.h"
23 #include "td/utils/logging.h"
24 #include "td/utils/Slice.h"
25 #include "td/utils/Status.h"
26 #include "td/utils/Variant.h"
27 
28 #include <unordered_map>
29 
30 namespace td {
31 
32 class Td;
33 
34 extern int VERBOSITY_NAME(file_references);
35 
36 class FileReferenceManager final : public Actor {
37  public:
38   static bool is_file_reference_error(const Status &error);
39   static size_t get_file_reference_error_pos(const Status &error);
40 
41   FileSourceId create_message_file_source(FullMessageId full_message_id);
42   FileSourceId create_user_photo_file_source(UserId user_id, int64 photo_id);
43   // file reference aren't used for chat/channel photo download and the photos can't be reused
44   // FileSourceId create_chat_photo_file_source(ChatId chat_id);
45   // FileSourceId create_channel_photo_file_source(ChannelId channel_id);
46   // FileSourceId create_wallpapers_file_source();  old wallpapers can't be repaired
47   FileSourceId create_web_page_file_source(string url);
48   FileSourceId create_saved_animations_file_source();
49   FileSourceId create_recent_stickers_file_source(bool is_attached);
50   FileSourceId create_favorite_stickers_file_source();
51   FileSourceId create_background_file_source(BackgroundId background_id, int64 access_hash);
52   FileSourceId create_chat_full_file_source(ChatId chat_id);
53   FileSourceId create_channel_full_file_source(ChannelId channel_id);
54   FileSourceId create_app_config_file_source();
55 
56   using NodeId = FileId;
57   void repair_file_reference(NodeId node_id, Promise<> promise);
58 
59   static void reload_photo(PhotoSizeSource source, Promise<Unit> promise);
60 
61   bool add_file_source(NodeId node_id, FileSourceId file_source_id);
62 
63   vector<FileSourceId> get_some_file_sources(NodeId node_id);
64 
65   vector<FullMessageId> get_some_message_file_sources(NodeId node_id);
66 
67   bool remove_file_source(NodeId node_id, FileSourceId file_source_id);
68 
69   void merge(NodeId to_node_id, NodeId from_node_id);
70 
71   template <class StorerT>
72   void store_file_source(FileSourceId file_source_id, StorerT &storer) const;
73 
74   template <class ParserT>
75   FileSourceId parse_file_source(Td *td, ParserT &parser);
76 
77  private:
78   struct Destination {
79     NodeId node_id;
80     int64 generation{0};
81 
82     Destination() = default;
DestinationDestination83     Destination(NodeId node_id, int64 generation) : node_id(node_id), generation(generation) {
84     }
is_emptyDestination85     bool is_empty() const {
86       return node_id.empty();
87     }
88   };
89   struct Query {
90     std::vector<Promise<>> promises;
91     int32 active_queries{0};
92     Destination proxy;
93     int64 generation{0};
94   };
95 
96   struct Node {
97     SetWithPosition<FileSourceId> file_source_ids;
98     unique_ptr<Query> query;
99     double last_successful_repair_time = -1e10;
100   };
101 
102   struct FileSourceMessage {
103     FullMessageId full_message_id;
104   };
105   struct FileSourceUserPhoto {
106     int64 photo_id;
107     UserId user_id;
108   };
109   struct FileSourceChatPhoto {
110     ChatId chat_id;
111   };
112   struct FileSourceChannelPhoto {
113     ChannelId channel_id;
114   };
115   struct FileSourceWallpapers {
116     // empty
117   };
118   struct FileSourceWebPage {
119     string url;
120   };
121   struct FileSourceSavedAnimations {
122     // empty
123   };
124   struct FileSourceRecentStickers {
125     bool is_attached;
126   };
127   struct FileSourceFavoriteStickers {
128     // empty
129   };
130   struct FileSourceBackground {
131     BackgroundId background_id;
132     int64 access_hash;
133   };
134   struct FileSourceChatFull {
135     ChatId chat_id;
136   };
137   struct FileSourceChannelFull {
138     ChannelId channel_id;
139   };
140   struct FileSourceAppConfig {
141     // empty
142   };
143 
144   // append only
145   using FileSource =
146       Variant<FileSourceMessage, FileSourceUserPhoto, FileSourceChatPhoto, FileSourceChannelPhoto, FileSourceWallpapers,
147               FileSourceWebPage, FileSourceSavedAnimations, FileSourceRecentStickers, FileSourceFavoriteStickers,
148               FileSourceBackground, FileSourceChatFull, FileSourceChannelFull, FileSourceAppConfig>;
149   vector<FileSource> file_sources_;
150 
151   int64 query_generation_{0};
152 
153   std::unordered_map<NodeId, Node, FileIdHash> nodes_;
154 
155   void run_node(NodeId node);
156   void send_query(Destination dest, FileSourceId file_source_id);
157   Destination on_query_result(Destination dest, FileSourceId file_source_id, Status status, int32 sub = 0);
158 
159   template <class T>
160   FileSourceId add_file_source_id(T source, Slice source_str);
161 
162   FileSourceId get_current_file_source_id() const;
163 };
164 
165 }  // namespace td
166