Add td_api::getMessageLinkInfo.
GitOrigin-RevId: 34213fdada780b9bb8fe6a6db5a0de3be097b55c
This commit is contained in:
parent
b4cc4fea93
commit
5ca0a72ddf
@ -641,7 +641,7 @@ chatInviteLink invite_link:string = ChatInviteLink;
|
||||
//@photo Chat photo; may be null
|
||||
//@member_count Number of members
|
||||
//@member_user_ids User identifiers of some chat members that may be known to the current user
|
||||
//@is_public True, if the chat is a public supergroup or channel with a username
|
||||
//@is_public True, if the chat is a public supergroup or a channel with a username
|
||||
chatInviteLinkInfo chat_id:int53 type:ChatType title:string photo:chatPhoto member_count:int32 member_user_ids:vector<int32> is_public:Bool = ChatInviteLinkInfo;
|
||||
|
||||
|
||||
@ -2005,7 +2005,7 @@ checkChatUsernameResultUsernameInvalid = CheckChatUsernameResult;
|
||||
//@description The username is occupied
|
||||
checkChatUsernameResultUsernameOccupied = CheckChatUsernameResult;
|
||||
|
||||
//@description The user has too much public chats, one of them should be made private first
|
||||
//@description The user has too much chats with username, one of them should be made private first
|
||||
checkChatUsernameResultPublicChatsTooMuch = CheckChatUsernameResult;
|
||||
|
||||
//@description The user can't be a member of a public supergroup
|
||||
@ -2278,9 +2278,16 @@ chatReportReasonCopyright = ChatReportReason;
|
||||
chatReportReasonCustom text:string = ChatReportReason;
|
||||
|
||||
|
||||
//@description Contains a public HTTPS link to a message in a public supergroup or channel @link Message link @html HTML-code for embedding the message
|
||||
//@description Contains a public HTTPS link to a message in a public supergroup or channel with a username @link Message link @html HTML-code for embedding the message
|
||||
publicMessageLink link:string html:string = PublicMessageLink;
|
||||
|
||||
//@description Contains information about a link to a message in a chat
|
||||
//@is_public True, if the link is a public link for a message in a chat
|
||||
//@chat_id If found, identifier of the chat to which the message belongs, 0 otherwise
|
||||
//@message If found, the linked message; may be null
|
||||
//@for_album True, if the whole media album to which the message belongs is linked
|
||||
messageLinkInfo is_public:Bool chat_id:int53 message:message for_album:Bool = MessageLinkInfo;
|
||||
|
||||
|
||||
//@description Contains a part of a file @data File bytes
|
||||
filePart data:bytes = FilePart;
|
||||
@ -2959,7 +2966,7 @@ clearRecentlyFoundChats = Ok;
|
||||
//@description Checks whether a username can be set for a chat @chat_id Chat identifier; should be identifier of a supergroup chat, or a channel chat, or a private chat with self, or zero if chat is being created @username Username to be checked
|
||||
checkChatUsername chat_id:int53 username:string = CheckChatUsernameResult;
|
||||
|
||||
//@description Returns a list of public chats created by the user
|
||||
//@description Returns a list of public chats with username created by the user
|
||||
getCreatedPublicChats = Chats;
|
||||
|
||||
|
||||
@ -3032,7 +3039,7 @@ removeNotification notification_group_id:int32 notification_id:int32 = Ok;
|
||||
removeNotificationGroup notification_group_id:int32 max_notification_id:int32 = Ok;
|
||||
|
||||
|
||||
//@description Returns a public HTTPS link to a message. Available only for messages in public supergroups and channels
|
||||
//@description Returns a public HTTPS link to a message. Available only for messages in supergroups and channels with username
|
||||
//@chat_id Identifier of the chat to which the message belongs
|
||||
//@message_id Identifier of the message
|
||||
//@for_album Pass true if a link for a whole media album should be returned
|
||||
@ -3043,6 +3050,9 @@ getPublicMessageLink chat_id:int53 message_id:int53 for_album:Bool = PublicMessa
|
||||
//@message_id Identifier of the message
|
||||
getMessageLink chat_id:int53 message_id:int53 = HttpUrl;
|
||||
|
||||
//@description Returns information about a public or private message link @url The message link in the format "https://t.me/c/...", or "tg://privatepost?...", or "https://t.me/username/...", or "tg://resolve?..."
|
||||
getMessageLinkInfo url:string = MessageLinkInfo;
|
||||
|
||||
|
||||
//@description Sends a message. Returns the sent message @chat_id Target chat @reply_to_message_id Identifier of the message to reply to or 0
|
||||
//@disable_notification Pass true to disable notification for the message. Not supported in secret chats @from_background Pass true if the message is sent from the background
|
||||
|
Binary file not shown.
@ -9528,7 +9528,7 @@ void ContactsManager::reload_channel(ChannelId channel_id, Promise<Unit> &&promi
|
||||
have_channel_force(channel_id);
|
||||
auto input_channel = get_input_channel(channel_id);
|
||||
if (input_channel == nullptr) {
|
||||
return promise.set_error(Status::Error(6, "Supergroup info not found"));
|
||||
input_channel = make_tl_object<telegram_api::inputChannel>(channel_id.get(), 0);
|
||||
}
|
||||
|
||||
// there is no much reason to combine different requests into one request
|
||||
|
@ -12061,6 +12061,7 @@ MessageId MessagesManager::get_replied_message_id(const Message *m) {
|
||||
|
||||
void MessagesManager::get_message_force_from_server(Dialog *d, MessageId message_id, Promise<Unit> &&promise,
|
||||
tl_object_ptr<telegram_api::InputMessage> input_message) {
|
||||
LOG(INFO) << "Get " << message_id << " in " << d->dialog_id << " using " << to_string(input_message);
|
||||
auto m = get_message_force(d, message_id, "get_message_force_from_server");
|
||||
if (m == nullptr && message_id.is_valid() && message_id.is_server()) {
|
||||
auto dialog_type = d->dialog_id.get_type();
|
||||
@ -12371,6 +12372,214 @@ string MessagesManager::get_message_link(FullMessageId full_message_id, Promise<
|
||||
<< dialog_id.get_channel_id().get() << "/" << message_id.get_server_message_id().get();
|
||||
}
|
||||
|
||||
Result<MessagesManager::MessageLinkInfo> MessagesManager::get_message_link_info(Slice url) {
|
||||
if (url.empty()) {
|
||||
return Status::Error("URL must be non-empty");
|
||||
}
|
||||
|
||||
url.truncate(url.find('#'));
|
||||
|
||||
string lower_cased_url = to_lower(url);
|
||||
url = lower_cased_url;
|
||||
|
||||
Slice username;
|
||||
Slice channel_id_slice;
|
||||
Slice message_id_slice;
|
||||
bool is_single = false;
|
||||
if (begins_with(url, "tg:")) {
|
||||
url = url.substr(3);
|
||||
if (begins_with(url, "//")) {
|
||||
url = url.substr(2);
|
||||
}
|
||||
|
||||
// resolve?domain=username&post=12345&single
|
||||
// privatepost?channel=123456789&msg_id=12345
|
||||
|
||||
bool is_resolve = false;
|
||||
if (begins_with(url, "resolve")) {
|
||||
url = url.substr(7);
|
||||
is_resolve = true;
|
||||
} else if (begins_with(url, "privatepost")) {
|
||||
url = url.substr(11);
|
||||
} else {
|
||||
return Status::Error("Wrong message link URL");
|
||||
}
|
||||
|
||||
if (begins_with(url, "/")) {
|
||||
url = url.substr(1);
|
||||
}
|
||||
if (!begins_with(url, "?")) {
|
||||
return Status::Error("Wrong message link URL");
|
||||
}
|
||||
url = url.substr(1);
|
||||
|
||||
auto args = full_split(url, '&');
|
||||
for (auto arg : args) {
|
||||
auto key_value = split(arg, '=');
|
||||
if (is_resolve) {
|
||||
if (key_value.first == "domain") {
|
||||
username = key_value.second;
|
||||
}
|
||||
if (key_value.first == "post") {
|
||||
message_id_slice = key_value.second;
|
||||
}
|
||||
} else {
|
||||
if (key_value.first == "channel") {
|
||||
channel_id_slice = key_value.second;
|
||||
}
|
||||
if (key_value.first == "msg_id") {
|
||||
message_id_slice = key_value.second;
|
||||
}
|
||||
}
|
||||
if (key_value.first == "single") {
|
||||
is_single = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (begins_with(url, "http://") || begins_with(url, "https://")) {
|
||||
url = url.substr(url[4] == 's' ? 8 : 7);
|
||||
}
|
||||
|
||||
// t.me/c/123456789/12345
|
||||
// t.me/username/12345?single
|
||||
|
||||
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 (begins_with(cur_t_me_url, "http://") || begins_with(cur_t_me_url, "https://")) {
|
||||
Slice t_me_url = cur_t_me_url;
|
||||
t_me_url = t_me_url.substr(url[4] == 's' ? 8 : 7);
|
||||
if (std::find(t_me_urls.begin(), t_me_urls.end(), t_me_url) == t_me_urls.end()) {
|
||||
t_me_urls.push_back(t_me_url);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto t_me_url : t_me_urls) {
|
||||
if (begins_with(url, t_me_url)) {
|
||||
url = url.substr(t_me_url.size());
|
||||
auto username_end_pos = url.find('/');
|
||||
if (username_end_pos == Slice::npos) {
|
||||
return Status::Error("Wrong message link URL");
|
||||
}
|
||||
username = url.substr(0, username_end_pos);
|
||||
url = url.substr(username_end_pos + 1);
|
||||
if (username == "c") {
|
||||
username = Slice();
|
||||
auto channel_id_end_pos = url.find('/');
|
||||
if (channel_id_end_pos == Slice::npos) {
|
||||
return Status::Error("Wrong message link URL");
|
||||
}
|
||||
channel_id_slice = url.substr(0, channel_id_end_pos);
|
||||
url = url.substr(channel_id_end_pos + 1);
|
||||
}
|
||||
|
||||
auto query_pos = url.find('?');
|
||||
message_id_slice = url.substr(0, query_pos);
|
||||
is_single = query_pos != Slice::npos && url.substr(query_pos + 1) == "single";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChannelId channel_id;
|
||||
if (username.empty()) {
|
||||
auto r_channel_id = to_integer_safe<int32>(channel_id_slice);
|
||||
if (r_channel_id.is_error() || !ChannelId(r_channel_id.ok()).is_valid()) {
|
||||
return Status::Error("Wrong channel ID");
|
||||
}
|
||||
channel_id = ChannelId(r_channel_id.ok());
|
||||
}
|
||||
|
||||
auto r_message_id = to_integer_safe<int32>(message_id_slice);
|
||||
if (r_message_id.is_error() || !ServerMessageId(r_message_id.ok()).is_valid()) {
|
||||
return Status::Error("Wrong message ID");
|
||||
}
|
||||
|
||||
MessageLinkInfo info;
|
||||
info.username = username.str();
|
||||
info.channel_id = channel_id;
|
||||
info.message_id = MessageId(ServerMessageId(r_message_id.ok()));
|
||||
info.is_single = is_single;
|
||||
LOG(INFO) << "Have link to " << info.message_id << " in chat @" << info.username << "/" << channel_id.get();
|
||||
return std::move(info);
|
||||
}
|
||||
|
||||
void MessagesManager::get_message_link_info(Slice url, Promise<MessageLinkInfo> &&promise) {
|
||||
auto r_message_link_info = get_message_link_info(url);
|
||||
if (r_message_link_info.is_error()) {
|
||||
return promise.set_error(Status::Error(400, r_message_link_info.error().message()));
|
||||
}
|
||||
|
||||
auto info = r_message_link_info.move_as_ok();
|
||||
CHECK(info.username.empty() == info.channel_id.is_valid());
|
||||
|
||||
bool have_dialog = info.username.empty() ? td_->contacts_manager_->have_channel_force(info.channel_id)
|
||||
: resolve_dialog_username(info.username).is_valid();
|
||||
if (!have_dialog) {
|
||||
auto query_promise = PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this), info, promise = std::move(promise)](Result<Unit> &&result) mutable {
|
||||
if (result.is_error()) {
|
||||
return promise.set_value(std::move(info));
|
||||
}
|
||||
send_closure(actor_id, &MessagesManager::on_get_message_link_dialog, std::move(info), std::move(promise));
|
||||
});
|
||||
if (info.username.empty()) {
|
||||
td_->contacts_manager_->reload_channel(info.channel_id, std::move(query_promise));
|
||||
} else {
|
||||
td_->create_handler<ResolveUsernameQuery>(std::move(query_promise))->send(info.username);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return on_get_message_link_dialog(std::move(info), std::move(promise));
|
||||
}
|
||||
|
||||
void MessagesManager::on_get_message_link_dialog(MessageLinkInfo &&info, Promise<MessageLinkInfo> &&promise) {
|
||||
DialogId dialog_id;
|
||||
if (info.username.empty()) {
|
||||
if (!td_->contacts_manager_->have_channel(info.channel_id)) {
|
||||
return promise.set_error(Status::Error(500, "Chat info not found"));
|
||||
}
|
||||
|
||||
dialog_id = DialogId(info.channel_id);
|
||||
force_create_dialog(dialog_id, "on_get_message_link_dialog");
|
||||
} else {
|
||||
dialog_id = resolve_dialog_username(info.username);
|
||||
}
|
||||
Dialog *d = get_dialog_force(dialog_id);
|
||||
if (d == nullptr) {
|
||||
return promise.set_error(Status::Error(500, "Chat not found"));
|
||||
}
|
||||
|
||||
get_message_force_from_server(
|
||||
d, info.message_id,
|
||||
PromiseCreator::lambda([info = std::move(info), promise = std::move(promise)](Result<Unit> &&result) mutable {
|
||||
promise.set_value(std::move(info));
|
||||
}));
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::messageLinkInfo> MessagesManager::get_message_link_info_object(
|
||||
const MessageLinkInfo &info) const {
|
||||
CHECK(info.username.empty() == info.channel_id.is_valid());
|
||||
|
||||
bool is_public = !info.username.empty();
|
||||
DialogId dialog_id = is_public ? resolve_dialog_username(info.username) : DialogId(info.channel_id);
|
||||
td_api::object_ptr<td_api::message> message;
|
||||
bool for_album = false;
|
||||
|
||||
const Dialog *d = get_dialog(dialog_id);
|
||||
if (d == nullptr) {
|
||||
dialog_id = DialogId();
|
||||
} else {
|
||||
const Message *m = get_message(d, info.message_id);
|
||||
if (m != nullptr) {
|
||||
message = get_message_object(dialog_id, m);
|
||||
for_album = !info.is_single && m->media_album_id != 0;
|
||||
}
|
||||
}
|
||||
|
||||
return td_api::make_object<td_api::messageLinkInfo>(is_public, dialog_id.get(), std::move(message), for_album);
|
||||
}
|
||||
|
||||
Status MessagesManager::delete_dialog_reply_markup(DialogId dialog_id, MessageId message_id) {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return Status::Error(6, "Bots can't delete chat reply markup");
|
||||
@ -20864,13 +21073,14 @@ void MessagesManager::on_dialog_permissions_updated(DialogId dialog_id) {
|
||||
}
|
||||
}
|
||||
|
||||
DialogId MessagesManager::resolve_dialog_username(const string &username) {
|
||||
auto it = resolved_usernames_.find(clean_username(username));
|
||||
DialogId MessagesManager::resolve_dialog_username(const string &username) const {
|
||||
auto cleaned_username = clean_username(username);
|
||||
auto it = resolved_usernames_.find(cleaned_username);
|
||||
if (it != resolved_usernames_.end()) {
|
||||
return it->second.dialog_id;
|
||||
}
|
||||
|
||||
auto it2 = inaccessible_resolved_usernames_.find(clean_username(username));
|
||||
auto it2 = inaccessible_resolved_usernames_.find(cleaned_username);
|
||||
if (it2 != inaccessible_resolved_usernames_.end()) {
|
||||
return it2->second;
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ class MessagesManager : public Actor {
|
||||
|
||||
void clear_recently_found_dialogs();
|
||||
|
||||
DialogId resolve_dialog_username(const string &username);
|
||||
DialogId resolve_dialog_username(const string &username) const;
|
||||
|
||||
DialogId search_public_dialog(const string &username_to_search, bool force, Promise<Unit> &&promise);
|
||||
|
||||
@ -496,6 +496,18 @@ class MessagesManager : public Actor {
|
||||
|
||||
string get_message_link(FullMessageId full_message_id, Promise<Unit> &&promise);
|
||||
|
||||
struct MessageLinkInfo {
|
||||
string username;
|
||||
// or
|
||||
ChannelId channel_id;
|
||||
|
||||
MessageId message_id;
|
||||
bool is_single = false;
|
||||
};
|
||||
void get_message_link_info(Slice url, Promise<MessageLinkInfo> &&promise);
|
||||
|
||||
td_api::object_ptr<td_api::messageLinkInfo> get_message_link_info_object(const MessageLinkInfo &info) const;
|
||||
|
||||
Status delete_dialog_reply_markup(DialogId dialog_id, MessageId message_id) TD_WARN_UNUSED_RESULT;
|
||||
|
||||
Status set_dialog_draft_message(DialogId dialog_id,
|
||||
@ -1916,6 +1928,10 @@ class MessagesManager : public Actor {
|
||||
void ttl_db_loop(double server_now);
|
||||
void ttl_db_on_result(Result<std::pair<std::vector<std::pair<DialogId, BufferSlice>>, int32>> r_result, bool dummy);
|
||||
|
||||
static Result<MessageLinkInfo> get_message_link_info(Slice url);
|
||||
|
||||
void on_get_message_link_dialog(MessageLinkInfo &&info, Promise<MessageLinkInfo> &&promise);
|
||||
|
||||
static MessageId get_first_database_message_id_by_index(const Dialog *d, SearchMessagesFilter filter);
|
||||
|
||||
void on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id,
|
||||
|
@ -1175,6 +1175,33 @@ class GetMessageLinkRequest : public RequestActor<> {
|
||||
}
|
||||
};
|
||||
|
||||
class GetMessageLinkInfoRequest : public RequestActor<MessagesManager::MessageLinkInfo> {
|
||||
string url_;
|
||||
|
||||
MessagesManager::MessageLinkInfo message_link_info_;
|
||||
|
||||
void do_run(Promise<MessagesManager::MessageLinkInfo> &&promise) override {
|
||||
if (get_tries() < 2) {
|
||||
promise.set_value(std::move(message_link_info_));
|
||||
return;
|
||||
}
|
||||
td->messages_manager_->get_message_link_info(url_, std::move(promise));
|
||||
}
|
||||
|
||||
void do_set_result(MessagesManager::MessageLinkInfo &&result) override {
|
||||
message_link_info_ = std::move(result);
|
||||
}
|
||||
|
||||
void do_send_result() override {
|
||||
send_result(td->messages_manager_->get_message_link_info_object(message_link_info_));
|
||||
}
|
||||
|
||||
public:
|
||||
GetMessageLinkInfoRequest(ActorShared<Td> td, uint64 request_id, string url)
|
||||
: RequestActor(std::move(td), request_id), url_(std::move(url)) {
|
||||
}
|
||||
};
|
||||
|
||||
class EditMessageTextRequest : public RequestOnceActor {
|
||||
FullMessageId full_message_id_;
|
||||
tl_object_ptr<td_api::ReplyMarkup> reply_markup_;
|
||||
@ -5195,6 +5222,11 @@ void Td::on_request(uint64 id, const td_api::getMessageLink &request) {
|
||||
CREATE_REQUEST(GetMessageLinkRequest, request.chat_id_, request.message_id_);
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getMessageLinkInfo &request) {
|
||||
CLEAN_INPUT_STRING(request.url_);
|
||||
CREATE_REQUEST(GetMessageLinkInfoRequest, std::move(request.url_));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getFile &request) {
|
||||
send_closure(actor_id(this), &Td::send_result, id, file_manager_->get_file_object(FileId(request.file_id_, 0)));
|
||||
}
|
||||
|
@ -474,6 +474,8 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, const td_api::getMessageLink &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getMessageLinkInfo &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::getFile &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getRemoteFile &request);
|
||||
|
@ -2352,6 +2352,8 @@ class CliClient final : public Actor {
|
||||
string message_id;
|
||||
std::tie(chat_id, message_id) = split(args);
|
||||
send_request(td_api::make_object<td_api::getMessageLink>(as_chat_id(chat_id), as_message_id(message_id)));
|
||||
} else if (op == "gmli") {
|
||||
send_request(td_api::make_object<td_api::getMessageLinkInfo>(args));
|
||||
} else if (op == "gcmbd") {
|
||||
string chat_id;
|
||||
string date;
|
||||
|
Reference in New Issue
Block a user