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