diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index e93da322f..7d6d9324a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4918,11 +4918,12 @@ storyInteractionInfo view_count:int32 recent_viewer_user_ids:vector = Sto //@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 expiration +//@can_get_viewers True, users viewed the story can be received through getStoryViewers //@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 //@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 content:StoryContent caption:formattedText = Story; +story id:int32 sender_user_id:int53 date:int32 is_pinned:Bool can_get_viewers:Bool interaction_info:storyInteractionInfo privacy_rules:userPrivacySettingRules 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; diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index c9d039cc6..5066f58e3 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -1560,6 +1560,7 @@ void ConfigManager::process_app_config(tl_object_ptr &c bool premium_gift_text_field_icon = false; int32 dialog_filter_update_period = 300; bool archive_all_stories = false; + int32 story_viewers_expire_period = 86400; if (config->get_id() == telegram_api::jsonObject::ID) { for (auto &key_value : static_cast(config.get())->value_) { Slice key = key_value->key_; @@ -1960,6 +1961,10 @@ void ConfigManager::process_app_config(tl_object_ptr &c archive_all_stories = get_json_value_bool(std::move(key_value->value_), key); continue; } + if (key == "story_viewers_expire_period") { + story_viewers_expire_period = get_json_value_int(std::move(key_value->value_), key); + continue; + } new_values.push_back(std::move(key_value)); } @@ -2126,6 +2131,10 @@ void ConfigManager::process_app_config(tl_object_ptr &c options.set_option_empty("gift_premium_from_input_field"); } + if (story_viewers_expire_period >= 0) { + options.set_option_integer("story_viewers_expire_period", story_viewers_expire_period); + } + if (!options.get_option_boolean("need_synchronize_archive_all_stories")) { options.set_option_boolean("archive_all_stories", archive_all_stories); } diff --git a/td/telegram/ConfigManager.h b/td/telegram/ConfigManager.h index e3f8eb761..8f6659d28 100644 --- a/td/telegram/ConfigManager.h +++ b/td/telegram/ConfigManager.h @@ -106,7 +106,7 @@ class ConfigManager final : public NetQueryCallback { private: struct AppConfig { - static constexpr int32 CURRENT_VERSION = 4; + static constexpr int32 CURRENT_VERSION = 5; int32 version_ = 0; int32 hash_ = 0; telegram_api::object_ptr config_; diff --git a/td/telegram/OptionManager.cpp b/td/telegram/OptionManager.cpp index 6840b547d..1a231a090 100644 --- a/td/telegram/OptionManager.cpp +++ b/td/telegram/OptionManager.cpp @@ -292,7 +292,8 @@ bool OptionManager::is_internal_option(Slice name) { return name == "saved_animations_limit" || name == "saved_gifs_limit_default" || name == "saved_gifs_limit_premium" || name == "session_count" || name == "since_last_open" || name == "stickers_faved_limit_default" || name == "stickers_faved_limit_premium" || - name == "stickers_normal_by_emoji_per_premium_num" || name == "stickers_premium_by_emoji_num"; + name == "stickers_normal_by_emoji_per_premium_num" || name == "stickers_premium_by_emoji_num" || + name == "story_viewers_expire_period"; case 'v': return name == "video_note_size_max"; case 'w': diff --git a/td/telegram/StoryManager.cpp b/td/telegram/StoryManager.cpp index 36877ce5f..4eb5c799d 100644 --- a/td/telegram/StoryManager.cpp +++ b/td/telegram/StoryManager.cpp @@ -990,6 +990,21 @@ void StoryManager::read_stories_on_server(DialogId owner_dialog_id, StoryId stor td_->create_handler(get_erase_log_event_promise(log_event_id))->send(owner_dialog_id, story_id); } +Status StoryManager::can_get_story_viewers(StoryFullId story_full_id, const Story *story) const { + CHECK(story != nullptr); + if (!is_story_owned(story_full_id.get_dialog_id())) { + return Status::Error(400, "Story is not outgoing"); + } + if (!story_full_id.get_story_id().is_server()) { + return Status::Error(400, "Story is not sent yet"); + } + if (G()->unix_time() >= + story->expire_date_ + td_->option_manager_->get_option_integer("story_viewers_expire_period", 86400)) { + return Status::Error(400, "Story is too old"); + } + return Status::OK(); +} + void StoryManager::get_story_viewers(StoryId story_id, const td_api::messageViewer *offset, int32 limit, Promise> &&promise) { DialogId owner_dialog_id(td_->contacts_manager_->get_my_id()); @@ -998,14 +1013,13 @@ void StoryManager::get_story_viewers(StoryId story_id, const td_api::messageView if (story == nullptr) { return promise.set_error(Status::Error(400, "Story not found")); } - if (!story_id.is_server()) { - return promise.set_value(td_api::object_ptr()); - } - // TRY_STATUS_PROMISE(promise, can_get_story_viewers(story_full_id)); - if (limit <= 0) { return promise.set_error(Status::Error(400, "Parameter limit must be positive")); } + if (can_get_story_viewers(story_full_id, story).is_error()) { + return promise.set_value(td_api::object_ptr()); + } + int32 offset_date = 0; int64 offset_user_id = 0; if (offset != nullptr) { @@ -1159,7 +1173,8 @@ td_api::object_ptr StoryManager::get_story_object(StoryFullId sto 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_pinned_, can_get_story_viewers(story_full_id, story).is_ok(), + story->interaction_info_.get_story_interaction_info_object(td_), std::move(privacy_rules), get_story_content_object(td_, content), get_formatted_text_object(story->caption_, true, get_story_content_duration(td_, content))); } diff --git a/td/telegram/StoryManager.h b/td/telegram/StoryManager.h index b5ed6351c..9d69c35d8 100644 --- a/td/telegram/StoryManager.h +++ b/td/telegram/StoryManager.h @@ -23,6 +23,7 @@ #include "td/utils/common.h" #include "td/utils/Promise.h" +#include "td/utils/Status.h" #include "td/utils/WaitFreeHashMap.h" #include "td/utils/WaitFreeHashSet.h" @@ -133,6 +134,8 @@ class StoryManager final : public Actor { bool on_update_read_stories(DialogId owner_dialog_id, StoryId max_read_story_id); + Status can_get_story_viewers(StoryFullId story_full_id, const Story *story) const; + void on_get_story_views(const vector &story_ids, telegram_api::object_ptr &&story_views);