Add internalLinkTypePublicChat.

This commit is contained in:
levlam 2021-05-31 04:15:33 +03:00
parent 27369944a7
commit 3860e8eea5
4 changed files with 117 additions and 39 deletions

View File

@ -3041,6 +3041,9 @@ internalLinkTypePhoneNumberConfirmation hash:string phone_number:string = Intern
//@server Proxy server IP address @port Proxy server port @type Type of the proxy
internalLinkTypeProxy server:string port:int32 type:ProxyType = InternalLinkType;
//@description The link is a link to a chat by its username. Call searchPublicChat with the given chat username to process the link @chat_username Username of the chat
internalLinkTypePublicChat chat_username:string = InternalLinkType;
//@description The link can be used to login the current user on another device, but it must be scanned from QR-code using in-app camera. An alert similar to
//-"This code can be used to allow someone to log in to your Telegram account. To confirm Telegram login, please go to Settings > Devices > Scan QR and scan the code" needs to be shown
internalLinkTypeQrCodeAuthentication = InternalLinkType;
@ -3054,7 +3057,7 @@ internalLinkTypeTheme theme_name:string = InternalLinkType;
//@description The link is an unknown tg: link. Call getDeepLinkInfo to process the link
internalLinkTypeUnknownDeepLink = InternalLinkType;
//@description The link is a link to a voice chat. Call searchPublicChat with the given chat username and then joinGoupCall with the given invite hash to process the link
//@description The link is a link to a voice chat. Call searchPublicChat with the given chat username, and then joinGoupCall with the given invite hash to process the link
//@chat_username Username of the chat with the voice chat @invite_hash If non-empty, invite hash to be used to join the voice chat without being muted by administrators
internalLinkTypeVoiceChat chat_username:string invite_hash:string = InternalLinkType;

View File

