From 3da733520db0080c0bccd76038e7965982263027 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 9 Oct 2023 05:09:23 +0300 Subject: [PATCH] Added API support to request list of public forwards for single message. --- Telegram/SourceFiles/api/api_statistics.cpp | 101 ++++++++++++++++++++ Telegram/SourceFiles/api/api_statistics.h | 29 ++++++ 2 files changed, 130 insertions(+) diff --git a/Telegram/SourceFiles/api/api_statistics.cpp b/Telegram/SourceFiles/api/api_statistics.cpp index aeddce54a..5ca74ab1c 100644 --- a/Telegram/SourceFiles/api/api_statistics.cpp +++ b/Telegram/SourceFiles/api/api_statistics.cpp @@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "data/data_channel.h" #include "data/data_peer.h" +#include "data/data_session.h" +#include "history/history.h" #include "main/main_session.h" #include "statistics/statistics_data_deserialize.h" @@ -287,4 +289,103 @@ Data::SupergroupStatistics Statistics::supergroupStats() const { return _supergroupStats; } +PublicForwards::PublicForwards( + not_null channel, + FullMsgId fullId) +: _channel(channel) +, _fullId(fullId) +, _api(&channel->session().api().instance()) { +} + +void PublicForwards::request( + const OffsetToken &token, + Fn done) { + if (_requestId) { + return; + } + const auto offsetPeer = _channel->owner().peer(token.fullId.peer); + const auto tlOffsetPeer = offsetPeer + ? offsetPeer->input + : MTP_inputPeerEmpty(); + constexpr auto kLimit = tl::make_int(100); + _requestId = _api.request(MTPstats_GetMessagePublicForwards( + _channel->inputChannel, + MTP_int(_fullId.msg), + MTP_int(token.rate), + tlOffsetPeer, + MTP_int(token.fullId.msg), + kLimit + )).done([=, channel = _channel](const MTPmessages_Messages &result) { + using Messages = QVector; + _requestId = 0; + + auto nextToken = OffsetToken(); + const auto process = [&](const MTPVector &messages) { + auto result = Messages(); + for (const auto &message : messages.v) { + const auto msgId = IdFromMessage(message); + const auto peerId = PeerFromMessage(message); + const auto lastDate = DateFromMessage(message); + if (const auto peer = channel->owner().peerLoaded(peerId)) { + if (lastDate) { + channel->owner().addNewMessage( + message, + MessageFlags(), + NewMessageType::Existing); + nextToken.fullId = { peerId, msgId }; + result.push_back(nextToken.fullId); + } + } + } + return result; + }; + + auto allLoaded = false; + auto fullCount = 0; + auto messages = result.match([&](const MTPDmessages_messages &data) { + channel->owner().processUsers(data.vusers()); + channel->owner().processChats(data.vchats()); + auto list = process(data.vmessages()); + allLoaded = true; + fullCount = list.size(); + return list; + }, [&](const MTPDmessages_messagesSlice &data) { + channel->owner().processUsers(data.vusers()); + channel->owner().processChats(data.vchats()); + auto list = process(data.vmessages()); + + if (const auto nextRate = data.vnext_rate()) { + const auto rateUpdated = (nextRate->v != token.rate); + if (rateUpdated) { + nextToken.rate = nextRate->v; + } else { + allLoaded = true; + } + } + fullCount = data.vcount().v; + return list; + }, [&](const MTPDmessages_channelMessages &data) { + channel->owner().processUsers(data.vusers()); + channel->owner().processChats(data.vchats()); + auto list = process(data.vmessages()); + allLoaded = true; + fullCount = data.vcount().v; + return list; + }, [&](const MTPDmessages_messagesNotModified &) { + allLoaded = true; + return Messages(); + }); + + _lastTotal = std::max(_lastTotal, fullCount); + done({ + .list = std::move(messages), + .total = _lastTotal, + .allLoaded = allLoaded, + .token = nextToken, + }); + }).fail([=] { + _requestId = 0; + }).send(); +} + } // namespace Api diff --git a/Telegram/SourceFiles/api/api_statistics.h b/Telegram/SourceFiles/api/api_statistics.h index 76df8bc49..e3a282c96 100644 --- a/Telegram/SourceFiles/api/api_statistics.h +++ b/Telegram/SourceFiles/api/api_statistics.h @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/sender.h" class ApiWrap; +class ChannelData; class PeerData; namespace Api { @@ -40,4 +41,32 @@ private: }; +class PublicForwards final { +public: + struct OffsetToken final { + int rate = 0; + FullMsgId fullId; + }; + + struct Slice { + QVector list; + int total = 0; + bool allLoaded = false; + OffsetToken token; + }; + + explicit PublicForwards(not_null channel, FullMsgId fullId); + + void request(const OffsetToken &token, Fn done); + +private: + const not_null _channel; + const FullMsgId _fullId; + mtpRequestId _requestId = 0; + int _lastTotal = 0; + + MTP::Sender _api; + +}; + } // namespace Api