diff --git a/CMakeLists.txt b/CMakeLists.txt index b8d730090..f0b6142d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -470,6 +470,7 @@ set(TDLIB_SOURCE td/telegram/StorageManager.cpp td/telegram/StoryContent.cpp td/telegram/StoryContentType.cpp + td/telegram/StoryInteractionInfo.cpp td/telegram/StoryManager.cpp td/telegram/SuggestedAction.cpp td/telegram/Support.cpp @@ -763,6 +764,7 @@ set(TDLIB_SOURCE td/telegram/StoryContent.h td/telegram/StoryContentType.h td/telegram/StoryId.h + td/telegram/StoryInteractionInfo.h td/telegram/StoryManager.h td/telegram/SuggestedAction.h td/telegram/Support.h diff --git a/td/telegram/StoryInteractionInfo.cpp b/td/telegram/StoryInteractionInfo.cpp new file mode 100644 index 000000000..bad3df074 --- /dev/null +++ b/td/telegram/StoryInteractionInfo.cpp @@ -0,0 +1,47 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/StoryInteractionInfo.h" + +#include "td/telegram/ContactsManager.h" +#include "td/telegram/Td.h" + +#include "td/utils/logging.h" + +namespace td { + +StoryInteractionInfo::StoryInteractionInfo(Td *td, telegram_api::object_ptr &&story_views) { + if (story_views == nullptr) { + return; + } + for (auto &viewer_id : story_views->recent_viewers_) { + UserId user_id(viewer_id); + if (user_id.is_valid() && td->contacts_manager_->have_min_user(user_id)) { + if (recent_viewer_user_ids_.size() == MAX_RECENT_VIEWERS) { + LOG(ERROR) << "Receive too many recent story viewers: " << story_views->recent_viewers_; + break; + } + recent_viewer_user_ids_.push_back(user_id); + } else { + LOG(ERROR) << "Receive " << user_id << " as recent viewer"; + } + } + view_count_ = story_views->views_count_; + if (view_count_ < 0) { + LOG(ERROR) << "Receive " << view_count_ << " story views"; + view_count_ = 0; + } +} + +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_; +} + +StringBuilder &operator<<(StringBuilder &string_builder, const StoryInteractionInfo &info) { + return string_builder << info.view_count_ << " views by " << info.recent_viewer_user_ids_; +} + +} // namespace td diff --git a/td/telegram/StoryInteractionInfo.h b/td/telegram/StoryInteractionInfo.h new file mode 100644 index 000000000..e24b13409 --- /dev/null +++ b/td/telegram/StoryInteractionInfo.h @@ -0,0 +1,47 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/telegram_api.h" +#include "td/telegram/UserId.h" + +#include "td/utils/common.h" +#include "td/utils/StringBuilder.h" + +namespace td { + +class Td; + +class StoryInteractionInfo { + vector recent_viewer_user_ids_; + int32 view_count_ = -1; + + static constexpr size_t MAX_RECENT_VIEWERS = 3; + + friend bool operator==(const StoryInteractionInfo &lhs, const StoryInteractionInfo &rhs); + + friend StringBuilder &operator<<(StringBuilder &string_builder, const StoryInteractionInfo &info); + + public: + StoryInteractionInfo() = default; + + StoryInteractionInfo(Td *td, telegram_api::object_ptr &&story_views); + + bool is_empty() const { + return view_count_ < 0; + } +}; + +bool operator==(const StoryInteractionInfo &lhs, const StoryInteractionInfo &rhs); + +inline bool operator!=(const StoryInteractionInfo &lhs, const StoryInteractionInfo &rhs) { + return !(lhs == rhs); +} + +StringBuilder &operator<<(StringBuilder &string_builder, const StoryInteractionInfo &info); + +} // namespace td diff --git a/td/telegram/StoryManager.cpp b/td/telegram/StoryManager.cpp index 24114cc83..56748889f 100644 --- a/td/telegram/StoryManager.cpp +++ b/td/telegram/StoryManager.cpp @@ -63,39 +63,6 @@ StoryId StoryManager::on_get_story(DialogId owner_dialog_id, return StoryId(); } auto content_type = content->get_type(); - - auto privacy_rules = UserPrivacySettingRules::get_user_privacy_setting_rules(td_, std::move(story_item->privacy_)); - - vector recent_viewer_user_ids; - int32 view_count = 0; - if (story_item->views_ != nullptr) { - for (auto &viewer_id : story_item->views_->recent_viewers_) { - UserId user_id(viewer_id); - if (user_id.is_valid() && td_->contacts_manager_->have_min_user(user_id)) { - recent_viewer_user_ids.push_back(user_id); - } else { - LOG(ERROR) << "Receive " << user_id << " as recent viewer in " << story_id; - } - } - view_count = story_item->views_->views_count_; - } - - if (story->is_pinned_ != story_item->pinned_ || story->is_public_ != story_item->public_ || - story->is_for_close_friends_ != story_item->close_friends_ || story->date_ != story_item->date_ || - story->expire_date_ != story_item->expire_date_ || !(story->privacy_rules_ == privacy_rules) || - story->recent_viewer_user_ids_ != recent_viewer_user_ids || story->view_count_ != view_count || - story->caption_ != caption) { - story->is_pinned_ = story_item->pinned_; - story->is_public_ = story_item->public_; - story->is_for_close_friends_ = story_item->close_friends_; - story->date_ = story_item->date_; - story->expire_date_ = story_item->expire_date_; - story->privacy_rules_ = std::move(privacy_rules); - story->recent_viewer_user_ids_ = std::move(recent_viewer_user_ids); - story->view_count_ = view_count; - story->caption_ = std::move(caption); - is_changed = true; - } if (story->content_ == nullptr || story->content_->get_type() != content_type) { story->content_ = std::move(content); is_changed = true; @@ -104,6 +71,23 @@ StoryId StoryManager::on_get_story(DialogId owner_dialog_id, is_changed); } + auto privacy_rules = UserPrivacySettingRules::get_user_privacy_setting_rules(td_, std::move(story_item->privacy_)); + auto interaction_info = StoryInteractionInfo(td_, std::move(story_item->views_)); + if (story->is_pinned_ != story_item->pinned_ || story->is_public_ != story_item->public_ || + story->is_for_close_friends_ != story_item->close_friends_ || story->date_ != story_item->date_ || + story->expire_date_ != story_item->expire_date_ || !(story->privacy_rules_ == privacy_rules) || + story->interaction_info_ != interaction_info || story->caption_ != caption) { + story->is_pinned_ = story_item->pinned_; + story->is_public_ = story_item->public_; + story->is_for_close_friends_ = story_item->close_friends_; + story->date_ = story_item->date_; + story->expire_date_ = story_item->expire_date_; + story->privacy_rules_ = std::move(privacy_rules); + story->interaction_info_ = std::move(interaction_info); + story->caption_ = std::move(caption); + is_changed = true; + } + if (is_changed || need_save_to_database) { // save_story(story, story_id); } diff --git a/td/telegram/StoryManager.h b/td/telegram/StoryManager.h index da5845dd6..cd3c38b70 100644 --- a/td/telegram/StoryManager.h +++ b/td/telegram/StoryManager.h @@ -9,6 +9,7 @@ #include "td/telegram/DialogId.h" #include "td/telegram/MessageEntity.h" #include "td/telegram/StoryId.h" +#include "td/telegram/StoryInteractionInfo.h" #include "td/telegram/UserId.h" #include "td/telegram/UserPrivacySettingRule.h" @@ -40,8 +41,7 @@ class StoryManager final : public Actor { bool is_pinned_ = false; bool is_public_ = false; bool is_for_close_friends_ = false; - vector recent_viewer_user_ids_; - int32 view_count_ = 0; + StoryInteractionInfo interaction_info_; UserPrivacySettingRules privacy_rules_; unique_ptr content_; FormattedText caption_;