Support links to comments in getMessageLinkInfo.

GitOrigin-RevId: 5f52a6bbf183c01423724bc540af52f39463d2fe
This commit is contained in:
levlam 2020-09-18 04:14:59 +03:00
parent 153521be4f
commit 8405b08f0a
4 changed files with 104 additions and 9 deletions

View File

@ -2738,7 +2738,8 @@ publicMessageLink link:string html:string = PublicMessageLink;
//@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;
//@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 for_album:Bool for_comment:Bool = MessageLinkInfo;
//@description Contains a part of a file @data File bytes
@ -3686,14 +3687,14 @@ removeNotificationGroup notification_group_id:int32 max_notification_id:int32 =
//@chat_id Identifier of the chat to which the message belongs
//@message_id Identifier of the message
//@for_album Pass true to create a link for the whole media album
//@for_comment Pass true to create a link to the message as a channel post comment. The channel or the discussion supergroup must have a username
//@for_comment Pass true to create a link to the message as a channel post comment, or from a message thread. The channel or the discussion supergroup must have a username
getPublicMessageLink chat_id:int53 message_id:int53 for_album:Bool for_comment:Bool = PublicMessageLink;
//@description Returns a private HTTPS link to a message in a chat. Available only for already sent messages in supergroups and channels. The link will work only for members of the chat
//@chat_id Identifier of the chat to which the message belongs
//@message_id Identifier of the message
//@for_album Pass true to create a link for the whole media album
//@for_comment Pass true to create a link to the message as a channel post comment
//@for_comment Pass true to create a link to the message as a channel post comment, or from a message thread
getMessageLink chat_id:int53 message_id:int53 for_album:Bool for_comment:Bool = 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?..."

Binary file not shown.

View File

