From a278aa0f89175094a871f72e469d2ece136463a3 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 24 Mar 2024 20:56:58 +0300 Subject: [PATCH] Added initial api support for channel earn statistics. --- Telegram/SourceFiles/api/api_statistics.cpp | 108 ++++++++++++++++++++ Telegram/SourceFiles/api/api_statistics.h | 21 ++++ Telegram/SourceFiles/data/data_statistics.h | 49 +++++++++ 3 files changed, 178 insertions(+) diff --git a/Telegram/SourceFiles/api/api_statistics.cpp b/Telegram/SourceFiles/api/api_statistics.cpp index 789211f33..78028313b 100644 --- a/Telegram/SourceFiles/api/api_statistics.cpp +++ b/Telegram/SourceFiles/api/api_statistics.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_statistics.h" #include "apiwrap.h" +#include "base/unixtime.h" #include "data/data_channel.h" #include "data/data_session.h" #include "data/data_stories.h" @@ -746,4 +747,111 @@ Data::BoostStatus Boosts::boostStatus() const { return _boostStatus; } +EarnStatistics::EarnStatistics(not_null channel) +: StatisticsRequestSender(channel) { +} + +rpl::producer EarnStatistics::request() { + return [=](auto consumer) { + auto lifetime = rpl::lifetime(); + + makeRequest(MTPstats_GetBroadcastRevenueStats( + MTP_flags(0), + channel()->inputChannel + )).done([=](const MTPstats_BroadcastRevenueStats &result) { + const auto &data = result.data(); + + _data = Data::EarnStatistics{ + .topHoursGraph = StatisticalGraphFromTL( + data.vtop_hours_graph()), + .revenueGraph = StatisticalGraphFromTL(data.vrevenue_graph()), + .currentBalance = data.vcurrent_balance().v, + .availableBalance = data.vavailable_balance().v, + .overallRevenue = data.voverall_revenue().v, + .usdRate = data.vusd_rate().v, + }; + + requestBoosts({}, [=](Data::EarnHistorySlice &&slice) { + _data.firstHistorySlice = std::move(slice); + consumer.put_done(); + }); + }).fail([=](const MTP::Error &error) { + consumer.put_error_copy(error.type()); + }).send(); + + return lifetime; + }; +} + +void EarnStatistics::requestBoosts( + const Data::EarnHistorySlice::OffsetToken &token, + Fn done) { + if (_requestId) { + return; + } + constexpr auto kTlFirstSlice = tl::make_int(kFirstSlice); + constexpr auto kTlLimit = tl::make_int(kLimit); + _requestId = api().request(MTPstats_GetBroadcastRevenueTransactions( + channel()->inputChannel, + MTP_int(token), + (!token) ? kTlFirstSlice : kTlLimit + )).done([=](const MTPstats_BroadcastRevenueTransactions &result) { + _requestId = 0; + + const auto &tlTransactions = result.data().vtransactions().v; + + auto list = std::vector(); + list.reserve(tlTransactions.size()); + for (const auto &tlTransaction : tlTransactions) { + list.push_back(tlTransaction.match([&]( + const MTPDbroadcastRevenueTransactionProceeds &d) { + return Data::EarnHistoryEntry{ + .type = Data::EarnHistoryEntry::Type::In, + .amount = d.vamount().v, + .date = base::unixtime::parse(d.vfrom_date().v), + .dateTo = base::unixtime::parse(d.vto_date().v), + }; + }, [&](const MTPDbroadcastRevenueTransactionWithdrawal &d) { + return Data::EarnHistoryEntry{ + .type = Data::EarnHistoryEntry::Type::Out, + .status = d.is_pending() + ? Data::EarnHistoryEntry::Status::Pending + : d.is_failed() + ? Data::EarnHistoryEntry::Status::Failed + : Data::EarnHistoryEntry::Status::Success, + .amount = d.vamount().v, + .date = base::unixtime::parse(d.vdate().v), + .provider = qs(d.vprovider()), + .successDate = d.vtransaction_date() + ? base::unixtime::parse(d.vtransaction_date()->v) + : QDateTime(), + .successLink = d.vtransaction_url() + ? qs(*d.vtransaction_url()) + : QString(), + }; + }, [&](const MTPDbroadcastRevenueTransactionRefund &d) { + return Data::EarnHistoryEntry{ + .type = Data::EarnHistoryEntry::Type::Return, + .amount = d.vamount().v, + .date = base::unixtime::parse(d.vdate().v), + .provider = qs(d.vprovider()), + }; + })); + } + const auto nextToken = token + tlTransactions.size(); + done(Data::EarnHistorySlice{ + .list = std::move(list), + .total = result.data().vcount().v, + .allLoaded = (result.data().vcount().v == nextToken), + .token = Data::EarnHistorySlice::OffsetToken(nextToken), + }); + }).fail([=] { + _requestId = 0; + }).send(); +} + +Data::EarnStatistics EarnStatistics::data() const { + return _data; +} + } // namespace Api diff --git a/Telegram/SourceFiles/api/api_statistics.h b/Telegram/SourceFiles/api/api_statistics.h index f5360adb2..2643ae1bc 100644 --- a/Telegram/SourceFiles/api/api_statistics.h +++ b/Telegram/SourceFiles/api/api_statistics.h @@ -107,6 +107,27 @@ private: }; +class EarnStatistics final : public StatisticsRequestSender { +public: + explicit EarnStatistics(not_null channel); + + [[nodiscard]] rpl::producer request(); + void requestBoosts( + const Data::EarnHistorySlice::OffsetToken &token, + Fn done); + + [[nodiscard]] Data::EarnStatistics data() const; + + static constexpr auto kFirstSlice = int(10); + static constexpr auto kLimit = int(40); + +private: + Data::EarnStatistics _data; + + mtpRequestId _requestId = 0; + +}; + class Boosts final { public: explicit Boosts(not_null peer); diff --git a/Telegram/SourceFiles/data/data_statistics.h b/Telegram/SourceFiles/data/data_statistics.h index 9d2b2c74a..5e438d88d 100644 --- a/Telegram/SourceFiles/data/data_statistics.h +++ b/Telegram/SourceFiles/data/data_statistics.h @@ -155,4 +155,53 @@ struct PublicForwardsSlice final { OffsetToken token; }; +struct EarnHistoryEntry final { + enum class Type { + In, + Out, + Return, + }; + + enum class Status { + Success, + Failed, + Pending, + }; + + Type type; + Status status; + + uint64 amount = 0; + QDateTime date; + QDateTime dateTo; + + QString provider; + + QDateTime successDate; + QString successLink; + +}; + +struct EarnHistorySlice final { + using OffsetToken = int; + std::vector list; + int total = 0; + bool allLoaded = false; + OffsetToken token; +}; + +struct EarnStatistics final { + explicit operator bool() const { + return !!usdRate; + } + Data::StatisticalGraph topHoursGraph; + Data::StatisticalGraph revenueGraph; + uint64 currentBalance = 0; + uint64 availableBalance = 0; + uint64 overallRevenue = 0; + float64 usdRate = 0.; + + EarnHistorySlice firstHistorySlice; +}; + } // namespace Data