@ -22,6 +22,7 @@
#include "td/utils/buffer.h"
#include "td/utils/HttpUrl.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SliceBuilder.h"
namespace td {
@ -30,6 +31,30 @@ static bool is_valid_start_parameter(Slice start_parameter) {
return start_parameter.size() <= 64 && is_base64url_characters(start_parameter);
}
static bool is_valid_username(Slice username) {
if (username.empty() || username.size() > 32) {
return false;
}
if (!is_alpha(username[0])) {
return false;
}
for (auto c : username) {
if (!is_alpha(c) && !is_digit(c) && c != '_') {
return false;
}
}
if (username.back() == '_') {
return false;
}
for (size_t i = 1; i < username.size(); i++) {
if (username[i - 1] == '_' && username[i] == '_') {
return false;
}
}
return true;
}
class LinkManager::InternalLinkAuthenticationCode : public InternalLink {
string code_;
@ -223,6 +248,22 @@ class LinkManager::InternalLinkProxy : public InternalLink {
}
};
class LinkManager::InternalLinkPublicDialog : public InternalLink {
string dialog_username_;
td_api::object_ptr<td_api::InternalLinkType> get_internal_link_type_object() const final {
return td_api::make_object<td_api::internalLinkTypePublicChat>(dialog_username_);
}
InternalLinkType get_type() const final {
return InternalLinkType::PublicDialog;
}
public:
explicit InternalLinkPublicDialog(string dialog_username) : dialog_username_(std::move(dialog_username)) {
}
};
class LinkManager::InternalLinkQrCodeAuthentication : public InternalLink {
td_api::object_ptr<td_api::InternalLinkType> get_internal_link_type_object() const final {
return td_api::make_object<td_api::internalLinkTypeQrCodeAuthentication>();
@ -276,11 +317,11 @@ class LinkManager::InternalLinkUnknownDeepLink : public InternalLink {
};
class LinkManager::InternalLinkVoiceChat : public InternalLink {
string chat_username_;
string dialog_username_;
string invite_hash_;
td_api::object_ptr<td_api::InternalLinkType> get_internal_link_type_object() const final {
return td_api::make_object<td_api::internalLinkTypeVoiceChat>(chat_username_, invite_hash_);
return td_api::make_object<td_api::internalLinkTypeVoiceChat>(dialog_username_, invite_hash_);
}
InternalLinkType get_type() const final {
@ -288,8 +329,8 @@ class LinkManager::InternalLinkVoiceChat : public InternalLink {
}
public:
InternalLinkVoiceChat(string chat_username, string invite_hash)
: chat_username_(std::move(chat_username)), invite_hash_(std::move(invite_hash)) {
InternalLinkVoiceChat(string dialog_username, string invite_hash)
: dialog_username_(std::move(dialog_username)), invite_hash_(std::move(invite_hash)) {
}
};
@ -614,7 +655,7 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_tg_link_query(Slice que
};
if (path.size() == 1 && path[0] == "resolve") {
if (has_arg("domain")) {
if (is_valid_username(get_arg("domain"))) {
if (has_arg("post")) {
// resolve?domain=<username>&post=12345&single
return td::make_unique<InternalLinkMessage>();
@ -638,6 +679,8 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_tg_link_query(Slice que
return td::make_unique<InternalLinkGame>(get_arg("domain"), arg.second);
}
}
// resolve?domain=<username>
return td::make_unique<InternalLinkPublicDialog>(get_arg("domain"));
}
} else if (path.size() == 1 && path[0] == "login") {
// login?code=123456
@ -819,31 +862,32 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_t_me_link_query(Slice q
// /share/url?url=<url>&text=<text>
return get_internal_link_message_draft(get_arg("url"), get_arg("text"));
}
} else if (path[0].size() <= 64) {
} else if (is_valid_username(path[0])) {
if (path.size() >= 2 && to_integer<int64>(path[1]) > 0) {
// /<username>/12345?single&thread=<thread_id>&comment=<message_id>
return td::make_unique<InternalLinkMessage>();
} else {
for (auto &arg : url_query.args_) {
if (arg.first == "voicechat") {
// /<username>?voicechat
// /<username>?voicechat=<invite_hash>
return td::make_unique<InternalLinkVoiceChat>(path[0], arg.second);
}
if (arg.first == "start" && is_valid_start_parameter(arg.second)) {
// /<bot_username>?start=<parameter>
return td::make_unique<InternalLinkBotStart>(path[0], arg.second);
}
if (arg.first == "startgroup" && is_valid_start_parameter(arg.second)) {
// /<bot_username>?startgroup=<parameter>
return td::make_unique<InternalLinkBotStartInGroup>(path[0], arg.second);
}
if (arg.first == "game" && !arg.second.empty()) {
// /<bot_username>?game=<short_name>
return td::make_unique<InternalLinkGame>(path[0], arg.second);
}
}
for (auto &arg : url_query.args_) {
if (arg.first == "voicechat") {
// /<username>?voicechat
// /<username>?voicechat=<invite_hash>
return td::make_unique<InternalLinkVoiceChat>(path[0], arg.second);
}
if (arg.first == "start" && is_valid_start_parameter(arg.second)) {
// /<bot_username>?start=<parameter>
return td::make_unique<InternalLinkBotStart>(path[0], arg.second);
}
if (arg.first == "startgroup" && is_valid_start_parameter(arg.second)) {
// /<bot_username>?startgroup=<parameter>
return td::make_unique<InternalLinkBotStartInGroup>(path[0], arg.second);
}
if (arg.first == "game" && !arg.second.empty()) {
// /<bot_username>?game=<short_name>
return td::make_unique<InternalLinkGame>(path[0], arg.second);
}
}
// /<username>
return td::make_unique<InternalLinkPublicDialog>(path[0]);
}
return nullptr;
}

View File

@ -46,6 +46,7 @@ class LinkManager : public Actor {
Message,
MessageDraft,
Proxy,
PublicDialog,
QrCodeAuthentication,
StickerSet,
Theme,
@ -102,6 +103,7 @@ class LinkManager : public Actor {
class InternalLinkMessage;
class InternalLinkMessageDraft;
class InternalLinkProxy;
class InternalLinkPublicDialog;
class InternalLinkQrCodeAuthentication;
class InternalLinkStickerSet;
class InternalLinkTheme;

View File

@ -56,7 +56,7 @@ static void parse_internal_link(td::string url, td::td_api::object_ptr<td::td_ap
if (object->get_id() == td::td_api::internalLinkTypeMessageDraft::ID) {
static_cast<td::td_api::internalLinkTypeMessageDraft *>(object.get())->text_->entities_.clear();
}
ASSERT_STREQ(url + to_string(expected), url + to_string(object));
ASSERT_STREQ(url + " " + to_string(expected), url + " " + to_string(object));
} else {
ASSERT_TRUE(expected == nullptr);
}
@ -103,6 +103,9 @@ TEST(Link, parse_internal_link) {
return td::td_api::make_object<td::td_api::internalLinkTypeProxy>(
server, port, td::td_api::make_object<td::td_api::proxyTypeSocks5>(username, password));
};
auto public_chat = [](td::string chat_username) {
return td::td_api::make_object<td::td_api::internalLinkTypePublicChat>(chat_username);
};
auto qr_code_authentication = []() {
return td::td_api::make_object<td::td_api::internalLinkTypeQrCodeAuthentication>();
};
@ -146,7 +149,7 @@ TEST(Link, parse_internal_link) {
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("tg:resolve?domain=telegram&post=&single", public_chat("telegram"));
parse_internal_link("t.me/username/12345?single", message());
parse_internal_link("t.me/username/12345?asdasd", message());
@ -156,11 +159,11 @@ TEST(Link, parse_internal_link) {
parse_internal_link("t.me/username/12345//?voicechat=&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/username/asd", public_chat("username"));
parse_internal_link("t.me/username/0", public_chat("username"));
parse_internal_link("t.me/username/-12345", public_chat("username"));
parse_internal_link("t.me//12345?single", nullptr);
parse_internal_link("https://telegram.dog/telegram/?single", nullptr);
parse_internal_link("https://telegram.dog/telegram/?single", public_chat("telegram"));
parse_internal_link("tg:privatepost?domain=username/12345&single", unknown_deep_link());
parse_internal_link("tg:privatepost?channel=username/12345&single", unknown_deep_link());
@ -216,7 +219,7 @@ TEST(Link, parse_internal_link) {
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/abacaba", public_chat("Bg"));
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"));
@ -455,7 +458,7 @@ TEST(Link, parse_internal_link) {
parse_internal_link("t.me/username/0?voicechat=", voice_chat("username", ""));
parse_internal_link("t.me/username/-1?voicechat=asdasd", voice_chat("username", "asdasd"));
parse_internal_link("t.me/username?voicechat=", voice_chat("username", ""));
parse_internal_link("t.me/username#voicechat=asdas", nullptr);
parse_internal_link("t.me/username#voicechat=asdas", public_chat("username"));
parse_internal_link("t.me//username?voicechat=", nullptr);
parse_internal_link("https://telegram.dog/tele%63ram?voi%63e%63hat=t%63st", voice_chat("telecram", "tcst"));
@ -473,7 +476,7 @@ TEST(Link, parse_internal_link) {
parse_internal_link("t.me/username/0?start=", bot_start("username", ""));
parse_internal_link("t.me/username/-1?start=asdasd", bot_start("username", "asdasd"));
parse_internal_link("t.me/username?start=", bot_start("username", ""));
parse_internal_link("t.me/username#start=asdas", nullptr);
parse_internal_link("t.me/username#start=asdas", public_chat("username"));
parse_internal_link("t.me//username?start=", nullptr);
parse_internal_link("https://telegram.dog/tele%63ram?start=t%63st", bot_start("telecram", "tcst"));
@ -491,12 +494,12 @@ TEST(Link, parse_internal_link) {
parse_internal_link("t.me/username/0?startgroup=", bot_start_in_group("username", ""));
parse_internal_link("t.me/username/-1?startgroup=asdasd", bot_start_in_group("username", "asdasd"));
parse_internal_link("t.me/username?startgroup=", bot_start_in_group("username", ""));
parse_internal_link("t.me/username#startgroup=asdas", nullptr);
parse_internal_link("t.me/username#startgroup=asdas", public_chat("username"));
parse_internal_link("t.me//username?startgroup=", nullptr);
parse_internal_link("https://telegram.dog/tele%63ram?startgroup=t%63st", bot_start_in_group("telecram", "tcst"));
parse_internal_link("tg:resolve?domain=username&game=aasdasd", game("username", "aasdasd"));
parse_internal_link("TG://resolve?domain=username&game=", unknown_deep_link());
parse_internal_link("TG://resolve?domain=username&game=", public_chat("username"));
parse_internal_link("TG://test@resolve?domain=username&game=asd", nullptr);
parse_internal_link("tg:resolve:80?domain=username&game=asd", nullptr);
parse_internal_link("tg:http://resolve?domain=username&game=asd", nullptr);
@ -509,8 +512,34 @@ TEST(Link, parse_internal_link) {
parse_internal_link("t.me/username/0?game=asd", game("username", "asd"));
parse_internal_link("t.me/username/-1?game=asdasd", game("username", "asdasd"));
parse_internal_link("t.me/username?game=asd", game("username", "asd"));
parse_internal_link("t.me/username?game=", nullptr);
parse_internal_link("t.me/username#game=asdas", nullptr);
parse_internal_link("t.me/username?game=", public_chat("username"));
parse_internal_link("t.me/username#game=asdas", public_chat("username"));
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&Game=asd", public_chat("username"));
parse_internal_link("TG://test@resolve?domain=username", nullptr);
parse_internal_link("tg:resolve:80?domain=username", nullptr);
parse_internal_link("tg:http://resolve?domain=username", nullptr);
parse_internal_link("tg:https://resolve?domain=username", nullptr);
parse_internal_link("tg:resolve?domain=", unknown_deep_link());
parse_internal_link("tg:resolve?&&&&&&&domain=telegram", public_chat("telegram"));
parse_internal_link("t.me/a", public_chat("a"));
parse_internal_link("t.me/abcdefghijklmnopqrstuvwxyz123456", public_chat("abcdefghijklmnopqrstuvwxyz123456"));
parse_internal_link("t.me/abcdefghijklmnopqrstuvwxyz1234567", nullptr);
parse_internal_link("t.me/abcdefghijklmnop-qrstuvwxyz", nullptr);
parse_internal_link("t.me/abcdefghijklmnop~qrstuvwxyz", nullptr);
parse_internal_link("t.me/_asdf", nullptr);
parse_internal_link("t.me/0asdf", nullptr);
parse_internal_link("t.me/9asdf", nullptr);
parse_internal_link("t.me/Aasdf", public_chat("Aasdf"));
parse_internal_link("t.me/asdf_", nullptr);
parse_internal_link("t.me/asdf0", public_chat("asdf0"));
parse_internal_link("t.me/asd__fg", nullptr);
parse_internal_link("t.me/username/0/a//s/as?gam=asd", public_chat("username"));
parse_internal_link("t.me/username/aasdas?test=1", public_chat("username"));
parse_internal_link("t.me/username/0", public_chat("username"));
parse_internal_link("t.me//username", nullptr);
parse_internal_link("https://telegram.dog/tele%63ram", public_chat("telecram"));
}