@ -15999,7 +15999,9 @@ Result<MessagesManager::MessageLinkInfo> MessagesManager::get_message_link_info(
Slice username;
Slice channel_id_slice;
Slice message_id_slice;
Slice comment_message_id_slice = "0";
bool is_single = false;
bool for_comment = false;
if (begins_with(url, "tg:")) {
url = url.substr(3);
if (begins_with(url, "//")) {
@ -16048,6 +16050,12 @@ Result<MessagesManager::MessageLinkInfo> MessagesManager::get_message_link_info(
if (key_value.first == "single") {
is_single = true;
}
if (key_value.first == "comment") {
comment_message_id_slice = key_value.second;
}
if (key_value.first == "thread") {
for_comment = true;
}
}
} else {
if (begins_with(url, "http://") || begins_with(url, "https://")) {
@ -16088,7 +16096,21 @@ Result<MessagesManager::MessageLinkInfo> MessagesManager::get_message_link_info(
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";
if (query_pos != Slice::npos) {
auto args = full_split(url.substr(query_pos + 1), '&');
for (auto arg : args) {
auto key_value = split(arg, '=');
if (key_value.first == "single") {
is_single = true;
}
if (key_value.first == "comment") {
comment_message_id_slice = key_value.second;
}
if (key_value.first == "thread") {
for_comment = true;
}
}
}
break;
}
}
@ -16108,11 +16130,19 @@ Result<MessagesManager::MessageLinkInfo> MessagesManager::get_message_link_info(
return Status::Error("Wrong message ID");
}
auto r_comment_message_id = to_integer_safe<int32>(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())) {
return Status::Error("Wrong comment message ID");
}
MessageLinkInfo info;
info.username = username.str();
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.is_single = is_single;
info.for_comment = for_comment;
LOG(INFO) << "Have link to " << info.message_id << " in chat @" << info.username << "/" << channel_id.get();
return std::move(info);
}
@ -16167,10 +16197,59 @@ void MessagesManager::on_get_message_link_dialog(MessageLinkInfo &&info, Promise
return promise.set_error(Status::Error(500, "Chat not found"));
}
get_message_force_from_server(d, info.message_id,
PromiseCreator::lambda([actor_id = actor_id(this), info = std::move(info), dialog_id,
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_message, std::move(info),
dialog_id, std::move(promise));
}));
}
void MessagesManager::on_get_message_link_message(MessageLinkInfo &&info, DialogId dialog_id,
Promise<MessageLinkInfo> &&promise) {
Message *m = get_message_force({dialog_id, info.message_id}, "on_get_message_link_message");
if (info.comment_message_id == MessageId() || m == nullptr || !is_broadcast_channel(dialog_id) ||
!m->reply_info.is_comment || !is_active_message_reply_info(dialog_id, m->reply_info)) {
return promise.set_value(std::move(info));
}
if (td_->contacts_manager_->have_channel_force(m->reply_info.channel_id)) {
force_create_dialog(DialogId(m->reply_info.channel_id), "on_get_message_link_message");
on_get_message_link_discussion_message(std::move(info), DialogId(m->reply_info.channel_id), std::move(promise));
return;
}
auto query_promise =
PromiseCreator::lambda([actor_id = actor_id(this), info = std::move(info),
promise = std::move(promise)](Result<vector<FullMessageId>> result) mutable {
if (result.is_error() || result.ok().empty()) {
return promise.set_value(std::move(info));
}
send_closure(actor_id, &MessagesManager::on_get_message_link_discussion_message, std::move(info),
result.ok()[0].get_dialog_id(), std::move(promise));
});
td_->create_handler<GetDiscussionMessageQuery>(std::move(query_promise))
->send(dialog_id, info.message_id, m->reply_info.channel_id);
}
void MessagesManager::on_get_message_link_discussion_message(MessageLinkInfo &&info, DialogId comment_dialog_id,
Promise<MessageLinkInfo> &&promise) {
CHECK(comment_dialog_id.is_valid());
info.comment_dialog_id = comment_dialog_id;
Dialog *d = get_dialog_force(comment_dialog_id);
if (d == nullptr) {
return promise.set_error(Status::Error(500, "Chat not found"));
}
get_message_force_from_server(
d, info.message_id,
d, info.comment_message_id,
PromiseCreator::lambda([info = std::move(info), promise = std::move(promise)](Result<Unit> &&result) mutable {
promise.set_value(std::move(info));
return promise.set_value(std::move(info));
}));
}
@ -16179,22 +16258,28 @@ td_api::object_ptr<td_api::messageLinkInfo> MessagesManager::get_message_link_in
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);
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 message_id = info.comment_dialog_id.is_valid() ? info.comment_message_id : info.message_id;
td_api::object_ptr<td_api::message> message;
bool for_album = false;
bool for_comment = false;
const Dialog *d = get_dialog(dialog_id);
if (d == nullptr) {
dialog_id = DialogId();
} else {
const Message *m = get_message(d, info.message_id);
const Message *m = get_message(d, message_id);
if (m != nullptr) {
message = get_message_object(dialog_id, m);
for_album = !info.is_single && m->media_album_id != 0;
for_comment = (info.comment_dialog_id.is_valid() || info.for_comment) && m->top_reply_message_id.is_valid();
}
}
return td_api::make_object<td_api::messageLinkInfo>(is_public, dialog_id.get(), std::move(message), for_album);
return td_api::make_object<td_api::messageLinkInfo>(is_public, dialog_id.get(), std::move(message), for_album,
for_comment);
}
InputDialogId MessagesManager::get_input_dialog_id(DialogId dialog_id) const {

View File

@ -588,6 +588,10 @@ class MessagesManager : public Actor {
MessageId message_id;
bool is_single = false;
DialogId comment_dialog_id;
MessageId comment_message_id;
bool for_comment = false;
};
void get_message_link_info(Slice url, Promise<MessageLinkInfo> &&promise);
@ -2530,6 +2534,11 @@ class MessagesManager : public Actor {
void on_get_message_link_dialog(MessageLinkInfo &&info, Promise<MessageLinkInfo> &&promise);
void on_get_message_link_message(MessageLinkInfo &&info, DialogId dialog_id, Promise<MessageLinkInfo> &&promise);
void on_get_message_link_discussion_message(MessageLinkInfo &&info, DialogId comment_dialog_id,
Promise<MessageLinkInfo> &&promise);
static MessageId get_first_database_message_id_by_index(const Dialog *d, MessageSearchFilter filter);
void on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id,