From b3e16c5dd7b9c6c6e693306ace1e53b0083b9784 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 26 Sep 2022 19:24:39 +0300 Subject: [PATCH] Use the same template recursively for instant view links. --- td/telegram/LinkManager.cpp | 31 +++++++++++++++++++++++++++++++ td/telegram/LinkManager.h | 6 ++++++ td/telegram/WebPageBlock.cpp | 24 ++++++++++++++++++++++-- td/telegram/WebPageBlock.h | 2 +- td/telegram/WebPagesManager.cpp | 12 ++++++++---- td/telegram/WebPagesManager.h | 2 +- tdutils/td/utils/HttpUrl.cpp | 8 ++++++++ tdutils/td/utils/HttpUrl.h | 2 ++ 8 files changed, 79 insertions(+), 8 deletions(-) diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index f87366bfd..925661ac4 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -1617,6 +1617,37 @@ string LinkManager::get_dialog_invite_link(Slice hash, bool is_internal) { } } +string LinkManager::get_instant_view_link_url(Slice link) { + auto link_info = get_link_info(link); + if (link_info.type_ != LinkType::TMe) { + return string(); + } + const auto url_query = parse_url_query(link_info.query_); + const auto &path = url_query.path_; + if (path.size() == 1 && path[0] == "iv") { + return url_query.get_arg("url").str(); + } + return string(); +} + +string LinkManager::get_instant_view_link_rhash(Slice link) { + auto link_info = get_link_info(link); + if (link_info.type_ != LinkType::TMe) { + return string(); + } + const auto url_query = parse_url_query(link_info.query_); + const auto &path = url_query.path_; + if (path.size() == 1 && path[0] == "iv" && !url_query.get_arg("url").empty()) { + return url_query.get_arg("rhash").str(); + } + return string(); +} + +string LinkManager::get_instant_view_link(Slice url, Slice rhash) { + return PSTRING() << G()->get_option_string("t_me_url", "https://t.me/") << "iv?url=" << url_encode(url) + << "&rhash=" << url_encode(rhash); +} + UserId LinkManager::get_link_user_id(Slice url) { string lower_cased_url = to_lower(url); url = lower_cased_url; diff --git a/td/telegram/LinkManager.h b/td/telegram/LinkManager.h index bcd284bb3..b1cab61c2 100644 --- a/td/telegram/LinkManager.h +++ b/td/telegram/LinkManager.h @@ -78,6 +78,12 @@ class LinkManager final : public Actor { static string get_dialog_invite_link(Slice hash, bool is_internal); + static string get_instant_view_link_url(Slice link); + + static string get_instant_view_link_rhash(Slice link); + + static string get_instant_view_link(Slice url, Slice rhash); + static UserId get_link_user_id(Slice url); static Result get_link_custom_emoji_document_id(Slice url); diff --git a/td/telegram/WebPageBlock.cpp b/td/telegram/WebPageBlock.cpp index bdf2ab925..f791e4b52 100644 --- a/td/telegram/WebPageBlock.cpp +++ b/td/telegram/WebPageBlock.cpp @@ -18,6 +18,7 @@ #include "td/telegram/DocumentsManager.h" #include "td/telegram/DocumentsManager.hpp" #include "td/telegram/files/FileId.h" +#include "td/telegram/LinkManager.h" #include "td/telegram/Location.h" #include "td/telegram/Photo.h" #include "td/telegram/Photo.hpp" @@ -32,6 +33,7 @@ #include "td/utils/algorithm.h" #include "td/utils/common.h" +#include "td/utils/HttpUrl.h" #include "td/utils/logging.h" #include "td/utils/misc.h" #include "td/utils/SliceBuilder.h" @@ -47,6 +49,8 @@ class RichText; struct GetWebPageBlockObjectContext { Td *td_ = nullptr; Slice base_url_; + string real_url_host_; + string real_url_rhash_; bool is_first_pass_ = true; bool has_anchor_urls_ = false; @@ -147,6 +151,15 @@ class RichText { } } } + if (!context->real_url_rhash_.empty() && get_url_host(content) == context->real_url_host_) { + if (context->is_first_pass_) { + context->has_anchor_urls_ = true; + } else { + return make_tl_object( + texts[0].get_rich_text_object(context), + LinkManager::get_instant_view_link(content, context->real_url_rhash_), true); + } + } return make_tl_object(texts[0].get_rich_text_object(context), content, web_page_id.is_valid()); case RichText::Type::EmailAddress: @@ -2387,12 +2400,19 @@ vector> get_web_page_blocks( } vector> get_page_blocks_object( - const vector> &page_blocks, Td *td, Slice base_url) { + const vector> &page_blocks, Td *td, Slice base_url, Slice real_url) { GetWebPageBlockObjectContext context; context.td_ = td; context.base_url_ = base_url; + context.real_url_rhash_ = LinkManager::get_instant_view_link_rhash(real_url); + if (!context.real_url_rhash_.empty()) { + context.real_url_host_ = get_url_host(LinkManager::get_instant_view_link_url(real_url)); + if (context.real_url_host_.empty()) { + context.real_url_rhash_ = string(); + } + } auto blocks = get_page_blocks_object(page_blocks, &context); - if (context.anchors_.empty() || !context.has_anchor_urls_) { + if (!context.has_anchor_urls_) { return blocks; } diff --git a/td/telegram/WebPageBlock.h b/td/telegram/WebPageBlock.h index 81e5f4701..887a0f1b9 100644 --- a/td/telegram/WebPageBlock.h +++ b/td/telegram/WebPageBlock.h @@ -102,6 +102,6 @@ vector> get_web_page_blocks( const FlatHashMap &videos, const FlatHashMap &voice_notes); vector> get_page_blocks_object( - const vector> &page_blocks, Td *td, Slice base_url); + const vector> &page_blocks, Td *td, Slice base_url, Slice real_url); } // namespace td diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index 3112fe6c0..3ad2881cc 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -1299,11 +1299,15 @@ tl_object_ptr WebPagesManager::get_web_page_object(WebPageId we tl_object_ptr WebPagesManager::get_web_page_instant_view_object( WebPageId web_page_id) const { - return get_web_page_instant_view_object(web_page_id, get_web_page_instant_view(web_page_id)); + const WebPage *web_page = get_web_page(web_page_id); + if (web_page == nullptr || web_page->instant_view.is_empty) { + return nullptr; + } + return get_web_page_instant_view_object(web_page_id, &web_page->instant_view, web_page->url); } tl_object_ptr WebPagesManager::get_web_page_instant_view_object( - WebPageId web_page_id, const WebPageInstantView *web_page_instant_view) const { + WebPageId web_page_id, const WebPageInstantView *web_page_instant_view, Slice web_page_url) const { if (web_page_instant_view == nullptr) { return nullptr; } @@ -1314,7 +1318,7 @@ tl_object_ptr WebPagesManager::get_web_page_instant_ auto feedback_link = td_api::make_object( "previews", PSTRING() << "webpage" << web_page_id.get(), true); return td_api::make_object( - get_page_blocks_object(web_page_instant_view->page_blocks, td_, web_page_instant_view->url), + get_page_blocks_object(web_page_instant_view->page_blocks, td_, web_page_instant_view->url, web_page_url), web_page_instant_view->view_count, web_page_instant_view->is_v2 ? 2 : 1, web_page_instant_view->is_rtl, web_page_instant_view->is_full, std::move(feedback_link)); } @@ -1500,7 +1504,7 @@ void WebPagesManager::on_get_web_page_instant_view(WebPage *web_page, tl_object_ web_page->instant_view.is_loaded = true; LOG(DEBUG) << "Receive web page instant view: " - << to_string(get_web_page_instant_view_object(WebPageId(), &web_page->instant_view)); + << to_string(get_web_page_instant_view_object(WebPageId(), &web_page->instant_view, web_page->url)); } class WebPagesManager::WebPageLogEvent { diff --git a/td/telegram/WebPagesManager.h b/td/telegram/WebPagesManager.h index b02422d5e..5c2d29687 100644 --- a/td/telegram/WebPagesManager.h +++ b/td/telegram/WebPagesManager.h @@ -126,7 +126,7 @@ class WebPagesManager final : public Actor { void get_web_page_instant_view_impl(WebPageId web_page_id, bool force_full, Promise &&promise); tl_object_ptr get_web_page_instant_view_object( - WebPageId web_page_id, const WebPageInstantView *web_page_instant_view) const; + WebPageId web_page_id, const WebPageInstantView *web_page_instant_view, Slice web_page_url) const; static void on_pending_web_page_timeout_callback(void *web_pages_manager_ptr, int64 web_page_id_int); diff --git a/tdutils/td/utils/HttpUrl.cpp b/tdutils/td/utils/HttpUrl.cpp index e1d46964b..e793f940a 100644 --- a/tdutils/td/utils/HttpUrl.cpp +++ b/tdutils/td/utils/HttpUrl.cpp @@ -232,6 +232,14 @@ Slice HttpUrlQuery::get_arg(Slice key) const { return it == args_.end() ? Slice() : it->second; } +string get_url_host(Slice url) { + auto r_http_url = parse_url(url); + if (r_http_url.is_error()) { + return string(); + } + return r_http_url.ok().host_; +} + string get_url_query_file_name(const string &query) { Slice query_slice = query; query_slice.truncate(query.find_first_of("?#")); diff --git a/tdutils/td/utils/HttpUrl.h b/tdutils/td/utils/HttpUrl.h index 8ac5e5623..9b4e92edc 100644 --- a/tdutils/td/utils/HttpUrl.h +++ b/tdutils/td/utils/HttpUrl.h @@ -55,6 +55,8 @@ class HttpUrlQuery { HttpUrlQuery parse_url_query(Slice query); +string get_url_host(Slice url); + string get_url_query_file_name(const string &query); string get_url_file_name(Slice url);