From 426c308e23a72d720098357a4705380808816320 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Dec 2022 17:37:09 +0300 Subject: [PATCH] Add ForumTopic cache. --- CMakeLists.txt | 1 + td/telegram/ForumTopic.h | 6 ++ td/telegram/ForumTopic.hpp | 106 ++++++++++++++++++++++++++++++ td/telegram/ForumTopicManager.cpp | 100 +++++++++++++++++++++------- td/telegram/ForumTopicManager.h | 11 +++- td/telegram/MessagesManager.cpp | 2 +- 6 files changed, 201 insertions(+), 25 deletions(-) create mode 100644 td/telegram/ForumTopic.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f3676c68..03ca1fbbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -757,6 +757,7 @@ set(TDLIB_SOURCE td/telegram/files/FileLocation.hpp td/telegram/files/FileManager.hpp td/telegram/files/FileSourceId.hpp + td/telegram/ForumTopic.hpp td/telegram/ForumTopicEditedData.hpp td/telegram/ForumTopicIcon.hpp td/telegram/ForumTopicInfo.hpp diff --git a/td/telegram/ForumTopic.h b/td/telegram/ForumTopic.h index fe16fba7b..9adfef8df 100644 --- a/td/telegram/ForumTopic.h +++ b/td/telegram/ForumTopic.h @@ -42,6 +42,12 @@ class ForumTopic { td_api::object_ptr get_forum_topic_object(Td *td, DialogId dialog_id, const ForumTopicInfo &info) const; + + template + void store(StorerT &storer) const; + + template + void parse(ParserT &parser); }; } // namespace td diff --git a/td/telegram/ForumTopic.hpp b/td/telegram/ForumTopic.hpp new file mode 100644 index 000000000..832a028bf --- /dev/null +++ b/td/telegram/ForumTopic.hpp @@ -0,0 +1,106 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/DialogNotificationSettings.hpp" +#include "td/telegram/DraftMessage.hpp" +#include "td/telegram/ForumTopic.h" + +#include "td/utils/common.h" +#include "td/utils/tl_helpers.h" + +namespace td { + +template +void ForumTopic::store(StorerT &storer) const { + bool has_unread_count = unread_count_ != 0; + bool has_last_message_id = last_message_id_.is_valid(); + bool has_last_read_inbox_message_id = last_read_inbox_message_id_.is_valid(); + bool has_last_read_outbox_message_id = last_read_outbox_message_id_.is_valid(); + bool has_unread_mention_count = unread_mention_count_ != 0; + bool has_unread_reaction_count = unread_reaction_count_ != 0; + bool has_draft_message = draft_message_ != nullptr; + BEGIN_STORE_FLAGS(); + STORE_FLAG(is_short_); + STORE_FLAG(is_pinned_); + STORE_FLAG(has_unread_count); + STORE_FLAG(has_last_message_id); + STORE_FLAG(has_last_read_inbox_message_id); + STORE_FLAG(has_last_read_outbox_message_id); + STORE_FLAG(has_unread_mention_count); + STORE_FLAG(has_unread_reaction_count); + STORE_FLAG(has_draft_message); + END_STORE_FLAGS(); + if (has_unread_count) { + td::store(unread_count_, storer); + } + if (has_last_message_id) { + td::store(last_message_id_, storer); + } + if (has_last_read_inbox_message_id) { + td::store(last_read_inbox_message_id_, storer); + } + if (has_last_read_outbox_message_id) { + td::store(last_read_outbox_message_id_, storer); + } + if (has_unread_mention_count) { + td::store(unread_mention_count_, storer); + } + if (has_unread_reaction_count) { + td::store(unread_reaction_count_, storer); + } + td::store(notification_settings_, storer); + if (has_draft_message) { + td::store(draft_message_, storer); + } +} + +template +void ForumTopic::parse(ParserT &parser) { + bool has_unread_count; + bool has_last_message_id; + bool has_last_read_inbox_message_id; + bool has_last_read_outbox_message_id; + bool has_unread_mention_count; + bool has_unread_reaction_count; + bool has_draft_message; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(is_short_); + PARSE_FLAG(is_pinned_); + PARSE_FLAG(has_unread_count); + PARSE_FLAG(has_last_message_id); + PARSE_FLAG(has_last_read_inbox_message_id); + PARSE_FLAG(has_last_read_outbox_message_id); + PARSE_FLAG(has_unread_mention_count); + PARSE_FLAG(has_unread_reaction_count); + PARSE_FLAG(has_draft_message); + END_PARSE_FLAGS(); + if (has_unread_count) { + td::parse(unread_count_, parser); + } + if (has_last_message_id) { + td::parse(last_message_id_, parser); + } + if (has_last_read_inbox_message_id) { + td::parse(last_read_inbox_message_id_, parser); + } + if (has_last_read_outbox_message_id) { + td::parse(last_read_outbox_message_id_, parser); + } + if (has_unread_mention_count) { + td::parse(unread_mention_count_, parser); + } + if (has_unread_reaction_count) { + td::parse(unread_reaction_count_, parser); + } + td::parse(notification_settings_, parser); + if (has_draft_message) { + td::parse(draft_message_, parser); + } +} + +} // namespace td diff --git a/td/telegram/ForumTopicManager.cpp b/td/telegram/ForumTopicManager.cpp index b22f958ca..4681c7fda 100644 --- a/td/telegram/ForumTopicManager.cpp +++ b/td/telegram/ForumTopicManager.cpp @@ -12,6 +12,7 @@ #include "td/telegram/ContactsManager.h" #include "td/telegram/CustomEmojiId.h" #include "td/telegram/ForumTopic.h" +#include "td/telegram/ForumTopic.hpp" #include "td/telegram/ForumTopicIcon.h" #include "td/telegram/ForumTopicInfo.hpp" #include "td/telegram/Global.h" @@ -235,26 +236,15 @@ class GetForumTopicQuery final : public Td::ResultHandler { return promise_.set_value(nullptr); } - auto topic = std::move(ptr->topics_[0]); - switch (topic->get_id()) { - case telegram_api::forumTopicDeleted::ID: - return promise_.set_value(nullptr); - case telegram_api::forumTopic::ID: { - ForumTopicInfo forum_topic_info(topic); - ForumTopic forum_topic(td_, std::move(topic)); - if (forum_topic.is_short()) { - return promise_.set_error(Status::Error(500, "Receive short forum topic")); - } - if (forum_topic_info.get_top_thread_message_id() != top_thread_message_id_) { - return promise_.set_error(Status::Error(500, "Wrong forum topic received")); - } - td_->forum_topic_manager_->on_get_forum_topic_info(DialogId(channel_id_), forum_topic_info, - "GetForumTopicQuery"); - return promise_.set_value(forum_topic.get_forum_topic_object(td_, DialogId(channel_id_), forum_topic_info)); - } - default: - UNREACHABLE(); + auto top_thread_message_id = + td_->forum_topic_manager_->on_get_forum_topic(DialogId(channel_id_), std::move(ptr->topics_[0])); + if (!top_thread_message_id.is_valid()) { + return promise_.set_value(nullptr); } + if (top_thread_message_id != top_thread_message_id_) { + return promise_.set_error(Status::Error(500, "Wrong forum topic received")); + } + promise_.set_value(td_->forum_topic_manager_->get_forum_topic_object(DialogId(channel_id_), top_thread_message_id)); } void on_error(Status status) final { @@ -269,9 +259,15 @@ void ForumTopicManager::Topic::store(StorerT &storer) const { using td::store; store(MAGIC, storer); + + bool has_topic = topic_ != nullptr; BEGIN_STORE_FLAGS(); + STORE_FLAG(has_topic); END_STORE_FLAGS(); store(info_, storer); + if (has_topic) { + store(topic_, storer); + } } template @@ -284,9 +280,15 @@ void ForumTopicManager::Topic::parse(ParserT &parser) { if (magic != MAGIC) { return parser.set_error("Invalid magic"); } + + bool has_topic; BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_topic); END_PARSE_FLAGS(); parse(info_, parser); + if (has_topic) { + parse(topic_, parser); + } } ForumTopicManager::ForumTopicManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { @@ -507,9 +509,9 @@ void ForumTopicManager::on_get_forum_topic_info(DialogId dialog_id, const ForumT } } -void ForumTopicManager::on_get_forum_topics(DialogId dialog_id, - vector> &&forum_topics, - const char *source) { +void ForumTopicManager::on_get_forum_topic_infos(DialogId dialog_id, + vector> &&forum_topics, + const char *source) { if (forum_topics.empty()) { return; } @@ -535,6 +537,60 @@ void ForumTopicManager::on_get_forum_topics(DialogId dialog_id, } } +MessageId ForumTopicManager::on_get_forum_topic(DialogId dialog_id, + tl_object_ptr &&forum_topic) { + CHECK(forum_topic != nullptr); + switch (forum_topic->get_id()) { + case telegram_api::forumTopicDeleted::ID: { + auto top_thread_message_id = + MessageId(ServerMessageId(static_cast(forum_topic.get())->id_)); + if (!top_thread_message_id.is_valid()) { + LOG(ERROR) << "Receive " << to_string(forum_topic); + return MessageId(); + } + on_delete_forum_topic(dialog_id, top_thread_message_id, Promise()); + return MessageId(); + } + case telegram_api::forumTopic::ID: { + auto forum_topic_info = td::make_unique(forum_topic); + auto forum_topic_full = td::make_unique(td_, std::move(forum_topic)); + if (forum_topic_full->is_short()) { + LOG(ERROR) << "Receive short " << to_string(forum_topic); + return MessageId(); + } + MessageId top_thread_message_id = forum_topic_info->get_top_thread_message_id(); + Topic *topic = add_topic(dialog_id, top_thread_message_id); + bool need_save = false; + if (topic->topic_ == nullptr || true) { + topic->topic_ = std::move(forum_topic_full); + need_save = true; + } + if (topic->info_ == nullptr || *topic->info_ != *forum_topic_info) { + topic->info_ = std::move(forum_topic_info); + send_update_forum_topic_info(dialog_id, topic->info_.get()); + need_save = true; + } + if (need_save) { + save_topic_to_database(dialog_id, topic); + } + return top_thread_message_id; + } + default: + UNREACHABLE(); + return MessageId(); + } +} + +td_api::object_ptr ForumTopicManager::get_forum_topic_object( + DialogId dialog_id, MessageId top_thread_message_id) const { + auto topic = get_topic(dialog_id, top_thread_message_id); + if (topic == nullptr || topic->topic_ == nullptr) { + return nullptr; + } + CHECK(topic->info_ != nullptr); + return topic->topic_->get_forum_topic_object(td_, dialog_id, *topic->info_); +} + Status ForumTopicManager::is_forum(DialogId dialog_id) { if (!td_->messages_manager_->have_dialog_force(dialog_id, "ForumTopicManager::is_forum")) { return Status::Error(400, "Chat not found"); diff --git a/td/telegram/ForumTopicManager.h b/td/telegram/ForumTopicManager.h index 577594af9..6715e77b4 100644 --- a/td/telegram/ForumTopicManager.h +++ b/td/telegram/ForumTopicManager.h @@ -8,6 +8,7 @@ #include "td/telegram/CustomEmojiId.h" #include "td/telegram/DialogId.h" +#include "td/telegram/ForumTopic.h" #include "td/telegram/ForumTopicEditedData.h" #include "td/telegram/ForumTopicInfo.h" #include "td/telegram/MessageId.h" @@ -62,8 +63,13 @@ class ForumTopicManager final : public Actor { void on_get_forum_topic_info(DialogId dialog_id, const ForumTopicInfo &topic_info, const char *source); - void on_get_forum_topics(DialogId dialog_id, vector> &&forum_topics, - const char *source); + void on_get_forum_topic_infos(DialogId dialog_id, vector> &&forum_topics, + const char *source); + + MessageId on_get_forum_topic(DialogId dialog_id, tl_object_ptr &&forum_topic); + + td_api::object_ptr get_forum_topic_object(DialogId dialog_id, + MessageId top_thread_message_id) const; void on_topic_message_count_changed(DialogId dialog_id, MessageId top_thread_message_id, int diff); @@ -72,6 +78,7 @@ class ForumTopicManager final : public Actor { struct Topic { unique_ptr info_; + unique_ptr topic_; int32 message_count_ = 0; template diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 451b1dedd..f81e2776d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -9868,7 +9868,7 @@ MessagesManager::MessagesInfo MessagesManager::get_messages_info( td_->contacts_manager_->on_get_users(std::move(users), source); td_->contacts_manager_->on_get_chats(std::move(chats), source); - td_->forum_topic_manager_->on_get_forum_topics(dialog_id, std::move(topics), source); + td_->forum_topic_manager_->on_get_forum_topic_infos(dialog_id, std::move(topics), source); return result; }