diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0fc307978..1ec06d876 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1662,7 +1662,7 @@ forumTopicIcon color:int32 custom_emoji_id:int64 = ForumTopicIcon; //@message_thread_id Message thread identifier of the topic //@name Name of the topic //@icon Icon of the topic -//@creation_date Date the topic was created +//@creation_date Point in time (Unix timestamp) when the topic was created //@creator_id Identifier of the creator of the topic //@is_general True, if the topic is the General topic list //@is_outgoing True, if the topic was created by the current user @@ -2680,7 +2680,7 @@ messagePassportDataReceived elements:vector credential //@description A user in the chat came within proximity alert range @traveler_id The identifier of a user or chat that triggered the proximity alert @watcher_id The identifier of a user or chat that subscribed for the proximity alert @distance The distance between the users messageProximityAlertTriggered traveler_id:MessageSender watcher_id:MessageSender distance:int32 = MessageContent; -//@description Message content that is not supported in the current TDLib version +//@description A message content that is not supported in the current TDLib version messageUnsupported = MessageContent; @@ -2756,7 +2756,7 @@ inputThumbnail thumbnail:InputFile width:int32 height:int32 = InputThumbnail; //@class MessageSchedulingState @description Contains information about the time when a scheduled message will be sent -//@description The message will be sent at the specified date @send_date Date the message will be sent. The date must be within 367 days in the future +//@description The message will be sent at the specified date @send_date Point in time (Unix timestamp) when the message will be sent. The date must be within 367 days in the future messageSchedulingStateSendAtDate send_date:int32 = MessageSchedulingState; //@description The message will be sent when the peer will be online. Applicable to private chats only and when the exact online status of the peer is known @@ -4833,6 +4833,37 @@ messageLink link:string is_public:Bool = MessageLink; messageLinkInfo is_public:Bool chat_id:int53 message_thread_id:int53 message:message media_timestamp:int32 for_album:Bool = MessageLinkInfo; +//@class StoryContent @description Contains the content of a story + +//@description A photo story @photo The photo +storyContentPhoto photo:photo = StoryContent; + +//@description A video story @video The video in MPEG4 format, encoded by x265 codec @alternative_video Alternative version of the video in MPEG4 format, encoded by x264 codec; may be null +storyContentVideo video:video alternative_video:video = StoryContent; + +//@description A story content that is not supported in the current TDLib version +storyContentUnsupported = StoryContent; + + +//@description Contains information about interactions with a story +//@view_count Number of times the story was viewed +//@recent_viewer_user_ids Identifiers of at most 3 recent viewers of the story +storyInteractionInfo view_count:int32 recent_viewer_user_ids:vector = StoryInteractionInfo; + +//@description Represents a story +//@id Unique story identifier among stories of the given sender +//@sender_user_id Identifier of the user that created the story +//@date Point in time (Unix timestamp) when the story was published +//@is_pinned True, if the story is saved in the sender's profile and will be available there after the expiration +//@interaction_info Information about interactions with the story; may be null if the story isn't owned or there were no interactions +//@privacy_rules Pryvacy rules affecting story visibility; may be null if the story isn't owned +//@is_public True, if the story is available for everyone +//@is_for_close_friends True, if the story is available only for close friends +//@content Content of the story +//@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 Contains a part of a file @data File bytes filePart data:bytes = FilePart; diff --git a/td/telegram/StoryContent.cpp b/td/telegram/StoryContent.cpp index 41b7be4bc..d6ae450da 100644 --- a/td/telegram/StoryContent.cpp +++ b/td/telegram/StoryContent.cpp @@ -164,4 +164,28 @@ void merge_story_contents(Td *td, const StoryContent *old_content, StoryContent } } +td_api::object_ptr get_story_content_object(Td *td, const StoryContent *content) { + CHECK(content != nullptr); + switch (content->get_type()) { + case StoryContentType::Photo: { + const auto *s = static_cast(content); + auto photo = get_photo_object(td->file_manager_.get(), s->photo_); + if (photo == nullptr) { + return td_api::make_object(); + } + return td_api::make_object(std::move(photo)); + } + case StoryContentType::Video: { + const auto *s = static_cast(content); + return td_api::make_object(td->videos_manager_->get_video_object(s->file_id_), + td->videos_manager_->get_video_object(s->alt_file_id_)); + } + case StoryContentType::Unsupported: + return td_api::make_object(); + default: + UNREACHABLE(); + return nullptr; + } +} + } // namespace td diff --git a/td/telegram/StoryContent.h b/td/telegram/StoryContent.h index 96c24d94b..82634cb45 100644 --- a/td/telegram/StoryContent.h +++ b/td/telegram/StoryContent.h @@ -8,6 +8,7 @@ #include "td/telegram/DialogId.h" #include "td/telegram/StoryContentType.h" +#include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" namespace td { @@ -32,4 +33,6 @@ unique_ptr get_story_content(Td *td, telegram_api::object_ptr get_story_content_object(Td *td, const StoryContent *content); + } // namespace td diff --git a/td/telegram/StoryInteractionInfo.cpp b/td/telegram/StoryInteractionInfo.cpp index bad3df074..7cc143295 100644 --- a/td/telegram/StoryInteractionInfo.cpp +++ b/td/telegram/StoryInteractionInfo.cpp @@ -36,6 +36,15 @@ StoryInteractionInfo::StoryInteractionInfo(Td *td, telegram_api::object_ptr StoryInteractionInfo::get_story_interaction_info_object(Td *td) const { + if (is_empty()) { + return nullptr; + } + return td_api::make_object( + view_count_, + td->contacts_manager_->get_user_ids_object(recent_viewer_user_ids_, "get_story_interaction_info_object")); +} + bool operator==(const StoryInteractionInfo &lhs, const StoryInteractionInfo &rhs) { return lhs.recent_viewer_user_ids_ == rhs.recent_viewer_user_ids_ && lhs.view_count_ == rhs.view_count_; } diff --git a/td/telegram/StoryInteractionInfo.h b/td/telegram/StoryInteractionInfo.h index e24b13409..db7258490 100644 --- a/td/telegram/StoryInteractionInfo.h +++ b/td/telegram/StoryInteractionInfo.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" #include "td/telegram/UserId.h" @@ -34,6 +35,8 @@ class StoryInteractionInfo { bool is_empty() const { return view_count_ < 0; } + + td_api::object_ptr get_story_interaction_info_object(Td *td) const; }; bool operator==(const StoryInteractionInfo &lhs, const StoryInteractionInfo &rhs); diff --git a/td/telegram/StoryManager.cpp b/td/telegram/StoryManager.cpp index b18473487..ee6bd2de2 100644 --- a/td/telegram/StoryManager.cpp +++ b/td/telegram/StoryManager.cpp @@ -28,6 +28,10 @@ bool StoryManager::is_local_story_id(StoryId story_id) { return story_id.get() < 0; } +bool StoryManager::is_story_owned(DialogId owner_dialog_id) const { + return owner_dialog_id == DialogId(td_->contacts_manager_->get_my_id()); +} + const StoryManager::Story *StoryManager::get_story(StoryFullId story_full_id) const { return stories_.get_pointer(story_full_id); } @@ -36,6 +40,34 @@ StoryManager::Story *StoryManager::get_story_editable(StoryFullId story_full_id) return stories_.get_pointer(story_full_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)); +} + +td_api::object_ptr StoryManager::get_story_object(StoryFullId story_full_id, const Story *story) const { + if (story == nullptr) { + return nullptr; + } + auto dialog_id = story_full_id.get_dialog_id(); + bool is_owned = is_story_owned(dialog_id); + if (!is_owned && !story->is_pinned_ && G()->unix_time() >= story->expire_date_) { + return nullptr; + } + + td_api::object_ptr privacy_rules; + if (is_owned) { + privacy_rules = story->privacy_rules_.get_user_privacy_setting_rules_object(td_); + } + + CHECK(dialog_id.get_type() == DialogType::User); + return td_api::make_object( + story_full_id.get_story_id().get(), + td_->contacts_manager_->get_user_id_object(dialog_id.get_user_id(), "get_story_object"), story->date_, + story->is_pinned_, story->interaction_info_.get_story_interaction_info_object(td_), std::move(privacy_rules), + story->is_public_, story->is_for_close_friends_, get_story_content_object(td_, story->content_.get()), + get_formatted_text_object(story->caption_, true, -1)); +} + StoryId StoryManager::on_get_story(DialogId owner_dialog_id, telegram_api::object_ptr &&story_item) { CHECK(story_item != nullptr); diff --git a/td/telegram/StoryManager.h b/td/telegram/StoryManager.h index fbe53b372..0533096d7 100644 --- a/td/telegram/StoryManager.h +++ b/td/telegram/StoryManager.h @@ -11,6 +11,7 @@ #include "td/telegram/StoryFullId.h" #include "td/telegram/StoryId.h" #include "td/telegram/StoryInteractionInfo.h" +#include "td/telegram/td_api.h" #include "td/telegram/UserId.h" #include "td/telegram/UserPrivacySettingRule.h" @@ -35,6 +36,8 @@ class StoryManager final : public Actor { StoryId on_get_story(DialogId owner_dialog_id, telegram_api::object_ptr &&story_item); + td_api::object_ptr get_story_object(StoryFullId story_full_id) const; + private: struct Story { int32 date_ = 0; @@ -50,10 +53,14 @@ class StoryManager final : public Actor { void tear_down() final; + bool is_story_owned(DialogId owner_dialog_id) const; + const Story *get_story(StoryFullId story_full_id) const; Story *get_story_editable(StoryFullId story_full_id); + td_api::object_ptr get_story_object(StoryFullId story_full_id, const Story *story) const; + static bool is_local_story_id(StoryId story_id); WaitFreeHashMap, StoryFullIdHash> stories_;