diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 13f052fbd..4783f42a0 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -7189,6 +7189,9 @@ getEmojiSuggestionsUrl language_code:string = HttpUrl; //@description Returns list of custom emoji stickers by their identifiers. Stickers are returned in arbitrary order. Only found stickers are returned @custom_emoji_ids Identifiers of custom emoji stickers. At most 200 custom emoji stickers can be received simultaneously getCustomEmojiStickers custom_emoji_ids:vector = Stickers; +//@description Returns default list of custom emoji stickers for placing on a chat photo +getDefaultChatPhotoCustomEmojiStickers = Stickers; + //@description Returns saved animations getSavedAnimations = Animations; @@ -7281,7 +7284,7 @@ setCommands scope:BotCommandScope language_code:string commands:vector> promise_; + + public: + explicit GetDefaultDialogPhotoEmojisQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(int64 hash) { + send_query(G()->net_query_creator().create(telegram_api::account_getDefaultGroupPhotoEmojis(hash))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + promise_.set_value(result_ptr.move_as_ok()); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + class SendAnimatedEmojiClicksQuery final : public Td::ResultHandler { DialogId dialog_id_; string emoji_; @@ -6202,7 +6228,7 @@ td_api::object_ptr StickersManager::get_custom_emoji_stickers_ return td_api::make_object(std::move(stickers)); } -void StickersManager::get_custom_emoji_stickers(vector &&custom_emoji_ids, bool use_database, +void StickersManager::get_custom_emoji_stickers(vector custom_emoji_ids, bool use_database, Promise> &&promise) { TRY_STATUS_PROMISE(promise, G()->close_status()); @@ -6278,6 +6304,147 @@ void StickersManager::on_get_custom_emoji_documents( promise.set_value(get_custom_emoji_stickers_object(custom_emoji_ids)); } +string StickersManager::get_default_dialog_photo_custom_emoji_ids_database_key() { + return "default_dialog_photo_custom_emoji_ids"; +} + +void StickersManager::get_default_dialog_photo_custom_emoji_stickers( + Promise> &&promise) { + if (are_default_dialog_photo_custom_emoji_ids_loaded_) { + return get_custom_emoji_stickers(default_dialog_photo_custom_emoji_ids_, true, std::move(promise)); + } + + auto &queries = default_dialog_photo_custom_emoji_ids_load_queries_; + queries.push_back(std::move(promise)); + if (queries.size() != 1) { + // query has already been sent, just wait for the result + return; + } + if (G()->parameters().use_file_db) { + LOG(INFO) << "Trying to load chat photo custom emoji identifiers from database"; + return G()->td_db()->get_sqlite_pmc()->get( + get_default_dialog_photo_custom_emoji_ids_database_key(), PromiseCreator::lambda([](string value) { + send_closure(G()->stickers_manager(), + &StickersManager::on_load_default_dialog_photo_custom_emoji_ids_from_database, std::move(value)); + })); + } + + reload_default_dialog_photo_custom_emoji_ids(); +} + +class StickersManager::CustomEmojiIdsLogEvent { + public: + vector custom_emoji_ids_; + int64 hash_ = 0; + + CustomEmojiIdsLogEvent() = default; + + CustomEmojiIdsLogEvent(vector custom_emoji_ids, int64 hash) + : custom_emoji_ids_(std::move(custom_emoji_ids)), hash_(hash) { + } + + template + void store(StorerT &storer) const { + td::store(custom_emoji_ids_, storer); + td::store(hash_, storer); + } + + template + void parse(ParserT &parser) { + td::parse(custom_emoji_ids_, parser); + td::parse(hash_, parser); + } +}; + +void StickersManager::on_load_default_dialog_photo_custom_emoji_ids_from_database(string value) { + if (G()->close_flag()) { + fail_promises(default_dialog_photo_custom_emoji_ids_load_queries_, G()->close_status()); + return; + } + + if (value.empty()) { + return reload_default_dialog_photo_custom_emoji_ids(); + } + + LOG(INFO) << "Successfully loaded default chat photo custom emoji identifiers of size " << value.size() + << " from database"; + CustomEmojiIdsLogEvent log_event; + if (log_event_parse(log_event, value).is_error()) { + LOG(ERROR) << "Delete invalid default chat photo custom emoji identifiers from database"; + G()->td_db()->get_sqlite_pmc()->erase(get_default_dialog_photo_custom_emoji_ids_database_key(), Auto()); + return reload_default_dialog_photo_custom_emoji_ids(); + } + + on_get_default_dialog_photo_custom_emoji_ids_success(std::move(log_event.custom_emoji_ids_), log_event.hash_); +} + +void StickersManager::reload_default_dialog_photo_custom_emoji_ids() { + if (are_default_dialog_photo_custom_emoji_ids_being_loaded_) { + return; + } + if (G()->close_flag()) { + fail_promises(default_dialog_photo_custom_emoji_ids_load_queries_, G()->close_status()); + return; + } + CHECK(!td_->auth_manager_->is_bot()); + are_default_dialog_photo_custom_emoji_ids_being_loaded_ = true; + + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this)](Result> r_emoji_list) mutable { + send_closure(actor_id, &StickersManager::on_get_default_dialog_photo_custom_emoji_ids, std::move(r_emoji_list)); + }); + td_->create_handler(std::move(query_promise)) + ->send(default_dialog_photo_custom_emoji_ids_hash_); +} + +void StickersManager::on_get_default_dialog_photo_custom_emoji_ids( + Result> r_emoji_list) { + CHECK(are_default_dialog_photo_custom_emoji_ids_being_loaded_); + are_default_dialog_photo_custom_emoji_ids_being_loaded_ = false; + + if (G()->close_flag()) { + r_emoji_list = G()->close_status(); + } + if (r_emoji_list.is_error()) { + fail_promises(default_dialog_photo_custom_emoji_ids_load_queries_, r_emoji_list.move_as_error()); + return; + } + + auto emoji_list_ptr = r_emoji_list.move_as_ok(); + int32 constructor_id = emoji_list_ptr->get_id(); + if (constructor_id == telegram_api::emojiListNotModified::ID) { + LOG(INFO) << "Default chat photo custom emoji identifiers aren't modified"; + if (!are_default_dialog_photo_custom_emoji_ids_loaded_) { + on_get_default_dialog_photo_custom_emoji_ids_success({}, 0); + } + CHECK(default_dialog_photo_custom_emoji_ids_load_queries_.empty()); + return; + } + CHECK(constructor_id == telegram_api::emojiList::ID); + auto emoji_list = move_tl_object_as(emoji_list_ptr); + auto custom_emoji_ids = + transform(std::move(emoji_list->document_id_), [](int64 document_id) { return CustomEmojiId(document_id); }); + auto hash = emoji_list->hash_; + + CustomEmojiIdsLogEvent log_event(custom_emoji_ids, hash); + G()->td_db()->get_sqlite_pmc()->set(get_default_dialog_photo_custom_emoji_ids_database_key(), + log_event_store(log_event).as_slice().str(), Auto()); + + on_get_default_dialog_photo_custom_emoji_ids_success(std::move(custom_emoji_ids), hash); +} + +void StickersManager::on_get_default_dialog_photo_custom_emoji_ids_success(vector custom_emoji_ids, + int64 hash) { + default_dialog_photo_custom_emoji_ids_ = std::move(custom_emoji_ids); + default_dialog_photo_custom_emoji_ids_hash_ = hash; + are_default_dialog_photo_custom_emoji_ids_loaded_ = true; + + auto promises = std::move(default_dialog_photo_custom_emoji_ids_load_queries_); + for (auto &promise : promises) { + get_custom_emoji_stickers(default_dialog_photo_custom_emoji_ids_, true, std::move(promise)); + } +} + void StickersManager::get_premium_gift_option_sticker(int32 month_count, bool is_recursive, Promise> &&promise) { TRY_STATUS_PROMISE(promise, G()->close_status()); diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index 160dcaaee..1a359db2e 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -119,9 +119,11 @@ class StickersManager final : public Actor { void get_default_topic_icons(bool is_recursive, Promise> &&promise); - void get_custom_emoji_stickers(vector &&custom_emoji_ids, bool use_database, + void get_custom_emoji_stickers(vector custom_emoji_ids, bool use_database, Promise> &&promise); + void get_default_dialog_photo_custom_emoji_stickers(Promise> &&promise); + void get_premium_gift_option_sticker(int32 month_count, bool is_recursive, Promise> &&promise); @@ -596,6 +598,7 @@ class StickersManager final : public Actor { }; class CustomEmojiLogEvent; + class CustomEmojiIdsLogEvent; class StickerListLogEvent; class StickerSetListLogEvent; @@ -637,6 +640,15 @@ class StickersManager final : public Actor { void on_load_custom_emoji_from_database(CustomEmojiId custom_emoji_id, string value); + void on_load_default_dialog_photo_custom_emoji_ids_from_database(string value); + + void reload_default_dialog_photo_custom_emoji_ids(); + + void on_get_default_dialog_photo_custom_emoji_ids( + Result> r_emoji_list); + + void on_get_default_dialog_photo_custom_emoji_ids_success(vector custom_emoji_ids, int64 hash); + FileId on_get_sticker(unique_ptr new_sticker, bool replace); StickerSet *get_sticker_set(StickerSetId sticker_set_id); @@ -933,6 +945,8 @@ class StickersManager final : public Actor { static string get_emoji_language_codes_database_key(const vector &language_codes); + static string get_default_dialog_photo_custom_emoji_ids_database_key(); + int32 get_emoji_language_code_version(const string &language_code); double get_emoji_language_code_last_difference_time(const string &language_code); @@ -1138,6 +1152,12 @@ class StickersManager final : public Actor { string emoji_sounds_str_; FlatHashMap emoji_sounds_; + vector default_dialog_photo_custom_emoji_ids_; + int64 default_dialog_photo_custom_emoji_ids_hash_ = 0; + vector>> default_dialog_photo_custom_emoji_ids_load_queries_; + bool are_default_dialog_photo_custom_emoji_ids_loaded_ = false; + bool are_default_dialog_photo_custom_emoji_ids_being_loaded_ = false; + WaitFreeHashMap custom_emoji_to_sticker_id_; double animated_emoji_zoom_ = 0.0; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 6653acda2..d7bf4a793 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -7335,6 +7335,11 @@ void Td::on_request(uint64 id, const td_api::getCustomEmojiStickers &request) { std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getDefaultChatPhotoCustomEmojiStickers &request) { + CREATE_REQUEST_PROMISE(); + stickers_manager_->get_default_dialog_photo_custom_emoji_stickers(std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getSavedAnimations &request) { CHECK_IS_USER(); CREATE_NO_ARGS_REQUEST(GetSavedAnimationsRequest); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index e7b40873e..6e6b89c06 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1210,6 +1210,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getCustomEmojiStickers &request); + void on_request(uint64 id, const td_api::getDefaultChatPhotoCustomEmojiStickers &request); + void on_request(uint64 id, const td_api::getFavoriteStickers &request); void on_request(uint64 id, td_api::addFavoriteSticker &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index b9bbe4d71..decf69834 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2902,6 +2902,8 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "gces") { send_request(td_api::make_object(to_integers(args))); + } else if (op == "gdcpces") { + send_request(td_api::make_object()); } else if (op == "gsan") { send_request(td_api::make_object()); } else if (op == "asan") {