From c3fe3f97eca674a6afeb8da79c4696f30d3eb6c3 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 21 Feb 2018 00:20:45 +0300 Subject: [PATCH] Accept formattedText in getWebPageInstantView. GitOrigin-RevId: b9f2345eb170da6cbdbb6c70abf11fa682630802 --- CMakeLists.txt | 2 +- README.md | 2 +- example/cpp/CMakeLists.txt | 2 +- td/generate/scheme/td_api.tl | 5 +- td/generate/scheme/td_api.tlo | Bin 111128 -> 111120 bytes td/telegram/MessagesManager.cpp | 2 +- td/telegram/Td.cpp | 17 ++--- td/telegram/Td.h | 2 +- td/telegram/WebPagesManager.cpp | 128 ++++++++++++++++++++------------ td/telegram/WebPagesManager.h | 19 +++-- td/telegram/cli.cpp | 6 +- 11 files changed, 109 insertions(+), 76 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34d0d6acc..1352b36d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) -project(TDLib VERSION 1.1.2 LANGUAGES CXX C) +project(TDLib VERSION 1.1.3 LANGUAGES CXX C) option(TD_ENABLE_JNI "Use \"ON\" to enable JNI-compatible TDLib API.") diff --git a/README.md b/README.md index 327caac61..b7e7efa6b 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic) Or you could install `TDLib` and then reference it in your CMakeLists.txt like this: ``` -find_package(Td 1.1.2 REQUIRED) +find_package(Td 1.1.3 REQUIRED) target_link_libraries(YourTarget PRIVATE Td::TdStatic) ``` See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt). diff --git a/example/cpp/CMakeLists.txt b/example/cpp/CMakeLists.txt index 3af049efa..36aff073a 100644 --- a/example/cpp/CMakeLists.txt +++ b/example/cpp/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) project(TdExample VERSION 1.0 LANGUAGES CXX) -find_package(Td 1.1.2 REQUIRED) +find_package(Td 1.1.3 REQUIRED) add_executable(tdjson_example tdjson_example.cpp) target_link_libraries(tdjson_example PRIVATE Td::TdJson) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index d242063ca..b45920f2e 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2302,6 +2302,7 @@ viewMessages chat_id:int53 message_ids:vector force_read:Bool = Ok; //@description This method should be called if the message content has been opened (e.g., the user has opened a photo, video, document, location or venue, or has listened to an audio file or voice note message). An updateMessageContentOpened update will be generated if something has changed @chat_id Chat identifier of the message @message_id Identifier of the message with the opened content openMessageContent chat_id:int53 message_id:int53 = Ok; + //@description Marks all mentions in a chat as read @chat_id Chat identifier readAllChatMentions chat_id:int53 = Ok; @@ -2545,8 +2546,8 @@ searchHashtags prefix:string limit:int32 = Hashtags; removeRecentHashtag hashtag:string = Ok; -//@description Returns a web page preview by the text of the message. Do not call this function too often. Returns a 404 error if the web page has no preview @message_text Message text -getWebPagePreview message_text:string = WebPage; +//@description Returns a web page preview by the text of the message. Do not call this function too often. Returns a 404 error if the web page has no preview @text Message text with formatting +getWebPagePreview text:formattedText = WebPage; //@description Returns an instant view version of a web page if available. Returns a 404 error if the web page has no instant view page @url The web page URL @force_full If true, the full instant view for the web page will be returned getWebPageInstantView url:string force_full:Bool = WebPageInstantView; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 346065843d6c60e7101d73ecf72ab86ccac152fa..e32f2a9270c831ba8f1f3b318aae7504539436ed 100644 GIT binary patch delta 39 vcmbR7gl)nTwuUW?2^B0lYiS9Gx@>-j_q427*i|(EY=S5 delta 41 xcmbR6gl)zXwuUW?2^B1Vvd{ZXPpM#3;pE9pEiO(>PmQ0Pctv^pnhM4gO8{{#5a$2@ diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 96ef9da2b..1d412c704 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -16278,7 +16278,7 @@ bool MessagesManager::can_edit_message(DialogId dialog_id, const Message *m, boo auto channel_id = dialog_id.get_channel_id(); auto channel_status = td_->contacts_manager_->get_channel_status(channel_id); if (m->is_channel_post) { - if (!channel_status.can_edit_messages() && (!channel_status.can_post_messages() || !m->is_outgoing)) { + if (!channel_status.can_edit_messages() && !(channel_status.can_post_messages() && m->is_outgoing)) { return false; } } else { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 4a030282d..c733328a2 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1727,22 +1727,22 @@ class ReadAllChatMentionsRequest : public RequestOnceActor { } }; -class GetWebPagePreviewRequest : public RequestActor<> { - string message_text_; +class GetWebPagePreviewRequest : public RequestOnceActor { + td_api::object_ptr text_; - WebPageId web_page_id_; + int64 request_id_ = 0; void do_run(Promise &&promise) override { - web_page_id_ = td->web_pages_manager_->get_web_page_preview(message_text_, std::move(promise)); + request_id_ = td->web_pages_manager_->get_web_page_preview(std::move(text_), std::move(promise)); } void do_send_result() override { - send_result(td->web_pages_manager_->get_web_page_object(web_page_id_)); + send_result(td->web_pages_manager_->get_web_page_preview_result(request_id_)); } public: - GetWebPagePreviewRequest(ActorShared td, uint64 request_id, string message_text) - : RequestActor(std::move(td), request_id), message_text_(std::move(message_text)) { + GetWebPagePreviewRequest(ActorShared td, uint64 request_id, td_api::object_ptr text) + : RequestOnceActor(std::move(td), request_id), text_(std::move(text)) { } }; @@ -5531,8 +5531,7 @@ void Td::on_request(uint64 id, const td_api::forwardMessages &request) { void Td::on_request(uint64 id, td_api::getWebPagePreview &request) { CHECK_AUTH(); CHECK_IS_USER(); - CLEAN_INPUT_STRING(request.message_text_); - CREATE_REQUEST(GetWebPagePreviewRequest, std::move(request.message_text_)); + CREATE_REQUEST(GetWebPagePreviewRequest, std::move(request.text_)); } void Td::on_request(uint64 id, td_api::getWebPageInstantView &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 7985c3a65..c56974e9d 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -192,7 +192,7 @@ class Td final : public NetQueryCallback { static td_api::object_ptr static_request(td_api::object_ptr function); private: - static constexpr const char *tdlib_version = "1.1.2"; + static constexpr const char *tdlib_version = "1.1.3"; static constexpr int64 ONLINE_ALARM_ID = 0; static constexpr int32 ONLINE_TIMEOUT = 240; static constexpr int64 PING_SERVER_ALARM_ID = -1; diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index 5d0182ea9..4e0157e36 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -51,16 +51,25 @@ namespace td { class GetWebPagePreviewQuery : public Td::ResultHandler { Promise promise_; - string message_text_; + int64 request_id_; + string url_; public: explicit GetWebPagePreviewQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(const string &message_text) { - message_text_ = message_text; + void send(const string &text, vector> &&entities, int64 request_id, + string url) { + request_id_ = request_id; + url_ = std::move(url); + + int32 flags = 0; + if (!entities.empty()) { + flags |= telegram_api::messages_getWebPagePreview::ENTITIES_MASK; + } + send_query(G()->net_query_creator().create( - create_storer(telegram_api::messages_getWebPagePreview(0, message_text, Auto())))); + create_storer(telegram_api::messages_getWebPagePreview(flags, text, std::move(entities))))); } void on_result(uint64 id, BufferSlice packet) override { @@ -71,11 +80,11 @@ class GetWebPagePreviewQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for GetWebPagePreviewQuery " << to_string(ptr); - td->web_pages_manager_->on_get_web_page_preview_success(message_text_, std::move(ptr), std::move(promise_)); + td->web_pages_manager_->on_get_web_page_preview_success(request_id_, url_, std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { - td->web_pages_manager_->on_get_web_page_preview_fail(message_text_, std::move(status), std::move(promise_)); + td->web_pages_manager_->on_get_web_page_preview_fail(request_id_, url_, std::move(status), std::move(promise_)); } }; @@ -1619,19 +1628,19 @@ void WebPagesManager::wait_for_pending_web_page(DialogId dialog_id, MessageId me pending_web_pages_timeout_.add_timeout_in(web_page_id.get(), 1.0); } -void WebPagesManager::on_get_web_page_preview_success(const string &message_text, +void WebPagesManager::on_get_web_page_preview_success(int64 request_id, const string &url, tl_object_ptr &&message_media_ptr, Promise &&promise) { CHECK(message_media_ptr != nullptr); int32 constructor_id = message_media_ptr->get_id(); if (constructor_id != telegram_api::messageMediaWebPage::ID) { if (constructor_id == telegram_api::messageMediaEmpty::ID) { - on_get_web_page_preview_success(message_text, WebPageId(), std::move(promise)); + on_get_web_page_preview_success(request_id, url, WebPageId(), std::move(promise)); return; } LOG(ERROR) << "Receive " << to_string(message_media_ptr) << " instead of web page"; - on_get_web_page_preview_fail(message_text, Status::Error(500, "Receive not web page in GetWebPagePreview"), + on_get_web_page_preview_fail(request_id, url, Status::Error(500, "Receive not web page in GetWebPagePreview"), std::move(promise)); return; } @@ -1641,65 +1650,86 @@ void WebPagesManager::on_get_web_page_preview_success(const string &message_text auto web_page_id = on_get_web_page(std::move(message_media_web_page->webpage_), DialogId()); if (web_page_id.is_valid() && !have_web_page(web_page_id)) { - pending_get_web_pages_[web_page_id].emplace(message_text, std::move(promise)); // TODO MultiPromise ? + pending_get_web_pages_[web_page_id].emplace(request_id, + std::make_pair(url, std::move(promise))); // TODO MultiPromise ? pending_web_pages_timeout_.add_timeout_in(web_page_id.get(), 1.0); return; } - on_get_web_page_preview_success(message_text, web_page_id, std::move(promise)); + on_get_web_page_preview_success(request_id, url, web_page_id, std::move(promise)); } -void WebPagesManager::on_get_web_page_preview_success(const string &message_text, WebPageId web_page_id, +void WebPagesManager::on_get_web_page_preview_success(int64 request_id, const string &url, WebPageId web_page_id, Promise &&promise) { CHECK(web_page_id == WebPageId() || have_web_page(web_page_id)); - CHECK(got_web_page_previews_.find(message_text) == got_web_page_previews_.end()); - got_web_page_previews_[message_text] = web_page_id; + CHECK(got_web_page_previews_.find(request_id) == got_web_page_previews_.end()); + got_web_page_previews_[request_id] = web_page_id; - auto erased_count = running_get_web_page_previews_.erase(message_text); - CHECK(erased_count > 0); + if (web_page_id.is_valid() && !url.empty()) { + on_get_web_page_by_url(url, web_page_id, true); + } promise.set_value(Unit()); } -void WebPagesManager::on_get_web_page_preview_fail(const string &message_text, Status error, Promise &&promise) { - LOG(INFO) << "Clean up getting of web page preview"; - auto erased_count = running_get_web_page_previews_.erase(message_text); - CHECK(erased_count > 0); - +void WebPagesManager::on_get_web_page_preview_fail(int64 request_id, const string &url, Status error, + Promise &&promise) { + LOG(INFO) << "Clean up getting of web page preview with url \"" << url << '"'; CHECK(error.is_error()); promise.set_error(std::move(error)); } -WebPageId WebPagesManager::get_web_page_preview(const string &message_text, Promise &&promise) { - LOG(INFO) << "Trying to get web page preview for message \"" << message_text << '"'; - - auto it = got_web_page_previews_.find(message_text); - if (it != got_web_page_previews_.end()) { - auto web_page_id = it->second; - - if (web_page_id.is_valid()) { - auto entities = find_entities(message_text, true, true); - auto url = get_first_url(message_text, entities); - if (!url.empty()) { - on_get_web_page_by_url(url, web_page_id, true); - } - } - - got_web_page_previews_.erase(it); - +int64 WebPagesManager::get_web_page_preview(td_api::object_ptr &&text, Promise &&promise) { + if (text == nullptr) { promise.set_value(Unit()); - return web_page_id; + return 0; } - if (!running_get_web_page_previews_.insert(message_text).second) { - // TODO MultiPromise - promise.set_error(Status::Error(3, "Request with the same text is already running")); - return WebPageId(); + auto r_entities = get_message_entities(td_->contacts_manager_.get(), text->entities_); + if (r_entities.is_error()) { + promise.set_error(r_entities.move_as_error()); + return 0; + } + auto entities = r_entities.move_as_ok(); + + auto result = fix_formatted_text(text->text_, entities, true, false, true, false); + if (text->text_.empty()) { + promise.set_value(Unit()); + return 0; } - td_->create_handler(std::move(promise))->send(message_text); - return WebPageId(); + auto url = get_first_url(text->text_, entities); + if (url.empty()) { + promise.set_value(Unit()); + return 0; + } + + LOG(INFO) << "Trying to get web page preview for message \"" << text->text_ << '"'; + int64 request_id = get_web_page_preview_request_id_++; + + auto web_page_id = get_web_page_by_url(url); + if (web_page_id.is_valid()) { + got_web_page_previews_[request_id] = web_page_id; + promise.set_value(Unit()); + } else { + td_->create_handler(std::move(promise)) + ->send(text->text_, get_input_message_entities(td_->contacts_manager_.get(), entities), request_id, + std::move(url)); + } + return request_id; +} + +tl_object_ptr WebPagesManager::get_web_page_preview_result(int64 request_id) { + if (request_id == 0) { + return nullptr; + } + + auto it = got_web_page_previews_.find(request_id); + CHECK(it != got_web_page_previews_.end()); + auto web_page_id = it->second; + got_web_page_previews_.erase(it); + return get_web_page_object(web_page_id); } WebPageId WebPagesManager::get_web_page_instant_view(const string &url, bool force_full, Promise &&promise) { @@ -2077,8 +2107,8 @@ void WebPagesManager::update_messages_content(WebPageId web_page_id, bool have_w auto requests = std::move(get_it->second); pending_get_web_pages_.erase(get_it); for (auto &request : requests) { - on_get_web_page_preview_success(request.first, have_web_page ? web_page_id : WebPageId(), - std::move(request.second)); + on_get_web_page_preview_success(request.first, request.second.first, have_web_page ? web_page_id : WebPageId(), + std::move(request.second.second)); } } pending_web_pages_timeout_.cancel_timeout(web_page_id.get()); @@ -2139,8 +2169,8 @@ void WebPagesManager::on_pending_web_page_timeout(WebPageId web_page_id) { auto requests = std::move(get_it->second); pending_get_web_pages_.erase(get_it); for (auto &request : requests) { - on_get_web_page_preview_fail(request.first, Status::Error(500, "Request timeout exceeded"), - std::move(request.second)); + on_get_web_page_preview_fail(request.first, request.second.first, Status::Error(500, "Request timeout exceeded"), + std::move(request.second.second)); count++; } } diff --git a/td/telegram/WebPagesManager.h b/td/telegram/WebPagesManager.h index 02f4898b9..7c491a8f7 100644 --- a/td/telegram/WebPagesManager.h +++ b/td/telegram/WebPagesManager.h @@ -26,6 +26,7 @@ #include #include +#include namespace td { @@ -55,7 +56,9 @@ class WebPagesManager : public Actor { tl_object_ptr get_web_page_instant_view_object(WebPageId web_page_id) const; - WebPageId get_web_page_preview(const string &message_text, Promise &&promise); + int64 get_web_page_preview(td_api::object_ptr &&text, Promise &&promise); + + tl_object_ptr get_web_page_preview_result(int64 request_id); WebPageId get_web_page_instant_view(const string &url, bool force_full, Promise &&promise); @@ -63,11 +66,11 @@ class WebPagesManager : public Actor { WebPageId get_web_page_by_url(const string &url, Promise &&promise); - void on_get_web_page_preview_success(const string &message_text, + void on_get_web_page_preview_success(int64 request_id, const string &url, tl_object_ptr &&message_media_ptr, Promise &&promise); - void on_get_web_page_preview_fail(const string &message_text, Status error, Promise &&promise); + void on_get_web_page_preview_fail(int64 request_id, const string &url, Status error, Promise &&promise); SecretInputMedia get_secret_input_media(WebPageId web_page_id) const; @@ -152,7 +155,8 @@ class WebPagesManager : public Actor { static void on_pending_web_page_timeout_callback(void *web_pages_manager_ptr, int64 web_page_id); void on_pending_web_page_timeout(WebPageId web_page_id); - void on_get_web_page_preview_success(const string &message_text, WebPageId web_page_id, Promise &&promise); + void on_get_web_page_preview_success(int64 request_id, const string &url, WebPageId web_page_id, + Promise &&promise); static RichText get_rich_text(tl_object_ptr &&rich_text_ptr); @@ -229,10 +233,11 @@ class WebPagesManager : public Actor { std::unordered_map load_web_page_instant_view_queries_; std::unordered_map, WebPageIdHash> pending_web_pages_; - std::unordered_map>, WebPageIdHash> pending_get_web_pages_; + std::unordered_map>>, WebPageIdHash> + pending_get_web_pages_; - std::unordered_map got_web_page_previews_; - std::unordered_set running_get_web_page_previews_; + int64 get_web_page_preview_request_id_ = 1; + std::unordered_map got_web_page_previews_; std::unordered_map url_to_web_page_id_; diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 8dbb181fa..72123040f 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -762,9 +762,7 @@ class CliClient final : public Actor { auto parsed_caption = execute(make_tl_object(caption, make_tl_object())); if (parsed_caption->get_id() == td_api::formattedText::ID) { - auto text = td_api::move_object_as(parsed_caption); - caption = std::move(text->text_); - entities = std::move(text->entities_); + return td_api::move_object_as(parsed_caption); } } return make_tl_object(caption, std::move(entities)); @@ -2702,7 +2700,7 @@ class CliClient final : public Actor { } else if (op == "crfcs") { send_request(make_tl_object()); } else if (op == "gwpp") { - send_request(make_tl_object(args)); + send_request(make_tl_object(as_caption(args))); } else if (op == "gwpiv") { string url; string force_full;