Register quick reply message web pages.

This commit is contained in:
levlam 2024-06-17 23:13:11 +03:00
parent 9a059f073c
commit 6dc9a25622
5 changed files with 188 additions and 50 deletions

View File

@ -5614,10 +5614,32 @@ void unregister_reply_message_content(Td *td, const MessageContent *content) {
void register_quick_reply_message_content(Td *td, const MessageContent *content,
QuickReplyMessageFullId message_full_id, const char *source) {
switch (content->get_type()) {
case MessageContentType::Text: {
auto text = static_cast<const MessageText *>(content);
if (text->web_page_id.is_valid()) {
td->web_pages_manager_->register_quick_reply_web_page(text->web_page_id, message_full_id, source);
}
return;
}
default:
return;
}
}
void unregister_quick_reply_message_content(Td *td, const MessageContent *content,
QuickReplyMessageFullId message_full_id, const char *source) {
switch (content->get_type()) {
case MessageContentType::Text: {
auto text = static_cast<const MessageText *>(content);
if (text->web_page_id.is_valid()) {
td->web_pages_manager_->unregister_quick_reply_web_page(text->web_page_id, message_full_id, source);
}
return;
}
default:
return;
}
}
template <class ToT, class FromT>

View File

@ -1646,6 +1646,34 @@ void QuickReplyManager::update_quick_reply_message(QuickReplyShortcutId shortcut
change_message_files({shortcut_id, old_message->message_id}, old_message.get(), old_file_ids);
}
void QuickReplyManager::on_external_update_message_content(QuickReplyMessageFullId message_full_id, const char *source,
bool expect_no_message) {
const auto *s = get_shortcut(message_full_id.get_quick_reply_shortcut_id());
auto message_id = message_full_id.get_message_id();
const auto *m = get_message(s, message_id);
if (expect_no_message && m == nullptr) {
return;
}
CHECK(m != nullptr);
if (s->messages_[0]->message_id == message_id) {
send_update_quick_reply_shortcut(s, "on_external_update_message_content");
}
send_update_quick_reply_shortcut_messages(s, "on_external_update_message_content");
// must not call save_quick_reply_shortcuts, because the message itself wasn't changed
}
void QuickReplyManager::delete_pending_message_web_page(QuickReplyMessageFullId message_full_id) {
auto *m = get_message_editable(message_full_id);
CHECK(has_message_content_web_page(m->content.get()));
unregister_message_content(m, "delete_pending_message_web_page");
remove_message_content_web_page(m->content.get());
register_message_content(m, "delete_pending_message_web_page");
// don't need to send updates, because the web page was pending
save_quick_reply_shortcuts();
}
void QuickReplyManager::delete_quick_reply_messages_from_updates(QuickReplyShortcutId shortcut_id,
const vector<MessageId> &message_ids) {
if (td_->auth_manager_->is_bot()) {

View File

@ -53,6 +53,11 @@ class QuickReplyManager final : public Actor {
void update_quick_reply_message(telegram_api::object_ptr<telegram_api::Message> &&message_ptr);
void delete_pending_message_web_page(QuickReplyMessageFullId message_full_id);
void on_external_update_message_content(QuickReplyMessageFullId message_full_id, const char *source,
bool expect_no_message = false);
void delete_quick_reply_messages_from_updates(QuickReplyShortcutId shortcut_id, const vector<MessageId> &message_ids);
void get_quick_reply_shortcut_messages(QuickReplyShortcutId shortcut_id, Promise<Unit> &&promise);

View File

@ -26,6 +26,7 @@
#include "td/telegram/MessagesManager.h"
#include "td/telegram/Photo.h"
#include "td/telegram/PhotoFormat.h"
#include "td/telegram/QuickReplyManager.h"
#include "td/telegram/StickerFormat.h"
#include "td/telegram/StickersManager.h"
#include "td/telegram/StickersManager.hpp"
@ -468,7 +469,8 @@ void WebPagesManager::tear_down() {
WebPagesManager::~WebPagesManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), web_pages_, web_page_messages_,
url_to_web_page_id_, url_to_file_source_id_);
web_page_quick_reply_messages_, url_to_web_page_id_,
url_to_file_source_id_);
}
string WebPagesManager::get_web_page_url(const tl_object_ptr<telegram_api::WebPage> &web_page_ptr) {
@ -879,11 +881,38 @@ void WebPagesManager::unregister_web_page(WebPageId web_page_id, MessageFullId m
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());
} else {
LOG(INFO) << "Still waiting for " << web_page_id;
}
}
}
void WebPagesManager::register_quick_reply_web_page(WebPageId web_page_id, QuickReplyMessageFullId message_full_id,
const char *source) {
if (!web_page_id.is_valid()) {
return;
}
LOG(INFO) << "Register " << web_page_id << " from " << message_full_id << " from " << source;
bool is_inserted = web_page_quick_reply_messages_[web_page_id].insert(message_full_id).second;
LOG_CHECK(is_inserted) << source << " " << web_page_id << " " << message_full_id;
if (!have_web_page_force(web_page_id)) {
LOG(INFO) << "Waiting for " << web_page_id << " needed in " << message_full_id;
pending_web_pages_timeout_.add_timeout_in(web_page_id.get(), 1.0);
}
}
void WebPagesManager::unregister_quick_reply_web_page(WebPageId web_page_id, QuickReplyMessageFullId message_full_id,
const char *source) {
if (!web_page_id.is_valid()) {
return;
}
LOG(INFO) << "Unregister " << web_page_id << " from " << message_full_id << " from " << source;
auto &message_ids = web_page_quick_reply_messages_[web_page_id];
auto is_deleted = message_ids.erase(message_full_id) > 0;
LOG_CHECK(is_deleted) << source << " " << web_page_id << " " << message_full_id;
if (message_ids.empty()) {
web_page_quick_reply_messages_.erase(web_page_id);
}
}
@ -1499,37 +1528,67 @@ tl_object_ptr<td_api::webPageInstantView> WebPagesManager::get_web_page_instant_
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<MessageFullId> message_full_ids;
for (const auto &message_full_id : it->second) {
message_full_ids.push_back(message_full_id);
}
CHECK(!message_full_ids.empty());
for (const auto &message_full_id : message_full_ids) {
if (!have_web_page) {
td_->messages_manager_->delete_pending_message_web_page(message_full_id);
} else {
td_->messages_manager_->on_external_update_message_content(message_full_id, "on_web_page_changed");
{
auto it = web_page_messages_.find(web_page_id);
if (it != web_page_messages_.end()) {
vector<MessageFullId> message_full_ids;
for (const auto &message_full_id : it->second) {
message_full_ids.push_back(message_full_id);
}
CHECK(!message_full_ids.empty());
for (const auto &message_full_id : message_full_ids) {
if (!have_web_page) {
td_->messages_manager_->delete_pending_message_web_page(message_full_id);
} else {
td_->messages_manager_->on_external_update_message_content(message_full_id, "on_web_page_changed");
}
}
}
// don't check that on_external_update_message_content doesn't load new messages
if (!have_web_page && web_page_messages_.count(web_page_id) != 0) {
vector<MessageFullId> new_message_full_ids;
for (const auto &message_full_id : web_page_messages_[web_page_id]) {
new_message_full_ids.push_back(message_full_id);
// don't check that on_external_update_message_content doesn't load new messages
if (!have_web_page && web_page_messages_.count(web_page_id) != 0) {
vector<MessageFullId> new_message_full_ids;
for (const auto &message_full_id : web_page_messages_[web_page_id]) {
new_message_full_ids.push_back(message_full_id);
}
LOG(FATAL) << message_full_ids << ' ' << new_message_full_ids;
}
LOG(FATAL) << message_full_ids << ' ' << new_message_full_ids;
}
}
auto get_it = pending_get_web_pages_.find(web_page_id);
if (get_it != pending_get_web_pages_.end()) {
auto requests = std::move(get_it->second);
pending_get_web_pages_.erase(get_it);
for (auto &request : requests) {
on_get_web_page_preview_success(std::move(request.first), have_web_page ? web_page_id : WebPageId(),
std::move(request.second));
{
auto it = web_page_quick_reply_messages_.find(web_page_id);
if (it != web_page_quick_reply_messages_.end()) {
vector<QuickReplyMessageFullId> message_full_ids;
for (const auto &message_full_id : it->second) {
message_full_ids.push_back(message_full_id);
}
CHECK(!message_full_ids.empty());
for (const auto &message_full_id : message_full_ids) {
if (!have_web_page) {
td_->quick_reply_manager_->delete_pending_message_web_page(message_full_id);
} else {
td_->quick_reply_manager_->on_external_update_message_content(message_full_id, "on_web_page_changed");
}
}
// don't check that on_external_update_message_content doesn't load new messages
if (!have_web_page && web_page_quick_reply_messages_.count(web_page_id) != 0) {
vector<QuickReplyMessageFullId> new_message_full_ids;
for (const auto &message_full_id : web_page_quick_reply_messages_[web_page_id]) {
new_message_full_ids.push_back(message_full_id);
}
LOG(FATAL) << message_full_ids << ' ' << new_message_full_ids;
}
}
}
{
auto it = pending_get_web_pages_.find(web_page_id);
if (it != pending_get_web_pages_.end()) {
auto requests = std::move(it->second);
pending_get_web_pages_.erase(it);
for (auto &request : requests) {
on_get_web_page_preview_success(std::move(request.first), have_web_page ? web_page_id : WebPageId(),
std::move(request.second));
}
}
}
pending_web_pages_timeout_.cancel_timeout(web_page_id.get());
@ -1578,27 +1637,42 @@ void WebPagesManager::on_pending_web_page_timeout(WebPageId web_page_id) {
LOG(INFO) << "Process timeout for " << web_page_id;
int32 count = 0;
auto it = web_page_messages_.find(web_page_id);
if (it != web_page_messages_.end()) {
vector<MessageFullId> message_full_ids;
for (const auto &message_full_id : it->second) {
if (message_full_id.get_dialog_id().get_type() != DialogType::SecretChat) {
message_full_ids.push_back(message_full_id);
{
auto it = web_page_messages_.find(web_page_id);
if (it != web_page_messages_.end()) {
vector<MessageFullId> message_full_ids;
for (const auto &message_full_id : it->second) {
if (message_full_id.get_dialog_id().get_type() != DialogType::SecretChat) {
message_full_ids.push_back(message_full_id);
}
count++;
}
if (!message_full_ids.empty()) {
send_closure_later(G()->messages_manager(), &MessagesManager::get_messages_from_server,
std::move(message_full_ids), Promise<Unit>(), "on_pending_web_page_timeout", nullptr);
}
count++;
}
if (!message_full_ids.empty()) {
send_closure_later(G()->messages_manager(), &MessagesManager::get_messages_from_server,
std::move(message_full_ids), Promise<Unit>(), "on_pending_web_page_timeout", nullptr);
}
}
auto get_it = pending_get_web_pages_.find(web_page_id);
if (get_it != pending_get_web_pages_.end()) {
auto requests = std::move(get_it->second);
pending_get_web_pages_.erase(get_it);
for (auto &request : requests) {
request.second.set_error(Status::Error(500, "Request timeout exceeded"));
count++;
{
auto it = web_page_quick_reply_messages_.find(web_page_id);
if (it != web_page_quick_reply_messages_.end()) {
for (const auto &message_full_id : it->second) {
send_closure_later(G()->quick_reply_manager(), &QuickReplyManager::reload_quick_reply_message,
message_full_id.get_quick_reply_shortcut_id(), message_full_id.get_message_id(),
Promise<Unit>());
count++;
}
}
}
{
auto it = pending_get_web_pages_.find(web_page_id);
if (it != pending_get_web_pages_.end()) {
auto requests = std::move(it->second);
pending_get_web_pages_.erase(it);
for (auto &request : requests) {
request.second.set_error(Status::Error(500, "Request timeout exceeded"));
count++;
}
}
}
if (count == 0) {

View File

@ -11,6 +11,7 @@
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/MessageFullId.h"
#include "td/telegram/QuickReplyMessageFullId.h"
#include "td/telegram/StoryFullId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
@ -64,6 +65,12 @@ class WebPagesManager final : public Actor {
void unregister_web_page(WebPageId web_page_id, MessageFullId message_full_id, const char *source);
void register_quick_reply_web_page(WebPageId web_page_id, QuickReplyMessageFullId message_full_id,
const char *source);
void unregister_quick_reply_web_page(WebPageId web_page_id, QuickReplyMessageFullId message_full_id,
const char *source);
bool have_web_page(WebPageId web_page_id) const;
bool have_web_page_force(WebPageId web_page_id);
@ -198,6 +205,8 @@ class WebPagesManager final : public Actor {
FlatHashMap<WebPageId, PendingWebPageInstantViewQueries, WebPageIdHash> load_web_page_instant_view_queries_;
FlatHashMap<WebPageId, FlatHashSet<MessageFullId, MessageFullIdHash>, WebPageIdHash> web_page_messages_;
FlatHashMap<WebPageId, FlatHashSet<QuickReplyMessageFullId, QuickReplyMessageFullIdHash>, WebPageIdHash>
web_page_quick_reply_messages_;
FlatHashMap<WebPageId,
vector<std::pair<unique_ptr<GetWebPagePreviewOptions>, Promise<td_api::object_ptr<td_api::webPage>>>>,