diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 62dc1cd58..c9e993e58 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -3582,12 +3582,22 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File return false; } +static bool can_be_animated_emoji(const FormattedText &text) { + return text.entities.empty() && is_emoji(text.text); +} + void register_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id, const char *source) { switch (content->get_type()) { - case MessageContentType::Text: - return td->web_pages_manager_->register_web_page(static_cast(content)->web_page_id, - full_message_id, source); + case MessageContentType::Text: { + auto text = static_cast(content); + if (text->web_page_id.is_valid()) { + td->web_pages_manager_->register_web_page(text->web_page_id, full_message_id, source); + } else if (can_be_animated_emoji(text->text)) { + td->stickers_manager_->register_emoji(text->text.text, full_message_id, source); + } + return; + } case MessageContentType::Poll: return td->poll_manager_->register_poll(static_cast(content)->poll_id, full_message_id, source); @@ -3606,12 +3616,16 @@ void reregister_message_content(Td *td, const MessageContent *old_content, const auto new_content_type = new_content->get_type(); if (old_content_type == new_content_type) { switch (old_content_type) { - case MessageContentType::Text: - if (static_cast(old_content)->web_page_id == - static_cast(new_content)->web_page_id) { + case MessageContentType::Text: { + auto old_text = static_cast(old_content); + auto new_text = static_cast(new_content); + if (old_text->web_page_id == new_text->web_page_id && + (old_text->text == new_text->text || + (!can_be_animated_emoji(old_text->text) && !can_be_animated_emoji(new_text->text)))) { return; } break; + } case MessageContentType::Poll: if (static_cast(old_content)->poll_id == static_cast(new_content)->poll_id) { @@ -3637,9 +3651,15 @@ void reregister_message_content(Td *td, const MessageContent *old_content, const void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id, const char *source) { switch (content->get_type()) { - case MessageContentType::Text: - return td->web_pages_manager_->unregister_web_page(static_cast(content)->web_page_id, - full_message_id, source); + case MessageContentType::Text: { + auto text = static_cast(content); + if (text->web_page_id.is_valid()) { + td->web_pages_manager_->unregister_web_page(text->web_page_id, full_message_id, source); + } else if (can_be_animated_emoji(text->text)) { + td->stickers_manager_->unregister_emoji(text->text.text, full_message_id, source); + } + return; + } case MessageContentType::Poll: return td->poll_manager_->unregister_poll(static_cast(content)->poll_id, full_message_id, source); @@ -4781,6 +4801,9 @@ tl_object_ptr get_message_content_object(const MessageCo } case MessageContentType::Text: { const auto *m = static_cast(content); + if (can_be_animated_emoji(m->text) && !m->web_page_id.is_valid()) { + return td->stickers_manager_->get_message_content_animated_emoji_object(m->text.text); + } return make_tl_object( get_formatted_text_object(m->text, skip_bot_commands, max_media_timestamp), td->web_pages_manager_->get_web_page_object(m->web_page_id)); @@ -5311,8 +5334,8 @@ void get_message_content_animated_emoji_click_sticker(const MessageContent *cont return promise.set_error(Status::Error(400, "Message is not an animated emoji message")); } - auto &text = static_cast(content)->text; - if (!text.entities.empty()) { + const auto &text = static_cast(content)->text; + if (!can_be_animated_emoji(text)) { return promise.set_error(Status::Error(400, "Message is not an animated emoji message")); } td->stickers_manager_->get_animated_emoji_click_sticker(text.text, full_message_id, std::move(promise)); diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 61271adb0..dd480bb87 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1280,6 +1280,8 @@ void StickersManager::init() { on_update_dice_success_values(); + load_special_sticker_set(add_special_sticker_set(SpecialStickerSetType::animated_emoji())); + if (G()->parameters().use_file_db) { auto old_featured_sticker_set_count_str = G()->td_db()->get_binlog_pmc()->get("old_featured_sticker_set_count"); if (!old_featured_sticker_set_count_str.empty()) { @@ -1404,6 +1406,27 @@ void StickersManager::on_load_special_sticker_set(const SpecialStickerSetType &t CHECK(sticker_set != nullptr); CHECK(sticker_set->was_loaded); + if (type.type_ == SpecialStickerSetType::animated_emoji()) { + for (auto sticker_it : sticker_set->sticker_emojis_map_) { + for (auto &emoji : sticker_it.second) { + auto it = emoji_messages_.find(emoji); + if (it == emoji_messages_.end()) { + continue; + } + + vector full_message_ids; + for (auto full_message_id : it->second) { + full_message_ids.push_back(full_message_id); + } + CHECK(!full_message_ids.empty()); + for (auto full_message_id : full_message_ids) { + td_->messages_manager_->on_external_update_message_content(full_message_id); + } + } + } + return; + } + if (type.type_ == SpecialStickerSetType::animated_emoji_click()) { auto pending_get_requests = std::move(pending_get_animated_emoji_click_stickers_); reset_to_empty(pending_get_animated_emoji_click_stickers_); @@ -1893,6 +1916,13 @@ tl_object_ptr StickersManager::get_sticker_set_info_obje std::move(stickers)); } +td_api::object_ptr StickersManager::get_message_content_animated_emoji_object( + const string &emoji) { + return td_api::make_object( + td_api::make_object(emoji, std::vector>()), + nullptr); +} + tl_object_ptr StickersManager::get_input_sticker_set(StickerSetId sticker_set_id) const { auto sticker_set = get_sticker_set(sticker_set_id); if (sticker_set == nullptr) { @@ -4028,6 +4058,51 @@ void StickersManager::unregister_dice(const string &emoji, int32 value, FullMess } } +void StickersManager::register_emoji(const string &emoji, FullMessageId full_message_id, const char *source) { + CHECK(!emoji.empty()); + if (td_->auth_manager_->is_bot()) { + return; + } + + LOG(INFO) << "Register emoji " << emoji << " from " << full_message_id << " from " << source; + bool is_inserted = emoji_messages_[emoji].insert(full_message_id).second; + LOG_CHECK(is_inserted) << source << " " << emoji << " " << full_message_id; + + auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_emoji()); + bool need_load = false; + if (!special_sticker_set.id_.is_valid()) { + need_load = true; + } else { + auto sticker_set = get_sticker_set(special_sticker_set.id_); + CHECK(sticker_set != nullptr); + need_load = !sticker_set->was_loaded; + } + + if (need_load) { + LOG(INFO) << "Waiting for the animated emoji sticker set needed in " << full_message_id; + load_special_sticker_set(special_sticker_set); + } else { + // TODO reload once in a while + // reload_special_sticker_set(special_sticker_set); + } +} + +void StickersManager::unregister_emoji(const string &emoji, FullMessageId full_message_id, const char *source) { + CHECK(!emoji.empty()); + if (td_->auth_manager_->is_bot()) { + return; + } + + LOG(INFO) << "Unregister emoji " << emoji << " from " << full_message_id << " from " << source; + auto &message_ids = emoji_messages_[emoji]; + auto is_deleted = message_ids.erase(full_message_id) > 0; + LOG_CHECK(is_deleted) << source << " " << emoji << " " << full_message_id; + + if (message_ids.empty()) { + emoji_messages_.erase(emoji); + } +} + void StickersManager::get_animated_emoji_click_sticker(const string &message_text, FullMessageId full_message_id, Promise> &&promise) { auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_emoji_click()); diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index a3ab9a092..8a1427488 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -63,12 +63,18 @@ class StickersManager final : public Actor { const vector &sticker_set_ids, size_t covers_limit) const; + td_api::object_ptr get_message_content_animated_emoji_object(const string &emoji); + tl_object_ptr get_input_sticker_set(StickerSetId sticker_set_id) const; void register_dice(const string &emoji, int32 value, FullMessageId full_message_id, const char *source); void unregister_dice(const string &emoji, int32 value, FullMessageId full_message_id, const char *source); + void register_emoji(const string &emoji, FullMessageId full_message_id, const char *source); + + void unregister_emoji(const string &emoji, FullMessageId full_message_id, const char *source); + void get_animated_emoji_click_sticker(const string &message_text, FullMessageId full_message_id, Promise> &&promise); @@ -795,6 +801,7 @@ class StickersManager final : public Actor { std::unordered_map emoji_suggestions_urls_; std::unordered_map> dice_messages_; + std::unordered_map> emoji_messages_; string dice_emojis_str_; vector dice_emojis_;