From 71deef61f569baf7b11a12f68199a465afc78f9f Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 16 Sep 2024 13:34:53 +0400 Subject: [PATCH] Add support for star gifts API. --- Telegram/SourceFiles/api/api_premium.cpp | 45 ++++++++++++ Telegram/SourceFiles/api/api_premium.h | 14 ++++ .../SourceFiles/boxes/gift_credits_box.cpp | 68 ++++++++++++------- 3 files changed, 101 insertions(+), 26 deletions(-) diff --git a/Telegram/SourceFiles/api/api_premium.cpp b/Telegram/SourceFiles/api/api_premium.cpp index 7c2934652..896fe7723 100644 --- a/Telegram/SourceFiles/api/api_premium.cpp +++ b/Telegram/SourceFiles/api/api_premium.cpp @@ -589,6 +589,51 @@ Data::PremiumSubscriptionOptions PremiumGiftCodeOptions::options(int amount) { } } +auto PremiumGiftCodeOptions::requestStarGifts() +-> rpl::producer { + return [=](auto consumer) { + auto lifetime = rpl::lifetime(); + + _api.request(MTPpayments_GetStarGifts( + MTP_int(0) + )).done([=](const MTPpayments_StarGifts &result) { + result.match([&](const MTPDpayments_starGifts &data) { + _giftsHash = data.vhash().v; + const auto &list = data.vgifts().v; + auto gifts = std::vector(); + gifts.reserve(list.size()); + for (const auto &gift : list) { + const auto &data = gift.data(); + const auto document = _peer->owner().processDocument( + data.vsticker()); + const auto remaining = data.vavailability_remains(); + const auto total = data.vavailability_total(); + if (document->sticker()) { + gifts.push_back(StarGift{ + .id = uint64(data.vid().v), + .stars = int64(data.vstars().v), + .document = document, + .limitedLeft = remaining.value_or_empty(), + .limitedCount = total.value_or_empty(), + }); + } + } + _gifts = std::move(gifts); + }, [&](const MTPDpayments_starGiftsNotModified &) { + }); + consumer.put_done(); + }).fail([=](const MTP::Error &error) { + consumer.put_error_copy(error.type()); + }).send(); + + return lifetime; + }; +} + +const std::vector &PremiumGiftCodeOptions::starGifts() const { + return _gifts; +} + int PremiumGiftCodeOptions::giveawayBoostsPerPremium() const { constexpr auto kFallbackCount = 4; return _peer->session().appConfig().get( diff --git a/Telegram/SourceFiles/api/api_premium.h b/Telegram/SourceFiles/api/api_premium.h index d778b00d4..2d8f2417d 100644 --- a/Telegram/SourceFiles/api/api_premium.h +++ b/Telegram/SourceFiles/api/api_premium.h @@ -73,6 +73,14 @@ struct GiftOptionData { int months = 0; }; +struct StarGift { + uint64 id = 0; + int64 stars = 0; + not_null document; + int limitedLeft = 0; + int limitedCount = 0; +}; + class Premium final { public: explicit Premium(not_null api); @@ -194,6 +202,9 @@ public: [[nodiscard]] int giveawayPeriodMax() const; [[nodiscard]] bool giveawayGiftsPurchaseAvailable() const; + [[nodiscard]] rpl::producer requestStarGifts(); + [[nodiscard]] const std::vector &starGifts() const; + private: struct Token final { int users = 0; @@ -221,6 +232,9 @@ private: base::flat_map _stores; + int32 _giftsHash = 0; + std::vector _gifts; + MTP::Sender _api; }; diff --git a/Telegram/SourceFiles/boxes/gift_credits_box.cpp b/Telegram/SourceFiles/boxes/gift_credits_box.cpp index b32ca2eef..e35d6fcac 100644 --- a/Telegram/SourceFiles/boxes/gift_credits_box.cpp +++ b/Telegram/SourceFiles/boxes/gift_credits_box.cpp @@ -84,8 +84,9 @@ struct GiftTypePremium { }; struct GiftTypeStars { + uint64 id = 0; + int64 stars = 0; DocumentData *document = nullptr; - int stars = 0; bool limited = false; [[nodiscard]] friend inline bool operator==( @@ -409,8 +410,11 @@ void PreviewWrap::paintEvent(QPaintEvent *e) { } } ranges::sort(list, ranges::less(), &GiftTypePremium::months); - Map[session].last = list; - consumer.put_next_copy(list); + auto &map = Map[session]; + if (map.last != list) { + map.last = list; + consumer.put_next_copy(list); + } }, lifetime); return lifetime; @@ -420,34 +424,46 @@ void PreviewWrap::paintEvent(QPaintEvent *e) { [[nodiscard]] rpl::producer> GiftsStars( not_null session, not_null peer) { - //struct Session { - // std::vector last; - //}; - //static auto Map = base::flat_map, Session>(); + struct Session { + std::vector last; + }; + static auto Map = base::flat_map, Session>(); + return [=](auto consumer) { auto lifetime = rpl::lifetime(); - auto list = std::vector(); + auto i = Map.find(session); + if (i == end(Map)) { + i = Map.emplace(session, Session()).first; + session->lifetime().add([=] { Map.remove(session); }); + } + if (!i->second.last.empty()) { + consumer.put_next_copy(i->second.last); + } - const auto add = [&](uint64 setId, int price, bool limited) { - auto &sets = session->data().stickers().setsRef(); - const auto i = sets.find(setId); - if (i != end(sets)) { - for (const auto document : i->second->stickers) { - price = document->isPremiumSticker() ? 1000 : price; - list.push_back({ - .document = document, - .stars = price, - .limited = limited, - }); - } + using namespace Api; + const auto api = lifetime.make_state(peer); + api->requestStarGifts( + ) | rpl::start_with_error_done([=](QString error) { + consumer.put_next({}); + }, [=] { + auto list = std::vector(); + const auto &gifts = api->starGifts(); + list.reserve(gifts.size()); + for (auto &gift : gifts) { + list.push_back({ + .id = gift.id, + .stars = gift.stars, + .document = gift.document, + .limited = (gift.limitedCount > 0), + }); } - }; - add(Data::Stickers::CloudRecentSetId, 100, false); - add(Data::Stickers::RecentSetId, 250, false); - add(Data::Stickers::FavedSetId, 50, true); - - consumer.put_next(std::move(list)); + auto &map = Map[session]; + if (map.last != list) { + map.last = list; + consumer.put_next_copy(list); + } + }, lifetime); return lifetime; };