Add td_api::getStoryStatistics.

This commit is contained in:
levlam 2023-11-17 14:26:51 +03:00
parent 362f43303e
commit cda21980b0
8 changed files with 127 additions and 0 deletions

View File

@ -5962,6 +5962,11 @@ chatStatisticsChannel period:dateRange member_count:statisticalValue mean_view_c
//@message_reaction_graph A graph containing number of message reactions
messageStatistics message_interaction_graph:StatisticalGraph message_reaction_graph:StatisticalGraph = MessageStatistics;
//@description A detailed statistics about a story
//@story_interaction_graph A graph containing number of story views and shares
//@story_reaction_graph A graph containing number of story reactions
storyStatistics story_interaction_graph:StatisticalGraph story_reaction_graph:StatisticalGraph = StoryStatistics;
//@description A point on a Cartesian plane @x The point's first coordinate @y The point's second coordinate
point x:double y:double = Point;
@ -9079,6 +9084,9 @@ getMessageStatistics chat_id:int53 message_id:int53 is_dark:Bool = MessageStatis
//@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit
getMessagePublicForwards chat_id:int53 message_id:int53 offset:string limit:int32 = FoundMessages;
//@description Returns detailed statistics about a story. Can be used only if story.can_get_statistics == true @chat_id Chat identifier @story_id Story identifier @is_dark Pass true if a dark theme is used by the application
getStoryStatistics chat_id:int53 story_id:int32 is_dark:Bool = StoryStatistics;
//@description Loads an asynchronous or a zoomed in statistical graph @chat_id Chat identifier @token The token for graph loading @x X-value for zoomed in graph or 0 otherwise
getStatisticalGraph chat_id:int53 token:string x:int53 = StatisticalGraph;

View File

