From f57ab79f6768db84c72c4286e8981667c5685f73 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 5 Jun 2023 17:56:16 +0300 Subject: [PATCH] Add td_api::internalLinkTypeStory. --- td/generate/scheme/td_api.tl | 5 +++++ td/telegram/LinkManager.cpp | 42 ++++++++++++++++++++++++++++++++++++ td/telegram/LinkManager.h | 1 + test/link.cpp | 29 +++++++++++++++++++++++++ 4 files changed, 77 insertions(+) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a63d93503..88543083a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4789,6 +4789,11 @@ internalLinkTypeSettings = InternalLinkType; //@expect_custom_emoji True, if the sticker set is expected to contain custom emoji internalLinkTypeStickerSet sticker_set_name:string expect_custom_emoji:Bool = InternalLinkType; +//@description The link is a link to a story. Call searchPublicChat with the given sender username, check that a user is returned, then call getStory with the received user identifier and the given story identifier +//@sender_username Username of the sender of the story +//@story_id Story identifier +internalLinkTypeStory sender_username:string story_id:int32 = InternalLinkType; + //@description The link is a link to a theme. TDLib has no theme support yet @theme_name Name of the theme internalLinkTypeTheme theme_name:string = InternalLinkType; diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index 7c0faeac5..5b115c148 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -21,6 +21,7 @@ #include "td/telegram/misc.h" #include "td/telegram/net/Proxy.h" #include "td/telegram/ServerMessageId.h" +#include "td/telegram/StoryId.h" #include "td/telegram/Td.h" #include "td/telegram/TdDb.h" #include "td/telegram/telegram_api.h" @@ -67,6 +68,11 @@ static bool is_valid_web_app_name(Slice name) { return name.size() >= 3 && is_valid_username(name); } +static bool is_valid_story_id(Slice story_id) { + auto r_story_id = to_integer_safe(story_id); + return r_story_id.is_ok() && StoryId(r_story_id.ok()).is_server(); +} + static string get_url_query_hash(bool is_tg, const HttpUrlQuery &url_query) { const auto &path = url_query.path_; if (is_tg) { @@ -605,6 +611,20 @@ class LinkManager::InternalLinkStickerSet final : public InternalLink { } }; +class LinkManager::InternalLinkStory final : public InternalLink { + string sender_username_; + StoryId story_id_; + + td_api::object_ptr get_internal_link_type_object() const final { + return td_api::make_object(sender_username_, story_id_.get()); + } + + public: + InternalLinkStory(string sender_username, StoryId story_id) + : sender_username_(std::move(sender_username)), story_id_(story_id) { + } +}; + class LinkManager::InternalLinkTheme final : public InternalLink { string theme_name_; @@ -1199,6 +1219,10 @@ unique_ptr LinkManager::parse_tg_link_query(Slice que return td::make_unique(std::move(username), arg.second, url_query.get_arg("startapp").str()); } + if (arg.first == "story" && is_valid_story_id(arg.second)) { + // resolve?domain=&story= + return td::make_unique(std::move(username), StoryId(to_integer(arg.second))); + } } if (!url_query.get_arg("attach").empty()) { // resolve?domain=&attach= @@ -1592,6 +1616,10 @@ unique_ptr LinkManager::parse_t_me_link_query(Slice q // /?game= return td::make_unique(std::move(username), arg.second); } + if (arg.first == "story" && is_valid_story_id(arg.second)) { + // /?story= + return td::make_unique(std::move(username), StoryId(to_integer(arg.second))); + } } if (!url_query.get_arg("attach").empty()) { // /?attach= @@ -2067,6 +2095,20 @@ Result LinkManager::get_internal_link_impl(const td_api::InternalLinkTyp << url_encode(link->sticker_set_name_); } } + case td_api::internalLinkTypeStory::ID: { + auto link = static_cast(type_ptr); + if (!is_valid_username(link->sender_username_)) { + return Status::Error(400, "Invalid sender username specified"); + } + if (!StoryId(link->story_id_).is_server()) { + return Status::Error(400, "Invalid story identifier specified"); + } + if (is_internal) { + return PSTRING() << "tg://resolve?domain=" << link->sender_username_ << "&story=" << link->story_id_; + } else { + return PSTRING() << get_t_me_url() << link->sender_username_ << "?story=" << link->story_id_; + } + } case td_api::internalLinkTypeTheme::ID: { auto link = static_cast(type_ptr); if (link->theme_name_.empty()) { diff --git a/td/telegram/LinkManager.h b/td/telegram/LinkManager.h index 0620815d9..5a9e4e0a0 100644 --- a/td/telegram/LinkManager.h +++ b/td/telegram/LinkManager.h @@ -144,6 +144,7 @@ class LinkManager final : public Actor { class InternalLinkRestorePurchases; class InternalLinkSettings; class InternalLinkStickerSet; + class InternalLinkStory; class InternalLinkTheme; class InternalLinkThemeSettings; class InternalLinkUnknownDeepLink; diff --git a/test/link.cpp b/test/link.cpp index 67b81c135..4a4666117 100644 --- a/test/link.cpp +++ b/test/link.cpp @@ -317,6 +317,10 @@ static auto sticker_set(const td::string &sticker_set_name, bool expect_custom_e return td::td_api::make_object(sticker_set_name, expect_custom_emoji); } +static auto story(const td::string &sender_username, td::int32 story_id) { + return td::td_api::make_object(sender_username, story_id); +} + static auto theme(const td::string &theme_name) { return td::td_api::make_object(theme_name); } @@ -1046,6 +1050,31 @@ TEST(Link, parse_internal_link_part4) { parse_internal_link("t.me//username?game=asd", nullptr); parse_internal_link("https://telegram.dog/tele%63ram?game=t%63st", game("telecram", "tcst")); + parse_internal_link("tg:resolve?domain=username&story=123", story("username", 123)); + parse_internal_link("TG://resolve?domain=username&story=", public_chat("username")); + parse_internal_link("TG://resolve?domain=username&story=0", public_chat("username")); + parse_internal_link("TG://resolve?domain=username&story=-1", public_chat("username")); + parse_internal_link("TG://test@resolve?domain=username&story=1", nullptr); + parse_internal_link("tg:resolve:80?domain=username&story=1", nullptr); + parse_internal_link("tg:http://resolve?domain=username&story=1", nullptr); + parse_internal_link("tg:https://resolve?domain=username&story=1", nullptr); + parse_internal_link("tg:resolve?domain=&story=1", unknown_deep_link("tg://resolve?domain=&story=1")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&story=%30", public_chat("telegram")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&story=%31", story("telegram", 1)); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&story=%31ab", public_chat("telegram")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&story=%31%39", story("telegram", 19)); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&story=2222222222", public_chat("telegram")); + + parse_internal_link("t.me/username/0/a//s/as?story=1234", story("username", 1234)); + parse_internal_link("t.me/username/aasdas/2?test=1&story=3#12312", story("username", 3)); + parse_internal_link("t.me/username/0?story=1", story("username", 1)); + parse_internal_link("t.me/username/-1?story=2", story("username", 2)); + parse_internal_link("t.me/username?story=5", story("username", 5)); + parse_internal_link("t.me/username?story=", public_chat("username")); + parse_internal_link("t.me/username#story=123", public_chat("username")); + parse_internal_link("t.me//username?story=123", nullptr); + parse_internal_link("https://telegram.dog/tele%63ram?story=%31%39", story("telecram", 19)); + parse_internal_link("tg:resolve?domain=username&appname=aasdasd&startapp=123asd", web_app("username", "aasdasd", "123asd")); parse_internal_link("TG://resolve?domain=username&appname=&startapp=123asd", public_chat("username"));