diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 901504b41..ebd814611 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3912,11 +3912,11 @@ messageLink link:string is_public:Bool = MessageLink; //@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_thread_id If found, identifier of the message thread in which to open the message, or which to open in case of a missing message //@message If found, the linked message; may be null //@media_timestamp Timestamp from which the video/audio/video note/voice note playing must start, in seconds; 0 if not specified. The media can be in the message content or in its web page preview //@for_album True, if the whole media album to which the message belongs is linked -//@for_comment True, if the message is linked as a channel post comment or from a message thread -messageLinkInfo is_public:Bool chat_id:int53 message:message media_timestamp:int32 for_album:Bool for_comment:Bool = MessageLinkInfo; +messageLinkInfo is_public:Bool chat_id:int53 message_thread_id:int53 message:message media_timestamp:int32 for_album:Bool = MessageLinkInfo; //@description Contains a part of a file @data File bytes diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index fdb03a497..3900d02ec 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -1752,6 +1752,7 @@ Result LinkManager::get_message_link_info(Slice url) { Slice channel_id_slice; Slice message_id_slice; Slice comment_message_id_slice = "0"; + Slice top_thread_message_id_slice; Slice media_timestamp_slice; bool is_single = false; bool for_comment = false; @@ -1803,10 +1804,12 @@ Result LinkManager::get_message_link_info(Slice url) { } if (key_value.first == "thread") { for_comment = true; + top_thread_message_id_slice = key_value.second; } } } else { // /c/123456789/12345 + // /c/123456789/1234/12345 // /username/12345?single CHECK(!url.empty() && url[0] == '/'); @@ -1845,9 +1848,15 @@ Result LinkManager::get_message_link_info(Slice url) { } if (key_value.first == "thread") { for_comment = true; + top_thread_message_id_slice = key_value.second; } } } + auto slash_pos = message_id_slice.find('/'); + if (slash_pos != Slice::npos) { + top_thread_message_id_slice = message_id_slice.substr(0, slash_pos); + message_id_slice.remove_prefix(slash_pos + 1); + } } ChannelId channel_id; @@ -1864,6 +1873,18 @@ Result LinkManager::get_message_link_info(Slice url) { return Status::Error("Wrong message ID"); } + int32 top_thread_message_id = 0; + if (!top_thread_message_id_slice.empty()) { + auto r_top_thread_message_id = to_integer_safe(top_thread_message_id_slice); + if (r_top_thread_message_id.is_error()) { + return Status::Error("Wrong message thread ID"); + } + top_thread_message_id = r_top_thread_message_id.ok(); + if (!ServerMessageId(top_thread_message_id).is_valid()) { + return Status::Error("Invalid message thread ID"); + } + } + auto r_comment_message_id = to_integer_safe(comment_message_id_slice); if (r_comment_message_id.is_error() || !(r_comment_message_id.ok() == 0 || ServerMessageId(r_comment_message_id.ok()).is_valid())) { @@ -1912,6 +1933,7 @@ Result LinkManager::get_message_link_info(Slice url) { info.channel_id = channel_id; info.message_id = MessageId(ServerMessageId(r_message_id.ok())); info.comment_message_id = MessageId(ServerMessageId(r_comment_message_id.ok())); + info.top_thread_message_id = MessageId(ServerMessageId(top_thread_message_id)); info.media_timestamp = is_media_timestamp_invalid ? 0 : media_timestamp; info.is_single = is_single; info.for_comment = for_comment; diff --git a/td/telegram/MessageLinkInfo.h b/td/telegram/MessageLinkInfo.h index dd4e30ae3..351923ace 100644 --- a/td/telegram/MessageLinkInfo.h +++ b/td/telegram/MessageLinkInfo.h @@ -23,6 +23,8 @@ struct MessageLinkInfo { bool is_single = false; int32 media_timestamp = 0; + MessageId top_thread_message_id; + DialogId comment_dialog_id; MessageId comment_message_id; bool for_comment = false; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 5806da4a6..1aac20086 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -19513,32 +19513,45 @@ td_api::object_ptr MessagesManager::get_message_link_in DialogId dialog_id = info.comment_dialog_id.is_valid() ? info.comment_dialog_id : (is_public ? resolve_dialog_username(info.username) : DialogId(info.channel_id)); + MessageId top_thread_message_id; MessageId message_id = info.comment_dialog_id.is_valid() ? info.comment_message_id : info.message_id; td_api::object_ptr message; int32 media_timestamp = 0; bool for_album = false; - bool for_comment = false; const Dialog *d = get_dialog(dialog_id); if (d == nullptr) { dialog_id = DialogId(); + top_thread_message_id = MessageId(); } else { const Message *m = get_message(d, message_id); if (m != nullptr) { message = get_message_object(dialog_id, m, "get_message_link_info_object"); for_album = !info.is_single && m->media_album_id != 0; - for_comment = (info.comment_dialog_id.is_valid() || info.for_comment) && m->top_thread_message_id.is_valid(); + if (info.comment_dialog_id.is_valid() || info.for_comment || m->is_topic_message) { + top_thread_message_id = m->top_thread_message_id; + } else { + top_thread_message_id = MessageId(); + } if (can_message_content_have_media_timestamp(m->content.get())) { auto duration = get_message_content_media_duration(m->content.get(), td_); if (duration == 0 || info.media_timestamp <= duration) { media_timestamp = info.media_timestamp; } } + if (m->content->get_type() == MessageContentType::TopicCreate && m->top_thread_message_id.is_valid()) { + message = nullptr; + CHECK(!for_album); + CHECK(media_timestamp == 0); + } + } else if (!info.comment_dialog_id.is_valid() && dialog_id.get_type() == DialogType::Channel && + !is_broadcast_channel(dialog_id)) { + top_thread_message_id = info.top_thread_message_id; } } - return td_api::make_object(is_public, dialog_id.get(), std::move(message), media_timestamp, - for_album, for_comment); + return td_api::make_object(is_public, dialog_id.get(), top_thread_message_id.get(), + std::move(message), media_timestamp, for_album); } InputDialogId MessagesManager::get_input_dialog_id(DialogId dialog_id) const {