diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index fb294d340..ebef8a94d 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -6905,6 +6905,20 @@ chatRevenueTransaction cryptocurrency:string cryptocurrency_amount:int64 type:Ch chatRevenueTransactions total_count:int32 transactions:vector = ChatRevenueTransactions; +//@description Contains information about Telegram stars earned by a bot or a chat +//@total_count Total number of the stars earned +//@current_count The number of Telegram stars that isn't withdrawn yet +//@available_count The number of Telegram stars that are available for withdrawal +//@withdrawal_enabled True, if Telegram stars can be withdrawn +starRevenueStatus total_count:int53 current_count:int53 available_count:int53 withdrawal_enabled:Bool = StarRevenueStatus; + +//@description A detailed statistics about Telegram stars earned by a bot or a chat +//@revenue_by_day_graph A graph containing amount of revenue in a given day +//@status Telegram star revenue status +//@usd_rate Current conversion rate of a Telegram star to USD +starRevenueStatistics revenue_by_day_graph:StatisticalGraph status:starRevenueStatus usd_rate:double = StarRevenueStatistics; + + //@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; @@ -10705,6 +10719,11 @@ getChatRevenueWithdrawalUrl chat_id:int53 password:string = HttpUrl; getChatRevenueTransactions chat_id:int53 offset:int32 limit:int32 = ChatRevenueTransactions; +//@description Returns detailed Telegram star revenue statistics +//@owner_id Identifier of the owner of the Telegram stars; can be identifier of an owned bot, or identifier of a channel chat with supergroupFullInfo.can_get_revenue_statistics == true +//@is_dark Pass true if a dark theme is used by the application +getStarRevenueStatistics owner_id:MessageSender is_dark:Bool = StarRevenueStatistics; + //@description Returns URL for Telegram star withdrawal //@owner_id Identifier of the owner of the Telegram stars; can be identifier of an owned bot, or identifier of a channel chat with supergroupFullInfo.can_get_revenue_statistics == true //@star_count The number of Telegram stars to withdraw diff --git a/td/telegram/StarManager.cpp b/td/telegram/StarManager.cpp index cc43c66c7..aec6552ff 100644 --- a/td/telegram/StarManager.cpp +++ b/td/telegram/StarManager.cpp @@ -15,6 +15,7 @@ #include "td/telegram/MessageSender.h" #include "td/telegram/PasswordManager.h" #include "td/telegram/Photo.h" +#include "td/telegram/StatisticsManager.h" #include "td/telegram/Td.h" #include "td/telegram/telegram_api.h" #include "td/telegram/UpdatesManager.h" @@ -70,8 +71,10 @@ class GetStarsTransactionsQuery final : public Td::ResultHandler { void send(DialogId dialog_id, const string &offset, int32 limit, td_api::object_ptr &&direction) { dialog_id_ = dialog_id; - auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Read); - CHECK(input_peer != nullptr); + auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Write); + if (input_peer == nullptr) { + return on_error(Status::Error(400, "Have no access to the chat")); + } int32 flags = 0; if (direction != nullptr) { switch (direction->get_id()) { @@ -194,6 +197,65 @@ class RefundStarsChargeQuery final : public Td::ResultHandler { } }; +static td_api::object_ptr convert_stars_revenue_status( + telegram_api::object_ptr obj) { + CHECK(obj != nullptr); + auto get_amount = [](int64 amount) { + if (amount < 0) { + LOG(ERROR) << "Receive star amount = " << amount; + return static_cast(0); + } + return amount; + }; + return td_api::make_object(get_amount(obj->overall_revenue_), + get_amount(obj->current_balance_), + get_amount(obj->available_balance_), obj->withdrawal_enabled_); +} + +class GetStarsRevenueStatsQuery final : public Td::ResultHandler { + Promise> promise_; + DialogId dialog_id_; + + public: + explicit GetStarsRevenueStatsQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, bool is_dark) { + dialog_id_ = dialog_id; + + auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Write); + if (input_peer == nullptr) { + return on_error(Status::Error(400, "Have no access to the chat")); + } + + int32 flags = 0; + if (is_dark) { + flags |= telegram_api::payments_getStarsRevenueStats::DARK_MASK; + } + send_query(G()->net_query_creator().create( + telegram_api::payments_getStarsRevenueStats(flags, false /*ignored*/, std::move(input_peer)))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(DEBUG) << "Receive result for GetStarsRevenueStatsQuery: " << to_string(ptr); + promise_.set_value(td_api::make_object( + convert_stats_graph(std::move(ptr->revenue_graph_)), convert_stars_revenue_status(std::move(ptr->status_)), + ptr->usd_rate_ > 0 ? clamp(ptr->usd_rate_ * 1e2, 1e-18, 1e18) : 1.3)); + } + + void on_error(Status status) final { + td_->dialog_manager_->on_get_dialog_error(dialog_id_, status, "GetStarsRevenueStatsQuery"); + promise_.set_error(std::move(status)); + } +}; + class GetStarsRevenueWithdrawalUrlQuery final : public Td::ResultHandler { Promise promise_; DialogId dialog_id_; @@ -208,7 +270,7 @@ class GetStarsRevenueWithdrawalUrlQuery final : public Td::ResultHandler { auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Write); if (input_peer == nullptr) { - return promise_.set_error(Status::Error(400, "Have no access to the chat")); + return on_error(Status::Error(400, "Have no access to the chat")); } send_query(G()->net_query_creator().create(telegram_api::payments_getStarsRevenueWithdrawalUrl( @@ -286,6 +348,13 @@ void StarManager::refund_star_payment(UserId user_id, const string &telegram_pay ->send(std::move(input_user), telegram_payment_charge_id); } +void StarManager::get_star_revenue_statistics(const td_api::object_ptr &owner_id, bool is_dark, + Promise> &&promise) { + TRY_RESULT_PROMISE(promise, dialog_id, get_message_sender_dialog_id(td_, owner_id, true, false)); + TRY_STATUS_PROMISE(promise, can_manage_stars(dialog_id)); + td_->create_handler(std::move(promise))->send(dialog_id, is_dark); +} + void StarManager::get_star_withdrawal_url(const td_api::object_ptr &owner_id, int64 star_count, const string &password, Promise &&promise) { TRY_RESULT_PROMISE(promise, dialog_id, get_message_sender_dialog_id(td_, owner_id, true, false)); diff --git a/td/telegram/StarManager.h b/td/telegram/StarManager.h index 23b8813c4..91a2672d2 100644 --- a/td/telegram/StarManager.h +++ b/td/telegram/StarManager.h @@ -32,6 +32,9 @@ class StarManager final : public Actor { void refund_star_payment(UserId user_id, const string &telegram_payment_charge_id, Promise &&promise); + void get_star_revenue_statistics(const td_api::object_ptr &owner_id, bool is_dark, + Promise> &&promise); + void get_star_withdrawal_url(const td_api::object_ptr &owner_id, int64 star_count, const string &password, Promise &&promise); diff --git a/td/telegram/StatisticsManager.cpp b/td/telegram/StatisticsManager.cpp index f405046ad..158f02373 100644 --- a/td/telegram/StatisticsManager.cpp +++ b/td/telegram/StatisticsManager.cpp @@ -34,7 +34,7 @@ static td_api::object_ptr convert_date_range( return td_api::make_object(obj->min_date_, obj->max_date_); } -static td_api::object_ptr convert_stats_graph( +td_api::object_ptr convert_stats_graph( telegram_api::object_ptr obj) { CHECK(obj != nullptr); @@ -325,7 +325,7 @@ class GetBroadcastRevenueStatsQuery final : public Td::ResultHandler { } void on_error(Status status) final { - td_->chat_manager_->on_get_channel_error(channel_id_, status, "GetBroadcastStatsQuery"); + td_->chat_manager_->on_get_channel_error(channel_id_, status, "GetBroadcastRevenueStatsQuery"); promise_.set_error(std::move(status)); } }; @@ -418,7 +418,7 @@ class GetBroadcastRevenueTransactionsQuery final : public Td::ResultHandler { auto state = [&]() -> td_api::object_ptr { if (transaction->transaction_date_ > 0) { return td_api::make_object(transaction->transaction_date_, - transaction->transaction_url_); + transaction->transaction_url_); } if (transaction->pending_) { return td_api::make_object(); diff --git a/td/telegram/StatisticsManager.h b/td/telegram/StatisticsManager.h index 5f2bc24af..7429b0989 100644 --- a/td/telegram/StatisticsManager.h +++ b/td/telegram/StatisticsManager.h @@ -23,6 +23,9 @@ namespace td { class Td; +td_api::object_ptr convert_stats_graph( + telegram_api::object_ptr obj); + class StatisticsManager final : public Actor { public: StatisticsManager(Td *td, ActorShared<> parent); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index e81148a72..e0fbd59b5 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -8734,6 +8734,12 @@ void Td::on_request(uint64 id, const td_api::getChatRevenueTransactions &request std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getStarRevenueStatistics &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + star_manager_->get_star_revenue_statistics(request.owner_id_, request.is_dark_, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getStarWithdrawalUrl &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 026591f50..41cf6252b 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1697,6 +1697,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getChatRevenueTransactions &request); + void on_request(uint64 id, const td_api::getStarRevenueStatistics &request); + void on_request(uint64 id, const td_api::getStarWithdrawalUrl &request); void on_request(uint64 id, const td_api::getMessageStatistics &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index c674084de..7260bbcba 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -6780,6 +6780,11 @@ class CliClient final : public Actor { string limit; get_args(args, chat_id, offset, limit); send_request(td_api::make_object(chat_id, offset, as_limit(limit))); + } else if (op == "gsrs") { + string owner_id; + bool is_dark; + get_args(args, owner_id, is_dark); + send_request(td_api::make_object(as_message_sender(owner_id), is_dark)); } else if (op == "gswu") { string owner_id; int32 star_count;