diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 152b12a5e..98fe9d10a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1644,7 +1644,10 @@ chatAvailableReactionsAll = ChatAvailableReactions; chatAvailableReactionsSome reactions:vector = ChatAvailableReactions; -//@description Represents a tag used in Saved Messages @tag The tag @label Label of the tag; 0-12 characters @count Number of times the tag was used; may be 0 if the tag has non-empty label +//@description Represents a tag used in Saved Messages or a Saved Messages topic +//@tag The tag +//@label Label of the tag; 0-12 characters. Always empty if the tag is returned for a Saved Messages topic +//@count Number of times the tag was used; may be 0 if the tag has non-empty label savedMessagesTag tag:ReactionType label:string count:int32 = SavedMessagesTag; //@description Contains a list of tags used in Saved Messages @tags List of tags @@ -6730,8 +6733,10 @@ updateActiveEmojiReactions emojis:vector = Update; //@description The type of default reaction has changed @reaction_type The new type of the default reaction updateDefaultReactionType reaction_type:ReactionType = Update; -//@description Used Saved Messages tags have changed @tags The new used tags -updateSavedMessagesTags tags:savedMessagesTags = Update; +//@description Tags used in Saved Messages or a Saved Messages topic have changed +//@saved_messages_topic Saved Messages topic which tags were changed; may be null if tags for the whole chat has changed +//@tags The new tags +updateSavedMessagesTags saved_messages_topic:SavedMessagesTopic tags:savedMessagesTags = Update; //@description The parameters of speech recognition without Telegram Premium subscription has changed //@max_media_duration The maximum allowed duration of media for speech recognition without Telegram Premium subscription @@ -7738,8 +7743,9 @@ getMessageAddedReactions chat_id:int53 message_id:int53 reaction_type:ReactionTy //@description Changes type of default reaction for the current user @reaction_type New type of the default reaction setDefaultReactionType reaction_type:ReactionType = Ok; -//@description Returns tags used in Saved Messages; for Telegram Premium users only -getSavedMessagesTags = SavedMessagesTags; +//@description Returns tags used in Saved Messages or a Saved Messages topic; for Telegram Premium users only +//@saved_messages_topic Saved Messages topic which tags will be returned; pass null to get all Saved Messages tags +getSavedMessagesTags saved_messages_topic:SavedMessagesTopic = SavedMessagesTags; //@description Changes label of a Saved Messages tag; for Telegram Premium users only @tag The tag which label will be changed @label New label for the tag; 0-12 characters setSavedMessagesTagLabel tag:ReactionType label:string = Ok; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 05e9875ea..5155e37e5 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6650,7 +6650,7 @@ bool MessagesManager::update_message_interaction_info(Dialog *d, Message *m, int unread_reaction_diff += (has_unread_message_reactions(dialog_id, m) ? 1 : 0); auto new_chosen_tags = get_chosen_tags(m->reactions); - td_->reaction_manager_->update_saved_messages_tags(old_chosen_tags, new_chosen_tags); + td_->reaction_manager_->update_saved_messages_tags(m->saved_messages_topic_id, old_chosen_tags, new_chosen_tags); if (is_visible_message_reactions(dialog_id, m)) { need_update |= need_update_reactions; @@ -15394,7 +15394,7 @@ void MessagesManager::on_message_deleted_from_database(Dialog *d, const Message update_message_count_by_index(d, -1, m); update_reply_count_by_message(d, -1, m); - td_->reaction_manager_->update_saved_messages_tags(get_chosen_tags(m->reactions), {}); + td_->reaction_manager_->update_saved_messages_tags(m->saved_messages_topic_id, get_chosen_tags(m->reactions), {}); } void MessagesManager::on_message_deleted(Dialog *d, Message *m, bool is_permanently_deleted, const char *source) { @@ -22883,7 +22883,8 @@ void MessagesManager::add_message_reaction(MessageFullId message_full_id, Reacti set_message_reactions(d, m, is_big, add_to_recent, std::move(promise)); if (is_tag) { - td_->reaction_manager_->update_saved_messages_tags(old_chosen_tags, get_chosen_tags(m->reactions)); + td_->reaction_manager_->update_saved_messages_tags(m->saved_messages_topic_id, old_chosen_tags, + get_chosen_tags(m->reactions)); } else if (add_to_recent) { td_->reaction_manager_->add_recent_reaction(reaction_type); } @@ -22919,7 +22920,8 @@ void MessagesManager::remove_message_reaction(MessageFullId message_full_id, Rea set_message_reactions(d, m, false, false, std::move(promise)); if (!old_chosen_tags.empty()) { - td_->reaction_manager_->update_saved_messages_tags(old_chosen_tags, get_chosen_tags(m->reactions)); + td_->reaction_manager_->update_saved_messages_tags(m->saved_messages_topic_id, old_chosen_tags, + get_chosen_tags(m->reactions)); } } diff --git a/td/telegram/ReactionManager.cpp b/td/telegram/ReactionManager.cpp index ddf29b29c..5bd0f4666 100644 --- a/td/telegram/ReactionManager.cpp +++ b/td/telegram/ReactionManager.cpp @@ -180,10 +180,17 @@ class GetSavedReactionTagsQuery final : public Td::ResultHandler { : promise_(std::move(promise)) { } - void send(int64 hash) { + void send(SavedMessagesTopicId saved_messages_topic_id, int64 hash) { int32 flags = 0; - send_query(G()->net_query_creator().create(telegram_api::messages_getSavedReactionTags(flags, nullptr, hash), - {td_->dialog_manager_->get_my_dialog_id()})); + telegram_api::object_ptr saved_input_peer; + if (saved_messages_topic_id.is_valid()) { + flags |= telegram_api::messages_getSavedReactionTags::PEER_MASK; + saved_input_peer = saved_messages_topic_id.get_input_peer(td_); + CHECK(saved_input_peer != nullptr); + } + send_query(G()->net_query_creator().create( + telegram_api::messages_getSavedReactionTags(flags, std::move(saved_input_peer), hash), + {td_->dialog_manager_->get_my_dialog_id()})); } void on_result(BufferSlice packet) final { @@ -873,31 +880,76 @@ void ReactionManager::send_set_default_reaction_query() { ReactionType(td_->option_manager_->get_option_string("default_reaction"))); } -void ReactionManager::get_saved_messages_tags(Promise> &&promise) { - if (tags_.is_inited_) { - return promise.set_value(tags_.get_saved_messages_tags_object()); +ReactionManager::SavedReactionTags *ReactionManager::get_saved_reaction_tags( + SavedMessagesTopicId saved_messages_topic_id) { + if (saved_messages_topic_id == SavedMessagesTopicId()) { + return &all_tags_; } - reget_saved_messages_tags(std::move(promise)); + auto it = topic_tags_.find(saved_messages_topic_id); + if (it != topic_tags_.end()) { + return it->second.get(); + } + return nullptr; } -void ReactionManager::reget_saved_messages_tags(Promise> &&promise) { - auto &promises = pending_get_saved_reaction_tags_queries_; +ReactionManager::SavedReactionTags *ReactionManager::add_saved_reaction_tags( + SavedMessagesTopicId saved_messages_topic_id) { + if (saved_messages_topic_id == SavedMessagesTopicId()) { + return &all_tags_; + } + auto &tags = topic_tags_[saved_messages_topic_id]; + if (tags == nullptr) { + tags = make_unique(); + } + return tags.get(); +} + +void ReactionManager::get_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, + Promise> &&promise) { + if (!saved_messages_topic_id.is_valid() && saved_messages_topic_id != SavedMessagesTopicId()) { + return promise.set_error(Status::Error(400, "Invalid Saved Messages topic specified")); + } + const auto *tags = get_saved_reaction_tags(saved_messages_topic_id); + if (tags != nullptr && tags->is_inited_) { + return promise.set_value(tags->get_saved_messages_tags_object()); + } + reget_saved_messages_tags(saved_messages_topic_id, std::move(promise)); +} + +void ReactionManager::reget_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, + Promise> &&promise) { + auto &promises = saved_messages_topic_id == SavedMessagesTopicId() + ? pending_get_all_saved_reaction_tags_queries_ + : pending_get_topic_saved_reaction_tags_queries_[saved_messages_topic_id]; promises.push_back(std::move(promise)); if (promises.size() != 1) { return; } - auto query_promise = PromiseCreator::lambda( - [actor_id = actor_id(this)](Result> r_tags) { - send_closure(actor_id, &ReactionManager::on_get_saved_messages_tags, std::move(r_tags)); + auto query_promise = + PromiseCreator::lambda([actor_id = actor_id(this), saved_messages_topic_id]( + Result> r_tags) { + send_closure(actor_id, &ReactionManager::on_get_saved_messages_tags, saved_messages_topic_id, + std::move(r_tags)); }); - td_->create_handler(std::move(query_promise))->send(tags_.hash_); + const auto *tags = get_saved_reaction_tags(saved_messages_topic_id); + td_->create_handler(std::move(query_promise)) + ->send(saved_messages_topic_id, tags != nullptr ? tags->hash_ : 0); } void ReactionManager::on_get_saved_messages_tags( + SavedMessagesTopicId saved_messages_topic_id, Result> &&r_tags) { G()->ignore_result_if_closing(r_tags); - auto promises = std::move(pending_get_saved_reaction_tags_queries_); - reset_to_empty(pending_get_saved_reaction_tags_queries_); + vector>> promises; + if (saved_messages_topic_id == SavedMessagesTopicId()) { + promises = std::move(pending_get_all_saved_reaction_tags_queries_); + reset_to_empty(pending_get_all_saved_reaction_tags_queries_); + } else { + auto it = pending_get_topic_saved_reaction_tags_queries_.find(saved_messages_topic_id); + CHECK(it != pending_get_topic_saved_reaction_tags_queries_.end()); + promises = std::move(it->second); + pending_get_topic_saved_reaction_tags_queries_.erase(it); + } CHECK(!promises.empty()); if (r_tags.is_error()) { @@ -906,9 +958,12 @@ void ReactionManager::on_get_saved_messages_tags( auto tags_ptr = r_tags.move_as_ok(); bool need_send_update = false; + auto *reaction_tags = add_saved_reaction_tags(saved_messages_topic_id); switch (tags_ptr->get_id()) { case telegram_api::messages_savedReactionTagsNotModified::ID: - // nothing to do + if (!reaction_tags->is_inited_) { + LOG(ERROR) << "Receive messages.savedReactionTagsNotModified for non-inited tags"; + } break; case telegram_api::messages_savedReactionTags::ID: { auto tags = telegram_api::move_object_as(tags_ptr); @@ -921,15 +976,15 @@ void ReactionManager::on_get_saved_messages_tags( } } std::sort(saved_reaction_tags.begin(), saved_reaction_tags.end()); - tags_.hash_ = tags->hash_; - if (saved_reaction_tags != tags_.tags_) { - tags_.tags_ = std::move(saved_reaction_tags); + reaction_tags->hash_ = tags->hash_; + if (saved_reaction_tags != reaction_tags->tags_) { + reaction_tags->tags_ = std::move(saved_reaction_tags); need_send_update = true; } - if (tags_.hash_ != tags_.calc_hash()) { + if (reaction_tags->hash_ != reaction_tags->calc_hash()) { LOG(ERROR) << "Receive unexpected Saved Messages tag hash"; } - tags_.is_inited_ = true; + reaction_tags->is_inited_ = true; break; } default: @@ -937,35 +992,50 @@ void ReactionManager::on_get_saved_messages_tags( } if (need_send_update) { - send_update_saved_messages_tags(); + send_update_saved_messages_tags(saved_messages_topic_id, reaction_tags); } for (auto &promise : promises) { - promise.set_value(tags_.get_saved_messages_tags_object()); + if (promise) { + promise.set_value(reaction_tags->get_saved_messages_tags_object()); + } } } -td_api::object_ptr ReactionManager::get_update_saved_messages_tags_object() const { - return td_api::make_object(tags_.get_saved_messages_tags_object()); +td_api::object_ptr ReactionManager::get_update_saved_messages_tags_object( + SavedMessagesTopicId saved_messages_topic_id, const SavedReactionTags *tags) const { + CHECK(tags != nullptr); + return td_api::make_object( + saved_messages_topic_id.get_saved_messages_topic_object(td_), tags->get_saved_messages_tags_object()); } -void ReactionManager::send_update_saved_messages_tags() { - send_closure(G()->td(), &Td::send_update, get_update_saved_messages_tags_object()); +void ReactionManager::send_update_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, + const SavedReactionTags *tags) { + send_closure(G()->td(), &Td::send_update, get_update_saved_messages_tags_object(saved_messages_topic_id, tags)); } void ReactionManager::on_update_saved_reaction_tags(Promise &&promise) { - reget_saved_messages_tags(PromiseCreator::lambda( - [promise = std::move(promise)](Result> result) mutable { - promise.set_value(Unit()); - })); + reget_saved_messages_tags( + SavedMessagesTopicId(), + PromiseCreator::lambda( + [promise = std::move(promise)](Result> result) mutable { + promise.set_value(Unit()); + })); } -void ReactionManager::update_saved_messages_tags(const vector &old_tags, +void ReactionManager::update_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, + const vector &old_tags, const vector &new_tags) { if (old_tags == new_tags) { return; } - if (tags_.update_saved_messages_tags(old_tags, new_tags)) { - send_update_saved_messages_tags(); + if (all_tags_.update_saved_messages_tags(old_tags, new_tags)) { + send_update_saved_messages_tags(SavedMessagesTopicId(), &all_tags_); + } + if (saved_messages_topic_id != SavedMessagesTopicId()) { + auto tags = get_saved_reaction_tags(saved_messages_topic_id); + if (tags != nullptr && tags->update_saved_messages_tags(old_tags, new_tags)) { + send_update_saved_messages_tags(saved_messages_topic_id, tags); + } } } @@ -975,8 +1045,8 @@ void ReactionManager::set_saved_messages_tag_title(ReactionType reaction_type, s } title = clean_name(title, MAX_TAG_TITLE_LENGTH); - if (tags_.set_tag_title(reaction_type, title)) { - send_update_saved_messages_tags(); + if (all_tags_.set_tag_title(reaction_type, title)) { + send_update_saved_messages_tags(SavedMessagesTopicId(), &all_tags_); } auto query_promise = @@ -998,8 +1068,11 @@ void ReactionManager::get_current_state(vector> &&promise); + void get_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, + Promise> &&promise); void on_update_saved_reaction_tags(Promise &&promise); - void update_saved_messages_tags(const vector &old_tags, const vector &new_tags); + void update_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, const vector &old_tags, + const vector &new_tags); void set_saved_messages_tag_title(ReactionType reaction_type, string title, Promise &&promise); @@ -197,18 +200,26 @@ class ReactionManager final : public Actor { td_api::object_ptr get_update_active_emoji_reactions_object() const; - void reget_saved_messages_tags(Promise> &&promise); + SavedReactionTags *get_saved_reaction_tags(SavedMessagesTopicId saved_messages_topic_id); - void on_get_saved_messages_tags(Result> &&r_tags); + SavedReactionTags *add_saved_reaction_tags(SavedMessagesTopicId saved_messages_topic_id); - td_api::object_ptr get_update_saved_messages_tags_object() const; + void reget_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, + Promise> &&promise); - void send_update_saved_messages_tags(); + void on_get_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, + Result> &&r_tags); + + td_api::object_ptr get_update_saved_messages_tags_object( + SavedMessagesTopicId saved_messages_topic_id, const SavedReactionTags *tags) const; + + void send_update_saved_messages_tags(SavedMessagesTopicId saved_messages_topic_id, const SavedReactionTags *tags); Td *td_; ActorShared<> parent_; bool is_inited_ = false; + bool are_reactions_loaded_from_database_ = false; vector>>> pending_get_emoji_reaction_queries_; @@ -217,10 +228,13 @@ class ReactionManager final : public Actor { ReactionList reaction_lists_[MAX_REACTION_LIST_TYPE]; - SavedReactionTags tags_; - vector>> pending_get_saved_reaction_tags_queries_; + SavedReactionTags all_tags_; + FlatHashMap, SavedMessagesTopicIdHash> topic_tags_; - bool are_reactions_loaded_from_database_ = false; + vector>> pending_get_all_saved_reaction_tags_queries_; + FlatHashMap>>, + SavedMessagesTopicIdHash> + pending_get_topic_saved_reaction_tags_queries_; }; } // namespace td diff --git a/td/telegram/SavedMessagesTopicId.cpp b/td/telegram/SavedMessagesTopicId.cpp index 5be5e1d64..9b4512680 100644 --- a/td/telegram/SavedMessagesTopicId.cpp +++ b/td/telegram/SavedMessagesTopicId.cpp @@ -69,7 +69,8 @@ SavedMessagesTopicId::SavedMessagesTopicId(const Td *td, } } -td_api::object_ptr SavedMessagesTopicId::get_saved_messages_topic_object(Td *td) const { +td_api::object_ptr SavedMessagesTopicId::get_saved_messages_topic_object( + const Td *td) const { if (dialog_id_ == DialogId()) { return nullptr; } diff --git a/td/telegram/SavedMessagesTopicId.h b/td/telegram/SavedMessagesTopicId.h index 1739441e1..f92ceaaa1 100644 --- a/td/telegram/SavedMessagesTopicId.h +++ b/td/telegram/SavedMessagesTopicId.h @@ -53,7 +53,7 @@ class SavedMessagesTopicId { bool is_author_hidden() const; - td_api::object_ptr get_saved_messages_topic_object(Td *td) const; + td_api::object_ptr get_saved_messages_topic_object(const Td *td) const; telegram_api::object_ptr get_input_peer(const Td *td) const; @@ -74,7 +74,7 @@ class SavedMessagesTopicId { struct SavedMessagesTopicIdHash { uint32 operator()(SavedMessagesTopicId saved_messages_topic_id) const { - return Hash()(saved_messages_topic_id.dialog_id_); + return DialogIdHash()(saved_messages_topic_id.dialog_id_); } }; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 8c8857653..15999f046 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5489,7 +5489,8 @@ void Td::on_request(uint64 id, const td_api::setDefaultReactionType &request) { void Td::on_request(uint64 id, const td_api::getSavedMessagesTags &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); - reaction_manager_->get_saved_messages_tags(std::move(promise)); + reaction_manager_->get_saved_messages_tags(SavedMessagesTopicId(this, request.saved_messages_topic_), + std::move(promise)); } void Td::on_request(uint64 id, td_api::setSavedMessagesTagLabel &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 2ca8abb7b..98aa00885 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2865,7 +2865,7 @@ class CliClient final : public Actor { send_request(td_api::make_object( chat_id, message_id, as_reaction_type(reaction), offset, as_limit(limit))); } else if (op == "gsmts") { - send_request(td_api::make_object()); + send_request(td_api::make_object(get_saved_messages_topic())); } else if (op == "ssmtl") { string reaction; string label;