From efbb5bde966a9661916c503d9960db4716d659a9 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 7 Sep 2021 17:21:18 +0300 Subject: [PATCH] Combine getSponsoredMessages queries. --- td/telegram/SponsoredMessageManager.cpp | 135 ++++++++++++++++++------ td/telegram/SponsoredMessageManager.h | 16 +++ 2 files changed, 119 insertions(+), 32 deletions(-) diff --git a/td/telegram/SponsoredMessageManager.cpp b/td/telegram/SponsoredMessageManager.cpp index 34bc3c77b..e81a38ac5 100644 --- a/td/telegram/SponsoredMessageManager.cpp +++ b/td/telegram/SponsoredMessageManager.cpp @@ -16,6 +16,7 @@ #include "td/telegram/Td.h" #include "td/telegram/telegram_api.h" +#include "td/utils/algorithm.h" #include "td/utils/buffer.h" #include "td/utils/logging.h" #include "td/utils/Status.h" @@ -23,11 +24,12 @@ namespace td { class GetSponsoredMessagesQuery final : public Td::ResultHandler { - Promise> promise_; + Promise> promise_; ChannelId channel_id_; public: - explicit GetSponsoredMessagesQuery(Promise> &&promise) + explicit GetSponsoredMessagesQuery( + Promise> &&promise) : promise_(std::move(promise)) { } @@ -46,35 +48,7 @@ class GetSponsoredMessagesQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto sponsored_messages = result_ptr.move_as_ok(); - - td->contacts_manager_->on_get_users(std::move(sponsored_messages->users_), "GetSponsoredMessagesQuery"); - td->contacts_manager_->on_get_chats(std::move(sponsored_messages->chats_), "GetSponsoredMessagesQuery"); - - vector> messages; - for (auto &sponsored_message : sponsored_messages->messages_) { - DialogId dialog_id(sponsored_message->from_id_); - if (!dialog_id.is_valid() || !td->messages_manager_->have_dialog_info_force(dialog_id)) { - LOG(ERROR) << "Receive unknown sponsor " << dialog_id; - continue; - } - td->messages_manager_->force_create_dialog(dialog_id, "GetSponsoredMessagesQuery"); - auto message_text = - get_message_text(td->contacts_manager_.get(), std::move(sponsored_message->message_), - std::move(sponsored_message->entities_), true, true, 0, false, "GetSponsoredMessagesQuery"); - int32 ttl = 0; - auto content = get_message_content(td, std::move(message_text), nullptr, dialog_id, true, UserId(), &ttl); - if (ttl != 0) { - LOG(ERROR) << "Receive sponsored message with TTL " << ttl; - continue; - } - - messages.push_back(td_api::make_object( - sponsored_message->random_id_.as_slice().str(), dialog_id.get(), sponsored_message->start_param_, - get_message_content_object(content.get(), td, DialogId(channel_id_), 0, false, true, -1))); - } - - promise_.set_value(td_api::make_object(std::move(messages))); + promise_.set_value(result_ptr.move_as_ok()); } void on_error(uint64 id, Status status) final { @@ -116,6 +90,26 @@ class ViewSponsoredMessageQuery final : public Td::ResultHandler { } }; +struct SponsoredMessageManager::SponsoredMessage { + string random_id; + DialogId sponsor_dialog_id; + string start_param; + unique_ptr content; + + SponsoredMessage() = default; + SponsoredMessage(string random_id, DialogId sponsor_dialog_id, string start_param, unique_ptr content) + : random_id(std::move(random_id)) + , sponsor_dialog_id(sponsor_dialog_id) + , start_param(std::move(start_param)) + , content(std::move(content)) { + } +}; + +struct SponsoredMessageManager::DialogSponsoredMessages { + vector>> promises; + vector messages; +}; + SponsoredMessageManager::SponsoredMessageManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { } @@ -125,6 +119,21 @@ void SponsoredMessageManager::tear_down() { parent_.reset(); } +td_api::object_ptr SponsoredMessageManager::get_sponsored_message_object( + DialogId dialog_id, const SponsoredMessage &sponsored_message) const { + return td_api::make_object( + sponsored_message.random_id, sponsored_message.sponsor_dialog_id.get(), sponsored_message.start_param, + get_message_content_object(sponsored_message.content.get(), td_, dialog_id, 0, false, true, -1)); +} + +td_api::object_ptr SponsoredMessageManager::get_sponsored_messages_object( + DialogId dialog_id, const DialogSponsoredMessages &sponsored_messages) const { + return td_api::make_object( + transform(sponsored_messages.messages, [this, dialog_id](const SponsoredMessage &sponsored_message) { + return get_sponsored_message_object(dialog_id, sponsored_message); + })); +} + void SponsoredMessageManager::get_dialog_sponsored_messages( DialogId dialog_id, Promise> &&promise) { if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_sponsored_messages")) { @@ -135,7 +144,69 @@ void SponsoredMessageManager::get_dialog_sponsored_messages( return promise.set_value(td_api::make_object()); } - td_->create_handler(std::move(promise))->send(dialog_id.get_channel_id()); + auto &messages = dialog_sponsored_messages_[dialog_id]; + if (messages == nullptr) { + messages = make_unique(); + } + messages->promises.push_back(std::move(promise)); + if (messages->promises.size() == 1) { + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), + dialog_id](Result> &&result) mutable { + send_closure(actor_id, &SponsoredMessageManager::on_get_dialog_sponsored_messages, dialog_id, + std::move(result)); + }); + td_->create_handler(std::move(query_promise))->send(dialog_id.get_channel_id()); + } +} + +void SponsoredMessageManager::on_get_dialog_sponsored_messages( + DialogId dialog_id, Result> &&result) { + auto &messages = dialog_sponsored_messages_[dialog_id]; + CHECK(messages != nullptr); + auto promises = std::move(messages->promises); + reset_to_empty(messages->promises); + + if (result.is_ok() && G()->close_flag()) { + result = Status::Error(500, "Request aborted"); + } + if (result.is_error()) { + for (auto &promise : promises) { + promise.set_error(result.error().clone()); + } + return; + } + + auto sponsored_messages = result.move_as_ok(); + + td_->contacts_manager_->on_get_users(std::move(sponsored_messages->users_), "on_get_dialog_sponsored_messages"); + td_->contacts_manager_->on_get_chats(std::move(sponsored_messages->chats_), "on_get_dialog_sponsored_messages"); + + reset_to_empty(messages->messages); + for (auto &sponsored_message : sponsored_messages->messages_) { + DialogId sponsor_dialog_id(sponsored_message->from_id_); + if (!sponsor_dialog_id.is_valid() || !td_->messages_manager_->have_dialog_info_force(sponsor_dialog_id)) { + LOG(ERROR) << "Receive unknown sponsor " << sponsor_dialog_id; + continue; + } + td_->messages_manager_->force_create_dialog(sponsor_dialog_id, "on_get_dialog_sponsored_messages"); + auto message_text = get_message_text(td_->contacts_manager_.get(), std::move(sponsored_message->message_), + std::move(sponsored_message->entities_), true, true, 0, false, + "on_get_dialog_sponsored_messages"); + int32 ttl = 0; + auto content = get_message_content(td_, std::move(message_text), nullptr, sponsor_dialog_id, true, UserId(), &ttl); + if (ttl != 0) { + LOG(ERROR) << "Receive sponsored message with TTL " << ttl; + continue; + } + + messages->messages.emplace_back(sponsored_message->random_id_.as_slice().str(), sponsor_dialog_id, + std::move(sponsored_message->start_param_), std::move(content)); + } + + for (auto &promise : promises) { + promise.set_value(get_sponsored_messages_object(dialog_id, *messages)); + } } void SponsoredMessageManager::view_sponsored_message(DialogId dialog_id, const string &message_id, diff --git a/td/telegram/SponsoredMessageManager.h b/td/telegram/SponsoredMessageManager.h index 01fde08e1..cb7a413e9 100644 --- a/td/telegram/SponsoredMessageManager.h +++ b/td/telegram/SponsoredMessageManager.h @@ -8,11 +8,13 @@ #include "td/telegram/DialogId.h" #include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" #include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" #include "td/utils/common.h" +#include "td/utils/Status.h" namespace td { @@ -33,8 +35,22 @@ class SponsoredMessageManager final : public Actor { void view_sponsored_message(DialogId dialog_id, const string &message_id, Promise &&promise); private: + struct SponsoredMessage; + struct DialogSponsoredMessages; + void tear_down() final; + td_api::object_ptr get_sponsored_message_object( + DialogId dialog_id, const SponsoredMessage &sponsored_message) const; + + td_api::object_ptr get_sponsored_messages_object( + DialogId dialog_id, const DialogSponsoredMessages &sponsored_messages) const; + + void on_get_dialog_sponsored_messages( + DialogId dialog_id, Result> &&result); + + std::unordered_map, DialogIdHash> dialog_sponsored_messages_; + Td *td_; ActorShared<> parent_; };