Use the same template recursively for instant view links.

This commit is contained in:
levlam 2022-09-26 19:24:39 +03:00
parent a3bb5913a7
commit b3e16c5dd7
8 changed files with 79 additions and 8 deletions

View File

@ -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) { UserId LinkManager::get_link_user_id(Slice url) {
string lower_cased_url = to_lower(url); string lower_cased_url = to_lower(url);
url = lower_cased_url; url = lower_cased_url;

View File

@ -78,6 +78,12 @@ class LinkManager final : public Actor {
static string get_dialog_invite_link(Slice hash, bool is_internal); 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 UserId get_link_user_id(Slice url);
static Result<int64> get_link_custom_emoji_document_id(Slice url); static Result<int64> get_link_custom_emoji_document_id(Slice url);

View File

@ -18,6 +18,7 @@
#include "td/telegram/DocumentsManager.h" #include "td/telegram/DocumentsManager.h"
#include "td/telegram/DocumentsManager.hpp" #include "td/telegram/DocumentsManager.hpp"
#include "td/telegram/files/FileId.h" #include "td/telegram/files/FileId.h"
#include "td/telegram/LinkManager.h"
#include "td/telegram/Location.h" #include "td/telegram/Location.h"
#include "td/telegram/Photo.h" #include "td/telegram/Photo.h"
#include "td/telegram/Photo.hpp" #include "td/telegram/Photo.hpp"
@ -32,6 +33,7 @@
#include "td/utils/algorithm.h" #include "td/utils/algorithm.h"
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/HttpUrl.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/misc.h" #include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h" #include "td/utils/SliceBuilder.h"
@ -47,6 +49,8 @@ class RichText;
struct GetWebPageBlockObjectContext { struct GetWebPageBlockObjectContext {
Td *td_ = nullptr; Td *td_ = nullptr;
Slice base_url_; Slice base_url_;
string real_url_host_;
string real_url_rhash_;
bool is_first_pass_ = true; bool is_first_pass_ = true;
bool has_anchor_urls_ = false; 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<td_api::richTextUrl>(
texts[0].get_rich_text_object(context),
LinkManager::get_instant_view_link(content, context->real_url_rhash_), true);
}
}
return make_tl_object<td_api::richTextUrl>(texts[0].get_rich_text_object(context), content, return make_tl_object<td_api::richTextUrl>(texts[0].get_rich_text_object(context), content,
web_page_id.is_valid()); web_page_id.is_valid());
case RichText::Type::EmailAddress: case RichText::Type::EmailAddress:
@ -2387,12 +2400,19 @@ vector<unique_ptr<WebPageBlock>> get_web_page_blocks(
} }
vector<td_api::object_ptr<td_api::PageBlock>> get_page_blocks_object( vector<td_api::object_ptr<td_api::PageBlock>> get_page_blocks_object(
const vector<unique_ptr<WebPageBlock>> &page_blocks, Td *td, Slice base_url) { const vector<unique_ptr<WebPageBlock>> &page_blocks, Td *td, Slice base_url, Slice real_url) {
GetWebPageBlockObjectContext context; GetWebPageBlockObjectContext context;
context.td_ = td; context.td_ = td;
context.base_url_ = base_url; 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); auto blocks = get_page_blocks_object(page_blocks, &context);
if (context.anchors_.empty() || !context.has_anchor_urls_) { if (!context.has_anchor_urls_) {
return blocks; return blocks;
} }

View File

@ -102,6 +102,6 @@ vector<unique_ptr<WebPageBlock>> get_web_page_blocks(
const FlatHashMap<int64, FileId> &videos, const FlatHashMap<int64, FileId> &voice_notes); const FlatHashMap<int64, FileId> &videos, const FlatHashMap<int64, FileId> &voice_notes);
vector<td_api::object_ptr<td_api::PageBlock>> get_page_blocks_object( vector<td_api::object_ptr<td_api::PageBlock>> get_page_blocks_object(
const vector<unique_ptr<WebPageBlock>> &page_blocks, Td *td, Slice base_url); const vector<unique_ptr<WebPageBlock>> &page_blocks, Td *td, Slice base_url, Slice real_url);
} // namespace td } // namespace td

View File

@ -1299,11 +1299,15 @@ tl_object_ptr<td_api::webPage> WebPagesManager::get_web_page_object(WebPageId we
tl_object_ptr<td_api::webPageInstantView> WebPagesManager::get_web_page_instant_view_object( tl_object_ptr<td_api::webPageInstantView> WebPagesManager::get_web_page_instant_view_object(
WebPageId web_page_id) const { 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<td_api::webPageInstantView> WebPagesManager::get_web_page_instant_view_object( tl_object_ptr<td_api::webPageInstantView> 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) { if (web_page_instant_view == nullptr) {
return nullptr; return nullptr;
} }
@ -1314,7 +1318,7 @@ tl_object_ptr<td_api::webPageInstantView> WebPagesManager::get_web_page_instant_
auto feedback_link = td_api::make_object<td_api::internalLinkTypeBotStart>( auto feedback_link = td_api::make_object<td_api::internalLinkTypeBotStart>(
"previews", PSTRING() << "webpage" << web_page_id.get(), true); "previews", PSTRING() << "webpage" << web_page_id.get(), true);
return td_api::make_object<td_api::webPageInstantView>( return td_api::make_object<td_api::webPageInstantView>(
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->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)); 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; web_page->instant_view.is_loaded = true;
LOG(DEBUG) << "Receive web page instant view: " 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 { class WebPagesManager::WebPageLogEvent {

View File

@ -126,7 +126,7 @@ class WebPagesManager final : public Actor {
void get_web_page_instant_view_impl(WebPageId web_page_id, bool force_full, Promise<WebPageId> &&promise); void get_web_page_instant_view_impl(WebPageId web_page_id, bool force_full, Promise<WebPageId> &&promise);
tl_object_ptr<td_api::webPageInstantView> get_web_page_instant_view_object( tl_object_ptr<td_api::webPageInstantView> 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); static void on_pending_web_page_timeout_callback(void *web_pages_manager_ptr, int64 web_page_id_int);

View File

@ -232,6 +232,14 @@ Slice HttpUrlQuery::get_arg(Slice key) const {
return it == args_.end() ? Slice() : it->second; 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) { string get_url_query_file_name(const string &query) {
Slice query_slice = query; Slice query_slice = query;
query_slice.truncate(query.find_first_of("?#")); query_slice.truncate(query.find_first_of("?#"));

View File

@ -55,6 +55,8 @@ class HttpUrlQuery {
HttpUrlQuery parse_url_query(Slice query); HttpUrlQuery parse_url_query(Slice query);
string get_url_host(Slice url);
string get_url_query_file_name(const string &query); string get_url_query_file_name(const string &query);
string get_url_file_name(Slice url); string get_url_file_name(Slice url);