From 017535cf7bcc3e52b93a126fdbdc1e1900037b85 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 7 Jan 2025 11:07:49 +0400 Subject: [PATCH] Handle t.me/nft/slug links. --- .../SourceFiles/core/local_url_handlers.cpp | 60 +++++++++++++++++++ Telegram/SourceFiles/data/data_credits.h | 1 + .../settings/settings_credits_graphics.cpp | 25 ++++++++ .../settings/settings_credits_graphics.h | 5 ++ 4 files changed, 91 insertions(+) diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index fa45db87b..bdeb03614 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -1344,6 +1344,59 @@ bool ResolveChatLink( return true; } +bool ResolveUniqueGift( + Window::SessionController *controller, + const Match &match, + const QVariant &context) { + if (!controller) { + return false; + } + const auto slug = match->captured(1); + if (slug.isEmpty()) { + return false; + } + struct Request { + base::weak_ptr weak; + QString slug; + mtpRequestId id = 0; + }; + static auto request = Request(); + if (request.weak.get() == controller && request.slug == slug) { + return true; + } else if (const auto strong = request.weak.get()) { + strong->session().api().request(request.id).cancel(); + } + const auto weak = request.weak = controller; + request.slug = slug; + const auto clear = [slug](not_null window) { + if (request.weak.get() == window && request.slug == slug) { + request = {}; + } + }; + request.id = controller->session().api().request( + MTPpayments_GetUniqueStarGift(MTP_string(slug)) + ).done([=](const MTPpayments_UniqueStarGift &result) { + if (const auto strong = weak.get()) { + clear(strong); + + const auto &data = result.data(); + const auto session = &strong->session(); + session->data().processUsers(data.vusers()); + if (const auto gift = Api::FromTL(session, data.vgift())) { + using namespace ::Settings; + strong->show(Box(GlobalStarGiftBox, strong, *gift)); + } + } + }).fail([=](const MTP::Error &error) { + if (const auto strong = weak.get()) { + clear(strong); + + strong->showToast(u"Error: "_q + error.type()); + } + }).send(); + return true; +} + } // namespace const std::vector &LocalUrlHandlers() { @@ -1436,6 +1489,10 @@ const std::vector &LocalUrlHandlers() { u"^stars_topup/?\\?(.+)(#|$)"_q, ResolveTopUp }, + { + u"^nft/?\\?slug=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"_q, + ResolveUniqueGift + }, { u"^([^\\?]+)(\\?|#|$)"_q, HandleUnknown @@ -1585,6 +1642,9 @@ QString TryConvertUrlToLocal(QString url) { } else if (const auto chatlinkMatch = regex_match(u"^m/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"_q, query, matchOptions)) { const auto slug = chatlinkMatch->captured(1); return u"tg://message?slug="_q + slug; + } else if (const auto nftMatch = regex_match(u"^nft/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"_q, query, matchOptions)) { + const auto slug = nftMatch->captured(1); + return u"tg://nft?slug="_q + slug; } else if (const auto privateMatch = regex_match(u"^" "c/(\\-?\\d+)" "(" diff --git a/Telegram/SourceFiles/data/data_credits.h b/Telegram/SourceFiles/data/data_credits.h index bf25cde0e..6bdf5563b 100644 --- a/Telegram/SourceFiles/data/data_credits.h +++ b/Telegram/SourceFiles/data/data_credits.h @@ -89,6 +89,7 @@ struct CreditsHistoryEntry final { bool giftUpgraded : 1 = false; bool savedToProfile : 1 = false; bool fromGiftsList : 1 = false; + bool fromGiftSlug : 1 = false; bool soldOutInfo : 1 = false; bool canUpgradeGift : 1 = false; bool hasGiftComment : 1 = false; diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index fa9396c54..b6a3acfd3 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -1689,6 +1689,31 @@ void CreditsPrizeBox( Data::SubscriptionEntry()); } +void GlobalStarGiftBox( + not_null box, + not_null controller, + const Data::StarGift &data) { + const auto ownerId = data.unique ? data.unique->ownerId.value : 0; + Settings::ReceiptCreditsBox( + box, + controller, + Data::CreditsHistoryEntry{ + .credits = StarsAmount(data.stars), + .bareGiftStickerId = data.document->id, + .bareGiftOwnerId = ownerId, + .stargiftId = data.id, + .uniqueGift = data.unique, + .peerType = Data::CreditsHistoryEntry::PeerType::Peer, + .limitedCount = data.limitedCount, + .limitedLeft = data.limitedLeft, + .stargift = true, + .fromGiftSlug = true, + .in = (ownerId == controller->session().userPeerId().value), + .gift = true, + }, + Data::SubscriptionEntry()); +} + void UserStarGiftBox( not_null box, not_null controller, diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.h b/Telegram/SourceFiles/settings/settings_credits_graphics.h index 3d042a082..6893fa2e0 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.h +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.h @@ -19,6 +19,7 @@ struct SubscriptionEntry; struct GiftCode; struct CreditTopupOption; struct UserStarGift; +struct StarGift; } // namespace Data namespace Main { @@ -97,6 +98,10 @@ void CreditsPrizeBox( not_null controller, const Data::GiftCode &data, TimeId date); +void GlobalStarGiftBox( + not_null box, + not_null controller, + const Data::StarGift &data); void UserStarGiftBox( not_null box, not_null controller,