Add separate StoryViewer class.

This commit is contained in:
levlam 2023-08-07 16:03:10 +03:00
parent 665662a160
commit eb74e6eb2a
9 changed files with 196 additions and 74 deletions

View File

@ -480,6 +480,7 @@ set(TDLIB_SOURCE
td/telegram/StoryInteractionInfo.cpp
td/telegram/StoryManager.cpp
td/telegram/StoryStealthMode.cpp
td/telegram/StoryViewer.cpp
td/telegram/SuggestedAction.cpp
td/telegram/Support.cpp
td/telegram/Td.cpp
@ -785,6 +786,7 @@ set(TDLIB_SOURCE
td/telegram/StoryListId.h
td/telegram/StoryManager.h
td/telegram/StoryStealthMode.h
td/telegram/StoryViewer.h
td/telegram/SuggestedAction.h
td/telegram/Support.h
td/telegram/Td.h

View File

@ -4931,6 +4931,13 @@ 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;
//@description Represents a viewer of a story @user_id User identifier of the viewer @view_date Approximate point in time (Unix timestamp) when the story was viewed
storyViewer user_id:int53 view_date:int32 = StoryViewer;
//@description Represents a list of story viewers @viewers List of story viewers
storyViewers viewers:vector<storyViewer> = StoryViewers;
//@description Describes position of a clickable rectangle area on a story media
//@x_percentage The abscissa of the rectangle's center, as a percentage of the media width
//@y_percentage The ordinate of the rectangle's center, as a percentage of the media height
@ -7473,7 +7480,7 @@ setStoryReaction story_sender_chat_id:int53 story_id:int32 reaction_type:Reactio
//@offset_viewer A viewer from which to return next viewers; pass null to get results from the beginning
//@limit The maximum number of story viewers to return
//-For optimal performance, the number of returned stories is chosen by TDLib and can be smaller than the specified limit
getStoryViewers story_id:int32 offset_viewer:messageViewer limit:int32 = MessageViewers;
getStoryViewers story_id:int32 offset_viewer:storyViewer limit:int32 = StoryViewers;
//@description Reports a story to the Telegram moderators
//@story_sender_chat_id The identifier of the sender of the story to report

View File

@ -35,17 +35,6 @@ StringBuilder &operator<<(StringBuilder &string_builder, const MessageViewer &vi
return string_builder << '[' << viewer.user_id_ << " at " << viewer.date_ << ']';
}
MessageViewers::MessageViewers(vector<telegram_api::object_ptr<telegram_api::storyView>> &&story_views) {
for (auto &story_view : story_views) {
UserId user_id(story_view->user_id_);
if (!user_id.is_valid()) {
LOG(ERROR) << "Receive " << user_id << " as story viewer";
continue;
}
message_viewers_.emplace_back(user_id, story_view->date_);
}
}
MessageViewers::MessageViewers(vector<telegram_api::object_ptr<telegram_api::readParticipantDate>> &&read_dates) {
for (auto &read_date : read_dates) {
message_viewers_.emplace_back(std::move(read_date));
@ -57,41 +46,6 @@ MessageViewers::MessageViewers(vector<telegram_api::object_ptr<telegram_api::rea
}
}
MessageViewers MessageViewers::get_sublist(const MessageViewer &offset, int32 limit) const {
MessageViewers result;
bool found = offset.is_empty();
for (auto &message_viewer : message_viewers_) {
if (found) {
if (limit-- <= 0) {
break;
}
result.message_viewers_.push_back(message_viewer);
} else if (message_viewer == offset) {
found = true;
}
}
return result;
}
void MessageViewers::add_sublist(const MessageViewer &offset, const MessageViewers &sublist) {
if (offset.is_empty()) {
if (message_viewers_.empty()) {
message_viewers_ = sublist.message_viewers_;
} else {
auto old_viewers = std::move(message_viewers_);
for (auto &viewer : sublist.message_viewers_) {
if (viewer == old_viewers[0]) {
append(message_viewers_, old_viewers);
return;
}
message_viewers_.push_back(viewer);
}
}
} else if (!message_viewers_.empty() && message_viewers_.back() == offset) {
append(message_viewers_, sublist.message_viewers_);
}
}
vector<UserId> MessageViewers::get_user_ids() const {
return transform(message_viewers_, [](auto &viewer) { return viewer.get_user_id(); });
}

View File

@ -56,18 +56,8 @@ class MessageViewers {
public:
MessageViewers() = default;
explicit MessageViewers(vector<telegram_api::object_ptr<telegram_api::storyView>> &&story_views);
explicit MessageViewers(vector<telegram_api::object_ptr<telegram_api::readParticipantDate>> &&read_dates);
bool is_empty() const {
return message_viewers_.empty();
}
MessageViewers get_sublist(const MessageViewer &offset, int32 limit) const;
void add_sublist(const MessageViewer &offset, const MessageViewers &sublist);
vector<UserId> get_user_ids() const;
td_api::object_ptr<td_api::messageViewers> get_message_viewers_object(ContactsManager *contacts_manager) const;

View File

@ -2321,8 +2321,8 @@ Status StoryManager::can_get_story_viewers(StoryFullId story_full_id, const Stor
return Status::OK();
}
void StoryManager::get_story_viewers(StoryId story_id, const td_api::messageViewer *offset, int32 limit,
Promise<td_api::object_ptr<td_api::messageViewers>> &&promise) {
void StoryManager::get_story_viewers(StoryId story_id, const td_api::storyViewer *offset, int32 limit,
Promise<td_api::object_ptr<td_api::storyViewers>> &&promise) {
DialogId owner_dialog_id(td_->contacts_manager_->get_my_id());
StoryFullId story_full_id{owner_dialog_id, story_id};
const Story *story = get_story(story_full_id);
@ -2333,7 +2333,7 @@ void StoryManager::get_story_viewers(StoryId story_id, const td_api::messageView
return promise.set_error(Status::Error(400, "Parameter limit must be positive"));
}
if (can_get_story_viewers(story_full_id, story).is_error() || story->interaction_info_.get_view_count() == 0) {
return promise.set_value(td_api::make_object<td_api::messageViewers>());
return promise.set_value(td_api::make_object<td_api::storyViewers>());
}
int32 offset_date = 0;
@ -2342,7 +2342,7 @@ void StoryManager::get_story_viewers(StoryId story_id, const td_api::messageView
offset_date = offset->view_date_;
offset_user_id = offset->user_id_;
}
MessageViewer offset_viewer{UserId(offset_user_id), offset_date};
StoryViewer offset_viewer{UserId(offset_user_id), offset_date};
auto &cached_viewers = cached_story_viewers_[story_full_id];
if (cached_viewers != nullptr && story->content_ != nullptr &&
@ -2352,7 +2352,7 @@ void StoryManager::get_story_viewers(StoryId story_id, const td_api::messageView
// can return the viewers
// don't need to reget the viewers, because story->interaction_info_.get_view_count() is updated every 10 seconds
td_->contacts_manager_->on_view_user_active_stories(result.get_user_ids());
return promise.set_value(result.get_message_viewers_object(td_->contacts_manager_.get()));
return promise.set_value(result.get_story_viewers_object(td_->contacts_manager_.get()));
}
}
@ -2368,9 +2368,9 @@ void StoryManager::get_story_viewers(StoryId story_id, const td_api::messageView
}
void StoryManager::on_get_story_viewers(
StoryId story_id, MessageViewer offset,
StoryId story_id, StoryViewer offset,
Result<telegram_api::object_ptr<telegram_api::stories_storyViewsList>> r_view_list,
Promise<td_api::object_ptr<td_api::messageViewers>> &&promise) {
Promise<td_api::object_ptr<td_api::storyViewers>> &&promise) {
G()->ignore_result_if_closing(r_view_list);
if (r_view_list.is_error()) {
return promise.set_error(r_view_list.move_as_error());
@ -2382,7 +2382,7 @@ void StoryManager::on_get_story_viewers(
StoryFullId story_full_id{owner_dialog_id, story_id};
Story *story = get_story_editable(story_full_id);
if (story == nullptr) {
return promise.set_value(td_api::make_object<td_api::messageViewers>());
return promise.set_value(td_api::make_object<td_api::storyViewers>());
}
td_->contacts_manager_->on_get_users(std::move(view_list->users_), "on_get_story_viewers");
@ -2393,7 +2393,7 @@ void StoryManager::on_get_story_viewers(
total_count = static_cast<int32>(view_list->views_.size());
}
MessageViewers story_viewers(std::move(view_list->views_));
StoryViewers story_viewers(std::move(view_list->views_));
if (story->content_ != nullptr) {
if (story->interaction_info_.set_view_count(view_list->count_)) {
if (offset.is_empty()) {
@ -2414,7 +2414,7 @@ void StoryManager::on_get_story_viewers(
}
td_->contacts_manager_->on_view_user_active_stories(story_viewers.get_user_ids());
promise.set_value(story_viewers.get_message_viewers_object(td_->contacts_manager_.get()));
promise.set_value(story_viewers.get_story_viewers_object(td_->contacts_manager_.get()));
}
void StoryManager::report_story(StoryFullId story_full_id, ReportReason &&reason, Promise<Unit> &&promise) {

View File

@ -13,7 +13,6 @@
#include "td/telegram/FullMessageId.h"
#include "td/telegram/MediaArea.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageViewer.h"
#include "td/telegram/ReactionType.h"
#include "td/telegram/StoryDb.h"
#include "td/telegram/StoryFullId.h"
@ -21,6 +20,7 @@
#include "td/telegram/StoryInteractionInfo.h"
#include "td/telegram/StoryListId.h"
#include "td/telegram/StoryStealthMode.h"
#include "td/telegram/StoryViewer.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
@ -159,7 +159,7 @@ class StoryManager final : public Actor {
struct CachedStoryViewers {
int32 total_count_ = -1;
MessageViewers viewers_;
StoryViewers viewers_;
};
struct StoryList {
@ -249,8 +249,8 @@ class StoryManager final : public Actor {
void set_story_reaction(StoryFullId story_full_id, ReactionType reaction_type, bool add_to_recent,
Promise<Unit> &&promise);
void get_story_viewers(StoryId story_id, const td_api::messageViewer *offset, int32 limit,
Promise<td_api::object_ptr<td_api::messageViewers>> &&promise);
void get_story_viewers(StoryId story_id, const td_api::storyViewer *offset, int32 limit,
Promise<td_api::object_ptr<td_api::storyViewers>> &&promise);
void report_story(StoryFullId story_full_id, ReportReason &&reason, Promise<Unit> &&promise);
@ -527,9 +527,9 @@ class StoryManager final : public Actor {
void set_story_stealth_mode(StoryStealthMode stealth_mode);
void on_get_story_viewers(StoryId story_id, MessageViewer offset,
void on_get_story_viewers(StoryId story_id, StoryViewer offset,
Result<telegram_api::object_ptr<telegram_api::stories_storyViewsList>> r_view_list,
Promise<td_api::object_ptr<td_api::messageViewers>> &&promise);
Promise<td_api::object_ptr<td_api::storyViewers>> &&promise);
void on_set_story_reaction(StoryFullId story_full_id, Result<Unit> &&result, Promise<Unit> &&promise);

View File

@ -0,0 +1,95 @@
//
// 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/StoryViewer.h"
#include "td/telegram/ContactsManager.h"
#include "td/utils/algorithm.h"
#include "td/utils/logging.h"
namespace td {
td_api::object_ptr<td_api::storyViewer> StoryViewer::get_story_viewer_object(ContactsManager *contacts_manager) const {
return td_api::make_object<td_api::storyViewer>(
contacts_manager->get_user_id_object(user_id_, "get_story_viewer_object"), date_);
}
bool operator==(const StoryViewer &lhs, const StoryViewer &rhs) {
return lhs.user_id_ == rhs.user_id_ && lhs.date_ == rhs.date_;
}
bool operator!=(const StoryViewer &lhs, const StoryViewer &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const StoryViewer &viewer) {
return string_builder << '[' << viewer.user_id_ << " at " << viewer.date_ << ']';
}
StoryViewers::StoryViewers(vector<telegram_api::object_ptr<telegram_api::storyView>> &&story_views) {
for (auto &story_view : story_views) {
UserId user_id(story_view->user_id_);
if (!user_id.is_valid()) {
LOG(ERROR) << "Receive " << user_id << " as story viewer";
continue;
}
story_viewers_.emplace_back(user_id, story_view->date_);
}
}
StoryViewers StoryViewers::get_sublist(const StoryViewer &offset, int32 limit) const {
StoryViewers result;
bool found = offset.is_empty();
for (auto &story_viewer : story_viewers_) {
if (found) {
if (limit-- <= 0) {
break;
}
result.story_viewers_.push_back(story_viewer);
} else if (story_viewer == offset) {
found = true;
}
}
return result;
}
void StoryViewers::add_sublist(const StoryViewer &offset, const StoryViewers &sublist) {
if (offset.is_empty()) {
if (story_viewers_.empty()) {
story_viewers_ = sublist.story_viewers_;
} else {
auto old_viewers = std::move(story_viewers_);
for (auto &viewer : sublist.story_viewers_) {
if (viewer == old_viewers[0]) {
append(story_viewers_, old_viewers);
return;
}
story_viewers_.push_back(viewer);
}
}
} else if (!story_viewers_.empty() && story_viewers_.back() == offset) {
append(story_viewers_, sublist.story_viewers_);
}
}
vector<UserId> StoryViewers::get_user_ids() const {
return transform(story_viewers_, [](auto &viewer) { return viewer.get_user_id(); });
}
td_api::object_ptr<td_api::storyViewers> StoryViewers::get_story_viewers_object(
ContactsManager *contacts_manager) const {
return td_api::make_object<td_api::storyViewers>(
transform(story_viewers_, [contacts_manager](const StoryViewer &story_viewer) {
return story_viewer.get_story_viewer_object(contacts_manager);
}));
}
StringBuilder &operator<<(StringBuilder &string_builder, const StoryViewers &viewers) {
return string_builder << viewers.story_viewers_;
}
} // namespace td

74
td/telegram/StoryViewer.h Normal file
View File

@ -0,0 +1,74 @@
//
// 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/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class ContactsManager;
class StoryViewer {
UserId user_id_;
int32 date_ = 0;
friend StringBuilder &operator<<(StringBuilder &string_builder, const StoryViewer &viewer);
friend bool operator==(const StoryViewer &lhs, const StoryViewer &rhs);
public:
StoryViewer(UserId user_id, int32 date) : user_id_(user_id), date_(td::max(date, static_cast<int32>(0))) {
}
UserId get_user_id() const {
return user_id_;
}
bool is_empty() const {
return user_id_ == UserId() && date_ == 0;
}
td_api::object_ptr<td_api::storyViewer> get_story_viewer_object(ContactsManager *contacts_manager) const;
};
bool operator==(const StoryViewer &lhs, const StoryViewer &rhs);
bool operator!=(const StoryViewer &lhs, const StoryViewer &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const StoryViewer &viewer);
class StoryViewers {
vector<StoryViewer> story_viewers_;
friend StringBuilder &operator<<(StringBuilder &string_builder, const StoryViewers &viewers);
public:
StoryViewers() = default;
explicit StoryViewers(vector<telegram_api::object_ptr<telegram_api::storyView>> &&story_views);
bool is_empty() const {
return story_viewers_.empty();
}
StoryViewers get_sublist(const StoryViewer &offset, int32 limit) const;
void add_sublist(const StoryViewer &offset, const StoryViewers &sublist);
vector<UserId> get_user_ids() const;
td_api::object_ptr<td_api::storyViewers> get_story_viewers_object(ContactsManager *contacts_manager) const;
};
StringBuilder &operator<<(StringBuilder &string_builder, const StoryViewers &viewers);
} // namespace td

View File

@ -4155,7 +4155,7 @@ class CliClient final : public Actor {
UserId offset_user_id;
get_args(args, story_id, limit, offset_date, offset_user_id);
send_request(td_api::make_object<td_api::getStoryViewers>(
story_id, td_api::make_object<td_api::messageViewer>(offset_user_id, offset_date), as_limit(limit)));
story_id, td_api::make_object<td_api::storyViewer>(offset_user_id, offset_date), as_limit(limit)));
} else if (op == "rst") {
ChatId story_sender_chat_id;
StoryId story_id;