@ -12,6 +12,7 @@
#include "td/telegram/MessagesInfo.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/ServerMessageId.h"
#include "td/telegram/StoryManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
@ -282,6 +283,52 @@ class GetMessageStatsQuery final : public Td::ResultHandler {
}
};
static td_api::object_ptr<td_api::storyStatistics> convert_story_stats(
telegram_api::object_ptr<telegram_api::stats_storyStats> obj) {
return td_api::make_object<td_api::storyStatistics>(convert_stats_graph(std::move(obj->views_graph_)),
convert_stats_graph(std::move(obj->reactions_by_emotion_graph_)));
}
class GetStoryStatsQuery final : public Td::ResultHandler {
Promise<td_api::object_ptr<td_api::storyStatistics>> promise_;
ChannelId channel_id_;
public:
explicit GetStoryStatsQuery(Promise<td_api::object_ptr<td_api::storyStatistics>> &&promise)
: promise_(std::move(promise)) {
}
void send(ChannelId channel_id, StoryId story_id, bool is_dark, DcId dc_id) {
channel_id_ = channel_id;
auto input_peer = td_->messages_manager_->get_input_peer(DialogId(channel_id), AccessRights::Read);
if (input_peer == nullptr) {
return promise_.set_error(Status::Error(400, "Chat not found"));
}
int32 flags = 0;
if (is_dark) {
flags |= telegram_api::stats_getStoryStats::DARK_MASK;
}
send_query(G()->net_query_creator().create(
telegram_api::stats_getStoryStats(flags, false /*ignored*/, std::move(input_peer), story_id.get()), {}, dc_id));
}
void on_result(BufferSlice packet) final {
auto result_ptr = fetch_result<telegram_api::stats_getStoryStats>(packet);
if (result_ptr.is_error()) {
return on_error(result_ptr.move_as_error());
}
promise_.set_value(convert_story_stats(result_ptr.move_as_ok()));
}
void on_error(Status status) final {
td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetStoryStatsQuery");
promise_.set_error(std::move(status));
}
};
class LoadAsyncGraphQuery final : public Td::ResultHandler {
Promise<td_api::object_ptr<td_api::StatisticalGraph>> promise_;
@ -427,6 +474,36 @@ void StatisticsManager::send_get_channel_message_stats_query(
->send(dialog_id.get_channel_id(), message_full_id.get_message_id(), is_dark, dc_id);
}
void StatisticsManager::get_channel_story_statistics(StoryFullId story_full_id, bool is_dark,
Promise<td_api::object_ptr<td_api::storyStatistics>> &&promise) {
auto dc_id_promise = PromiseCreator::lambda(
[actor_id = actor_id(this), story_full_id, is_dark, promise = std::move(promise)](Result<DcId> r_dc_id) mutable {
if (r_dc_id.is_error()) {
return promise.set_error(r_dc_id.move_as_error());
}
send_closure(actor_id, &StatisticsManager::send_get_channel_story_stats_query, r_dc_id.move_as_ok(),
story_full_id, is_dark, std::move(promise));
});
td_->contacts_manager_->get_channel_statistics_dc_id(story_full_id.get_dialog_id(), false, std::move(dc_id_promise));
}
void StatisticsManager::send_get_channel_story_stats_query(
DcId dc_id, StoryFullId story_full_id, bool is_dark,
Promise<td_api::object_ptr<td_api::storyStatistics>> &&promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
auto dialog_id = story_full_id.get_dialog_id();
if (!td_->story_manager_->have_story_force(story_full_id)) {
return promise.set_error(Status::Error(400, "Story not found"));
}
if (!td_->story_manager_->can_get_story_statistics(story_full_id)) {
return promise.set_error(Status::Error(400, "Story statistics is inaccessible"));
}
CHECK(dialog_id.get_type() == DialogType::Channel);
td_->create_handler<GetStoryStatsQuery>(std::move(promise))
->send(dialog_id.get_channel_id(), story_full_id.get_story_id(), is_dark, dc_id);
}
void StatisticsManager::load_statistics_graph(DialogId dialog_id, string token, int64 x,
Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise) {
auto dc_id_promise = PromiseCreator::lambda([actor_id = actor_id(this), token = std::move(token), x,

View File

@ -10,6 +10,7 @@
#include "td/telegram/DialogId.h"
#include "td/telegram/MessageFullId.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/StoryFullId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
@ -32,6 +33,9 @@ class StatisticsManager final : public Actor {
void get_channel_message_statistics(MessageFullId message_full_id, bool is_dark,
Promise<td_api::object_ptr<td_api::messageStatistics>> &&promise);
void get_channel_story_statistics(StoryFullId message_full_id, bool is_dark,
Promise<td_api::object_ptr<td_api::storyStatistics>> &&promise);
void load_statistics_graph(DialogId dialog_id, string token, int64 x,
Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise);
@ -51,6 +55,9 @@ class StatisticsManager final : public Actor {
void send_get_channel_message_stats_query(DcId dc_id, MessageFullId message_full_id, bool is_dark,
Promise<td_api::object_ptr<td_api::messageStatistics>> &&promise);
void send_get_channel_story_stats_query(DcId dc_id, StoryFullId story_full_id, bool is_dark,
Promise<td_api::object_ptr<td_api::storyStatistics>> &&promise);
void send_load_async_graph_query(DcId dc_id, string token, int64 x,
Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise);

View File

@ -1711,6 +1711,22 @@ StoryManager::Story *StoryManager::on_get_story_from_database(StoryFullId story_
return result;
}
bool StoryManager::can_get_story_statistics(StoryFullId story_full_id) {
return can_get_story_statistics(story_full_id.get_dialog_id(),
get_story_force(story_full_id, "can_get_story_statistics"));
}
bool StoryManager::can_get_story_statistics(DialogId owner_dialog_id, const Story *story) const {
if (td_->auth_manager_->is_bot()) {
return false;
}
if (owner_dialog_id.get_type() != DialogType::Channel ||
!td_->contacts_manager_->is_broadcast_channel(owner_dialog_id.get_channel_id())) {
return false;
}
return true;
}
const StoryManager::ActiveStories *StoryManager::get_active_stories(DialogId owner_dialog_id) const {
return active_stories_.get_pointer(owner_dialog_id);
}

View File

@ -302,6 +302,8 @@ class StoryManager final : public Actor {
bool have_story_force(StoryFullId story_full_id);
bool can_get_story_statistics(StoryFullId story_full_id);
bool is_inaccessible_story(StoryFullId story_full_id) const;
int32 get_story_duration(StoryFullId story_full_id) const;
@ -368,6 +370,8 @@ class StoryManager final : public Actor {
bool can_access_expired_story(DialogId owner_dialog_id, const Story *story) const;
bool can_get_story_statistics(DialogId owner_dialog_id, const Story *story) const;
bool can_get_story_view_count(DialogId owner_dialog_id);
bool can_post_stories(DialogId owner_dialog_id) const;

View File

@ -8138,6 +8138,13 @@ void Td::on_request(uint64 id, const td_api::getMessageStatistics &request) {
request.is_dark_, std::move(promise));
}
void Td::on_request(uint64 id, const td_api::getStoryStatistics &request) {
CHECK_IS_USER();
CREATE_REQUEST_PROMISE();
statistics_manager_->get_channel_story_statistics({DialogId(request.chat_id_), StoryId(request.story_id_)},
request.is_dark_, std::move(promise));
}
void Td::on_request(uint64 id, td_api::getStatisticalGraph &request) {
CHECK_IS_USER();
CLEAN_INPUT_STRING(request.token_);

View File

@ -1450,6 +1450,8 @@ class Td final : public Actor {
void on_request(uint64 id, const td_api::getMessageStatistics &request);
void on_request(uint64 id, const td_api::getStoryStatistics &request);
void on_request(uint64 id, td_api::getStatisticalGraph &request);
void on_request(uint64 id, const td_api::getMapThumbnailFile &request);

View File

@ -5990,6 +5990,12 @@ class CliClient final : public Actor {
bool is_dark;
get_args(args, chat_id, message_id, is_dark);
send_request(td_api::make_object<td_api::getMessageStatistics>(chat_id, message_id, is_dark));
} else if (op == "gsst") {
ChatId chat_id;
StoryId story_id;
bool is_dark;
get_args(args, chat_id, story_id, is_dark);
send_request(td_api::make_object<td_api::getStoryStatistics>(chat_id, story_id, is_dark));
} else if (op == "gstg") {
ChatId chat_id;
string token;