From 4f65363ef82952587b17ec57766378b13e3fa8a7 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 4 Apr 2024 13:55:24 +0300 Subject: [PATCH] Add td_api::getChatRevenueTransactions. --- td/generate/scheme/td_api.tl | 41 +++++++++++- td/telegram/StatisticsManager.cpp | 101 +++++++++++++++++++++++++++--- td/telegram/StatisticsManager.h | 3 + td/telegram/Td.cpp | 7 +++ td/telegram/Td.h | 2 + td/telegram/cli.cpp | 6 ++ 6 files changed, 151 insertions(+), 9 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 937317d77..11b6a68ae 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -6599,6 +6599,37 @@ messageStatistics message_interaction_graph:StatisticalGraph message_reaction_gr storyStatistics story_interaction_graph:StatisticalGraph story_reaction_graph:StatisticalGraph = StoryStatistics; +//@class ChatRevenueTransaction @description Describes a transaction for revenue earned from sponsored messages in a chat + +//@description Describes earnings from sponsored messages in a chat in some time frame +//@cryptocurrency Cryptocurrency in which revenue is calculated +//@cryptocurrency_amount The earned amount, in the smallest units of the cryptocurrency +//@start_date Point in time (Unix timestamp) when the earnings started +//@end_date Point in time (Unix timestamp) when the earnings ended +chatRevenueTransactionEarnings cryptocurrency:string cryptocurrency_amount:int64 start_date:int32 end_date:int32 = ChatRevenueTransaction; + +//@description Describes a withdrawal of earnings +//@cryptocurrency Cryptocurrency in which revenue is calculated +//@cryptocurrency_amount The withdrawn amount, in the smallest units of the cryptocurrency +//@withdrawal_date Point in time (Unix timestamp) when the earnings were withdrawn +//@is_pending True, if the transaction didn't complete yet +//@is_failed True, if the transaction has failed +//@provider Name of the payment provider +//@transaction_date Point in time (Unix timestamp) when the withdrawal was completed; 0 if none +//@transaction_url The URL where the transaction can be viewed; empty if none +chatRevenueTransactionWithdrawal cryptocurrency:string cryptocurrency_amount:int64 withdrawal_date:int32 is_pending:Bool is_failed:Bool provider:string transaction_date:int32 transaction_url:string = ChatRevenueTransaction; + +//@description Describes a refund for failed withdrawal of earnings +//@cryptocurrency Cryptocurrency in which revenue is calculated +//@cryptocurrency_amount The withdrawn amount, in the smallest units of the cryptocurrency +//@refund_date Point in time (Unix timestamp) when the transaction was refunded +//@provider Name of the payment provider +chatRevenueTransactionRefund cryptocurrency:string cryptocurrency_amount:int64 refund_date:int32 provider:string = ChatRevenueTransaction; + +//@description Contains a list of chat revenue transactions @total_count Total number of transactions @transactions List of transactions +chatRevenueTransactions total_count:int32 transactions:vector = ChatRevenueTransactions; + + //@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; @@ -9879,7 +9910,7 @@ reportSupergroupAntiSpamFalsePositive supergroup_id:int53 message_id:int53 = Ok; //@supergroup_id Identifier of the supergroup or channel //@filter The type of users to return; pass null to use supergroupMembersFilterRecent //@offset Number of users to skip -//@limit The maximum number of users be returned; up to 200 +//@limit The maximum number of users to be returned; up to 200 getSupergroupMembers supergroup_id:int53 filter:SupergroupMembersFilter offset:int32 limit:int32 = ChatMembers; @@ -10100,9 +10131,15 @@ reportMessageReactions chat_id:int53 message_id:int53 sender_id:MessageSender = //@description Returns detailed statistics about a chat. Currently, this method can be used only for supergroups and channels. Can be used only if supergroupFullInfo.can_get_statistics == true @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the application getChatStatistics chat_id:int53 is_dark:Bool = ChatStatistics; -//@description Returns detailed revemue statistics about a chat. Currently, this method can be used only for channels. Can be used only if supergroupFullInfo.can_get_revenue_statistics == true @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the application +//@description Returns detailed revenue statistics about a chat. Currently, this method can be used only for channels if supergroupFullInfo.can_get_revenue_statistics == true @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the application getChatRevenueStatistics chat_id:int53 is_dark:Bool = ChatRevenueStatistics; +//@description Returns list of revenue transactions for a chat. Currently, this method can be used only for channels if supergroupFullInfo.can_get_revenue_statistics == true +//@chat_id Chat identifier +//@offset Number of transactions to skip +//@limit The maximum number of transactions to be returned; up to 200 +getChatRevenueTransactions chat_id:int53 offset:int32 limit:int32 = ChatRevenueTransactions; + //@description Returns detailed statistics about a message. Can be used only if message.can_get_statistics == true @chat_id Chat identifier @message_id Message identifier @is_dark Pass true if a dark theme is used by the application getMessageStatistics chat_id:int53 message_id:int53 is_dark:Bool = MessageStatistics; diff --git a/td/telegram/StatisticsManager.cpp b/td/telegram/StatisticsManager.cpp index ebad7a6ce..24e4ba62d 100644 --- a/td/telegram/StatisticsManager.cpp +++ b/td/telegram/StatisticsManager.cpp @@ -266,16 +266,17 @@ class GetBroadcastStatsQuery final : public Td::ResultHandler { } }; +static int64 get_amount(int64 amount, bool allow_negative = false) { + if (!allow_negative && amount < 0) { + LOG(ERROR) << "Receive currency amount = " << amount; + return 0; + } + return amount; +} + static td_api::object_ptr convert_broadcast_revenue_stats( telegram_api::object_ptr obj) { CHECK(obj != nullptr); - auto get_amount = [](int64 amount) { - if (amount < 0 || !check_currency_amount(amount)) { - LOG(ERROR) << "Receive currency amount = " << amount; - return static_cast(0); - } - return amount; - }; return td_api::make_object( convert_stats_graph(std::move(obj->top_hours_graph_)), convert_stats_graph(std::move(obj->revenue_graph_)), "TON", get_amount(obj->overall_revenue_), get_amount(obj->current_balance_), get_amount(obj->available_balance_), @@ -322,6 +323,79 @@ class GetBroadcastRevenueStatsQuery final : public Td::ResultHandler { } }; +class GetBroadcastRevenueTransactionsQuery final : public Td::ResultHandler { + Promise> promise_; + ChannelId channel_id_; + + public: + explicit GetBroadcastRevenueTransactionsQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(ChannelId channel_id, int32 offset, int32 limit) { + channel_id_ = channel_id; + + auto input_channel = td_->chat_manager_->get_input_channel(channel_id); + if (input_channel == nullptr) { + return on_error(Status::Error(500, "Chat info not found")); + } + + send_query(G()->net_query_creator().create( + telegram_api::stats_getBroadcastRevenueTransactions(std::move(input_channel), offset, limit))); + } + + 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(INFO) << "Receive result for GetBroadcastRevenueTransactionsQuery: " << to_string(ptr); + auto total_count = ptr->count_; + if (total_count < static_cast(ptr->transactions_.size())) { + LOG(ERROR) << "Receive total_count = " << total_count << " and " << ptr->transactions_.size() << " transactions"; + total_count = static_cast(ptr->transactions_.size()); + } + vector> transactions; + for (auto &transaction_ptr : ptr->transactions_) { + switch (transaction_ptr->get_id()) { + case telegram_api::broadcastRevenueTransactionProceeds::ID: { + auto transaction = + telegram_api::move_object_as(transaction_ptr); + transactions.push_back(td_api::make_object( + "TON", get_amount(transaction->amount_), transaction->from_date_, transaction->to_date_)); + break; + } + case telegram_api::broadcastRevenueTransactionWithdrawal::ID: { + auto transaction = + telegram_api::move_object_as(transaction_ptr); + transactions.push_back(td_api::make_object( + "TON", get_amount(transaction->amount_, true), transaction->date_, transaction->pending_, + transaction->failed_, transaction->provider_, transaction->transaction_date_, + transaction->transaction_url_)); + break; + } + case telegram_api::broadcastRevenueTransactionRefund::ID: { + auto transaction = + telegram_api::move_object_as(transaction_ptr); + transactions.push_back(td_api::make_object( + "TON", get_amount(transaction->amount_), transaction->date_, transaction->provider_)); + break; + } + default: + UNREACHABLE(); + } + } + promise_.set_value(td_api::make_object(total_count, std::move(transactions))); + } + + void on_error(Status status) final { + td_->chat_manager_->on_get_channel_error(channel_id_, status, "GetBroadcastRevenueTransactionsQuery"); + promise_.set_error(std::move(status)); + } +}; + static td_api::object_ptr convert_message_stats( telegram_api::object_ptr obj) { return td_api::make_object( @@ -566,6 +640,19 @@ void StatisticsManager::get_channel_revenue_statistics( td_->create_handler(std::move(promise))->send(dialog_id.get_channel_id(), is_dark); } +void StatisticsManager::get_channel_revenue_transactions( + DialogId dialog_id, int32 offset, int32 limit, + Promise> &&promise) { + if (!td_->dialog_manager_->have_dialog_force(dialog_id, "get_channel_revenue_transactions")) { + return promise.set_error(Status::Error(400, "Chat not found")); + } + if (!td_->dialog_manager_->is_broadcast_channel(dialog_id)) { + return promise.set_error(Status::Error(400, "Chat is not a channel")); + } + td_->create_handler(std::move(promise)) + ->send(dialog_id.get_channel_id(), offset, limit); +} + void StatisticsManager::get_channel_message_statistics( MessageFullId message_full_id, bool is_dark, Promise> &&promise) { auto dc_id_promise = PromiseCreator::lambda([actor_id = actor_id(this), message_full_id, is_dark, diff --git a/td/telegram/StatisticsManager.h b/td/telegram/StatisticsManager.h index c6169f2cb..6e04f170f 100644 --- a/td/telegram/StatisticsManager.h +++ b/td/telegram/StatisticsManager.h @@ -33,6 +33,9 @@ class StatisticsManager final : public Actor { void get_channel_revenue_statistics(DialogId dialog_id, bool is_dark, Promise> &&promise); + void get_channel_revenue_transactions(DialogId dialog_id, int32 offset, int32 limit, + Promise> &&promise); + void get_channel_message_statistics(MessageFullId message_full_id, bool is_dark, Promise> &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 2da4dd4f4..330e44fb4 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -8548,6 +8548,13 @@ void Td::on_request(uint64 id, const td_api::getChatRevenueStatistics &request) statistics_manager_->get_channel_revenue_statistics(DialogId(request.chat_id_), request.is_dark_, std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getChatRevenueTransactions &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + statistics_manager_->get_channel_revenue_transactions(DialogId(request.chat_id_), request.offset_, request.limit_, + std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getMessageStatistics &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index e1ec948e1..8ea187ff3 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1615,6 +1615,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getChatRevenueStatistics &request); + void on_request(uint64 id, const td_api::getChatRevenueTransactions &request); + void on_request(uint64 id, const td_api::getMessageStatistics &request); void on_request(uint64 id, const td_api::getStoryStatistics &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 3e246cfca..076763578 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -6469,6 +6469,12 @@ class CliClient final : public Actor { bool is_dark; get_args(args, chat_id, is_dark); send_request(td_api::make_object(chat_id, is_dark)); + } else if (op == "gcrt") { + ChatId chat_id; + int32 offset; + string limit; + get_args(args, chat_id, offset, limit); + send_request(td_api::make_object(chat_id, offset, as_limit(limit))); } else { op_not_found_count++; }