From 2afbf38c33a2dbe3570306a5c4f687f2ef3bb3e5 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 20 Sep 2020 22:07:27 +0300 Subject: [PATCH] Make universal offline getMessageLink method. GitOrigin-RevId: 523db9044cfb2d41076ac98974d4a00f0740e2a6 --- td/generate/scheme/td_api.tl | 15 +-- td/generate/scheme/td_api.tlo | Bin 182208 -> 181992 bytes td/telegram/MessagesManager.cpp | 164 +++++++++----------------------- td/telegram/MessagesManager.h | 5 +- td/telegram/Td.cpp | 69 ++------------ td/telegram/Td.h | 2 - td/telegram/cli.cpp | 10 -- 7 files changed, 60 insertions(+), 205 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 3d924c2d2..e9a9039a0 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2732,8 +2732,8 @@ chatReportReasonUnrelatedLocation = ChatReportReason; chatReportReasonCustom text:string = ChatReportReason; -//@description Contains a public HTTPS link to a message in a supergroup or channel with a username @link Message link @html HTML-code for embedding the message; may be empty if unknown -publicMessageLink link:string html:string = PublicMessageLink; +//@description Contains an HTTPS link to a message in a supergroup or channel @link Message link @is_public True, if the link will work for non-members of the chat +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 @@ -3688,19 +3688,12 @@ 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 supergroups and channels with a username -//@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, 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 +//@description Returns an HTTPS link to a message in a chat. Available only for already sent messages in supergroups and channels. This is an offline request //@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, or from a message thread -getMessageLink chat_id:int53 message_id:int53 for_album:Bool for_comment:Bool = HttpUrl; +getMessageLink chat_id:int53 message_id:int53 for_album:Bool for_comment:Bool = MessageLink; //@description Returns an HTML code for embedding the message. Available only for messages in supergroups and channels with a username //@chat_id Identifier of the chat to which the message belongs diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 8a73cfa618a9ef6ed34d53eca3f364b66a04d615..7e3ea2eb38435881dd8e111a080c611ed0199dca 100644 GIT binary patch delta 159 zcmX@m&;6p8dqabiz%nbZ_1wOx#l?x~sXm!`*^>pBBsMol&ERbIP}%OG!nlW7609T_ zp#;Rgc}&QMX|kY|@^pbBM$XB9ih|>#hq1lqTh5Ci|uq7bm8t`ef#1GcZgRV3KHdP}%OF z!nlWddx-|)4i6cy+5$|qAo1w}8jL#AJ)9V2CO24fuz-ZND-<%$naedit_date >= G()->unix_time() - seconds; } -std::pair MessagesManager::get_public_message_link(FullMessageId full_message_id, bool for_group, - bool for_comment, Promise &&promise) { +Result> MessagesManager::get_message_link(FullMessageId full_message_id, bool for_group, + bool for_comment) { auto dialog_id = full_message_id.get_dialog_id(); auto d = get_dialog_force(dialog_id); if (d == nullptr) { - promise.set_error(Status::Error(400, "Chat not found")); - return {}; + return Status::Error(400, "Chat not found"); } if (!have_input_peer(dialog_id, AccessRights::Read)) { - promise.set_error(Status::Error(400, "Can't access the chat")); - return {}; + return Status::Error(400, "Can't access the chat"); } if (dialog_id.get_type() != DialogType::Channel) { - promise.set_error( - Status::Error(400, "Public message links are available only for messages in supergroups and channel chats")); - return {}; + return Status::Error(400, "Public message links are available only for messages in supergroups and channel chats"); } - auto *m = get_message_force(d, full_message_id.get_message_id(), "get_public_message_link"); + auto *m = get_message_force(d, full_message_id.get_message_id(), "get_message_link"); if (m == nullptr) { - promise.set_error(Status::Error(400, "Message not found")); - return {}; + return Status::Error(400, "Message not found"); } if (m->message_id.is_yet_unsent()) { - promise.set_error(Status::Error(400, "Message is yet unsent")); - return {}; + return Status::Error(400, "Message is yet unsent"); } if (m->message_id.is_scheduled()) { - promise.set_error(Status::Error(400, "Message is scheduled")); - return {}; + return Status::Error(400, "Message is scheduled"); } if (!m->message_id.is_server()) { - promise.set_error(Status::Error(400, "Message is local")); - return {}; + return Status::Error(400, "Message is local"); } if (m->media_album_id == 0) { @@ -16085,14 +16077,17 @@ std::pair MessagesManager::get_public_message_link(FullMessageId if (d->deleted_message_ids.count(m->top_reply_message_id) != 0) { for_comment = false; } - string comment_link; + if (for_comment && is_broadcast_channel(dialog_id)) { + for_comment = false; + } + + td_->create_handler(Promise()) + ->send(dialog_id.get_channel_id(), m->message_id, for_group, true); + + auto t_me = G()->shared_config().get_option_string("t_me_url", "https://t.me/"); if (for_comment) { auto *top_m = get_message_force(d, m->top_reply_message_id, "get_public_message_link"); - if (top_m == nullptr) { - get_message_force_from_server(d, m->top_reply_message_id, std::move(promise)); - return {}; - } - if (!top_m->sender_user_id.is_valid() && top_m->forward_info != nullptr && + if (top_m != nullptr && !top_m->sender_user_id.is_valid() && top_m->forward_info != nullptr && top_m->forward_info->sender_dialog_id.is_valid() && top_m->forward_info->message_id.is_valid() && DialogId(td_->contacts_manager_->get_channel_linked_channel_id(dialog_id.get_channel_id())) == top_m->forward_info->sender_dialog_id) { @@ -16101,104 +16096,27 @@ std::pair MessagesManager::get_public_message_link(FullMessageId auto linked_d = get_dialog(linked_dialog_id); CHECK(linked_d != nullptr); CHECK(linked_dialog_id.get_type() == DialogType::Channel); + auto *linked_m = get_message_force(linked_d, linked_message_id, "get_public_message_link"); auto channel_username = td_->contacts_manager_->get_channel_username(linked_dialog_id.get_channel_id()); - if (linked_message_id.is_server() && have_input_peer(linked_dialog_id, AccessRights::Read) && - !channel_username.empty() && linked_d->deleted_message_ids.count(linked_message_id) == 0) { - auto *linked_m = get_message_force(linked_d, linked_message_id, "get_public_message_link"); - if (linked_m == nullptr) { - get_message_force_from_server(linked_d, linked_message_id, std::move(promise)); - return {}; - } - - comment_link = PSTRING() << G()->shared_config().get_option_string("t_me_url", "https://t.me/") - << channel_username << '/' << linked_message_id.get_server_message_id().get() - << "?comment=" << m->message_id.get_server_message_id().get() - << (for_group ? "" : "&single"); + if (linked_m != nullptr && linked_message_id.is_server() && + have_input_peer(linked_dialog_id, AccessRights::Read) && !channel_username.empty() && + linked_d->deleted_message_ids.count(linked_message_id) == 0) { + return std::make_pair( + PSTRING() << t_me << channel_username << '/' << linked_message_id.get_server_message_id().get() + << "?comment=" << m->message_id.get_server_message_id().get() << (for_group ? "" : "&single"), + true); } } } - if (comment_link.empty() && td_->contacts_manager_->get_channel_username(dialog_id.get_channel_id()).empty()) { - promise.set_error( - Status::Error(400, "Public message links are available only for messages in chats with a username")); - return {}; - } - auto &links = public_message_links_[for_group][dialog_id].links_; - auto it = links.find(m->message_id); - if (it == links.end()) { - td_->create_handler(std::move(promise)) - ->send(dialog_id.get_channel_id(), m->message_id, for_group, false); - return {}; + auto dialog_username = td_->contacts_manager_->get_channel_username(dialog_id.get_channel_id()); + if (m->content->get_type() == MessageContentType::VideoNote && is_broadcast_channel(dialog_id) && + !dialog_username.empty()) { + return std::make_pair( + PSTRING() << "https://telesco.pe/" << dialog_username << '/' << m->message_id.get_server_message_id().get(), + true); } - if (for_comment && comment_link.empty()) { - comment_link = PSTRING() << it->second.first << (it->second.first.find('?') == string::npos ? '?' : '&') - << "thread=" << m->top_reply_message_id.get_server_message_id().get(); - } - - promise.set_value(Unit()); - if (!comment_link.empty()) { - return {std::move(comment_link), it->second.second}; - } else { - return it->second; - } -} - -void MessagesManager::on_get_public_message_link(FullMessageId full_message_id, bool for_group, string url, - string html) { - LOG_IF(ERROR, url.empty() && html.empty()) << "Receive empty public link for " << full_message_id; - public_message_links_[for_group][full_message_id.get_dialog_id()].links_[full_message_id.get_message_id()] = { - std::move(url), std::move(html)}; -} - -string MessagesManager::get_message_link(FullMessageId full_message_id, bool for_group, bool for_comment, - Promise &&promise) { - auto dialog_id = full_message_id.get_dialog_id(); - auto d = get_dialog_force(dialog_id); - if (d == nullptr) { - promise.set_error(Status::Error(400, "Chat not found")); - return {}; - } - if (!have_input_peer(dialog_id, AccessRights::Read)) { - promise.set_error(Status::Error(400, "Can't access the chat")); - return {}; - } - if (dialog_id.get_type() != DialogType::Channel) { - promise.set_error( - Status::Error(400, "Message links are available only for messages in supergroups and channel chats")); - return {}; - } - - auto *m = get_message_force(d, full_message_id.get_message_id(), "get_message_link"); - if (m == nullptr) { - promise.set_error(Status::Error(400, "Message not found")); - return {}; - } - if (m->message_id.is_scheduled()) { - promise.set_error(Status::Error(400, "Message is scheduled")); - return {}; - } - if (!m->message_id.is_server()) { - promise.set_error(Status::Error(400, "Message is local")); - return {}; - } - - if (m->media_album_id == 0) { - for_group = true; // default is true - } - - if (!m->top_reply_message_id.is_valid() || !m->top_reply_message_id.is_server()) { - for_comment = false; - } - if (d->deleted_message_ids.count(m->top_reply_message_id) != 0) { - for_comment = false; - } - - td_->create_handler(Promise()) - ->send(dialog_id.get_channel_id(), m->message_id, for_group, true); - - promise.set_value(Unit()); - string args; if (for_comment) { args = PSTRING() << "?thread=" << m->top_reply_message_id.get_server_message_id().get(); @@ -16208,8 +16126,13 @@ string MessagesManager::get_message_link(FullMessageId full_message_id, bool for args += "single"; } - return PSTRING() << G()->shared_config().get_option_string("t_me_url", "https://t.me/") << "c/" - << dialog_id.get_channel_id().get() << "/" << m->message_id.get_server_message_id().get() << args; + bool is_public = !dialog_username.empty(); + if (!is_public) { + dialog_username = PSTRING() << "c/" << dialog_id.get_channel_id().get(); + } + return std::make_pair(PSTRING() << G()->shared_config().get_option_string("t_me_url", "https://t.me/") + << dialog_username << '/' << m->message_id.get_server_message_id().get() << args, + is_public); } string MessagesManager::get_message_embedding_code(FullMessageId full_message_id, bool for_group, @@ -16265,6 +16188,13 @@ string MessagesManager::get_message_embedding_code(FullMessageId full_message_id return it->second.second; } +void MessagesManager::on_get_public_message_link(FullMessageId full_message_id, bool for_group, string url, + string html) { + LOG_IF(ERROR, url.empty() && html.empty()) << "Receive empty public link for " << full_message_id; + public_message_links_[for_group][full_message_id.get_dialog_id()].links_[full_message_id.get_message_id()] = { + std::move(url), std::move(html)}; +} + Result MessagesManager::get_message_link_info(Slice url) { if (url.empty()) { return Status::Error("URL must be non-empty"); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 9ec22e50b..55d2d0f40 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -586,15 +586,12 @@ class MessagesManager : public Actor { bool is_message_edited_recently(FullMessageId full_message_id, int32 seconds); - std::pair get_public_message_link(FullMessageId full_message_id, bool for_group, bool for_comment, - Promise &&promise); + Result> get_message_link(FullMessageId full_message_id, bool for_group, bool for_comment); string get_message_embedding_code(FullMessageId full_message_id, bool for_group, Promise &&promise); void on_get_public_message_link(FullMessageId full_message_id, bool for_group, string url, string html); - string get_message_link(FullMessageId full_message_id, bool for_group, bool for_comment, Promise &&promise); - struct MessageLinkInfo { string username; // or diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 6e4760d4a..5a45a99e9 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1112,59 +1112,6 @@ class GetMessagesRequest : public RequestOnceActor { } }; -class GetPublicMessageLinkRequest : public RequestActor<> { - FullMessageId full_message_id_; - bool for_group_; - bool for_comment_; - - string link_; - string html_; - - void do_run(Promise &&promise) override { - std::tie(link_, html_) = - td->messages_manager_->get_public_message_link(full_message_id_, for_group_, for_comment_, std::move(promise)); - } - - void do_send_result() override { - send_result(make_tl_object(link_, html_)); - } - - public: - GetPublicMessageLinkRequest(ActorShared td, uint64 request_id, int64 dialog_id, int64 message_id, bool for_group, - bool for_comment) - : RequestActor(std::move(td), request_id) - , full_message_id_(DialogId(dialog_id), MessageId(message_id)) - , for_group_(for_group) - , for_comment_(for_comment) { - set_tries(5); // get top message + get linked channel message + get message HTML + get linked channel message link - } -}; - -class GetMessageLinkRequest : public RequestActor<> { - FullMessageId full_message_id_; - bool for_group_; - bool for_comment_; - - string link_; - - void do_run(Promise &&promise) override { - link_ = td->messages_manager_->get_message_link(full_message_id_, for_group_, for_comment_, std::move(promise)); - } - - void do_send_result() override { - send_result(td_api::make_object(link_)); - } - - public: - GetMessageLinkRequest(ActorShared td, uint64 request_id, int64 dialog_id, int64 message_id, bool for_group, - bool for_comment) - : RequestActor(std::move(td), request_id) - , full_message_id_(DialogId(dialog_id), MessageId(message_id)) - , for_group_(for_group) - , for_comment_(for_comment) { - } -}; - class GetMessageEmbeddingCodeRequest : public RequestActor<> { FullMessageId full_message_id_; bool for_group_; @@ -5159,16 +5106,16 @@ void Td::on_request(uint64 id, const td_api::getMessages &request) { CREATE_REQUEST(GetMessagesRequest, request.chat_id_, request.message_ids_); } -void Td::on_request(uint64 id, const td_api::getPublicMessageLink &request) { - CHECK_IS_USER(); - CREATE_REQUEST(GetPublicMessageLinkRequest, request.chat_id_, request.message_id_, request.for_album_, - request.for_comment_); -} - void Td::on_request(uint64 id, const td_api::getMessageLink &request) { CHECK_IS_USER(); - CREATE_REQUEST(GetMessageLinkRequest, request.chat_id_, request.message_id_, request.for_album_, - request.for_comment_); + auto r_message_link = messages_manager_->get_message_link( + {DialogId(request.chat_id_), MessageId(request.message_id_)}, request.for_album_, request.for_comment_); + if (r_message_link.is_error()) { + send_closure(actor_id(this), &Td::send_error, id, r_message_link.move_as_error()); + } else { + send_closure(actor_id(this), &Td::send_result, id, + td_api::make_object(r_message_link.ok().first, r_message_link.ok().second)); + } } void Td::on_request(uint64 id, const td_api::getMessageEmbeddingCode &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 4986d3be6..c28f54c17 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -496,8 +496,6 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::getMessages &request); - void on_request(uint64 id, const td_api::getPublicMessageLink &request); - void on_request(uint64 id, const td_api::getMessageLink &request); void on_request(uint64 id, const td_api::getMessageEmbeddingCode &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index d38b0fd6e..d8fa528e6 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2613,16 +2613,6 @@ class CliClient final : public Actor { string message_ids; std::tie(chat_id, message_ids) = split(args); send_request(td_api::make_object(as_chat_id(chat_id), as_message_ids(message_ids))); - } else if (op == "gpml") { - string chat_id; - string message_id; - string for_album; - string for_comment; - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(for_album, for_comment) = split(args); - send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), - as_bool(for_album), as_bool(for_comment))); } else if (op == "gmlink") { string chat_id; string message_id;