Add ForumTopic cache.

This commit is contained in:
levlam 2022-12-05 17:37:09 +03:00
parent a40acdfcc3
commit 426c308e23
6 changed files with 201 additions and 25 deletions

View File

@ -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

View File

@ -42,6 +42,12 @@ class ForumTopic {
td_api::object_ptr<td_api::forumTopic> get_forum_topic_object(Td *td, DialogId dialog_id,
const ForumTopicInfo &info) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
} // namespace td

106
td/telegram/ForumTopic.hpp Normal file
View File

@ -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 <class StorerT>
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 <class ParserT>
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

View File

@ -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 <class ParserT>
@ -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<tl_object_ptr<telegram_api::ForumTopic>> &&forum_topics,
const char *source) {
void ForumTopicManager::on_get_forum_topic_infos(DialogId dialog_id,
vector<tl_object_ptr<telegram_api::ForumTopic>> &&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<telegram_api::ForumTopic> &&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<const telegram_api::forumTopicDeleted *>(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<Unit>());
return MessageId();
}
case telegram_api::forumTopic::ID: {
auto forum_topic_info = td::make_unique<ForumTopicInfo>(forum_topic);
auto forum_topic_full = td::make_unique<ForumTopic>(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<td_api::forumTopic> 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");

View File

@ -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<tl_object_ptr<telegram_api::ForumTopic>> &&forum_topics,
const char *source);
void on_get_forum_topic_infos(DialogId dialog_id, vector<tl_object_ptr<telegram_api::ForumTopic>> &&forum_topics,
const char *source);
MessageId on_get_forum_topic(DialogId dialog_id, tl_object_ptr<telegram_api::ForumTopic> &&forum_topic);
td_api::object_ptr<td_api::forumTopic> 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<ForumTopicInfo> info_;
unique_ptr<ForumTopic> topic_;
int32 message_count_ = 0;
template <class StorerT>

View File

@ -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;
}