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/DialogId.h"
10 #include "td/telegram/files/FileId.h"
11 #include "td/telegram/files/FileSourceId.h"
12 #include "td/telegram/FullMessageId.h"
13 #include "td/telegram/Photo.h"
14 #include "td/telegram/SecretInputMedia.h"
15 #include "td/telegram/SpecialStickerSetType.h"
16 #include "td/telegram/StickerSetId.h"
17 #include "td/telegram/td_api.h"
18 #include "td/telegram/telegram_api.h"
19 
20 #include "td/actor/actor.h"
21 #include "td/actor/MultiPromise.h"
22 #include "td/actor/PromiseFuture.h"
23 #include "td/actor/Timeout.h"
24 
25 #include "td/utils/buffer.h"
26 #include "td/utils/common.h"
27 #include "td/utils/Hints.h"
28 #include "td/utils/Slice.h"
29 #include "td/utils/Status.h"
30 
31 #include <memory>
32 #include <tuple>
33 #include <unordered_map>
34 #include <unordered_set>
35 #include <utility>
36 
37 namespace td {
38 
39 class Td;
40 
41 class StickersManager final : public Actor {
42  public:
43   static constexpr int64 GREAT_MINDS_SET_ID = 1842540969984001;
44 
45   static vector<StickerSetId> convert_sticker_set_ids(const vector<int64> &sticker_set_ids);
46   static vector<int64> convert_sticker_set_ids(const vector<StickerSetId> &sticker_set_ids);
47 
48   StickersManager(Td *td, ActorShared<> parent);
49 
50   void init();
51 
52   tl_object_ptr<td_api::sticker> get_sticker_object(FileId file_id, bool for_animated_emoji = false,
53                                                     bool for_clicked_animated_emoji = false) const;
54 
55   tl_object_ptr<td_api::stickers> get_stickers_object(const vector<FileId> &sticker_ids) const;
56 
57   tl_object_ptr<td_api::DiceStickers> get_dice_stickers_object(const string &emoji, int32 value) const;
58 
59   int32 get_dice_success_animation_frame_number(const string &emoji, int32 value) const;
60 
61   tl_object_ptr<td_api::stickerSet> get_sticker_set_object(StickerSetId sticker_set_id) const;
62 
63   tl_object_ptr<td_api::stickerSets> get_sticker_sets_object(int32 total_count,
64                                                              const vector<StickerSetId> &sticker_set_ids,
65                                                              size_t covers_limit) const;
66 
67   td_api::object_ptr<td_api::animatedEmoji> get_animated_emoji_object(const string &emoji);
68 
69   tl_object_ptr<telegram_api::InputStickerSet> get_input_sticker_set(StickerSetId sticker_set_id) const;
70 
71   void register_dice(const string &emoji, int32 value, FullMessageId full_message_id, const char *source);
72 
73   void unregister_dice(const string &emoji, int32 value, FullMessageId full_message_id, const char *source);
74 
75   void register_emoji(const string &emoji, FullMessageId full_message_id, const char *source);
76 
77   void unregister_emoji(const string &emoji, FullMessageId full_message_id, const char *source);
78 
79   void get_animated_emoji(string emoji, bool is_recursive,
80                           Promise<td_api::object_ptr<td_api::animatedEmoji>> &&promise);
81 
82   void get_animated_emoji_click_sticker(const string &message_text, FullMessageId full_message_id,
83                                         Promise<td_api::object_ptr<td_api::sticker>> &&promise);
84 
85   void on_send_animated_emoji_clicks(DialogId dialog_id, const string &emoji);
86 
87   bool is_sent_animated_emoji_click(DialogId dialog_id, Slice emoji);
88 
89   Status on_animated_emoji_message_clicked(Slice emoji, FullMessageId full_message_id, string data);
90 
91   void create_sticker(FileId file_id, string minithumbnail, PhotoSize thumbnail, Dimensions dimensions,
92                       tl_object_ptr<telegram_api::documentAttributeSticker> sticker, bool is_animated,
93                       MultiPromiseActor *load_data_multipromise_ptr);
94 
95   bool has_input_media(FileId sticker_file_id, bool is_secret) const;
96 
97   tl_object_ptr<telegram_api::InputMedia> get_input_media(FileId file_id,
98                                                           tl_object_ptr<telegram_api::InputFile> input_file,
99                                                           tl_object_ptr<telegram_api::InputFile> input_thumbnail,
100                                                           const string &emoji) const;
101 
102   SecretInputMedia get_secret_input_media(FileId sticker_file_id,
103                                           tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
104                                           BufferSlice thumbnail) const;
105 
106   vector<FileId> get_stickers(string emoji, int32 limit, bool force, Promise<Unit> &&promise);
107 
108   vector<FileId> search_stickers(string emoji, int32 limit, Promise<Unit> &&promise);
109 
110   vector<StickerSetId> get_installed_sticker_sets(bool is_masks, Promise<Unit> &&promise);
111 
112   static bool has_webp_thumbnail(const vector<tl_object_ptr<telegram_api::PhotoSize>> &thumbnails);
113 
114   StickerSetId get_sticker_set_id(const tl_object_ptr<telegram_api::InputStickerSet> &set_ptr);
115 
116   StickerSetId add_sticker_set(tl_object_ptr<telegram_api::InputStickerSet> &&set_ptr);
117 
118   StickerSetId get_sticker_set(StickerSetId set_id, Promise<Unit> &&promise);
119 
120   StickerSetId search_sticker_set(const string &short_name_to_search, Promise<Unit> &&promise);
121 
122   std::pair<int32, vector<StickerSetId>> search_installed_sticker_sets(bool is_masks, const string &query, int32 limit,
123                                                                        Promise<Unit> &&promise);
124 
125   vector<StickerSetId> search_sticker_sets(const string &query, Promise<Unit> &&promise);
126 
127   void change_sticker_set(StickerSetId set_id, bool is_installed, bool is_archived, Promise<Unit> &&promise);
128 
129   void view_featured_sticker_sets(const vector<StickerSetId> &sticker_set_ids);
130 
131   void on_get_installed_sticker_sets(bool is_masks, tl_object_ptr<telegram_api::messages_AllStickers> &&stickers_ptr);
132 
133   void on_get_installed_sticker_sets_failed(bool is_masks, Status error);
134 
135   StickerSetId on_get_messages_sticker_set(StickerSetId sticker_set_id,
136                                            tl_object_ptr<telegram_api::messages_StickerSet> &&set_ptr, bool is_changed,
137                                            const char *source);
138 
139   StickerSetId on_get_sticker_set(tl_object_ptr<telegram_api::stickerSet> &&set, bool is_changed, const char *source);
140 
141   StickerSetId on_get_sticker_set_covered(tl_object_ptr<telegram_api::StickerSetCovered> &&set_ptr, bool is_changed,
142                                           const char *source);
143 
144   void on_get_special_sticker_set(const SpecialStickerSetType &type, StickerSetId sticker_set_id);
145 
146   void on_load_special_sticker_set(const SpecialStickerSetType &type, Status result);
147 
148   void on_load_sticker_set_fail(StickerSetId sticker_set_id, const Status &error);
149 
150   void on_install_sticker_set(StickerSetId set_id, bool is_archived,
151                               tl_object_ptr<telegram_api::messages_StickerSetInstallResult> &&result);
152 
153   void on_uninstall_sticker_set(StickerSetId set_id);
154 
155   void on_update_animated_emoji_zoom();
156 
157   void on_update_disable_animated_emojis();
158 
159   void on_update_dice_emojis();
160 
161   void on_update_dice_success_values();
162 
163   void on_update_emoji_sounds();
164 
165   void on_update_sticker_sets();
166 
167   void on_update_sticker_sets_order(bool is_masks, const vector<StickerSetId> &sticker_set_ids);
168 
169   std::pair<int32, vector<StickerSetId>> get_archived_sticker_sets(bool is_masks, StickerSetId offset_sticker_set_id,
170                                                                    int32 limit, bool force, Promise<Unit> &&promise);
171 
172   void on_get_archived_sticker_sets(bool is_masks, StickerSetId offset_sticker_set_id,
173                                     vector<tl_object_ptr<telegram_api::StickerSetCovered>> &&sticker_sets,
174                                     int32 total_count);
175 
176   std::pair<int32, vector<StickerSetId>> get_featured_sticker_sets(int32 offset, int32 limit, Promise<Unit> &&promise);
177 
178   void on_get_featured_sticker_sets(int32 offset, int32 limit, uint32 generation,
179                                     tl_object_ptr<telegram_api::messages_FeaturedStickers> &&sticker_sets_ptr);
180 
181   void on_get_featured_sticker_sets_failed(int32 offset, int32 limit, uint32 generation, Status error);
182 
183   vector<StickerSetId> get_attached_sticker_sets(FileId file_id, Promise<Unit> &&promise);
184 
185   void on_get_attached_sticker_sets(FileId file_id,
186                                     vector<tl_object_ptr<telegram_api::StickerSetCovered>> &&sticker_sets);
187 
188   void reorder_installed_sticker_sets(bool is_masks, const vector<StickerSetId> &sticker_set_ids,
189                                       Promise<Unit> &&promise);
190 
191   FileId upload_sticker_file(UserId user_id, tl_object_ptr<td_api::InputSticker> &&sticker, Promise<Unit> &&promise);
192 
193   void get_suggested_sticker_set_name(string title, Promise<string> &&promise);
194 
195   enum class CheckStickerSetNameResult : uint8 { Ok, Invalid, Occupied };
196   void check_sticker_set_name(const string &name, Promise<CheckStickerSetNameResult> &&promise);
197 
198   static td_api::object_ptr<td_api::CheckStickerSetNameResult> get_check_sticker_set_name_result_object(
199       CheckStickerSetNameResult result);
200 
201   void create_new_sticker_set(UserId user_id, string &title, string &short_name, bool is_masks,
202                               vector<tl_object_ptr<td_api::InputSticker>> &&stickers, string software,
203                               Promise<Unit> &&promise);
204 
205   void add_sticker_to_set(UserId user_id, string &short_name, tl_object_ptr<td_api::InputSticker> &&sticker,
206                           Promise<Unit> &&promise);
207 
208   void set_sticker_set_thumbnail(UserId user_id, string &short_name, tl_object_ptr<td_api::InputFile> &&thumbnail,
209                                  Promise<Unit> &&promise);
210 
211   void set_sticker_position_in_set(const tl_object_ptr<td_api::InputFile> &sticker, int32 position,
212                                    Promise<Unit> &&promise);
213 
214   void remove_sticker_from_set(const tl_object_ptr<td_api::InputFile> &sticker, Promise<Unit> &&promise);
215 
216   vector<FileId> get_recent_stickers(bool is_attached, Promise<Unit> &&promise);
217 
218   void on_get_recent_stickers(bool is_repair, bool is_attached,
219                               tl_object_ptr<telegram_api::messages_RecentStickers> &&stickers_ptr);
220 
221   void on_get_recent_stickers_failed(bool is_repair, bool is_attached, Status error);
222 
223   FileSourceId get_recent_stickers_file_source_id(int is_attached);
224 
225   void add_recent_sticker(bool is_attached, const tl_object_ptr<td_api::InputFile> &input_file,
226                           Promise<Unit> &&promise);
227 
228   void add_recent_sticker_by_id(bool is_attached, FileId sticker_id);
229 
230   void remove_recent_sticker(bool is_attached, const tl_object_ptr<td_api::InputFile> &input_file,
231                              Promise<Unit> &&promise);
232 
233   void send_save_recent_sticker_query(bool is_attached, FileId sticker_id, bool unsave, Promise<Unit> &&promise);
234 
235   void clear_recent_stickers(bool is_attached, Promise<Unit> &&promise);
236 
237   void on_update_recent_stickers_limit(int32 recent_stickers_limit);
238 
239   void on_update_favorite_stickers_limit(int32 favorite_stickers_limit);
240 
241   void reload_favorite_stickers(bool force);
242 
243   void repair_favorite_stickers(Promise<Unit> &&promise);
244 
245   void on_get_favorite_stickers(bool is_repair,
246                                 tl_object_ptr<telegram_api::messages_FavedStickers> &&favorite_stickers_ptr);
247 
248   void on_get_favorite_stickers_failed(bool is_repair, Status error);
249 
250   FileSourceId get_app_config_file_source_id();
251 
252   FileSourceId get_favorite_stickers_file_source_id();
253 
254   vector<FileId> get_favorite_stickers(Promise<Unit> &&promise);
255 
256   void add_favorite_sticker(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
257 
258   void add_favorite_sticker_by_id(FileId sticker_id);
259 
260   void remove_favorite_sticker(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
261 
262   void send_fave_sticker_query(FileId sticker_id, bool unsave, Promise<Unit> &&promise);
263 
264   vector<FileId> get_attached_sticker_file_ids(const vector<int32> &int_file_ids);
265 
266   vector<string> get_sticker_emojis(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
267 
268   vector<string> search_emojis(const string &text, bool exact_match, const vector<string> &input_language_codes,
269                                bool force, Promise<Unit> &&promise);
270 
271   int64 get_emoji_suggestions_url(const string &language_code, Promise<Unit> &&promise);
272 
273   td_api::object_ptr<td_api::httpUrl> get_emoji_suggestions_url_result(int64 random_id);
274 
275   void reload_sticker_set(StickerSetId sticker_set_id, int64 access_hash, Promise<Unit> &&promise);
276 
277   void reload_installed_sticker_sets(bool is_masks, bool force);
278 
279   void reload_featured_sticker_sets(bool force);
280 
281   void reload_recent_stickers(bool is_attached, bool force);
282 
283   void repair_recent_stickers(bool is_attached, Promise<Unit> &&promise);
284 
285   FileId get_sticker_thumbnail_file_id(FileId file_id) const;
286 
287   vector<FileId> get_sticker_file_ids(FileId file_id) const;
288 
289   void delete_sticker_thumbnail(FileId file_id);
290 
291   FileId dup_sticker(FileId new_id, FileId old_id);
292 
293   void merge_stickers(FileId new_id, FileId old_id, bool can_delete_old);
294 
295   template <class StorerT>
296   void store_sticker(FileId file_id, bool in_sticker_set, StorerT &storer, const char *source) const;
297 
298   template <class ParserT>
299   FileId parse_sticker(bool in_sticker_set, ParserT &parser);
300 
301   void on_uploaded_sticker_file(FileId file_id, tl_object_ptr<telegram_api::MessageMedia> media,
302                                 Promise<Unit> &&promise);
303 
304   void on_find_stickers_success(const string &emoji, tl_object_ptr<telegram_api::messages_Stickers> &&stickers);
305 
306   void on_find_stickers_fail(const string &emoji, Status &&error);
307 
308   void on_find_sticker_sets_success(const string &query,
309                                     tl_object_ptr<telegram_api::messages_FoundStickerSets> &&sticker_sets);
310 
311   void on_find_sticker_sets_fail(const string &query, Status &&error);
312 
313   void send_get_attached_stickers_query(FileId file_id, Promise<Unit> &&promise);
314 
315   void after_get_difference();
316 
317   void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
318 
319   template <class StorerT>
320   void store_sticker_set_id(StickerSetId sticker_set_id, StorerT &storer) const;
321 
322   template <class ParserT>
323   void parse_sticker_set_id(StickerSetId &sticker_set_id, ParserT &parser);
324 
325  private:
326   static constexpr int32 MAX_FEATURED_STICKER_SET_VIEW_DELAY = 5;
327   static constexpr int32 OLD_FEATURED_STICKER_SET_SLICE_SIZE = 20;
328 
329   static constexpr int32 MAX_FOUND_STICKERS = 100;                    // server side limit
330   static constexpr int64 MAX_STICKER_FILE_SIZE = 1 << 19;             // server side limit
331   static constexpr int64 MAX_THUMBNAIL_FILE_SIZE = 1 << 17;           // server side limit
332   static constexpr int64 MAX_ANIMATED_STICKER_FILE_SIZE = 1 << 16;    // server side limit
333   static constexpr int64 MAX_ANIMATED_THUMBNAIL_FILE_SIZE = 1 << 15;  // server side limit
334   static constexpr size_t MAX_STICKER_SET_TITLE_LENGTH = 64;          // server side limit
335   static constexpr size_t MAX_STICKER_SET_SHORT_NAME_LENGTH = 64;     // server side limit
336 
337   static constexpr int32 EMOJI_KEYWORDS_UPDATE_DELAY = 3600;
338   static constexpr double MIN_ANIMATED_EMOJI_CLICK_DELAY = 0.2;
339 
340   class Sticker {
341    public:
342     StickerSetId set_id;
343     string alt;
344     Dimensions dimensions;
345     string minithumbnail;
346     PhotoSize s_thumbnail;
347     PhotoSize m_thumbnail;
348     FileId file_id;
349     bool is_animated = false;
350     bool is_mask = false;
351     int32 point = -1;
352     double x_shift = 0;
353     double y_shift = 0;
354     double scale = 0;
355   };
356 
357   class StickerSet {
358    public:
359     bool is_inited = false;  // basic information about the set
360     bool was_loaded = false;
361     bool is_loaded = false;
362 
363     StickerSetId id;
364     int64 access_hash = 0;
365     string title;
366     string short_name;
367     int32 sticker_count = 0;
368     int32 hash = 0;
369     int32 expires_at = 0;
370 
371     string minithumbnail;
372     PhotoSize thumbnail;
373 
374     vector<FileId> sticker_ids;
375     std::unordered_map<string, vector<FileId>> emoji_stickers_map_;              // emoji -> stickers
376     std::unordered_map<FileId, vector<string>, FileIdHash> sticker_emojis_map_;  // sticker -> emojis
377 
378     bool is_installed = false;
379     bool is_archived = false;
380     bool is_official = false;
381     bool is_animated = false;
382     bool is_masks = false;
383     bool is_viewed = true;
384     bool is_thumbnail_reloaded = false;
385     bool are_legacy_sticker_thumbnails_reloaded = false;
386     mutable bool was_update_sent = false;  // does the sticker set is known to the client
387     bool is_changed = true;                // have new changes that need to be sent to the client and database
388     bool need_save_to_database = true;     // have new changes that need only to be saved to the database
389 
390     vector<uint32> load_requests;
391     vector<uint32> load_without_stickers_requests;
392   };
393 
394   struct PendingNewStickerSet {
395     MultiPromiseActor upload_files_multipromise{"UploadNewStickerSetFilesMultiPromiseActor"};
396     UserId user_id;
397     string title;
398     string short_name;
399     bool is_masks = false;
400     bool is_animated = false;
401     vector<FileId> file_ids;
402     vector<tl_object_ptr<td_api::InputSticker>> stickers;
403     string software;
404     Promise<> promise;
405   };
406 
407   struct PendingAddStickerToSet {
408     string short_name;
409     FileId file_id;
410     tl_object_ptr<td_api::InputSticker> sticker;
411     Promise<> promise;
412   };
413 
414   struct PendingSetStickerSetThumbnail {
415     string short_name;
416     FileId file_id;
417     Promise<> promise;
418   };
419 
420   struct PendingGetAnimatedEmojiClickSticker {
421     string message_text_;
422     FullMessageId full_message_id_;
423     double start_time_ = 0;
424     Promise<td_api::object_ptr<td_api::sticker>> promise_;
425   };
426 
427   struct PendingOnAnimatedEmojiClicked {
428     string emoji_;
429     FullMessageId full_message_id_;
430     vector<std::pair<int, double>> clicks_;
431   };
432 
433   struct SpecialStickerSet {
434     StickerSetId id_;
435     int64 access_hash_ = 0;
436     string short_name_;
437     SpecialStickerSetType type_;
438     bool is_being_loaded_ = false;
439     bool is_being_reloaded_ = false;
440   };
441 
442   class StickerListLogEvent;
443   class StickerSetListLogEvent;
444 
445   class UploadStickerFileCallback;
446 
447   static vector<td_api::object_ptr<td_api::closedVectorPath>> get_sticker_minithumbnail(CSlice path,
448                                                                                         StickerSetId sticker_set_id,
449                                                                                         int64 document_id, double zoom);
450 
451   static tl_object_ptr<td_api::MaskPoint> get_mask_point_object(int32 point);
452 
453   tl_object_ptr<td_api::stickerSetInfo> get_sticker_set_info_object(StickerSetId sticker_set_id,
454                                                                     size_t covers_limit) const;
455 
456   Sticker *get_sticker(FileId file_id);
457   const Sticker *get_sticker(FileId file_id) const;
458 
459   FileId on_get_sticker(unique_ptr<Sticker> new_sticker, bool replace);
460 
461   StickerSet *get_sticker_set(StickerSetId sticker_set_id);
462   const StickerSet *get_sticker_set(StickerSetId sticker_set_id) const;
463 
464   StickerSet *add_sticker_set(StickerSetId sticker_set_id, int64 access_hash);
465 
466   std::pair<int64, FileId> on_get_sticker_document(tl_object_ptr<telegram_api::Document> &&document_ptr);
467 
468   static tl_object_ptr<telegram_api::InputStickerSet> get_input_sticker_set(const StickerSet *set);
469 
470   StickerSetId on_get_input_sticker_set(FileId sticker_file_id, tl_object_ptr<telegram_api::InputStickerSet> &&set_ptr,
471                                         MultiPromiseActor *load_data_multipromise_ptr = nullptr);
472 
473   void on_resolve_sticker_set_short_name(FileId sticker_file_id, const string &short_name);
474 
475   int apply_installed_sticker_sets_order(bool is_masks, const vector<StickerSetId> &sticker_set_ids);
476 
477   void on_update_sticker_set(StickerSet *sticker_set, bool is_installed, bool is_archived, bool is_changed,
478                              bool from_database = false);
479 
480   static string get_sticker_set_database_key(StickerSetId set_id);
481 
482   static string get_full_sticker_set_database_key(StickerSetId set_id);
483 
484   string get_sticker_set_database_value(const StickerSet *s, bool with_stickers, const char *source);
485 
486   void update_sticker_set(StickerSet *sticker_set, const char *source);
487 
488   void load_sticker_sets(vector<StickerSetId> &&sticker_set_ids, Promise<Unit> &&promise);
489 
490   void load_sticker_sets_without_stickers(vector<StickerSetId> &&sticker_set_ids, Promise<Unit> &&promise);
491 
492   void on_load_sticker_set_from_database(StickerSetId sticker_set_id, bool with_stickers, string value);
493 
494   void update_load_requests(StickerSet *sticker_set, bool with_stickers, const Status &status);
495 
496   void update_load_request(uint32 load_request_id, const Status &status);
497 
498   void do_reload_sticker_set(StickerSetId sticker_set_id,
499                              tl_object_ptr<telegram_api::InputStickerSet> &&input_sticker_set, int32 hash,
500                              Promise<Unit> &&promise) const;
501 
502   static void read_featured_sticker_sets(void *td_void);
503 
504   int64 get_sticker_sets_hash(const vector<StickerSetId> &sticker_set_ids) const;
505 
506   int64 get_featured_sticker_sets_hash() const;
507 
508   int64 get_recent_stickers_hash(const vector<FileId> &sticker_ids) const;
509 
510   void load_installed_sticker_sets(bool is_masks, Promise<Unit> &&promise);
511 
512   void load_featured_sticker_sets(Promise<Unit> &&promise);
513 
514   void load_old_featured_sticker_sets(Promise<Unit> &&promise);
515 
516   void load_recent_stickers(bool is_attached, Promise<Unit> &&promise);
517 
518   void on_load_installed_sticker_sets_from_database(bool is_masks, string value);
519 
520   void on_load_installed_sticker_sets_finished(bool is_masks, vector<StickerSetId> &&installed_sticker_set_ids,
521                                                bool from_database = false);
522 
523   void on_load_featured_sticker_sets_from_database(string value);
524 
525   void on_load_featured_sticker_sets_finished(vector<StickerSetId> &&featured_sticker_set_ids);
526 
527   void on_load_old_featured_sticker_sets_from_database(uint32 generation, string value);
528 
529   void on_load_old_featured_sticker_sets_finished(uint32 generation,
530                                                   vector<StickerSetId> &&old_featured_sticker_set_ids);
531 
532   void on_load_recent_stickers_from_database(bool is_attached, string value);
533 
534   void on_load_recent_stickers_finished(bool is_attached, vector<FileId> &&recent_sticker_ids,
535                                         bool from_database = false);
536 
537   td_api::object_ptr<td_api::updateInstalledStickerSets> get_update_installed_sticker_sets_object(int is_mask) const;
538 
539   void send_update_installed_sticker_sets(bool from_database = false);
540 
541   void reload_old_featured_sticker_sets(uint32 generation = 0);
542 
543   void on_old_featured_sticker_sets_invalidated();
544 
545   void invalidate_old_featured_sticker_sets();
546 
547   void set_old_featured_sticker_set_count(int32 count);
548 
549   // must be called after every call to set_old_featured_sticker_set_count or
550   // any change of old_featured_sticker_set_ids_ size
551   void fix_old_featured_sticker_set_count();
552 
553   td_api::object_ptr<td_api::updateTrendingStickerSets> get_update_trending_sticker_sets_object() const;
554 
555   void send_update_featured_sticker_sets();
556 
557   td_api::object_ptr<td_api::updateRecentStickers> get_update_recent_stickers_object(int is_attached) const;
558 
559   void send_update_recent_stickers(bool is_attached, bool from_database = false);
560 
561   void save_recent_stickers_to_database(bool is_attached);
562 
563   void add_recent_sticker_impl(bool is_attached, FileId sticker_id, bool add_on_server, Promise<Unit> &&promise);
564 
565   int64 get_favorite_stickers_hash() const;
566 
567   void add_favorite_sticker_impl(FileId sticker_id, bool add_on_server, Promise<Unit> &&promise);
568 
569   void load_favorite_stickers(Promise<Unit> &&promise);
570 
571   void on_load_favorite_stickers_from_database(const string &value);
572 
573   void on_load_favorite_stickers_finished(vector<FileId> &&favorite_sticker_ids, bool from_database = false);
574 
575   td_api::object_ptr<td_api::updateFavoriteStickers> get_update_favorite_stickers_object() const;
576 
577   void send_update_favorite_stickers(bool from_database = false);
578 
579   void save_favorite_stickers_to_database();
580 
581   template <class StorerT>
582   void store_sticker_set(const StickerSet *sticker_set, bool with_stickers, StorerT &storer, const char *source) const;
583 
584   template <class ParserT>
585   void parse_sticker_set(StickerSet *sticker_set, ParserT &parser);
586 
587   static string &get_input_sticker_emojis(td_api::InputSticker *sticker);
588 
589   Result<std::tuple<FileId, bool, bool, bool>> prepare_input_file(const tl_object_ptr<td_api::InputFile> &input_file,
590                                                                   bool is_animated, bool for_thumbnail);
591 
592   Result<std::tuple<FileId, bool, bool, bool>> prepare_input_sticker(td_api::InputSticker *sticker);
593 
594   tl_object_ptr<telegram_api::inputStickerSetItem> get_input_sticker(td_api::InputSticker *sticker,
595                                                                      FileId file_id) const;
596 
597   void upload_sticker_file(UserId user_id, FileId file_id, Promise<Unit> &&promise);
598 
599   void on_upload_sticker_file(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file);
600 
601   void on_upload_sticker_file_error(FileId file_id, Status status);
602 
603   void do_upload_sticker_file(UserId user_id, FileId file_id, tl_object_ptr<telegram_api::InputFile> &&input_file,
604                               Promise<Unit> &&promise);
605 
606   void on_new_stickers_uploaded(int64 random_id, Result<Unit> result);
607 
608   void on_added_sticker_uploaded(int64 random_id, Result<Unit> result);
609 
610   void on_sticker_set_thumbnail_uploaded(int64 random_id, Result<Unit> result);
611 
612   void do_set_sticker_set_thumbnail(UserId user_id, string short_name, tl_object_ptr<td_api::InputFile> &&thumbnail,
613                                     Promise<Unit> &&promise);
614 
615   bool update_sticker_set_cache(const StickerSet *sticker_set, Promise<Unit> &promise);
616 
617   const StickerSet *get_animated_emoji_sticker_set();
618 
619   static std::pair<FileId, int> get_animated_emoji_sticker(const StickerSet *sticker_set, const string &emoji);
620 
621   std::pair<FileId, int> get_animated_emoji_sticker(const string &emoji);
622 
623   FileId get_animated_emoji_sound_file_id(const string &emoji) const;
624 
625   td_api::object_ptr<td_api::animatedEmoji> get_animated_emoji_object(std::pair<FileId, int> animated_sticker,
626                                                                       FileId sound_file_id) const;
627 
628   void try_update_animated_emoji_messages();
629 
630   static int get_emoji_number(Slice emoji);
631 
632   vector<FileId> get_animated_emoji_click_stickers(const StickerSet *sticker_set, Slice emoji) const;
633 
634   void choose_animated_emoji_click_sticker(const StickerSet *sticker_set, Slice message_text,
635                                            FullMessageId full_message_id, double start_time,
636                                            Promise<td_api::object_ptr<td_api::sticker>> &&promise);
637 
638   void send_click_animated_emoji_message_response(FileId sticker_id,
639                                                   Promise<td_api::object_ptr<td_api::sticker>> &&promise);
640 
641   void flush_sent_animated_emoji_clicks();
642 
643   void flush_pending_animated_emoji_clicks();
644 
645   void schedule_update_animated_emoji_clicked(const StickerSet *sticker_set, Slice emoji, FullMessageId full_message_id,
646                                               vector<std::pair<int, double>> clicks);
647 
648   void send_update_animated_emoji_clicked(FullMessageId full_message_id, FileId sticker_id);
649 
650   td_api::object_ptr<td_api::updateDiceEmojis> get_update_dice_emojis_object() const;
651 
652   void start_up() final;
653 
654   void timeout_expired() final;
655 
656   void tear_down() final;
657 
658   SpecialStickerSet &add_special_sticker_set(const SpecialStickerSetType &type);
659 
660   static void init_special_sticker_set(SpecialStickerSet &sticker_set, int64 sticker_set_id, int64 access_hash,
661                                        string name);
662 
663   void load_special_sticker_set_info_from_binlog(SpecialStickerSet &sticker_set);
664 
665   void load_special_sticker_set_by_type(SpecialStickerSetType type);
666 
667   void load_special_sticker_set(SpecialStickerSet &sticker_set);
668 
669   void reload_special_sticker_set_by_type(SpecialStickerSetType type, bool is_recursive = false);
670 
671   void reload_special_sticker_set(SpecialStickerSet &sticker_set, int32 hash);
672 
673   static void add_sticker_thumbnail(Sticker *s, PhotoSize thumbnail);
674 
675   static string get_sticker_mime_type(const Sticker *s);
676 
677   static string get_emoji_language_code_version_database_key(const string &language_code);
678 
679   static string get_emoji_language_code_last_difference_time_database_key(const string &language_code);
680 
681   static string get_language_emojis_database_key(const string &language_code, const string &text);
682 
683   static string get_emoji_language_codes_database_key(const vector<string> &language_codes);
684 
685   int32 get_emoji_language_code_version(const string &language_code);
686 
687   double get_emoji_language_code_last_difference_time(const string &language_code);
688 
689   vector<string> get_emoji_language_codes(const vector<string> &input_language_codes, Slice text,
690                                           Promise<Unit> &promise);
691 
692   void load_language_codes(vector<string> language_codes, string key, Promise<Unit> &&promise);
693 
694   void on_get_language_codes(const string &key, Result<vector<string>> &&result);
695 
696   static vector<string> search_language_emojis(const string &language_code, const string &text, bool exact_match);
697 
698   void load_emoji_keywords(const string &language_code, Promise<Unit> &&promise);
699 
700   void on_get_emoji_keywords(const string &language_code,
701                              Result<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&result);
702 
703   void load_emoji_keywords_difference(const string &language_code);
704 
705   void on_get_emoji_keywords_difference(
706       const string &language_code, int32 from_version,
707       Result<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&result);
708 
709   void on_get_emoji_suggestions_url(int64 random_id, Promise<Unit> &&promise,
710                                     Result<telegram_api::object_ptr<telegram_api::emojiURL>> &&r_emoji_url);
711 
712   Td *td_;
713   ActorShared<> parent_;
714 
715   bool is_inited_ = false;
716 
717   std::unordered_map<FileId, unique_ptr<Sticker>, FileIdHash> stickers_;                     // file_id -> Sticker
718   std::unordered_map<StickerSetId, unique_ptr<StickerSet>, StickerSetIdHash> sticker_sets_;  // id -> StickerSet
719   std::unordered_map<string, StickerSetId> short_name_to_sticker_set_id_;
720 
721   vector<StickerSetId> installed_sticker_set_ids_[2];
722   vector<StickerSetId> featured_sticker_set_ids_;
723   vector<StickerSetId> old_featured_sticker_set_ids_;
724   vector<FileId> recent_sticker_ids_[2];
725   vector<FileId> favorite_sticker_ids_;
726 
727   double next_installed_sticker_sets_load_time_[2] = {0, 0};
728   double next_featured_sticker_sets_load_time_ = 0;
729   double next_recent_stickers_load_time_[2] = {0, 0};
730   double next_favorite_stickers_load_time_ = 0;
731 
732   int64 installed_sticker_sets_hash_[2] = {0, 0};
733   int64 featured_sticker_sets_hash_ = 0;
734   int64 recent_stickers_hash_[2] = {0, 0};
735 
736   int32 old_featured_sticker_set_count_ = -1;
737   uint32 old_featured_sticker_set_generation_ = 1;
738 
739   bool need_update_installed_sticker_sets_[2] = {false, false};
740   bool need_update_featured_sticker_sets_ = false;
741 
742   bool are_installed_sticker_sets_loaded_[2] = {false, false};
743   bool are_featured_sticker_sets_loaded_ = false;
744   bool are_recent_stickers_loaded_[2] = {false, false};
745   bool are_favorite_stickers_loaded_ = false;
746 
747   bool are_old_featured_sticker_sets_invalidated_ = false;
748 
749   vector<Promise<Unit>> load_installed_sticker_sets_queries_[2];
750   vector<Promise<Unit>> load_featured_sticker_sets_queries_;
751   vector<Promise<Unit>> load_old_featured_sticker_sets_queries_;
752   vector<Promise<Unit>> load_recent_stickers_queries_[2];
753   vector<Promise<Unit>> repair_recent_stickers_queries_[2];
754   vector<Promise<Unit>> load_favorite_stickers_queries_;
755   vector<Promise<Unit>> repair_favorite_stickers_queries_;
756 
757   vector<FileId> recent_sticker_file_ids_[2];
758   FileSourceId recent_stickers_file_source_id_[2];
759   vector<FileId> favorite_sticker_file_ids_;
760   FileSourceId favorite_stickers_file_source_id_;
761 
762   FileSourceId app_config_file_source_id_;
763 
764   vector<StickerSetId> archived_sticker_set_ids_[2];
765   int32 total_archived_sticker_set_count_[2] = {-1, -1};
766 
767   std::unordered_map<FileId, vector<StickerSetId>, FileIdHash> attached_sticker_sets_;
768 
769   Hints installed_sticker_sets_hints_[2];  // search installed sticker sets by their title and name
770 
771   struct FoundStickers {
772     vector<FileId> sticker_ids_;
773     int32 cache_time_ = 300;
774     double next_reload_time_ = 0;
775   };
776   std::unordered_map<string, FoundStickers> found_stickers_;
777   std::unordered_map<string, vector<Promise<Unit>>> search_stickers_queries_;
778 
779   std::unordered_map<string, vector<StickerSetId>> found_sticker_sets_;
780   std::unordered_map<string, vector<Promise<Unit>>> search_sticker_sets_queries_;
781 
782   std::unordered_set<StickerSetId, StickerSetIdHash> pending_viewed_featured_sticker_set_ids_;
783   Timeout pending_featured_sticker_set_views_timeout_;
784 
785   int32 recent_stickers_limit_ = 200;
786   int32 favorite_stickers_limit_ = 5;
787 
788   std::unordered_map<SpecialStickerSetType, SpecialStickerSet, SpecialStickerSetTypeHash> special_sticker_sets_;
789 
790   struct StickerSetLoadRequest {
791     Promise<Unit> promise;
792     Status error;
793     size_t left_queries = 0;
794   };
795 
796   std::unordered_map<uint32, StickerSetLoadRequest> sticker_set_load_requests_;
797   uint32 current_sticker_set_load_request_ = 0;
798 
799   std::unordered_map<int64, unique_ptr<PendingNewStickerSet>> pending_new_sticker_sets_;
800 
801   std::unordered_map<int64, unique_ptr<PendingAddStickerToSet>> pending_add_sticker_to_sets_;
802 
803   std::unordered_map<int64, unique_ptr<PendingSetStickerSetThumbnail>> pending_set_sticker_set_thumbnails_;
804 
805   vector<Promise<Unit>> pending_get_animated_emoji_queries_;
806 
807   double next_click_animated_emoji_message_time_ = 0;
808   double next_update_animated_emoji_clicked_time_ = 0;
809   vector<PendingGetAnimatedEmojiClickSticker> pending_get_animated_emoji_click_stickers_;
810   vector<PendingOnAnimatedEmojiClicked> pending_on_animated_emoji_message_clicked_;
811 
812   string last_clicked_animated_emoji_;
813   FullMessageId last_clicked_animated_emoji_full_message_id_;
814   std::vector<std::pair<int, double>> pending_animated_emoji_clicks_;
815 
816   struct SentAnimatedEmojiClicks {
817     double send_time = 0.0;
818     DialogId dialog_id;
819     string emoji;
820   };
821   std::vector<SentAnimatedEmojiClicks> sent_animated_emoji_clicks_;
822 
823   std::shared_ptr<UploadStickerFileCallback> upload_sticker_file_callback_;
824 
825   std::unordered_map<FileId, std::pair<UserId, Promise<Unit>>, FileIdHash> being_uploaded_files_;
826 
827   std::unordered_map<string, vector<string>> emoji_language_codes_;
828   std::unordered_map<string, int32> emoji_language_code_versions_;
829   std::unordered_map<string, double> emoji_language_code_last_difference_times_;
830   std::unordered_set<string> reloaded_emoji_keywords_;
831   std::unordered_map<string, vector<Promise<Unit>>> load_emoji_keywords_queries_;
832   std::unordered_map<string, vector<Promise<Unit>>> load_language_codes_queries_;
833   std::unordered_map<int64, string> emoji_suggestions_urls_;
834 
835   std::unordered_map<string, std::unordered_set<FullMessageId, FullMessageIdHash>> dice_messages_;
836 
837   struct EmojiMessages {
838     std::unordered_set<FullMessageId, FullMessageIdHash> full_message_ids;
839     std::pair<FileId, int> animated_emoji_sticker;
840     FileId sound_file_id;
841   };
842   std::unordered_map<string, EmojiMessages> emoji_messages_;
843 
844   string dice_emojis_str_;
845   vector<string> dice_emojis_;
846 
847   string dice_success_values_str_;
848   vector<std::pair<int32, int32>> dice_success_values_;
849 
850   string emoji_sounds_str_;
851   std::unordered_map<string, FileId> emoji_sounds_;
852 
853   double animated_emoji_zoom_ = 0.0;
854 
855   bool disable_animated_emojis_ = false;
856 };
857 
858 }  // namespace td
859