diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 72d71bb67..7c40dd14e 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2807,16 +2807,11 @@ bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *c } } -WebPageId get_message_content_web_page_id(const MessageContent *content) { - if (content->get_type() == MessageContentType::Text) { - return static_cast(content)->web_page_id; - } - return WebPageId(); -} - -void set_message_content_web_page_id(MessageContent *content, WebPageId web_page_id) { +void remove_message_content_web_page(MessageContent *content) { CHECK(content->get_type() == MessageContentType::Text); - static_cast(content)->web_page_id = web_page_id; + auto &web_page_id = static_cast(content)->web_page_id; + CHECK(web_page_id.is_valid()); + web_page_id = WebPageId(); } void set_message_content_poll_answer(Td *td, const MessageContent *content, FullMessageId full_message_id, @@ -3476,6 +3471,9 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File void register_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id) { switch (content->get_type()) { + case MessageContentType::Text: + return td->web_pages_manager_->register_web_page(static_cast(content)->web_page_id, + full_message_id); case MessageContentType::Poll: return td->poll_manager_->register_poll(static_cast(content)->poll_id, full_message_id); default: @@ -3489,6 +3487,12 @@ void reregister_message_content(Td *td, const MessageContent *old_content, const auto new_content_type = new_content->get_type(); if (old_content_type == new_content_type) { switch (old_content_type) { + case MessageContentType::Text: + if (static_cast(old_content)->web_page_id == + static_cast(new_content)->web_page_id) { + return; + } + break; case MessageContentType::Poll: if (static_cast(old_content)->poll_id == static_cast(new_content)->poll_id) { @@ -3505,6 +3509,9 @@ void reregister_message_content(Td *td, const MessageContent *old_content, const void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id) { switch (content->get_type()) { + case MessageContentType::Text: + return td->web_pages_manager_->unregister_web_page(static_cast(content)->web_page_id, + full_message_id); case MessageContentType::Poll: return td->poll_manager_->unregister_poll(static_cast(content)->poll_id, full_message_id); default: diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index ec46aecf0..2e0879e20 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -186,9 +186,7 @@ bool get_message_content_poll_is_closed(const Td *td, const MessageContent *cont bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *content); -WebPageId get_message_content_web_page_id(const MessageContent *content); - -void set_message_content_web_page_id(MessageContent *content, WebPageId web_page_id); +void remove_message_content_web_page(MessageContent *content); void set_message_content_poll_answer(Td *td, const MessageContent *content, FullMessageId full_message_id, vector &&option_ids, Promise &&promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index de566f3f8..8bcbdea6b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -11888,43 +11888,21 @@ void MessagesManager::on_update_sent_text_message(int64 random_id, } } -void MessagesManager::on_update_message_web_page(FullMessageId full_message_id, bool have_web_page) { - waiting_for_web_page_messages_.erase(full_message_id); +void MessagesManager::delete_pending_message_web_page(FullMessageId full_message_id) { auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog(dialog_id); - if (d == nullptr) { - LOG(INFO) << "Can't find " << dialog_id; - // dialog can be not yet added - return; - } + CHECK(d != nullptr); Message *m = get_message(d, full_message_id.get_message_id()); - if (m == nullptr) { - // message can be already deleted - return; - } - CHECK(m->date > 0); + CHECK(m != nullptr); MessageContent *content = m->content.get(); - auto old_web_page_id = get_message_content_web_page_id(content); - if (!old_web_page_id.is_valid()) { - // webpage has already been received as empty - LOG_IF(ERROR, have_web_page) << "Receive earlier not received web page"; - return; - } - CHECK(content->get_type() == MessageContentType::Text); + unregister_message_content(td_, content, full_message_id); + remove_message_content_web_page(content); + register_message_content(td_, content, full_message_id); - if (!have_web_page) { - unregister_message_content(td_, content, full_message_id); - set_message_content_web_page_id(content, WebPageId()); - register_message_content(td_, content, full_message_id); + // don't need to send an updateMessageContent, because the web page was pending - // don't need to send an update, because the web page was pending - on_message_changed(d, m, false, "on_update_message_web_page"); - return; - } - - send_update_message_content(dialog_id, m->message_id, content, m->date, m->is_content_secret, - "on_update_message_web_page"); + on_message_changed(d, m, false, "delete_pending_message_web_page"); } void MessagesManager::on_get_dialogs(FolderId folder_id, vector> &&dialog_folders, @@ -12324,7 +12302,6 @@ bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) cons CHECK(m->message_id.is_valid()); // don't want to unload messages from opened dialogs // don't want to unload messages to which there are replies in yet unsent messages - // don't want to unload messages with pending web pages // don't want to unload message with active reply markup // don't want to unload pinned message // don't want to unload last edited message, because server can send updateEditChannelMessage again @@ -12334,9 +12311,8 @@ bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) cons return !d->is_opened && m->message_id != d->last_message_id && m->message_id != d->last_database_message_id && !m->message_id.is_yet_unsent() && active_live_location_full_message_ids_.count(full_message_id) == 0 && replied_by_yet_unsent_messages_.count(full_message_id) == 0 && m->edited_content == nullptr && - waiting_for_web_page_messages_.count(full_message_id) == 0 && d->suffix_load_queries_.empty() && - m->message_id != d->reply_markup_message_id && m->message_id != d->pinned_message_id && - m->message_id != d->last_edited_message_id; + d->suffix_load_queries_.empty() && m->message_id != d->reply_markup_message_id && + m->message_id != d->pinned_message_id && m->message_id != d->last_edited_message_id; } void MessagesManager::unload_message(Dialog *d, MessageId message_id) { @@ -17152,12 +17128,6 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId message->from_database = true; auto old_message = get_message(d, message->message_id); - if (old_message == nullptr) { - auto web_page_id = get_message_content_web_page_id(message->content.get()); - if (web_page_id.is_valid()) { - td_->web_pages_manager_->have_web_page_force(web_page_id); - } - } Message *m = old_message ? old_message : add_message_to_dialog(d, std::move(message), false, &need_update, &need_update_dialog_pos, "on_get_history_from_database"); @@ -17463,10 +17433,6 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id continue; } - auto web_page_id = get_message_content_web_page_id(message->content.get()); - if (web_page_id.is_valid()) { - td_->web_pages_manager_->have_web_page_force(web_page_id); - } bool need_update = false; Message *m = add_scheduled_message_to_dialog(d, std::move(message), false, &need_update, "on_get_scheduled_messages_from_database"); @@ -25948,13 +25914,6 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq return nullptr; } - auto web_page_id = get_message_content_web_page_id(message->content.get()); - if (web_page_id.is_valid() && !td_->web_pages_manager_->have_web_page(web_page_id)) { - waiting_for_web_page_messages_.emplace(dialog_id, message_id); - send_closure(G()->web_pages_manager(), &WebPagesManager::wait_for_pending_web_page, - FullMessageId{dialog_id, message_id}, web_page_id); - } - if (*need_update && message_id <= d->last_new_message_id) { *need_update = false; } @@ -26527,13 +26486,6 @@ MessagesManager::Message *MessagesManager::add_scheduled_message_to_dialog(Dialo return nullptr; } - auto web_page_id = get_message_content_web_page_id(message->content.get()); - if (web_page_id.is_valid() && !td_->web_pages_manager_->have_web_page(web_page_id)) { - waiting_for_web_page_messages_.emplace(dialog_id, message_id); - send_closure(G()->web_pages_manager(), &WebPagesManager::wait_for_pending_web_page, - FullMessageId{dialog_id, message_id}, web_page_id); - } - { Message *m = message->from_database ? get_message(d, message_id) : get_message_force(d, message_id, "add_scheduled_message_to_dialog"); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 8ed22e34a..a1750ef43 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -266,7 +266,7 @@ class MessagesManager : public Actor { void on_update_sent_text_message(int64 random_id, tl_object_ptr message_media, vector> &&entities); - void on_update_message_web_page(FullMessageId full_message_id, bool have_web_page); + void delete_pending_message_web_page(FullMessageId full_message_id); void on_get_dialogs(FolderId folder_id, vector> &&dialog_folders, int32 total_count, vector> &&messages, @@ -2626,8 +2626,6 @@ class MessagesManager : public Actor { std::unordered_map replied_by_yet_unsent_messages_; - std::unordered_set waiting_for_web_page_messages_; - struct ActiveDialogAction { UserId user_id; int32 action_id; diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index bc72abc25..30526c840 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -10,6 +10,7 @@ #include "td/telegram/AnimationsManager.h" #include "td/telegram/AudiosManager.h" +#include "td/telegram/AuthManager.h" #include "td/telegram/Document.h" #include "td/telegram/Document.hpp" #include "td/telegram/DocumentsManager.h" @@ -412,20 +413,10 @@ WebPageId WebPagesManager::on_get_web_page(tl_object_ptr web_pages_.erase(web_page_id); } - update_messages_content(web_page_id, false); - if (!G()->parameters().use_message_db) { - // update_messages_content(web_page_id, false); - } else { + on_web_page_changed(web_page_id, false); + if (G()->parameters().use_message_db) { LOG(INFO) << "Delete " << web_page_id << " from database"; - G()->td_db()->get_sqlite_pmc()->erase(get_web_page_database_key(web_page_id), Auto() - /* - PromiseCreator::lambda([web_page_id](Result<> result) { - if (result.is_ok()) { - send_closure(G()->web_pages_manager(), &WebPagesManager::update_messages_content, web_page_id, false); - } - }) - */ - ); + G()->td_db()->get_sqlite_pmc()->erase(get_web_page_database_key(web_page_id), Auto()); G()->td_db()->get_sqlite_pmc()->erase(get_web_page_instant_view_database_key(web_page_id), Auto()); } @@ -555,13 +546,9 @@ void WebPagesManager::update_web_page(unique_ptr web_page, WebPageId we on_get_web_page_by_url(page->url, web_page_id, from_database); - if (!is_changed) { - return; - } + if (is_changed && !from_database) { + on_web_page_changed(web_page_id, true); - update_messages_content(web_page_id, true); - - if (!from_database) { save_web_page(page.get(), web_page_id, from_binlog); } } @@ -663,10 +650,37 @@ void WebPagesManager::on_get_web_page_by_url(const string &url, WebPageId web_pa cached_web_page_id = web_page_id; } -void WebPagesManager::wait_for_pending_web_page(FullMessageId full_message_id, WebPageId web_page_id) { - LOG(INFO) << "Waiting for " << web_page_id << " needed in " << full_message_id; - pending_web_pages_[web_page_id].emplace(full_message_id); - pending_web_pages_timeout_.add_timeout_in(web_page_id.get(), 1.0); +void WebPagesManager::register_web_page(WebPageId web_page_id, FullMessageId full_message_id) { + if (!web_page_id.is_valid()) { + return; + } + + LOG(INFO) << "Register " << web_page_id << " from " << full_message_id; + bool is_inserted = web_page_messages_[web_page_id].insert(full_message_id).second; + CHECK(is_inserted); + + if (!td_->auth_manager_->is_bot() && !have_web_page_force(web_page_id)) { + LOG(INFO) << "Waiting for " << web_page_id << " needed in " << full_message_id; + pending_web_pages_timeout_.add_timeout_in(web_page_id.get(), 1.0); + } +} + +void WebPagesManager::unregister_web_page(WebPageId web_page_id, FullMessageId full_message_id) { + if (!web_page_id.is_valid()) { + return; + } + + LOG(INFO) << "Unregister " << web_page_id << " from " << full_message_id; + auto &message_ids = web_page_messages_[web_page_id]; + auto is_deleted = message_ids.erase(full_message_id); + CHECK(is_deleted); + + if (message_ids.empty()) { + web_page_messages_.erase(web_page_id); + if (pending_get_web_pages_.count(web_page_id) == 0) { + pending_web_pages_timeout_.cancel_timeout(web_page_id.get()); + } + } } void WebPagesManager::on_get_web_page_preview_success(int64 request_id, const string &url, @@ -693,7 +707,6 @@ void WebPagesManager::on_get_web_page_preview_success(int64 request_id, const st if (web_page_id.is_valid() && !have_web_page(web_page_id)) { 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; } @@ -1163,15 +1176,26 @@ tl_object_ptr WebPagesManager::get_web_page_instant_ web_page_instant_view->is_rtl, web_page_instant_view->is_full); } -void WebPagesManager::update_messages_content(WebPageId web_page_id, bool have_web_page) { - LOG(INFO) << "Update messages awaiting " << web_page_id; - auto it = pending_web_pages_.find(web_page_id); - if (it != pending_web_pages_.end()) { - auto full_message_ids = std::move(it->second); - pending_web_pages_.erase(it); +void WebPagesManager::on_web_page_changed(WebPageId web_page_id, bool have_web_page) { + LOG(INFO) << "Updated " << web_page_id; + auto it = web_page_messages_.find(web_page_id); + if (it != web_page_messages_.end()) { + vector full_message_ids; + for (auto full_message_id : it->second) { + full_message_ids.push_back(full_message_id); + } + CHECK(!full_message_ids.empty()); for (auto full_message_id : full_message_ids) { - send_closure_later(G()->messages_manager(), &MessagesManager::on_update_message_web_page, full_message_id, - have_web_page); + if (!have_web_page) { + td_->messages_manager_->delete_pending_message_web_page(full_message_id); + } else { + td_->messages_manager_->on_external_update_message_content(full_message_id); + } + } + if (have_web_page) { + CHECK(web_page_messages_[web_page_id].size() == full_message_ids.size()); + } else { + CHECK(web_page_messages_.count(web_page_id) == 0); } } auto get_it = pending_get_web_pages_.find(web_page_id); @@ -1208,9 +1232,13 @@ void WebPagesManager::on_pending_web_page_timeout_callback(void *web_pages_manag } void WebPagesManager::on_pending_web_page_timeout(WebPageId web_page_id) { + if (have_web_page(web_page_id)) { + return; + } + int32 count = 0; - auto it = pending_web_pages_.find(web_page_id); - if (it != pending_web_pages_.end()) { + auto it = web_page_messages_.find(web_page_id); + if (it != web_page_messages_.end()) { vector full_message_ids; for (auto full_message_id : it->second) { full_message_ids.push_back(full_message_id); @@ -1230,7 +1258,7 @@ void WebPagesManager::on_pending_web_page_timeout(WebPageId web_page_id) { } } if (count == 0) { - LOG(WARNING) << "Have no messages waiting for " << web_page_id; + LOG(WARNING) << "Have no messages and requests waiting for " << web_page_id; } } diff --git a/td/telegram/WebPagesManager.h b/td/telegram/WebPagesManager.h index 05d2680a9..6ee613f24 100644 --- a/td/telegram/WebPagesManager.h +++ b/td/telegram/WebPagesManager.h @@ -13,7 +13,7 @@ #include "td/telegram/files/FileId.h" #include "td/telegram/files/FileSourceId.h" #include "td/telegram/FullMessageId.h" -#include "td/telegram/Photo.h" +#include "td/telegram/SecretInputMedia.h" #include "td/telegram/WebPageId.h" #include "td/actor/actor.h" @@ -47,7 +47,9 @@ class WebPagesManager : public Actor { void on_get_web_page_by_url(const string &url, WebPageId web_page_id, bool from_database); - void wait_for_pending_web_page(FullMessageId full_message_id, WebPageId web_page_id); + void register_web_page(WebPageId web_page_id, FullMessageId full_message_id); + + void unregister_web_page(WebPageId web_page_id, FullMessageId full_message_id); bool have_web_page(WebPageId web_page_id) const; @@ -111,7 +113,7 @@ class WebPagesManager : public Actor { static bool need_use_old_instant_view(const WebPageInstantView &new_instant_view, const WebPageInstantView &old_instant_view); - void update_messages_content(WebPageId web_page_id, bool have_web_page); + void on_web_page_changed(WebPageId web_page_id, bool have_web_page); const WebPage *get_web_page(WebPageId web_page_id) const; @@ -181,7 +183,8 @@ class WebPagesManager : public Actor { }; std::unordered_map load_web_page_instant_view_queries_; - std::unordered_map, WebPageIdHash> pending_web_pages_; + std::unordered_map, WebPageIdHash> web_page_messages_; + std::unordered_map>>, WebPageIdHash> pending_get_web_pages_;