From b8849a2f818e83c80497e783d6b4e941408a3a09 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 29 Jun 2023 14:22:50 +0300 Subject: [PATCH] Add td_api::loadActiveStories. --- td/generate/scheme/td_api.tl | 8 ++- td/telegram/StoryManager.cpp | 136 +++++++++++++++++++++++++++++++---- td/telegram/StoryManager.h | 17 +++++ td/telegram/Td.cpp | 6 ++ td/telegram/Td.h | 2 + td/telegram/cli.cpp | 4 ++ 6 files changed, 159 insertions(+), 14 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 68fcc3279..422baca9c 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4955,10 +4955,11 @@ storyInfo story_id:int32 date:int32 = StoryInfo; //@description Describes active stories sent by the same sender //@list Identifier of the story list in which the stories are shown; may be null if the stories aren't from a current user's contact +//@order A parameter used to determine order of the stories in the story list. Stories must be sorted by the pair (order, story_sender_chat_id) in descending order //@story_sender_chat_id Identifier of the sender of the stories //@max_read_story_id Identifier of the last read active story //@stories Basic information about the stories; use getStory to get full information about the stories -activeStories list:StoryList story_sender_chat_id:int53 max_read_story_id:int32 stories:vector = ActiveStories; +activeStories list:StoryList order:int53 story_sender_chat_id:int53 max_read_story_id:int32 stories:vector = ActiveStories; //@description Contains a part of a file @data File bytes @@ -7278,6 +7279,11 @@ toggleStoryIsPinned story_id:int32 is_pinned:Bool = Ok; //@description Deletes a previously sent story @story_id Identifier of the story to delete deleteStory story_id:int32 = Ok; +//@description Loads more active stories from a story list. The loaded stories will be sent through updates. Active stories are sorted by +//-the pair (active_stories.order, active_stories.story_sender_chat_id) in descending order. Returns a 404 error if all active stories have been loaded +//@story_list The story list in which to load active stories +loadActiveStories story_list:StoryList = Ok; + //@description Toggles whether stories posted by the chat are available above chat lists @chat_id Identifier of the chat that posted stories @are_hidden Pass true to make the stories unavailable above the chat lists; pass false to make them available toggleChatStoriesAreHidden chat_id:int53 are_hidden:Bool = Ok; diff --git a/td/telegram/StoryManager.cpp b/td/telegram/StoryManager.cpp index 3877f9aeb..7a4bfddc3 100644 --- a/td/telegram/StoryManager.cpp +++ b/td/telegram/StoryManager.cpp @@ -36,6 +36,45 @@ namespace td { +class GetAllStoriesQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetAllStoriesQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(bool is_next, bool is_hidden, const string &state) { + int32 flags = 0; + if (!state.empty()) { + flags |= telegram_api::stories_getAllStories::STATE_MASK; + } + if (is_next) { + flags |= telegram_api::stories_getAllStories::NEXT_MASK; + } + if (is_hidden) { + flags |= telegram_api::stories_getAllStories::HIDDEN_MASK; + } + send_query(G()->net_query_creator().create( + telegram_api::stories_getAllStories(flags, false /*ignored*/, false /*ignored*/, state))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto result = result_ptr.move_as_ok(); + LOG(DEBUG) << "Receive result for GetAllStoriesQuery: " << to_string(result); + promise_.set_value(std::move(result)); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + class ToggleStoriesHiddenQuery final : public Td::ResultHandler { Promise promise_; UserId user_id_; @@ -808,6 +847,73 @@ const StoryManager::ActiveStories *StoryManager::get_active_stories(DialogId own return active_stories_.get_pointer(owner_dialog_id); } +void StoryManager::load_active_stories(const td_api::object_ptr &story_list_ptr, + Promise &&promise) { + if (story_list_ptr == nullptr) { + return promise.set_error(Status::Error(400, "Story list must not be empty")); + } + bool is_hidden = story_list_ptr->get_id() == td_api::storyListHidden::ID; + auto &story_list = story_lists_[is_hidden]; + if (!story_list.has_more_) { + return promise.set_error(Status::Error(404, "Not found")); + } + story_list.load_list_queries_.push_back(std::move(promise)); + if (story_list.load_list_queries_.size() == 1u) { + bool is_next = !story_list.state_.empty(); + auto query_promise = + PromiseCreator::lambda([actor_id = actor_id(this), is_hidden]( + Result> r_all_stories) { + send_closure(actor_id, &StoryManager::on_load_active_stories, is_hidden, std::move(r_all_stories)); + }); + td_->create_handler(std::move(query_promise))->send(is_next, is_hidden, story_list.state_); + } +} + +void StoryManager::on_load_active_stories( + bool is_hidden, Result> r_all_stories) { + G()->ignore_result_if_closing(r_all_stories); + auto &story_list = story_lists_[is_hidden]; + auto promises = std::move(story_list.load_list_queries_); + CHECK(!promises.empty()); + if (r_all_stories.is_error()) { + return fail_promises(promises, r_all_stories.move_as_error()); + } + auto all_stories = r_all_stories.move_as_ok(); + switch (all_stories->get_id()) { + case telegram_api::stories_allStoriesNotModified::ID: { + auto stories = telegram_api::move_object_as(all_stories); + if (stories->state_.empty()) { + LOG(ERROR) << "Receive empty state in " << to_string(stories); + } else { + story_list.state_ = std::move(stories->state_); + } + break; + } + case telegram_api::stories_allStories::ID: { + auto stories = telegram_api::move_object_as(all_stories); + td_->contacts_manager_->on_get_users(std::move(stories->users_), "on_load_active_stories"); + if (stories->state_.empty()) { + LOG(ERROR) << "Receive empty state in " << to_string(stories); + } else { + story_list.state_ = std::move(stories->state_); + } + story_list.has_more_ = stories->has_more_; + story_list.server_total_count_ = stories->count_; + + // auto min_story_date = MIN_DIALOG_DATE; + for (auto &user_stories : stories->user_stories_) { + auto owner_dialog_id = on_get_user_stories(DialogId(), std::move(user_stories)); + // DialogDate story_date(0, owner_dialog_id); + } + break; + } + default: + UNREACHABLE(); + } + + set_promises(promises); +} + void StoryManager::try_synchronize_archive_all_stories() { if (G()->close_flag()) { return; @@ -1506,18 +1612,6 @@ td_api::object_ptr StoryManager::get_stories_object(int32 total } td_api::object_ptr StoryManager::get_active_stories_object(DialogId owner_dialog_id) const { - const auto *active_stories = get_active_stories(owner_dialog_id); - StoryId max_read_story_id; - vector> stories; - if (active_stories != nullptr) { - max_read_story_id = active_stories->max_read_story_id_; - for (auto story_id : active_stories->story_ids_) { - auto story_info = get_story_info_object({owner_dialog_id, story_id}); - if (story_info != nullptr) { - stories.push_back(std::move(story_info)); - } - } - } td_api::object_ptr list; if (is_subscribed_to_dialog_stories(owner_dialog_id)) { if (td_->contacts_manager_->get_user_stories_hidden(owner_dialog_id.get_user_id())) { @@ -1527,8 +1621,24 @@ td_api::object_ptr StoryManager::get_active_stories_objec } } + const auto *active_stories = get_active_stories(owner_dialog_id); + StoryId max_read_story_id; + vector> stories; + int64 order = 0; + if (active_stories != nullptr) { + max_read_story_id = active_stories->max_read_story_id_; + for (auto story_id : active_stories->story_ids_) { + auto story_info = get_story_info_object({owner_dialog_id, story_id}); + if (story_info != nullptr) { + stories.push_back(std::move(story_info)); + } + } + if (list != nullptr) { + order = active_stories->public_order_; + } + } return td_api::make_object( - std::move(list), td_->messages_manager_->get_chat_id_object(owner_dialog_id, "get_active_stories_object"), + std::move(list), order, td_->messages_manager_->get_chat_id_object(owner_dialog_id, "get_active_stories_object"), max_read_story_id.get(), std::move(stories)); } diff --git a/td/telegram/StoryManager.h b/td/telegram/StoryManager.h index 8d1fb02cf..300ba6390 100644 --- a/td/telegram/StoryManager.h +++ b/td/telegram/StoryManager.h @@ -84,6 +84,8 @@ class StoryManager final : public Actor { struct ActiveStories { StoryId max_read_story_id_; vector story_ids_; + int64 private_order_ = 0; + int64 public_order_ = 0; }; struct CachedStoryViewers { @@ -91,6 +93,14 @@ class StoryManager final : public Actor { MessageViewers viewers_; }; + struct StoryList { + bool has_more_ = true; + int32 server_total_count_ = -1; + string state_; + + vector> load_list_queries_; + }; + public: StoryManager(Td *td, ActorShared<> parent); StoryManager(const StoryManager &) = delete; @@ -118,6 +128,8 @@ class StoryManager final : public Actor { void delete_story(StoryId story_id, Promise &&promise); + void load_active_stories(const td_api::object_ptr &story_list_ptr, Promise &&promise); + void toggle_dialog_stories_hidden(DialogId dialog_id, bool are_hidden, Promise &&promise); void get_dialog_pinned_stories(DialogId owner_dialog_id, StoryId from_story_id, int32 limit, @@ -277,6 +289,9 @@ class StoryManager final : public Actor { void on_load_dialog_expiring_stories(DialogId owner_dialog_id); + void on_load_active_stories(bool is_hidden, + Result> r_all_stories); + vector get_story_file_ids(const Story *story) const; static uint64 save_delete_story_on_server_log_event(StoryFullId story_full_id); @@ -361,6 +376,8 @@ class StoryManager final : public Actor { FlatHashMap>, StoryFullIdHash> reload_story_queries_; + StoryList story_lists_[2]; + uint32 send_story_count_ = 0; int64 max_story_global_id_ = 0; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 233c0a85b..ac5984f2f 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5660,6 +5660,12 @@ void Td::on_request(uint64 id, const td_api::deleteStory &request) { story_manager_->delete_story(StoryId(request.story_id_), std::move(promise)); } +void Td::on_request(uint64 id, const td_api::loadActiveStories &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + story_manager_->load_active_stories(request.story_list_, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::toggleChatStoriesAreHidden &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 4e5dbc048..d3dc98691 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -798,6 +798,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::deleteStory &request); + void on_request(uint64 id, const td_api::loadActiveStories &request); + void on_request(uint64 id, const td_api::toggleChatStoriesAreHidden &request); void on_request(uint64 id, const td_api::getForumTopicDefaultIcons &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 31def8155..41edaad14 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4040,6 +4040,10 @@ class CliClient final : public Actor { StoryId story_id; get_args(args, story_id); send_request(td_api::make_object(story_id)); + } else if (op == "las") { + send_request(td_api::make_object(td_api::make_object())); + } else if (op == "lash") { + send_request(td_api::make_object(td_api::make_object())); } else if (op == "tcsah") { ChatId chat_id; bool are_hidden;