Add LinkManager::parse_internal_link test.

This commit is contained in:
levlam 2021-05-26 16:44:49 +03:00
parent f2ab121fe4
commit afb58801ec
3 changed files with 268 additions and 46 deletions

View File

@ -295,7 +295,7 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) {
result.is_internal_ = true;
result.is_tg_ = true;
result.query_ = link;
result.query_ = link.str();
return result;
} else {
if (http_url.port_ != 80 && http_url.port_ != 443) {
@ -303,26 +303,28 @@ LinkManager::LinkInfo LinkManager::get_link_info(Slice link) {
}
vector<Slice> t_me_urls{Slice("t.me"), Slice("telegram.me"), Slice("telegram.dog")};
string cur_t_me_url = G()->shared_config().get_option_string("t_me_url");
if (tolower_begins_with(cur_t_me_url, "http://") || tolower_begins_with(cur_t_me_url, "https://")) {
Slice t_me_url = cur_t_me_url;
t_me_url = t_me_url.substr(t_me_url[4] == 's' ? 8 : 7);
if (!td::contains(t_me_urls, t_me_url)) {
t_me_urls.push_back(t_me_url);
if (Scheduler::context() != nullptr) {
string cur_t_me_url = G()->shared_config().get_option_string("t_me_url");
if (tolower_begins_with(cur_t_me_url, "http://") || tolower_begins_with(cur_t_me_url, "https://")) {
Slice t_me_url = cur_t_me_url;
t_me_url = t_me_url.substr(t_me_url[4] == 's' ? 8 : 7);
if (!td::contains(t_me_urls, t_me_url)) {
t_me_urls.push_back(t_me_url);
}
}
}
// host is already lowercased
Slice host = http_url.host_;
auto host = url_decode(http_url.host_, false);
to_lower_inplace(host);
if (begins_with(host, "www.")) {
host.remove_prefix(4);
host = host.substr(4);
}
for (auto t_me_url : t_me_urls) {
if (host == t_me_url) {
result.is_internal_ = true;
result.is_tg_ = false;
result.query_ = http_url.query_;
result.query_ = std::move(http_url.query_);
return result;
}
}
@ -342,26 +344,51 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_internal_link(Slice lin
}
}
namespace {
struct CopyArg {
Slice name_;
const HttpUrlQuery *url_query_;
bool *is_first_;
CopyArg(Slice name, const HttpUrlQuery *url_query, bool *is_first)
: name_(name), url_query_(url_query), is_first_(is_first) {
}
};
StringBuilder &operator<<(StringBuilder &string_builder, const CopyArg &copy_arg) {
auto arg = copy_arg.url_query_->get_arg(copy_arg.name_);
if (arg.empty()) {
return string_builder;
}
char c = *copy_arg.is_first_ ? '?' : '&';
*copy_arg.is_first_ = false;
return string_builder << c << copy_arg.name_ << '=' << url_encode(arg);
}
} // namespace
unique_ptr<LinkManager::InternalLink> LinkManager::parse_tg_link_query(Slice query) {
const auto url_query = parse_url_query(query);
const auto &path = url_query.path_;
bool is_first_arg = true;
auto copy_arg = [&](Slice name) {
auto arg = url_query.get_arg(name);
if (arg.empty()) {
return string();
}
return PSTRING() << name << '=' << url_encode(arg);
return CopyArg(name, &url_query, &is_first_arg);
};
auto get_arg = [&](Slice name) {
return url_encode(url_query.get_arg(name));
};
auto has_arg = [&](Slice name) {
return !url_query.get_arg(name).empty();
};
if (path.size() == 1 && path[0] == "resolve") {
// resolve?domain=username&post=12345&single
if (!url_query.get_arg("domain").empty() && !url_query.get_arg("post").empty()) {
if (has_arg("domain") && has_arg("post")) {
return td::make_unique<InternalLinkMessage>();
}
} else if (path.size() == 1 && path[0] == "privatepost") {
// privatepost?channel=123456789&msg_id=12345
if (!url_query.get_arg("channel").empty() && !url_query.get_arg("msg_id").empty()) {
if (has_arg("channel") && has_arg("msg_id")) {
return td::make_unique<InternalLinkMessage>();
}
} else if (path.size() == 1 && path[0] == "bg") {
@ -370,17 +397,16 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_tg_link_query(Slice que
// bg?gradient=<hex_color>~<hex_color>~<hex_color>~<hex_color>
// bg?slug=<background_name>&mode=blur+motion
// bg?slug=<pattern_name>&intensity=...&bg_color=...&mode=blur+motion
if (!url_query.get_arg("color").empty()) {
return td::make_unique<InternalLinkBackground>(url_query.get_arg("color").str());
if (has_arg("color")) {
return td::make_unique<InternalLinkBackground>(get_arg("color"));
}
if (!url_query.get_arg("gradient").empty()) {
return td::make_unique<InternalLinkBackground>(PSTRING() << url_encode(url_query.get_arg("gradient")) << '?'
<< copy_arg("rotation"));
if (has_arg("gradient")) {
return td::make_unique<InternalLinkBackground>(PSTRING() << get_arg("gradient") << copy_arg("rotation"));
}
if (!url_query.get_arg("slug").empty()) {
return td::make_unique<InternalLinkBackground>(PSTRING() << url_encode(url_query.get_arg("slug")) << '?'
<< copy_arg("mode") << copy_arg("intensity")
<< copy_arg("bg_color") << copy_arg("rotation"));
if (has_arg("slug")) {
return td::make_unique<InternalLinkBackground>(PSTRING()
<< get_arg("slug") << copy_arg("mode") << copy_arg("intensity")
<< copy_arg("bg_color") << copy_arg("rotation"));
}
} else if (path.size() == 1 && (path[0] == "share" || path[0] == "msg" || path[0] == "msg_url")) {
// msg_url?url=<url>
@ -397,24 +423,45 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_t_me_link_query(Slice q
CHECK(query[0] == '/');
const auto url_query = parse_url_query(query);
const auto &path = url_query.path_;
if (path.size() == 3 && path[0] == "c") {
// /c/123456789/12345
return td::make_unique<InternalLinkMessage>();
} else if (path.size() == 2 && path[0] == "bg") {
// /bg/<hex_color>
// /bg/<hex_color>-<hex_color>?rotation=...
// /bg/<hex_color>~<hex_color>~<hex_color>~<hex_color>
// /bg/<background_name>?mode=blur+motion
// /bg/<pattern_name>?intensity=...&bg_color=...&mode=blur+motion
return td::make_unique<InternalLinkBackground>(query.substr(4).str());
} else if (path.size() >= 1 && (path[0] == "share" || path[0] == "msg") &&
(path.size() == 1 || (path[1] != "bookmarklet" && path[1] != "embed"))) {
// /share?url=<url>
// /share/url?url=<url>&text=<text>
return get_internal_link_message_draft(url_query.get_arg("url"), url_query.get_arg("text"));
} else if (path.size() == 2 && !path[0].empty()) {
// /<username>/12345?single
return td::make_unique<InternalLinkMessage>();
if (path.empty() || path[0].empty()) {
return nullptr;
}
bool is_first_arg = true;
auto copy_arg = [&](Slice name) {
return CopyArg(name, &url_query, &is_first_arg);
};
auto get_arg = [&](Slice name) {
return url_encode(url_query.get_arg(name));
};
if (path[0] == "c") {
if (path.size() >= 3 && to_integer<int64>(path[1]) > 0 && to_integer<int64>(path[2]) > 0) {
// /c/123456789/12345
return td::make_unique<InternalLinkMessage>();
}
} else if (path[0] == "bg") {
if (path.size() >= 2 && !path[1].empty()) {
// /bg/<hex_color>
// /bg/<hex_color>-<hex_color>?rotation=...
// /bg/<hex_color>~<hex_color>~<hex_color>~<hex_color>
// /bg/<background_name>?mode=blur+motion
// /bg/<pattern_name>?intensity=...&bg_color=...&mode=blur+motion
return td::make_unique<InternalLinkBackground>(PSTRING()
<< url_encode(path[1]) << copy_arg("mode") << copy_arg("intensity")
<< copy_arg("bg_color") << copy_arg("rotation"));
}
} else if (path[0] == "share" || path[0] == "msg") {
if (!(path.size() > 1 && (path[1] == "bookmarklet" || path[1] == "embed"))) {
// /share?url=<url>
// /share/url?url=<url>&text=<text>
return get_internal_link_message_draft(url_query.get_arg("url"), url_query.get_arg("text"));
}
} else {
if (path.size() >= 2 && to_integer<int64>(path[1]) > 0) {
// /<username>/12345?single
return td::make_unique<InternalLinkMessage>();
}
}
return nullptr;
}

View File

@ -55,7 +55,7 @@ class LinkManager : public Actor {
struct LinkInfo {
bool is_internal_ = false;
bool is_tg_ = false;
Slice query_;
string query_;
};
// returns information about the link
static LinkInfo get_link_info(Slice link);

View File

@ -6,6 +6,9 @@
//
#include "td/telegram/LinkManager.h"
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
#include "td/utils/tests.h"
static void check_link(td::string url, td::string expected) {
@ -45,3 +48,175 @@ TEST(Link, check_link) {
check_link("..", "http://../");
check_link("https://.", "");
}
static void parse_internal_link(td::string url, td::td_api::object_ptr<td::td_api::InternalLinkType> expected) {
// LOG(ERROR) << url;
auto result = td::LinkManager::parse_internal_link(url);
if (result != nullptr) {
auto object = result->get_internal_link_type_object();
if (object->get_id() == td::td_api::internalLinkTypeMessageDraft::ID) {
static_cast<td::td_api::internalLinkTypeMessageDraft *>(object.get())->text_->entities_.clear();
}
ASSERT_STREQ(to_string(expected), to_string(object));
} else {
ASSERT_TRUE(expected == nullptr);
}
}
TEST(Link, parse_internal_link) {
auto background = [](td::string background_name) {
return td::td_api::make_object<td::td_api::internalLinkTypeBackground>(background_name);
};
auto message = [] {
return td::td_api::make_object<td::td_api::internalLinkTypeMessage>();
};
auto message_draft = [](td::string text, bool contains_url) {
auto formatted_text = td::td_api::make_object<td::td_api::formattedText>();
formatted_text->text_ = std::move(text);
return td::td_api::make_object<td::td_api::internalLinkTypeMessageDraft>(std::move(formatted_text), contains_url);
};
auto unknown_deep_link = [] {
return td::td_api::make_object<td::td_api::internalLinkTypeUnknownDeepLink>();
};
parse_internal_link("t.me/levlam/1", message());
parse_internal_link("telegram.me/levlam/1", message());
parse_internal_link("telegram.dog/levlam/1", message());
parse_internal_link("www.t.me/levlam/1", message());
parse_internal_link("www%2etelegram.me/levlam/1", message());
parse_internal_link("www%2Etelegram.dog/levlam/1", message());
parse_internal_link("www%252Etelegram.dog/levlam/1", nullptr);
parse_internal_link("http://t.me/levlam/1", message());
parse_internal_link("https://t.me/levlam/1", message());
parse_internal_link("hTtp://www.t.me:443/levlam/1", message());
parse_internal_link("httPs://t.me:80/levlam/1", message());
parse_internal_link("https://t.me:200/levlam/1", nullptr);
parse_internal_link("http:t.me/levlam/1", nullptr);
parse_internal_link("t.dog/levlam/1", nullptr);
parse_internal_link("t.m/levlam/1", nullptr);
parse_internal_link("t.men/levlam/1", nullptr);
parse_internal_link("tg:resolve?domain=username&post=12345&single", message());
parse_internal_link("TG://resolve?domain=username&post=12345&single", message());
parse_internal_link("TG://test@resolve?domain=username&post=12345&single", nullptr);
parse_internal_link("tg:resolve:80?domain=username&post=12345&single", nullptr);
parse_internal_link("tg:http://resolve?domain=username&post=12345&single", nullptr);
parse_internal_link("tg:https://resolve?domain=username&post=12345&single", nullptr);
parse_internal_link("tg:resolve?domain=&post=12345&single", unknown_deep_link());
parse_internal_link("tg:resolve?domain=telegram&post=&single", unknown_deep_link());
parse_internal_link("t.me/username/12345?single", message());
parse_internal_link("t.me/username/12345?asdasd", message());
parse_internal_link("t.me/username/12345", message());
parse_internal_link("t.me/username/12345/", message());
parse_internal_link("t.me/username/12345#asdasd", message());
parse_internal_link("t.me/username/12345//?single", message());
parse_internal_link("t.me/username/12345/asdasd//asd/asd/asd/?single", message());
parse_internal_link("t.me/username/1asdasdas/asdasd//asd/asd/asd/?single", message());
parse_internal_link("t.me/username/asd", nullptr);
parse_internal_link("t.me/username/0", nullptr);
parse_internal_link("t.me/username/-12345", nullptr);
parse_internal_link("t.me//12345?single", nullptr);
parse_internal_link("https://telegram.dog/telegram/?single", nullptr);
parse_internal_link("tg:privatepost?domain=username/12345&single", unknown_deep_link());
parse_internal_link("tg:privatepost?channel=username/12345&single", unknown_deep_link());
parse_internal_link("tg:privatepost?channel=username&msg_id=12345", message());
parse_internal_link("t.me/c/12345?single", nullptr);
parse_internal_link("t.me/c/1/c?single", nullptr);
parse_internal_link("t.me/c/c/1?single", nullptr);
parse_internal_link("t.me/c//1?single", nullptr);
parse_internal_link("t.me/c/12345/123?single", message());
parse_internal_link("t.me/c/12345/123/asd/asd////?single", message());
parse_internal_link("tg:bg?color=111111#asdasd", background("111111"));
parse_internal_link("tg:bg?color=11111%31", background("111111"));
parse_internal_link("tg:bg?color=11111%20", background("11111%20"));
parse_internal_link("tg:bg?gradient=111111-222222", background("111111-222222"));
parse_internal_link("tg:bg?rotation=180%20&gradient=111111-222222%20",
background("111111-222222%20?rotation=180%20"));
parse_internal_link("tg:bg?gradient=111111~222222", background("111111~222222"));
parse_internal_link("tg:bg?gradient=abacaba", background("abacaba"));
parse_internal_link("tg:bg?slug=111111~222222#asdasd", background("111111~222222"));
parse_internal_link("tg:bg?slug=111111~222222&mode=12", background("111111~222222?mode=12"));
parse_internal_link("tg:bg?slug=111111~222222&mode=12&text=1", background("111111~222222?mode=12"));
parse_internal_link("tg:bg?slug=111111~222222&mode=12&mode=1", background("111111~222222?mode=12"));
parse_internal_link("tg:bg?slug=test&mode=12&rotation=4&intensity=2&bg_color=3",
background("test?mode=12&intensity=2&bg_color=3&rotation=4"));
parse_internal_link("tg:bg?mode=12&&slug=test&intensity=2&bg_color=3",
background("test?mode=12&intensity=2&bg_color=3"));
parse_internal_link("tg:bg?mode=12&intensity=2&bg_color=3", unknown_deep_link());
parse_internal_link("tg:bg?color=111111#asdasd", background("111111"));
parse_internal_link("tg:bg?color=11111%31", background("111111"));
parse_internal_link("tg:bg?color=11111%20", background("11111%20"));
parse_internal_link("tg:bg?gradient=111111-222222", background("111111-222222"));
parse_internal_link("tg:bg?rotation=180%20&gradient=111111-222222%20",
background("111111-222222%20?rotation=180%20"));
parse_internal_link("tg:bg?gradient=111111~222222", background("111111~222222"));
parse_internal_link("tg:bg?gradient=abacaba", background("abacaba"));
parse_internal_link("tg:bg?slug=111111~222222#asdasd", background("111111~222222"));
parse_internal_link("tg:bg?slug=111111~222222&mode=12", background("111111~222222?mode=12"));
parse_internal_link("tg:bg?slug=111111~222222&mode=12&text=1", background("111111~222222?mode=12"));
parse_internal_link("tg:bg?slug=111111~222222&mode=12&mode=1", background("111111~222222?mode=12"));
parse_internal_link("tg:bg?slug=test&mode=12&rotation=4&intensity=2&bg_color=3",
background("test?mode=12&intensity=2&bg_color=3&rotation=4"));
parse_internal_link("tg:bg?mode=12&&slug=test&intensity=2&bg_color=3",
background("test?mode=12&intensity=2&bg_color=3"));
parse_internal_link("tg:bg?mode=12&intensity=2&bg_color=3", unknown_deep_link());
parse_internal_link("%54.me/bg/111111#asdasd", background("111111"));
parse_internal_link("t.me/bg/11111%31", background("111111"));
parse_internal_link("t.me/bg/11111%20", background("11111%20"));
parse_internal_link("t.me/bg/111111-222222", background("111111-222222"));
parse_internal_link("t.me/bg/111111-222222%20?rotation=180%20", background("111111-222222%20?rotation=180%20"));
parse_internal_link("t.me/bg/111111~222222", background("111111~222222"));
parse_internal_link("t.me/bg/abacaba", background("abacaba"));
parse_internal_link("t.me/Bg/abacaba", nullptr);
parse_internal_link("t.me/bg/111111~222222#asdasd", background("111111~222222"));
parse_internal_link("t.me/bg/111111~222222?mode=12", background("111111~222222?mode=12"));
parse_internal_link("t.me/bg/111111~222222?mode=12&text=1", background("111111~222222?mode=12"));
parse_internal_link("t.me/bg/111111~222222?mode=12&mode=1", background("111111~222222?mode=12"));
parse_internal_link("t.me/bg/test?mode=12&rotation=4&intensity=2&bg_color=3",
background("test?mode=12&intensity=2&bg_color=3&rotation=4"));
parse_internal_link("t.me/%62g/test/?mode=12&&&intensity=2&bg_color=3",
background("test?mode=12&intensity=2&bg_color=3"));
parse_internal_link("t.me/bg//", nullptr);
parse_internal_link("t.me/bg/%20/", background("%20"));
parse_internal_link("t.me/bg/", nullptr);
parse_internal_link("tg:share?url=google.com&text=text#asdasd", message_draft("google.com\ntext", true));
parse_internal_link("tg:share?url=google.com&text=", message_draft("google.com", false));
parse_internal_link("tg:share?url=&text=google.com", message_draft("google.com", false));
parse_internal_link("tg:msg_url?url=google.com&text=text", message_draft("google.com\ntext", true));
parse_internal_link("tg:msg_url?url=google.com&text=", message_draft("google.com", false));
parse_internal_link("tg:msg_url?url=&text=google.com", message_draft("google.com", false));
parse_internal_link("tg:msg?url=google.com&text=text", message_draft("google.com\ntext", true));
parse_internal_link("tg:msg?url=google.com&text=", message_draft("google.com", false));
parse_internal_link("tg:msg?url=&text=google.com", message_draft("google.com", false));
parse_internal_link("tg:msg?url=&text=\n\n\n\n\n\n\n\n", nullptr);
parse_internal_link("tg:msg?url=%20\n&text=", nullptr);
parse_internal_link("tg:msg?url=%20\n&text=google.com", message_draft("google.com", false));
parse_internal_link("tg:msg?url=@&text=", message_draft(" @", false));
parse_internal_link("tg:msg?url=&text=@", message_draft(" @", false));
parse_internal_link("tg:msg?url=@&text=@", message_draft(" @\n@", true));
parse_internal_link("tg:msg?url=%FF&text=1", nullptr);
parse_internal_link("https://t.me/share?url=google.com&text=text#asdasd", message_draft("google.com\ntext", true));
parse_internal_link("https://t.me/share?url=google.com&text=", message_draft("google.com", false));
parse_internal_link("https://t.me/share?url=&text=google.com", message_draft("google.com", false));
parse_internal_link("https://t.me/msg?url=google.com&text=text", message_draft("google.com\ntext", true));
parse_internal_link("https://t.me/msg?url=google.com&text=", message_draft("google.com", false));
parse_internal_link("https://t.me/msg?url=&text=google.com", message_draft("google.com", false));
parse_internal_link("https://t.me/msg?url=google.com&text=text", message_draft("google.com\ntext", true));
parse_internal_link("https://t.me/msg?url=google.com&text=", message_draft("google.com", false));
parse_internal_link("https://t.me/msg?url=&text=google.com", message_draft("google.com", false));
parse_internal_link("https://t.me/msg?url=&text=\n\n\n\n\n\n\n\n", nullptr);
parse_internal_link("https://t.me/msg?url=%20\n&text=", nullptr);
parse_internal_link("https://t.me/msg?url=%20\n&text=google.com", message_draft("google.com", false));
parse_internal_link("https://t.me/msg?url=@&text=", message_draft(" @", false));
parse_internal_link("https://t.me/msg?url=&text=@", message_draft(" @", false));
parse_internal_link("https://t.me/msg?url=@&text=@", message_draft(" @\n@", true));
parse_internal_link("https://t.me/msg?url=%FF&text=1", nullptr);
}