Add support for star gifts API.

This commit is contained in:
John Preston 2024-09-16 13:34:53 +04:00
parent 46c8a55f56
commit 71deef61f5
3 changed files with 101 additions and 26 deletions

View file

@ -589,6 +589,51 @@ Data::PremiumSubscriptionOptions PremiumGiftCodeOptions::options(int amount) {
} }
} }
auto PremiumGiftCodeOptions::requestStarGifts()
-> rpl::producer<rpl::no_value, QString> {
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<StarGift>();
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<StarGift> &PremiumGiftCodeOptions::starGifts() const {
return _gifts;
}
int PremiumGiftCodeOptions::giveawayBoostsPerPremium() const { int PremiumGiftCodeOptions::giveawayBoostsPerPremium() const {
constexpr auto kFallbackCount = 4; constexpr auto kFallbackCount = 4;
return _peer->session().appConfig().get<int>( return _peer->session().appConfig().get<int>(

View file

@ -73,6 +73,14 @@ struct GiftOptionData {
int months = 0; int months = 0;
}; };
struct StarGift {
uint64 id = 0;
int64 stars = 0;
not_null<DocumentData*> document;
int limitedLeft = 0;
int limitedCount = 0;
};
class Premium final { class Premium final {
public: public:
explicit Premium(not_null<ApiWrap*> api); explicit Premium(not_null<ApiWrap*> api);
@ -194,6 +202,9 @@ public:
[[nodiscard]] int giveawayPeriodMax() const; [[nodiscard]] int giveawayPeriodMax() const;
[[nodiscard]] bool giveawayGiftsPurchaseAvailable() const; [[nodiscard]] bool giveawayGiftsPurchaseAvailable() const;
[[nodiscard]] rpl::producer<rpl::no_value, QString> requestStarGifts();
[[nodiscard]] const std::vector<StarGift> &starGifts() const;
private: private:
struct Token final { struct Token final {
int users = 0; int users = 0;
@ -221,6 +232,9 @@ private:
base::flat_map<Token, Store> _stores; base::flat_map<Token, Store> _stores;
int32 _giftsHash = 0;
std::vector<StarGift> _gifts;
MTP::Sender _api; MTP::Sender _api;
}; };

View file

@ -84,8 +84,9 @@ struct GiftTypePremium {
}; };
struct GiftTypeStars { struct GiftTypeStars {
uint64 id = 0;
int64 stars = 0;
DocumentData *document = nullptr; DocumentData *document = nullptr;
int stars = 0;
bool limited = false; bool limited = false;
[[nodiscard]] friend inline bool operator==( [[nodiscard]] friend inline bool operator==(
@ -409,8 +410,11 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
} }
} }
ranges::sort(list, ranges::less(), &GiftTypePremium::months); ranges::sort(list, ranges::less(), &GiftTypePremium::months);
Map[session].last = list; auto &map = Map[session];
consumer.put_next_copy(list); if (map.last != list) {
map.last = list;
consumer.put_next_copy(list);
}
}, lifetime); }, lifetime);
return lifetime; return lifetime;
@ -420,34 +424,46 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
[[nodiscard]] rpl::producer<std::vector<GiftTypeStars>> GiftsStars( [[nodiscard]] rpl::producer<std::vector<GiftTypeStars>> GiftsStars(
not_null<Main::Session*> session, not_null<Main::Session*> session,
not_null<PeerData*> peer) { not_null<PeerData*> peer) {
//struct Session { struct Session {
// std::vector<GiftTypeStars> last; std::vector<GiftTypeStars> last;
//}; };
//static auto Map = base::flat_map<not_null<Main::Session*>, Session>(); static auto Map = base::flat_map<not_null<Main::Session*>, Session>();
return [=](auto consumer) { return [=](auto consumer) {
auto lifetime = rpl::lifetime(); auto lifetime = rpl::lifetime();
auto list = std::vector<GiftTypeStars>(); 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) { using namespace Api;
auto &sets = session->data().stickers().setsRef(); const auto api = lifetime.make_state<PremiumGiftCodeOptions>(peer);
const auto i = sets.find(setId); api->requestStarGifts(
if (i != end(sets)) { ) | rpl::start_with_error_done([=](QString error) {
for (const auto document : i->second->stickers) { consumer.put_next({});
price = document->isPremiumSticker() ? 1000 : price; }, [=] {
list.push_back({ auto list = std::vector<GiftTypeStars>();
.document = document, const auto &gifts = api->starGifts();
.stars = price, list.reserve(gifts.size());
.limited = limited, for (auto &gift : gifts) {
}); list.push_back({
} .id = gift.id,
.stars = gift.stars,
.document = gift.document,
.limited = (gift.limitedCount > 0),
});
} }
}; auto &map = Map[session];
add(Data::Stickers::CloudRecentSetId, 100, false); if (map.last != list) {
add(Data::Stickers::RecentSetId, 250, false); map.last = list;
add(Data::Stickers::FavedSetId, 50, true); consumer.put_next_copy(list);
}
consumer.put_next(std::move(list)); }, lifetime);
return lifetime; return lifetime;
}; };