Allow tg URLs in text links and url buttons.
GitOrigin-RevId: 9708c3016375564e737bf5a8f79494807d61c10f
This commit is contained in:
parent
537d96cc8e
commit
1ef5c89a91
@ -582,7 +582,7 @@ keyboardButton text:string type:KeyboardButtonType = KeyboardButton;
|
|||||||
|
|
||||||
//@class InlineKeyboardButtonType @description Describes the type of an inline keyboard button
|
//@class InlineKeyboardButtonType @description Describes the type of an inline keyboard button
|
||||||
|
|
||||||
//@description A button that opens a specified URL @url URL to open
|
//@description A button that opens a specified URL @url HTTP or tg:// URL to open
|
||||||
inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType;
|
inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType;
|
||||||
|
|
||||||
//@description A button that sends a special callback query to a bot @data Data to be sent to the bot via a callback query
|
//@description A button that sends a special callback query to a bot @data Data to be sent to the bot via a callback query
|
||||||
@ -1179,7 +1179,7 @@ textEntityTypePre = TextEntityType;
|
|||||||
//@description Text that must be formatted as if inside pre, and code HTML tags @language Programming language of the code; as defined by the sender
|
//@description Text that must be formatted as if inside pre, and code HTML tags @language Programming language of the code; as defined by the sender
|
||||||
textEntityTypePreCode language:string = TextEntityType;
|
textEntityTypePreCode language:string = TextEntityType;
|
||||||
|
|
||||||
//@description A text description shown instead of a raw URL @url URL to be opened when the link is clicked
|
//@description A text description shown instead of a raw URL @url HTTP or tg:// URL to be opened when the link is clicked
|
||||||
textEntityTypeTextUrl url:string = TextEntityType;
|
textEntityTypeTextUrl url:string = TextEntityType;
|
||||||
|
|
||||||
//@description A text shows instead of a raw mention of the user (e.g., when the user has no username) @user_id Identifier of the mentioned user
|
//@description A text shows instead of a raw mention of the user (e.g., when the user has no username) @user_id Identifier of the mentioned user
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "td/telegram/ContactsManager.h"
|
#include "td/telegram/ContactsManager.h"
|
||||||
#include "td/telegram/misc.h"
|
#include "td/telegram/misc.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/unicode.h"
|
#include "td/utils/unicode.h"
|
||||||
@ -1329,10 +1328,10 @@ Result<vector<MessageEntity>> parse_markdown(string &text) {
|
|||||||
if (user_id.is_valid()) {
|
if (user_id.is_valid()) {
|
||||||
entities.emplace_back(utf16_offset, utf16_entity_length, user_id);
|
entities.emplace_back(utf16_offset, utf16_entity_length, user_id);
|
||||||
} else {
|
} else {
|
||||||
auto r_http_url = parse_url(url);
|
auto r_url = check_url(url);
|
||||||
if (r_http_url.is_ok() && url.find('.') != string::npos) {
|
if (r_url.is_ok()) {
|
||||||
entities.emplace_back(MessageEntity::Type::TextUrl, utf16_offset, utf16_entity_length,
|
entities.emplace_back(MessageEntity::Type::TextUrl, utf16_offset, utf16_entity_length,
|
||||||
r_http_url.ok().get_url());
|
r_url.move_as_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1585,10 +1584,9 @@ Result<vector<MessageEntity>> parse_html(string &text) {
|
|||||||
if (user_id.is_valid()) {
|
if (user_id.is_valid()) {
|
||||||
entities.emplace_back(utf16_offset, utf16_entity_length, user_id);
|
entities.emplace_back(utf16_offset, utf16_entity_length, user_id);
|
||||||
} else {
|
} else {
|
||||||
auto r_http_url = parse_url(url);
|
auto r_url = check_url(url);
|
||||||
if (r_http_url.is_ok() && url.find('.') != string::npos) {
|
if (r_url.is_ok()) {
|
||||||
entities.emplace_back(MessageEntity::Type::TextUrl, utf16_offset, utf16_entity_length,
|
entities.emplace_back(MessageEntity::Type::TextUrl, utf16_offset, utf16_entity_length, r_url.move_as_ok());
|
||||||
r_http_url.ok().get_url());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (tag_name == "pre") {
|
} else if (tag_name == "pre") {
|
||||||
@ -1746,12 +1744,11 @@ Result<vector<MessageEntity>> get_message_entities(const ContactsManager *contac
|
|||||||
if (!clean_input_string(entity_text_url->url_)) {
|
if (!clean_input_string(entity_text_url->url_)) {
|
||||||
return Status::Error(400, "MessageEntityTextUrl.url must be encoded in UTF-8");
|
return Status::Error(400, "MessageEntityTextUrl.url must be encoded in UTF-8");
|
||||||
}
|
}
|
||||||
auto r_http_url = parse_url(entity_text_url->url_);
|
auto r_url = check_url(entity_text_url->url_);
|
||||||
if (r_http_url.is_error()) {
|
if (r_url.is_error()) {
|
||||||
return Status::Error(400, PSTRING() << "Wrong message entity: " << r_http_url.error().message());
|
return Status::Error(400, PSTRING() << "Wrong message entity: " << r_url.error().message());
|
||||||
}
|
}
|
||||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_,
|
entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_, r_url.move_as_ok());
|
||||||
r_http_url.ok().get_url());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case td_api::textEntityTypeMentionName::ID: {
|
case td_api::textEntityTypeMentionName::ID: {
|
||||||
@ -1843,14 +1840,14 @@ vector<MessageEntity> get_message_entities(const ContactsManager *contacts_manag
|
|||||||
case telegram_api::messageEntityTextUrl::ID: {
|
case telegram_api::messageEntityTextUrl::ID: {
|
||||||
// TODO const telegram_api::messageEntityTextUrl *
|
// TODO const telegram_api::messageEntityTextUrl *
|
||||||
auto entity_text_url = static_cast<telegram_api::messageEntityTextUrl *>(entity.get());
|
auto entity_text_url = static_cast<telegram_api::messageEntityTextUrl *>(entity.get());
|
||||||
auto r_http_url = parse_url(entity_text_url->url_);
|
auto r_url = check_url(entity_text_url->url_);
|
||||||
if (r_http_url.is_error()) {
|
if (r_url.is_error()) {
|
||||||
LOG(ERROR) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_http_url.error().message()
|
LOG(ERROR) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_url.error().message() << " from "
|
||||||
<< " from " << source;
|
<< source;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity_text_url->offset_, entity_text_url->length_,
|
entities.emplace_back(MessageEntity::Type::TextUrl, entity_text_url->offset_, entity_text_url->length_,
|
||||||
r_http_url.ok().get_url());
|
r_url.move_as_ok());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::messageEntityMentionName::ID: {
|
case telegram_api::messageEntityMentionName::ID: {
|
||||||
@ -1947,13 +1944,13 @@ vector<MessageEntity> get_message_entities(vector<tl_object_ptr<secret_api::Mess
|
|||||||
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << '"';
|
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << '"';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto r_http_url = parse_url(entity_text_url->url_);
|
auto r_url = check_url(entity_text_url->url_);
|
||||||
if (r_http_url.is_error()) {
|
if (r_url.is_error()) {
|
||||||
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_http_url.error().message();
|
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_url.error().message();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity_text_url->offset_, entity_text_url->length_,
|
entities.emplace_back(MessageEntity::Type::TextUrl, entity_text_url->offset_, entity_text_url->length_,
|
||||||
r_http_url.ok().get_url());
|
r_url.move_as_ok());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case secret_api::messageEntityMentionName::ID:
|
case secret_api::messageEntityMentionName::ID:
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
#include "td/utils/format.h"
|
#include "td/utils/format.h"
|
||||||
#include "td/utils/HttpUrl.h"
|
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
@ -363,8 +362,8 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
|
|||||||
switch (button_type_id) {
|
switch (button_type_id) {
|
||||||
case td_api::inlineKeyboardButtonTypeUrl::ID: {
|
case td_api::inlineKeyboardButtonTypeUrl::ID: {
|
||||||
current_button.type = InlineKeyboardButton::Type::Url;
|
current_button.type = InlineKeyboardButton::Type::Url;
|
||||||
TRY_RESULT(http_url, parse_url(static_cast<td_api::inlineKeyboardButtonTypeUrl *>(button->type_.get())->url_));
|
TRY_RESULT(url, check_url(static_cast<td_api::inlineKeyboardButtonTypeUrl *>(button->type_.get())->url_));
|
||||||
current_button.data = http_url.get_url();
|
current_button.data = std::move(url);
|
||||||
if (!clean_input_string(current_button.data)) {
|
if (!clean_input_string(current_button.data)) {
|
||||||
return Status::Error(400, "Inline keyboard button url must be encoded in UTF-8");
|
return Status::Error(400, "Inline keyboard button url must be encoded in UTF-8");
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "td/telegram/misc.h"
|
#include "td/telegram/misc.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/Slice.h"
|
#include "td/utils/Slice.h"
|
||||||
@ -274,4 +275,32 @@ string get_emoji_fingerprint(uint64 num) {
|
|||||||
return emojis[(num & 0x7FFFFFFFFFFFFFFF) % emojis.size()].str();
|
return emojis[(num & 0x7FFFFFFFFFFFFFFF) % emojis.size()].str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<string> check_url(MutableSlice url) {
|
||||||
|
bool is_tg = false;
|
||||||
|
if (begins_with(url, "tg://")) {
|
||||||
|
url.remove_prefix(5);
|
||||||
|
is_tg = true;
|
||||||
|
} else if (begins_with(url, "tg:")) {
|
||||||
|
url.remove_prefix(3);
|
||||||
|
is_tg = true;
|
||||||
|
} else {
|
||||||
|
is_tg = false;
|
||||||
|
}
|
||||||
|
TRY_RESULT(http_url, parse_url(url));
|
||||||
|
if (is_tg) {
|
||||||
|
if (begins_with(url, "http://") || http_url.protocol_ == HttpUrl::Protocol::HTTPS || !http_url.userinfo_.empty() || http_url.specified_port_ != 0 || http_url.is_ipv6_) {
|
||||||
|
return Status::Error("Wrong tg URL");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = http_url.get_url();
|
||||||
|
CHECK(begins_with(result, "http://"));
|
||||||
|
return PSTRING() << "tg" << Slice(result).substr(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.find('.') == string::npos) {
|
||||||
|
return Status::Error("Wrong HTTP URL");
|
||||||
|
}
|
||||||
|
return http_url.get_url();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
|
#include "td/utils/Slice.h"
|
||||||
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
@ -31,4 +33,7 @@ int32 get_vector_hash(const vector<uint32> &numbers) TD_WARN_UNUSED_RESULT;
|
|||||||
// returns emoji corresponding to the specified number
|
// returns emoji corresponding to the specified number
|
||||||
string get_emoji_fingerprint(uint64 num);
|
string get_emoji_fingerprint(uint64 num);
|
||||||
|
|
||||||
|
// checks whether url is a valid tg or HTTP(S) URL and returns its in a canonical form
|
||||||
|
Result<string> check_url(MutableSlice url);
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -29,11 +29,11 @@ string HttpUrl::get_url() const {
|
|||||||
result += userinfo_;
|
result += userinfo_;
|
||||||
result += '@';
|
result += '@';
|
||||||
}
|
}
|
||||||
if (is_ipv6) {
|
if (is_ipv6_) {
|
||||||
result += '[';
|
result += '[';
|
||||||
}
|
}
|
||||||
result += host_;
|
result += host_;
|
||||||
if (is_ipv6) {
|
if (is_ipv6_) {
|
||||||
result += ']';
|
result += ']';
|
||||||
}
|
}
|
||||||
if (specified_port_ > 0) {
|
if (specified_port_ > 0) {
|
||||||
|
@ -18,7 +18,7 @@ class HttpUrl {
|
|||||||
enum class Protocol { HTTP, HTTPS } protocol_;
|
enum class Protocol { HTTP, HTTPS } protocol_;
|
||||||
string userinfo_;
|
string userinfo_;
|
||||||
string host_;
|
string host_;
|
||||||
bool is_ipv6;
|
bool is_ipv6_;
|
||||||
int specified_port_;
|
int specified_port_;
|
||||||
int port_;
|
int port_;
|
||||||
string query_;
|
string query_;
|
||||||
|
Loading…
Reference in New Issue
Block a user