From e763cb280339894d67f6815419c4a83a73650635 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 20 May 2023 23:24:36 +0300 Subject: [PATCH] Add td_api::getUserPinnedStories. --- td/generate/scheme/td_api.tl | 12 +++++ td/telegram/StoryId.h | 6 ++- td/telegram/StoryManager.cpp | 89 +++++++++++++++++++++++++++++++++++- td/telegram/StoryManager.h | 10 ++++ td/telegram/Td.cpp | 7 +++ td/telegram/Td.h | 2 + td/telegram/cli.cpp | 22 +++++++++ 7 files changed, 146 insertions(+), 2 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 4f178b33b..da6e69301 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4864,6 +4864,9 @@ storyInteractionInfo view_count:int32 recent_viewer_user_ids:vector = Sto //@caption Caption of the story story id:int32 sender_user_id:int53 date:int32 is_pinned:Bool interaction_info:storyInteractionInfo privacy_rules:userPrivacySettingRules is_public:Bool is_for_close_friends:Bool content:StoryContent caption:formattedText = Story; +//@description Represents a list of stories @total_count Approximate total number of stories found @stories The list of stories +stories total_count:int32 stories:vector = Stories; + //@description Contains a part of a file @data File bytes filePart data:bytes = FilePart; @@ -7145,6 +7148,15 @@ setPinnedChats chat_list:ChatList chat_ids:vector = Ok; readChatList chat_list:ChatList = Ok; +//@description Returns the list of pinned stories of a given user. The stories are returned in a reverse chronological order (i.e., in order of decreasing story_id). +//-For optimal performance, the number of returned stories is chosen by TDLib +//@user_id User identifier +//@from_story_id Identifier of the story starting from which stories must be returned; use 0 to get results from the last story +//@limit The maximum number of stories to be returned +//-For optimal performance, the number of returned stories is chosen by TDLib and can be smaller than the specified limit +getUserPinnedStories user_id:int53 from_story_id:int32 limit:int32 = Stories; + + //@description Returns information about a bot that can be added to attachment menu @bot_user_id Bot's user identifier getAttachmentMenuBot bot_user_id:int53 = AttachmentMenuBot; diff --git a/td/telegram/StoryId.h b/td/telegram/StoryId.h index 36f0d7df1..06a04a4a7 100644 --- a/td/telegram/StoryId.h +++ b/td/telegram/StoryId.h @@ -21,11 +21,15 @@ class StoryId { public: StoryId() = default; - explicit StoryId(int32 story_id) : id(story_id) { + explicit constexpr StoryId(int32 story_id) : id(story_id) { } template ::value>> StoryId(T story_id) = delete; + static constexpr StoryId max() { + return StoryId(std::numeric_limits::max()); + } + int32 get() const { return id; } diff --git a/td/telegram/StoryManager.cpp b/td/telegram/StoryManager.cpp index efccf6d67..53bfaa295 100644 --- a/td/telegram/StoryManager.cpp +++ b/td/telegram/StoryManager.cpp @@ -8,10 +8,11 @@ #include "td/telegram/AuthManager.h" #include "td/telegram/ContactsManager.h" -#include "td/telegram/files/FileManager.h" #include "td/telegram/FileReferenceManager.h" +#include "td/telegram/files/FileManager.h" #include "td/telegram/Global.h" #include "td/telegram/MessageEntity.h" +#include "td/telegram/MessagesManager.h" #include "td/telegram/StoryContent.h" #include "td/telegram/StoryContentType.h" #include "td/telegram/Td.h" @@ -58,6 +59,39 @@ class GetStoriesByIDQuery final : public Td::ResultHandler { } }; +class GetPinnedStoriesQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetPinnedStoriesQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(UserId user_id, StoryId offset_story_id, int32 limit) { + auto r_input_user = td_->contacts_manager_->get_input_user(user_id); + if (r_input_user.is_error()) { + return on_error(r_input_user.move_as_error()); + } + send_query(G()->net_query_creator().create( + telegram_api::stories_getPinnedStories(r_input_user.move_as_ok(), offset_story_id.get(), limit))); + } + + 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 GetPinnedStoriesQuery: " << to_string(result); + promise_.set_value(std::move(result)); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + StoryManager::StoryManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { } @@ -83,6 +117,49 @@ StoryManager::Story *StoryManager::get_story_editable(StoryFullId story_full_id) return stories_.get_pointer(story_full_id); } +void StoryManager::get_dialog_pinned_stories(DialogId owner_dialog_id, StoryId from_story_id, int32 limit, + Promise> &&promise) { + if (limit <= 0) { + return promise.set_error(Status::Error(400, "Parameter limit must be positive")); + } + + if (!td_->messages_manager_->have_dialog_force(owner_dialog_id, "get_dialog_pinned_stories")) { + return promise.set_error(Status::Error(400, "Chat not found")); + } + if (!td_->messages_manager_->have_input_peer(owner_dialog_id, AccessRights::Read)) { + return promise.set_error(Status::Error(400, "Can't access the chat")); + } + if (owner_dialog_id.get_type() != DialogType::User) { + return promise.set_value(td_api::make_object()); + } + + if (is_local_story_id(from_story_id)) { + return promise.set_error(Status::Error(400, "Invalid value of parameter from_story_id specified")); + } + + auto query_promise = + PromiseCreator::lambda([actor_id = actor_id(this), owner_dialog_id, promise = std::move(promise)]( + Result> &&result) mutable { + if (result.is_error()) { + return promise.set_error(result.move_as_error()); + } + send_closure(actor_id, &StoryManager::on_get_dialog_pinned_stories, owner_dialog_id, result.move_as_ok(), + std::move(promise)); + }); + td_->create_handler(std::move(query_promise)) + ->send(owner_dialog_id.get_user_id(), from_story_id, limit); +} + +void StoryManager::on_get_dialog_pinned_stories(DialogId owner_dialog_id, + telegram_api::object_ptr &&stories, + Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + auto result = on_get_stories(owner_dialog_id, std::move(stories)); + promise.set_value(get_stories_object(result.first, transform(result.second, [owner_dialog_id](StoryId story_id) { + return StoryFullId(owner_dialog_id, story_id); + }))); +} + td_api::object_ptr StoryManager::get_story_object(StoryFullId story_full_id) const { return get_story_object(story_full_id, get_story(story_full_id)); } @@ -111,6 +188,16 @@ td_api::object_ptr StoryManager::get_story_object(StoryFullId sto get_formatted_text_object(story->caption_, true, -1)); } +td_api::object_ptr StoryManager::get_stories_object(int32 total_count, + const vector &story_full_ids) const { + if (total_count == -1) { + total_count = static_cast(story_full_ids.size()); + } + return td_api::make_object(total_count, transform(story_full_ids, [this](StoryFullId story_full_id) { + return get_story_object(story_full_id); + })); +} + vector StoryManager::get_story_file_ids(const Story *story) const { if (story == nullptr) { return {}; diff --git a/td/telegram/StoryManager.h b/td/telegram/StoryManager.h index 73046d104..2fd9e8d14 100644 --- a/td/telegram/StoryManager.h +++ b/td/telegram/StoryManager.h @@ -39,6 +39,9 @@ class StoryManager final : public Actor { StoryManager &operator=(StoryManager &&) = delete; ~StoryManager() final; + void get_dialog_pinned_stories(DialogId owner_dialog_id, StoryId from_story_id, int32 limit, + Promise> &&promise); + StoryId on_get_story(DialogId owner_dialog_id, telegram_api::object_ptr &&story_item); std::pair> on_get_stories(DialogId owner_dialog_id, @@ -46,6 +49,9 @@ class StoryManager final : public Actor { td_api::object_ptr get_story_object(StoryFullId story_full_id) const; + td_api::object_ptr get_stories_object(int32 total_count, + const vector &story_full_ids) const; + FileSourceId get_story_file_source_id(StoryFullId story_full_id); void reload_story(StoryFullId story_full_id, Promise &&promise); @@ -73,6 +79,10 @@ class StoryManager final : public Actor { td_api::object_ptr get_story_object(StoryFullId story_full_id, const Story *story) const; + void on_get_dialog_pinned_stories(DialogId owner_dialog_id, + telegram_api::object_ptr &&stories, + Promise> &&promise); + vector get_story_file_ids(const Story *story) const; void delete_story_files(const Story *story) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index d18cd7b5f..47240e283 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6374,6 +6374,13 @@ void Td::on_request(uint64 id, const td_api::readChatList &request) { messages_manager_->read_all_dialogs_from_list(DialogListId(request.chat_list_), std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getUserPinnedStories &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + story_manager_->get_dialog_pinned_stories(DialogId(UserId(request.user_id_)), StoryId(request.from_story_id_), + request.limit_, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getAttachmentMenuBot &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 5bba822a6..4348bdbaf 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -986,6 +986,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::readChatList &request); + void on_request(uint64 id, const td_api::getUserPinnedStories &request); + void on_request(uint64 id, const td_api::getAttachmentMenuBot &request); void on_request(uint64 id, const td_api::toggleBotIsAddedToAttachmentMenu &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 591aa4f6f..b64daec8d 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -538,6 +538,10 @@ class CliClient final : public Actor { } } + static int32 as_story_id(Slice str) { + return to_integer(trim(str)); + } + static td_api::object_ptr as_sticker_format(string sticker_format) { if (!sticker_format.empty() && sticker_format.back() == 'a') { return td_api::make_object(); @@ -846,6 +850,18 @@ class CliClient final : public Actor { arg.chat_folder_id = as_chat_folder_id(args); } + struct StoryId { + int32 story_id = 0; + + operator int32() const { + return story_id; + } + }; + + void get_args(string &args, StoryId &arg) const { + arg.story_id = as_story_id(args); + } + struct FileId { int32 file_id = 0; @@ -3895,6 +3911,12 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_list(op), as_chat_ids(args))); } else if (op == "rcl" || op == "rcla" || begins_with(op, "rcl-")) { send_request(td_api::make_object(as_chat_list(op))); + } else if (op == "gups") { + UserId user_id; + StoryId from_story_id; + string limit; + get_args(args, user_id, from_story_id, limit); + send_request(td_api::make_object(user_id, from_story_id, as_limit(limit))); } else if (op == "gamb") { UserId user_id; get_args(args, user_id);