From db5adecbda3e1860618f96ff6adfb6a5d148009e Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 11 Sep 2020 20:12:31 +0300 Subject: [PATCH 01/22] Update reply count on new message receiving. GitOrigin-RevId: ba0831b13ee0ee816fee8a4cd8bd2878803e1453 --- td/telegram/MessageReplyInfo.cpp | 16 +++++++++++++++- td/telegram/MessageReplyInfo.h | 2 ++ td/telegram/MessagesManager.cpp | 24 ++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/td/telegram/MessageReplyInfo.cpp b/td/telegram/MessageReplyInfo.cpp index 54ed838f7..839422c3c 100644 --- a/td/telegram/MessageReplyInfo.cpp +++ b/td/telegram/MessageReplyInfo.cpp @@ -46,7 +46,21 @@ bool MessageReplyInfo::need_update_to(const MessageReplyInfo &other) const { if (other.pts < pts) { return false; } - return true; + return reply_count != other.reply_count || recent_replier_dialog_ids != other.recent_replier_dialog_ids; +} + +void MessageReplyInfo::add_reply(DialogId replier_dialog_id) { + CHECK(!is_empty()); + + reply_count++; + if (replier_dialog_id.is_valid() && + (recent_replier_dialog_ids.empty() || recent_replier_dialog_ids[0] != replier_dialog_id)) { + td::remove(recent_replier_dialog_ids, replier_dialog_id); + recent_replier_dialog_ids.insert(recent_replier_dialog_ids.begin(), replier_dialog_id); + if (recent_replier_dialog_ids.size() > 3) { + recent_replier_dialog_ids.pop_back(); + } + } } StringBuilder &operator<<(StringBuilder &string_builder, const MessageReplyInfo &reply_info) { diff --git a/td/telegram/MessageReplyInfo.h b/td/telegram/MessageReplyInfo.h index bc4c1f90e..fbfe0c02a 100644 --- a/td/telegram/MessageReplyInfo.h +++ b/td/telegram/MessageReplyInfo.h @@ -33,6 +33,8 @@ struct MessageReplyInfo { bool need_update_to(const MessageReplyInfo &other) const; + void add_reply(DialogId replier_dialog_id); + template void store(StorerT &storer) const { CHECK(!is_empty()); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index aca06dca0..5b1c5c217 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6186,7 +6186,7 @@ td_api::object_ptr MessagesManager::get_message_ if (is_active_reply_info) { reply_count = m->reply_info.reply_count; for (auto recent_replier_dialog_id : m->reply_info.recent_replier_dialog_ids) { - if (dialog_id.get_type() == DialogType::User) { + if (recent_replier_dialog_id.get_type() == DialogType::User) { recent_replier_user_ids.push_back(recent_replier_dialog_id.get_user_id()); } } @@ -12226,7 +12226,7 @@ std::pair> MessagesManager::creat if (reply_to_message_id.is_valid()) { if ((message_info.reply_header->flags_ & telegram_api::messageReplyHeader::REPLY_TO_TOP_ID_MASK) != 0) { top_reply_message_id = MessageId(ServerMessageId(message_info.reply_header->reply_to_top_id_)); - } else if (message_info.reply_info != nullptr && !is_broadcast_channel(dialog_id)) { + } else if (!is_broadcast_channel(dialog_id)) { top_reply_message_id = reply_to_message_id; } } @@ -12279,6 +12279,10 @@ std::pair> MessagesManager::creat forward_count = 0; } MessageReplyInfo reply_info(std::move(message_info.reply_info), td_->auth_manager_->is_bot()); + if (!top_reply_message_id.is_valid() && !is_broadcast_channel(dialog_id) && + is_active_message_reply_info(dialog_id, reply_info)) { + top_reply_message_id = message_id; + } bool has_forward_info = message_info.forward_header != nullptr; @@ -29176,6 +29180,10 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq LOG(INFO) << "Preloaded previously pinned " << d->pinned_message_notification_message_id << " from database"; } } + if (from_update && message->top_reply_message_id.is_valid() && message->top_reply_message_id != message_id && + have_message_force({dialog_id, message->top_reply_message_id}, "preload top reply message")) { + LOG(INFO) << "Preloaded top reply message pinned " << message->top_reply_message_id << " from database"; + } // there must be no two recursive calls to add_message_to_dialog LOG_CHECK(!d->being_added_message_id.is_valid()) @@ -29522,6 +29530,18 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq UNREACHABLE(); } } + + if (m->top_reply_message_id.is_valid() && m->top_reply_message_id != message_id) { + Message *top_m = get_message(d, m->top_reply_message_id); + if (top_m != nullptr && is_active_message_reply_info(dialog_id, top_m->reply_info)) { + top_m->reply_info.add_reply(m->sender_dialog_id.is_valid() ? m->sender_dialog_id : DialogId(m->sender_user_id)); + on_message_changed(d, top_m, true, "update_message_reply_count"); + send_closure( + G()->td(), &Td::send_update, + make_tl_object( + dialog_id.get(), top_m->message_id.get(), get_message_interaction_info_object(dialog_id, top_m))); + } + } } Message *result_message = treap_insert_message(&d->messages, std::move(message)); From 5ffca2bffb83307b35e6c1946688e104d3b9cd8a Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 11 Sep 2020 20:20:46 +0300 Subject: [PATCH 02/22] Add send_update_message_interaction_info. GitOrigin-RevId: 83ad785a336f4ca12f5dea4e9a9c8cc93e2e98a9 --- td/telegram/MessagesManager.cpp | 19 ++++++++++++------- td/telegram/MessagesManager.h | 2 ++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 5b1c5c217..1252ca550 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6215,9 +6215,7 @@ bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Messag if (need_update_reply_info) { m->reply_info = std::move(reply_info); } - send_closure(G()->td(), &Td::send_update, - make_tl_object( - dialog_id.get(), m->message_id.get(), get_message_interaction_info_object(dialog_id, m))); + send_update_message_interaction_info(dialog_id, m); return true; } return false; @@ -25379,6 +25377,16 @@ void MessagesManager::send_update_message_edited(DialogId dialog_id, const Messa get_reply_markup_object(m->reply_markup))); } +void MessagesManager::send_update_message_interaction_info(DialogId dialog_id, const Message *m) const { + if (td_->auth_manager_->is_bot()) { + return; + } + + send_closure(G()->td(), &Td::send_update, + make_tl_object(dialog_id.get(), m->message_id.get(), + get_message_interaction_info_object(dialog_id, m))); +} + void MessagesManager::send_update_message_live_location_viewed(FullMessageId full_message_id) { CHECK(get_message(full_message_id) != nullptr); send_closure(G()->td(), &Td::send_update, @@ -29536,10 +29544,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq if (top_m != nullptr && is_active_message_reply_info(dialog_id, top_m->reply_info)) { top_m->reply_info.add_reply(m->sender_dialog_id.is_valid() ? m->sender_dialog_id : DialogId(m->sender_user_id)); on_message_changed(d, top_m, true, "update_message_reply_count"); - send_closure( - G()->td(), &Td::send_update, - make_tl_object( - dialog_id.get(), top_m->message_id.get(), get_message_interaction_info_object(dialog_id, top_m))); + send_update_message_interaction_info(dialog_id, top_m); } } } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index b31df7c69..b4c3c5195 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2086,6 +2086,8 @@ class MessagesManager : public Actor { void send_update_message_edited(DialogId dialog_id, const Message *m); + void send_update_message_interaction_info(DialogId dialog_id, const Message *m) const; + void send_update_message_live_location_viewed(FullMessageId full_message_id); void send_update_delete_messages(DialogId dialog_id, vector &&message_ids, bool is_permanent, From 2aaf1ebe3f5493831ce61fee066688271c957c78 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 11 Sep 2020 20:27:10 +0300 Subject: [PATCH 03/22] Simplify forward count updating. GitOrigin-RevId: 7986012adffddb95728c2f08af46ccc32848feb0 --- td/telegram/MessagesManager.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 1252ca550..f96201715 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -23567,10 +23567,9 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i m->via_bot_user_id = forwarded_message->via_bot_user_id; m->in_game_share = in_game_share; if (forwarded_message->view_count > 0 && is_broadcast_channel(from_dialog_id)) { - if (update_message_interaction_info(from_dialog_id, forwarded_message, forwarded_message->view_count, - forwarded_message->forward_count + 1, false, {})) { - on_message_changed(from_dialog, forwarded_message, true, "forward_messages"); - } + forwarded_message->forward_count++; + send_update_message_interaction_info(from_dialog_id, forwarded_message); + on_message_changed(from_dialog, forwarded_message, true, "forward_messages"); } if (forwarded_message->view_count > 0 && m->forward_info != nullptr && m->view_count == 0 && !(m->message_id.is_scheduled() && is_broadcast_channel(to_dialog_id))) { @@ -32846,7 +32845,9 @@ void MessagesManager::update_forward_count(DialogId dialog_id, MessageId message CHECK(d != nullptr); Message *m = get_message_force(d, message_id, "update_forward_count"); if (m != nullptr && !m->message_id.is_scheduled() && m->message_id.is_server() && m->view_count > 0) { - if (m->forward_count == 0 && update_message_interaction_info(dialog_id, m, m->view_count, 1, false, {})) { + if (m->forward_count == 0) { + m->forward_count++; + send_update_message_interaction_info(dialog_id, m); on_message_changed(d, m, true, "update_forward_count"); } From f5572725c5e5cc631aebe5a4b65d1bcfb7cb2e13 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 11 Sep 2020 21:06:01 +0300 Subject: [PATCH 04/22] Support sending messages by anonymous administrators. GitOrigin-RevId: a84245ea5e27b7e7fe5d9b303f5456d321887136 --- td/telegram/MessagesManager.cpp | 35 +++++++++++++++++++++++++++++++-- td/telegram/MessagesManager.h | 2 ++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index f96201715..ab4b40cdc 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -20454,6 +20454,27 @@ tl_object_ptr MessagesManager::get_messages_object( return td_api::make_object(total_count, std::move(messages)); } +bool MessagesManager::is_anonymous_administrator(UserId sender_user_id, DialogId dialog_id, + string *author_signature) const { + if (!sender_user_id.is_valid()) { + return false; + } + CHECK(dialog_id.is_valid()); + + if (dialog_id.get_type() != DialogType::Channel || is_broadcast_channel(dialog_id)) { + return false; + } + + auto status = td_->contacts_manager_->get_channel_status(dialog_id.get_channel_id()); + if (!status.is_anonymous()) { + return false; + } + + CHECK(author_signature != nullptr); + *author_signature = status.get_rank(); + return true; +} + MessagesManager::Message *MessagesManager::get_message_to_send( Dialog *d, MessageId reply_to_message_id, const MessageSendOptions &options, unique_ptr &&content, bool *need_update_dialog_pos, unique_ptr forward_info, bool is_copy) { @@ -20478,8 +20499,13 @@ MessagesManager::Message *MessagesManager::get_message_to_send( if (!is_scheduled && td_->contacts_manager_->get_channel_sign_messages(dialog_id.get_channel_id())) { m->author_signature = td_->contacts_manager_->get_user_title(my_id); } + m->sender_dialog_id = d->dialog_id; } else { - m->sender_user_id = my_id; + if (is_anonymous_administrator(my_id, d->dialog_id, &m->author_signature)) { + m->sender_dialog_id = d->dialog_id; + } else { + m->sender_user_id = my_id; + } } m->send_date = G()->unix_time(); m->date = is_scheduled ? options.schedule_date : m->send_date; @@ -23972,8 +23998,13 @@ Result MessagesManager::add_local_message( if (td_->contacts_manager_->get_channel_sign_messages(dialog_id.get_channel_id())) { m->author_signature = td_->contacts_manager_->get_user_title(sender_user_id); } + m->sender_dialog_id = dialog_id; } else { - m->sender_user_id = sender_user_id; + if (is_anonymous_administrator(sender_user_id, dialog_id, &m->author_signature)) { + m->sender_dialog_id = dialog_id; + } else { + m->sender_user_id = sender_user_id; + } } m->date = G()->unix_time(); m->reply_to_message_id = get_reply_to_message_id(d, reply_to_message_id); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index b4c3c5195..a427f188d 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1691,6 +1691,8 @@ class MessagesManager : public Actor { const unique_ptr &content, int32 ttl); static Status can_use_message_send_options(const MessageSendOptions &options, const InputMessageContent &content); + bool is_anonymous_administrator(UserId sender_user_id, DialogId dialog_id, string *author_signature) const; + Message *get_message_to_send(Dialog *d, MessageId reply_to_message_id, const MessageSendOptions &options, unique_ptr &&content, bool *need_update_dialog_pos, unique_ptr forward_info = nullptr, bool is_copy = false); From a925c22469db933046132d82f450dc3abe8f05b8 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 11 Sep 2020 22:01:55 +0300 Subject: [PATCH 05/22] Do not send dialog actions by anonymous administrators. GitOrigin-RevId: c67c1fc5b2ca97fb4a261d224af42b0be49f6807 --- td/telegram/MessagesManager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index ab4b40cdc..0197c5974 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -20470,8 +20470,9 @@ bool MessagesManager::is_anonymous_administrator(UserId sender_user_id, DialogId return false; } - CHECK(author_signature != nullptr); - *author_signature = status.get_rank(); + if (author_signature != nullptr) { + *author_signature = status.get_rank(); + } return true; } @@ -27310,6 +27311,9 @@ bool MessagesManager::is_dialog_action_unneded(DialogId dialog_id) const { if (is_broadcast_channel(dialog_id)) { return true; } + if (is_anonymous_administrator(td_->contacts_manager_->get_my_id(), dialog_id, nullptr)) { + return true; + } auto dialog_type = dialog_id.get_type(); if (dialog_type == DialogType::User || dialog_type == DialogType::SecretChat) { From f24ec0c4907f13b2fdc67cd10c6280c0002f716c Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 12 Sep 2020 13:20:39 +0300 Subject: [PATCH 06/22] Disallow unsupported reply markup by anonymous bots. GitOrigin-RevId: 8bcd5df60b1938e6fc172d87c0d7a37bc59db205 --- td/telegram/MessagesManager.cpp | 18 +++++++++++------- td/telegram/MessagesManager.h | 2 ++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0197c5974..299a904c5 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -20454,6 +20454,13 @@ tl_object_ptr MessagesManager::get_messages_object( return td_api::make_object(total_count, std::move(messages)); } +bool MessagesManager::is_anonymous_administrator(DialogId dialog_id) const { + if (is_broadcast_channel(dialog_id)) { + return true; + } + return is_anonymous_administrator(td_->contacts_manager_->get_my_id(), dialog_id, nullptr); +} + bool MessagesManager::is_anonymous_administrator(UserId sender_user_id, DialogId dialog_id, string *author_signature) const { if (!sender_user_id.is_valid()) { @@ -23328,11 +23335,11 @@ Result> MessagesManager::get_dialog_reply_markup( } auto dialog_type = dialog_id.get_type(); - bool is_broadcast = is_broadcast_channel(dialog_id); + bool is_anonymous = is_anonymous_administrator(dialog_id); - bool only_inline_keyboard = is_broadcast; + bool only_inline_keyboard = is_anonymous; bool request_buttons_allowed = dialog_type == DialogType::User; - bool switch_inline_buttons_allowed = !is_broadcast; + bool switch_inline_buttons_allowed = !is_anonymous; TRY_RESULT(reply_markup, get_reply_markup(std::move(reply_markup_ptr), td_->auth_manager_->is_bot(), only_inline_keyboard, @@ -27308,10 +27315,7 @@ bool MessagesManager::get_dialog_has_scheduled_messages(const Dialog *d) const { } bool MessagesManager::is_dialog_action_unneded(DialogId dialog_id) const { - if (is_broadcast_channel(dialog_id)) { - return true; - } - if (is_anonymous_administrator(td_->contacts_manager_->get_my_id(), dialog_id, nullptr)) { + if (is_anonymous_administrator(dialog_id)) { return true; } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index a427f188d..52258ff95 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1691,6 +1691,8 @@ class MessagesManager : public Actor { const unique_ptr &content, int32 ttl); static Status can_use_message_send_options(const MessageSendOptions &options, const InputMessageContent &content); + bool is_anonymous_administrator(DialogId dialog_id) const; + bool is_anonymous_administrator(UserId sender_user_id, DialogId dialog_id, string *author_signature) const; Message *get_message_to_send(Dialog *d, MessageId reply_to_message_id, const MessageSendOptions &options, From 7842beed95dd2a35adb724fb719761b0c3907ce3 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 12 Sep 2020 17:10:06 +0300 Subject: [PATCH 07/22] Exit early some functions for bots. GitOrigin-RevId: b155610c1c61846d1c113b07cce4403333fa952e --- td/telegram/MessageReplyInfo.cpp | 16 +++++++--------- td/telegram/MessagesManager.cpp | 22 ++++++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/td/telegram/MessageReplyInfo.cpp b/td/telegram/MessageReplyInfo.cpp index 839422c3c..147dcbff8 100644 --- a/td/telegram/MessageReplyInfo.cpp +++ b/td/telegram/MessageReplyInfo.cpp @@ -11,7 +11,7 @@ namespace td { MessageReplyInfo::MessageReplyInfo(tl_object_ptr &&reply_info, bool is_bot) { - if (reply_info == nullptr) { + if (reply_info == nullptr || is_bot) { return; } if (reply_info->replies_ < 0) { @@ -21,14 +21,12 @@ MessageReplyInfo::MessageReplyInfo(tl_object_ptr & reply_count = reply_info->replies_; pts = reply_info->replies_pts_; - if (!is_bot) { - for (auto &peer : reply_info->recent_repliers_) { - DialogId dialog_id(peer); - if (dialog_id.is_valid()) { - recent_replier_dialog_ids.push_back(dialog_id); - } else { - LOG(ERROR) << "Receive " << dialog_id << " as a recent replier"; - } + for (auto &peer : reply_info->recent_repliers_) { + DialogId dialog_id(peer); + if (dialog_id.is_valid()) { + recent_replier_dialog_ids.push_back(dialog_id); + } else { + LOG(ERROR) << "Receive " << dialog_id << " as a recent replier"; } } diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 299a904c5..1e14ad541 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6594,8 +6594,8 @@ void MessagesManager::on_user_dialog_action(DialogId dialog_id, UserId user_id, void MessagesManager::cancel_user_dialog_action(DialogId dialog_id, const Message *m) { CHECK(m != nullptr); - if (m->forward_info != nullptr || m->had_forward_info || m->via_bot_user_id.is_valid() || m->hide_via_bot || - m->is_channel_post || m->message_id.is_scheduled()) { + if (td_->auth_manager_->is_bot() || m->forward_info != nullptr || m->had_forward_info || + m->via_bot_user_id.is_valid() || m->hide_via_bot || m->is_channel_post || m->message_id.is_scheduled()) { return; } @@ -12147,12 +12147,13 @@ std::pair> MessagesManager::creat UserId sender_user_id = message_info.sender_user_id; DialogId sender_dialog_id = message_info.sender_dialog_id; if (!sender_user_id.is_valid()) { - if (!is_broadcast_channel(dialog_id) && td_->auth_manager_->is_bot()) { - sender_user_id = td_->contacts_manager_->get_service_notifications_user_id(); - } else if (sender_user_id != UserId()) { + if (sender_user_id != UserId()) { LOG(ERROR) << "Receive invalid " << sender_user_id; sender_user_id = UserId(); } + if (!is_broadcast_channel(dialog_id) && td_->auth_manager_->is_bot()) { + sender_user_id = td_->contacts_manager_->get_service_notifications_user_id(); + } } if (sender_dialog_id.is_valid()) { CHECK(!sender_user_id.is_valid()); @@ -12221,7 +12222,7 @@ std::pair> MessagesManager::creat reply_in_dialog_id = DialogId(); } } - if (reply_to_message_id.is_valid()) { + if (reply_to_message_id.is_valid() && !td_->auth_manager_->is_bot()) { if ((message_info.reply_header->flags_ & telegram_api::messageReplyHeader::REPLY_TO_TOP_ID_MASK) != 0) { top_reply_message_id = MessageId(ServerMessageId(message_info.reply_header->reply_to_top_id_)); } else if (!is_broadcast_channel(dialog_id)) { @@ -12277,7 +12278,7 @@ std::pair> MessagesManager::creat forward_count = 0; } MessageReplyInfo reply_info(std::move(message_info.reply_info), td_->auth_manager_->is_bot()); - if (!top_reply_message_id.is_valid() && !is_broadcast_channel(dialog_id) && + if (!td_->auth_manager_->is_bot() && !top_reply_message_id.is_valid() && !is_broadcast_channel(dialog_id) && is_active_message_reply_info(dialog_id, reply_info)) { top_reply_message_id = message_id; } @@ -29553,7 +29554,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq cancel_user_dialog_action(dialog_id, m); try_hide_distance(dialog_id, m); - if (d->messages == nullptr && !m->is_outgoing && dialog_id != get_my_dialog_id()) { + if (!td_->auth_manager_->is_bot() && d->messages == nullptr && !m->is_outgoing && dialog_id != get_my_dialog_id()) { switch (dialog_id.get_type()) { case DialogType::User: td_->contacts_manager_->invalidate_user_full(dialog_id.get_user_id()); @@ -29577,7 +29578,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } } - if (m->top_reply_message_id.is_valid() && m->top_reply_message_id != message_id) { + if (!td_->auth_manager_->is_bot() && m->top_reply_message_id.is_valid() && m->top_reply_message_id != message_id) { Message *top_m = get_message(d, m->top_reply_message_id); if (top_m != nullptr && is_active_message_reply_info(dialog_id, top_m->reply_info)) { top_m->reply_info.add_reply(m->sender_dialog_id.is_valid() ? m->sender_dialog_id : DialogId(m->sender_user_id)); @@ -32880,6 +32881,7 @@ void MessagesManager::update_top_dialogs(DialogId dialog_id, const Message *m) { } void MessagesManager::update_forward_count(DialogId dialog_id, MessageId message_id) { + CHECK(!td_->auth_manager_->is_bot()); Dialog *d = get_dialog(dialog_id); CHECK(d != nullptr); Message *m = get_message_force(d, message_id, "update_forward_count"); @@ -32898,7 +32900,7 @@ void MessagesManager::update_forward_count(DialogId dialog_id, MessageId message void MessagesManager::try_hide_distance(DialogId dialog_id, const Message *m) { CHECK(m != nullptr); - if (!m->is_outgoing && dialog_id != get_my_dialog_id()) { + if (td_->auth_manager_->is_bot() || !m->is_outgoing && dialog_id != get_my_dialog_id()) { return; } From 324c0acbeacbdee207dc46768b400c19f3c1ff17 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 12 Sep 2020 17:31:20 +0300 Subject: [PATCH 08/22] Repair sender_dialog_id for old automatically forwarded to the discussion group messages. GitOrigin-RevId: f567e646f1d00e60523ea213ca2476e92dfef8d3 --- td/telegram/MessagesManager.cpp | 21 +++++++++++++++++++++ td/telegram/MessagesManager.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 1e14ad541..469c0cea6 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -22931,6 +22931,18 @@ void MessagesManager::edit_message_scheduling_state( } } +bool MessagesManager::has_message_sender_user_id(DialogId dialog_id, const Message *m) const { + if (!m->sender_user_id.is_valid()) { + return false; + } + if (td_->auth_manager_->is_bot() && !is_broadcast_channel(dialog_id) && + m->sender_user_id == td_->contacts_manager_->get_service_notifications_user_id() && m->forward_info != nullptr && + m->forward_info->sender_dialog_id.is_valid() && m->forward_info->message_id.is_valid()) { + return false; + } + return true; +} + bool MessagesManager::get_message_disable_web_page_preview(const Message *m) { // m->disable_web_page_preview is known only for sent from this client messages if (m->disable_web_page_preview) { @@ -28965,6 +28977,15 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq DialogId dialog_id = d->dialog_id; MessageId message_id = message->message_id; + if (!has_message_sender_user_id(dialog_id, message.get()) && !message->sender_dialog_id.is_valid()) { + const auto *forward_info = message->forward_info.get(); + if (forward_info != nullptr && forward_info->sender_dialog_id.is_valid() && forward_info->message_id.is_valid()) { + message->sender_dialog_id = forward_info->sender_dialog_id; + } else { + LOG(ERROR) << "Failed to repair sender chat in " << message_id << " in " << dialog_id; + } + } + if (!message_id.is_scheduled() && message_id <= d->last_clear_history_message_id) { LOG(INFO) << "Skip adding cleared " << message_id << " to " << dialog_id << " from " << source; debug_add_message_to_dialog_fail_reason_ = "cleared full history"; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 52258ff95..2a2ebf9d2 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2468,6 +2468,8 @@ class MessagesManager : public Actor { void cancel_send_deleted_message(DialogId dialog_id, Message *m, bool is_permanently_deleted); + bool has_message_sender_user_id(DialogId dialog_id, const Message *m) const; + static bool get_message_disable_web_page_preview(const Message *m); static int32 get_message_flags(const Message *m); From 80c6f207fb90d0be27b295bebd73c56d425a59db Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 12 Sep 2020 17:45:24 +0300 Subject: [PATCH 09/22] Do not allow switch inline buttons in anonymous messages. GitOrigin-RevId: 6f0d88ca9f926a42c12f3859035ae1a66f90876e --- td/telegram/MessagesManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 469c0cea6..73afdf675 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -22374,7 +22374,7 @@ void MessagesManager::edit_message_text(FullMessageId full_message_id, InputMessageText input_message_text = r_input_message_text.move_as_ok(); auto r_new_reply_markup = get_reply_markup(std::move(reply_markup), td_->auth_manager_->is_bot(), true, false, - !is_broadcast_channel(dialog_id)); + has_message_sender_user_id(dialog_id, m)); if (r_new_reply_markup.is_error()) { return promise.set_error(r_new_reply_markup.move_as_error()); } @@ -22431,7 +22431,7 @@ void MessagesManager::edit_message_live_location(FullMessageId full_message_id, } auto r_new_reply_markup = get_reply_markup(std::move(reply_markup), td_->auth_manager_->is_bot(), true, false, - !is_broadcast_channel(dialog_id)); + has_message_sender_user_id(dialog_id, m)); if (r_new_reply_markup.is_error()) { return promise.set_error(r_new_reply_markup.move_as_error()); } @@ -22594,7 +22594,7 @@ void MessagesManager::edit_message_media(FullMessageId full_message_id, } auto r_new_reply_markup = get_reply_markup(std::move(reply_markup), td_->auth_manager_->is_bot(), true, false, - !is_broadcast_channel(dialog_id)); + has_message_sender_user_id(dialog_id, m)); if (r_new_reply_markup.is_error()) { return promise.set_error(r_new_reply_markup.move_as_error()); } @@ -22648,7 +22648,7 @@ void MessagesManager::edit_message_caption(FullMessageId full_message_id, auto caption = r_caption.move_as_ok(); auto r_new_reply_markup = get_reply_markup(std::move(reply_markup), td_->auth_manager_->is_bot(), true, false, - !is_broadcast_channel(dialog_id)); + has_message_sender_user_id(dialog_id, m)); if (r_new_reply_markup.is_error()) { return promise.set_error(r_new_reply_markup.move_as_error()); } @@ -22689,7 +22689,7 @@ void MessagesManager::edit_message_reply_markup(FullMessageId full_message_id, } auto r_new_reply_markup = get_reply_markup(std::move(reply_markup), td_->auth_manager_->is_bot(), true, false, - !is_broadcast_channel(dialog_id)); + has_message_sender_user_id(dialog_id, m)); if (r_new_reply_markup.is_error()) { return promise.set_error(r_new_reply_markup.move_as_error()); } @@ -33956,7 +33956,7 @@ void MessagesManager::stop_poll(FullMessageId full_message_id, td_api::object_pt } auto r_new_reply_markup = get_reply_markup(std::move(reply_markup), td_->auth_manager_->is_bot(), true, false, - !is_broadcast_channel(full_message_id.get_dialog_id())); + has_message_sender_user_id(full_message_id.get_dialog_id(), m)); if (r_new_reply_markup.is_error()) { return promise.set_error(r_new_reply_markup.move_as_error()); } From 22265ab338d7a7eae372ba41df8704e3d70f150c Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 12 Sep 2020 17:55:52 +0300 Subject: [PATCH 10/22] Repair sender_dialog_id in channel messages. GitOrigin-RevId: 71cbcb1252798f54da9c40b2c7838ea5f9327683 --- td/telegram/MessagesManager.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 73afdf675..b877c1450 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -28978,11 +28978,15 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq MessageId message_id = message->message_id; if (!has_message_sender_user_id(dialog_id, message.get()) && !message->sender_dialog_id.is_valid()) { - const auto *forward_info = message->forward_info.get(); - if (forward_info != nullptr && forward_info->sender_dialog_id.is_valid() && forward_info->message_id.is_valid()) { - message->sender_dialog_id = forward_info->sender_dialog_id; + if (is_broadcast_channel(dialog_id)) { + message->sender_dialog_id = dialog_id; } else { - LOG(ERROR) << "Failed to repair sender chat in " << message_id << " in " << dialog_id; + const auto *forward_info = message->forward_info.get(); + if (forward_info != nullptr && forward_info->sender_dialog_id.is_valid() && forward_info->message_id.is_valid()) { + message->sender_dialog_id = forward_info->sender_dialog_id; + } else { + LOG(ERROR) << "Failed to repair sender chat in " << message_id << " in " << dialog_id; + } } } From 85be738d9dd2b29f029abf90c7071c3858047e8a Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 12 Sep 2020 20:50:16 +0300 Subject: [PATCH 11/22] Support automatic forward of media albums as albums. GitOrigin-RevId: cb1f6446eef0b49f944491d07e2d44fb67a2a1c8 --- td/generate/scheme/td_api.tl | 5 +- td/generate/scheme/td_api.tlo | Bin 181400 -> 181364 bytes td/telegram/MessagesManager.cpp | 91 +++++++++++++++----------------- td/telegram/MessagesManager.h | 1 - td/telegram/Td.cpp | 6 +-- td/telegram/cli.cpp | 6 +-- 6 files changed, 51 insertions(+), 58 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a7a6147be..9092f2f39 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3717,12 +3717,11 @@ sendBotStartMessage bot_user_id:int32 chat_id:int53 parameter:string = Message; sendInlineQueryResultMessage chat_id:int53 reply_to_message_id:int53 options:messageSendOptions query_id:int64 result_id:string hide_via_bot:Bool = Message; //@description Forwards previously sent messages. Returns the forwarded messages in the same order as the message identifiers passed in message_ids. If a message can't be forwarded, null will be returned instead of the message -//@chat_id Identifier of the chat to which to forward messages @from_chat_id Identifier of the chat from which to forward messages @message_ids Identifiers of the messages to forward +//@chat_id Identifier of the chat to which to forward messages @from_chat_id Identifier of the chat from which to forward messages @message_ids Identifiers of the messages to forward. Message identifiers must be in a strictly increasing order //@options Options to be used to send the messages -//@as_album True, if the messages should be grouped into an album after forwarding. For this to work, no more than 10 messages may be forwarded, and all of them must be photo or video messages //@send_copy True, if content of the messages needs to be copied without links to the original messages. Always true if the messages are forwarded to a secret chat //@remove_caption True, if media caption of message copies needs to be removed. Ignored if send_copy is false -forwardMessages chat_id:int53 from_chat_id:int53 message_ids:vector options:messageSendOptions as_album:Bool send_copy:Bool remove_caption:Bool = Messages; +forwardMessages chat_id:int53 from_chat_id:int53 message_ids:vector options:messageSendOptions send_copy:Bool remove_caption:Bool = Messages; //@description Resends messages which failed to send. Can be called only for messages for which messageSendingStateFailed.can_retry is true and after specified in messageSendingStateFailed.retry_after time passed. //-If a message is re-sent, the corresponding failed to send message is deleted. Returns the sent messages in the same order as the message identifiers passed in message_ids. If a message can't be re-sent, null will be returned instead of the message diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 72a96bc836e16a1a0c7b7073eae01376c76577a4..200fafae9683a284b47bf4ad00def92386edd791 100644 GIT binary patch delta 54 zcmbQy$^E5+yP<_~3loclZ0nWq8veBWqVmL|6yMb1;>7gSVnHXC|2K~b`LIn_v|w7k K{f!0Fnr;9-9u+nK delta 68 zcmey;!9AmsyP<_~3loclY|RNiE&jCpqVmL|6yMb1;>7gSVnHXC|2K~b`LIt{v|w7! Y$&pwbpO}+Wnmf7CSbF;j3#K*Q09E}N8UO$Q diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b877c1450..b23955e94 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -3022,7 +3022,7 @@ class ForwardMessagesActor : public NetActorOnce { } auto query = G()->net_query_creator().create(telegram_api::messages_forwardMessages( - flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, std::move(from_input_peer), + flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, std::move(from_input_peer), MessagesManager::get_server_message_ids(message_ids), std::move(random_ids), std::move(to_input_peer), schedule_date)); if (G()->shared_config().get_option_boolean("use_quick_ack")) { @@ -23434,9 +23434,6 @@ void MessagesManager::do_forward_messages(DialogId to_dialog_id, DialogId from_d if (messages[0]->from_background) { flags |= SEND_MESSAGE_FLAG_FROM_BACKGROUND; } - if (messages[0]->media_album_id != 0) { - flags |= SEND_MESSAGE_FLAG_GROUP_MEDIA; - } if (messages[0]->in_game_share) { flags |= SEND_MESSAGE_FLAG_WITH_MY_SCORE; } @@ -23457,7 +23454,7 @@ Result MessagesManager::forward_message(DialogId to_dialog_id, Dialog vector all_copy_options; all_copy_options.push_back(std::move(copy_options)); TRY_RESULT(result, forward_messages(to_dialog_id, from_dialog_id, {message_id}, std::move(options), in_game_share, - false, std::move(all_copy_options))); + std::move(all_copy_options))); CHECK(result.size() == 1); auto sent_message_id = result[0]; if (sent_message_id == MessageId()) { @@ -23469,7 +23466,7 @@ Result MessagesManager::forward_message(DialogId to_dialog_id, Dialog Result> MessagesManager::forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, vector message_ids, tl_object_ptr &&options, - bool in_game_share, bool as_album, + bool in_game_share, vector &©_options) { CHECK(copy_options.size() == message_ids.size()); if (message_ids.size() > 100) { // TODO replace with const from config or implement mass-forward @@ -23498,14 +23495,21 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i TRY_STATUS(can_send_message(to_dialog_id)); TRY_RESULT(message_send_options, process_message_send_options(to_dialog_id, std::move(options))); - for (auto message_id : message_ids) { - if (message_id.is_valid_scheduled()) { - return Status::Error(5, "Can't forward scheduled messages"); + { + MessageId last_message_id; + for (auto message_id : message_ids) { + if (message_id.is_valid_scheduled()) { + return Status::Error(5, "Can't forward scheduled messages"); + } + if (message_id.is_scheduled() || !message_id.is_valid()) { + return Status::Error(5, "Invalid message identifier"); + } + + if (message_id <= last_message_id) { + return Status::Error(400, "Message identifiers must be in a strictly increasing order"); + } + last_message_id = message_id; } - if (!message_id.is_valid()) { - return Status::Error(5, "Invalid message identifier"); - } - CHECK(!message_id.is_scheduled()); } bool to_secret = to_dialog_id.get_type() == DialogType::SecretChat; @@ -23517,11 +23521,14 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i struct CopiedMessage { unique_ptr content; unique_ptr reply_markup; + int64 media_album_id; bool disable_web_page_preview; size_t index; }; vector copied_messages; + std::unordered_map> new_media_album_ids; + auto my_id = td_->contacts_manager_->get_my_id(); bool need_update_dialog_pos = false; for (size_t i = 0; i < message_ids.size(); i++) { @@ -23562,9 +23569,22 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i continue; } + if (forwarded_message->media_album_id != 0) { + auto &new_media_album_id = new_media_album_ids[forwarded_message->media_album_id]; + new_media_album_id.second++; + if (new_media_album_id.second == 2) { // have at least 2 messages in the new album + CHECK(new_media_album_id.first == 0); + new_media_album_id.first = generate_new_media_album_id(); + } + if (new_media_album_id.second == MAX_GROUPED_MESSAGES + 1) { + CHECK(new_media_album_id.first != 0); + new_media_album_id.first = 0; // just in case + } + } + if (need_copy) { - copied_messages.push_back( - {std::move(content), std::move(reply_markup), get_message_disable_web_page_preview(forwarded_message), i}); + copied_messages.push_back({std::move(content), std::move(reply_markup), forwarded_message->media_album_id, + get_message_disable_web_page_preview(forwarded_message), i}); continue; } @@ -23613,6 +23633,7 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i m->real_forward_from_message_id = message_id; m->via_bot_user_id = forwarded_message->via_bot_user_id; m->in_game_share = in_game_share; + m->media_album_id = forwarded_message->media_album_id; if (forwarded_message->view_count > 0 && is_broadcast_channel(from_dialog_id)) { forwarded_message->forward_count++; send_update_message_interaction_info(from_dialog_id, forwarded_message); @@ -23671,24 +23692,11 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i } if (!forwarded_messages.empty()) { - if (as_album && forwarded_messages.size() > 1 && forwarded_messages.size() <= MAX_GROUPED_MESSAGES) { - bool allow_album = true; - for (auto m : forwarded_messages) { - if (!is_allowed_media_group_content(m->content->get_type())) { - allow_album = false; - break; - } - } - - if (allow_album) { - int64 media_album_id = generate_new_media_album_id(); - for (auto m : forwarded_messages) { - m->media_album_id = media_album_id; - } - } - } - for (auto m : forwarded_messages) { + if (m->media_album_id != 0) { + m->media_album_id = new_media_album_ids[m->media_album_id].first; + } + send_update_new_message(to_dialog, m); } @@ -23696,26 +23704,13 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i } if (!copied_messages.empty()) { - int64 media_album_id = 0; - if (as_album && copied_messages.size() > 1 && copied_messages.size() <= MAX_GROUPED_MESSAGES) { - bool allow_album = true; - for (auto &copied_message : copied_messages) { - if (!is_allowed_media_group_content(copied_message.content->get_type())) { - allow_album = false; - break; - } - } - - if (allow_album) { - media_album_id = generate_new_media_album_id(); - } - } - for (auto &copied_message : copied_messages) { Message *m = get_message_to_send(to_dialog, MessageId(), message_send_options, std::move(copied_message.content), &need_update_dialog_pos, nullptr, true); m->disable_web_page_preview = copied_message.disable_web_page_preview; - m->media_album_id = media_album_id; + if (copied_message.media_album_id != 0) { + m->media_album_id = new_media_album_ids[copied_message.media_album_id].first; + } m->reply_markup = std::move(copied_message.reply_markup); save_send_message_logevent(to_dialog_id, m); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 2a2ebf9d2..59a8a2452 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -402,7 +402,6 @@ class MessagesManager : public Actor { Result> forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, vector message_ids, tl_object_ptr &&options, bool in_game_share, - bool as_album, vector &©_options) TD_WARN_UNUSED_RESULT; Result> resend_messages(DialogId dialog_id, vector message_ids) TD_WARN_UNUSED_RESULT; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 22aa960a0..1b2c6501e 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5773,9 +5773,9 @@ void Td::on_request(uint64 id, td_api::forwardMessages &request) { auto message_copy_options = transform(input_message_ids, [send_copy = request.send_copy_, remove_caption = request.remove_caption_]( MessageId) { return MessageCopyOptions(send_copy, remove_caption); }); - auto r_message_ids = messages_manager_->forward_messages(dialog_id, DialogId(request.from_chat_id_), - std::move(input_message_ids), std::move(request.options_), - false, request.as_album_, std::move(message_copy_options)); + auto r_message_ids = + messages_manager_->forward_messages(dialog_id, DialogId(request.from_chat_id_), std::move(input_message_ids), + std::move(request.options_), false, std::move(message_copy_options)); if (r_message_ids.is_error()) { return send_closure(actor_id(this), &Td::send_error, id, r_message_ids.move_as_error()); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index d299187c8..22b10679f 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2726,7 +2726,7 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_id(chat_id), as_message_ids(message_ids), as_bool(revoke))); - } else if (op == "fm" || op == "fmg" || op == "cm" || op == "cmg") { + } else if (op == "fm" || op == "cm") { string chat_id; string from_chat_id; string message_ids; @@ -2735,8 +2735,8 @@ class CliClient final : public Actor { auto chat = as_chat_id(chat_id); send_request(td_api::make_object( - chat, as_chat_id(from_chat_id), as_message_ids(message_ids), default_message_send_options(), op[2] == 'g', - op[0] == 'c', Random::fast(0, 1) == 1)); + chat, as_chat_id(from_chat_id), as_message_ids(message_ids), default_message_send_options(), op[0] == 'c', + Random::fast(0, 1) == 1)); } else if (op == "resend") { string chat_id; string message_ids; From c60bdaeebaeefce32f1286cbaa42fd8f670cdad8 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 12 Sep 2020 22:24:04 +0300 Subject: [PATCH 12/22] Add reply_to_message_id support in message copies. GitOrigin-RevId: 1304da421b63721ba15a93e35b06cd6514190b71 --- td/telegram/MessageCopyOptions.h | 15 ++++++++++----- td/telegram/MessagesManager.cpp | 20 ++++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/td/telegram/MessageCopyOptions.h b/td/telegram/MessageCopyOptions.h index 9420c30b6..4f5126d97 100644 --- a/td/telegram/MessageCopyOptions.h +++ b/td/telegram/MessageCopyOptions.h @@ -18,6 +18,7 @@ struct MessageCopyOptions { bool send_copy = false; bool replace_caption = false; FormattedText new_caption; + MessageId reply_to_message_id; unique_ptr reply_markup; MessageCopyOptions() = default; @@ -28,11 +29,15 @@ struct MessageCopyOptions { inline StringBuilder &operator<<(StringBuilder &string_builder, MessageCopyOptions copy_options) { if (copy_options.send_copy) { string_builder << "CopyOptions[replace_caption = " << copy_options.replace_caption; - } - if (copy_options.replace_caption) { - string_builder << ", new_caption = " << copy_options.new_caption; - } - if (copy_options.send_copy) { + if (copy_options.replace_caption) { + string_builder << ", new_caption = " << copy_options.new_caption; + } + if (copy_options.reply_to_message_id.is_valid()) { + string_builder << ", reply to = " << copy_options.reply_to_message_id; + } + if (copy_options.reply_markup != nullptr) { + string_builder << ", with reply markup"; + } string_builder << "]"; } return string_builder; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b23955e94..361fdb401 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -21046,20 +21046,21 @@ Result MessagesManager::send_message(DialogId dialog_id, MessageId re return Status::Error(5, "Can't send message without content"); } + Dialog *d = get_dialog_force(dialog_id); + if (d == nullptr) { + return Status::Error(5, "Chat not found"); + } + LOG(INFO) << "Begin to send message to " << dialog_id << " in reply to " << reply_to_message_id; if (input_message_content->get_id() == td_api::inputMessageForwarded::ID) { auto input_message = td_api::move_object_as(input_message_content); TRY_RESULT(copy_options, process_message_copy_options(dialog_id, std::move(input_message->copy_options_))); + copy_options.reply_to_message_id = get_reply_to_message_id(d, reply_to_message_id); TRY_RESULT_ASSIGN(copy_options.reply_markup, get_dialog_reply_markup(dialog_id, std::move(reply_markup))); return forward_message(dialog_id, DialogId(input_message->from_chat_id_), MessageId(input_message->message_id_), std::move(options), input_message->in_game_share_, std::move(copy_options)); } - Dialog *d = get_dialog_force(dialog_id); - if (d == nullptr) { - return Status::Error(5, "Chat not found"); - } - TRY_STATUS(can_send_message(dialog_id)); TRY_RESULT(message_reply_markup, get_dialog_reply_markup(dialog_id, std::move(reply_markup))); TRY_RESULT(message_content, process_input_message_content(dialog_id, std::move(input_message_content))); @@ -23520,6 +23521,7 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i struct CopiedMessage { unique_ptr content; + MessageId reply_to_message_id; unique_ptr reply_markup; int64 media_album_id; bool disable_web_page_preview; @@ -23549,6 +23551,7 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i bool need_copy = !message_id.is_server() || to_secret || copy_options[i].send_copy; auto type = need_copy ? MessageContentDupType::Copy : MessageContentDupType::Forward; + auto reply_to_message_id = copy_options[i].reply_to_message_id; auto reply_markup = std::move(copy_options[i].reply_markup); unique_ptr content = dup_message_content(td_, to_dialog_id, forwarded_message->content.get(), type, std::move(copy_options[i])); @@ -23583,7 +23586,8 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i } if (need_copy) { - copied_messages.push_back({std::move(content), std::move(reply_markup), forwarded_message->media_album_id, + copied_messages.push_back({std::move(content), reply_to_message_id, std::move(reply_markup), + forwarded_message->media_album_id, get_message_disable_web_page_preview(forwarded_message), i}); continue; } @@ -23705,8 +23709,8 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i if (!copied_messages.empty()) { for (auto &copied_message : copied_messages) { - Message *m = get_message_to_send(to_dialog, MessageId(), message_send_options, std::move(copied_message.content), - &need_update_dialog_pos, nullptr, true); + Message *m = get_message_to_send(to_dialog, copied_message.reply_to_message_id, message_send_options, + std::move(copied_message.content), &need_update_dialog_pos, nullptr, true); m->disable_web_page_preview = copied_message.disable_web_page_preview; if (copied_message.media_album_id != 0) { m->media_album_id = new_media_album_ids[copied_message.media_album_id].first; From de1a582734adaebd22969912540728eb3cdc7440 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 13 Sep 2020 00:10:40 +0300 Subject: [PATCH 13/22] Improve inputChatPhotoAnimation documentation. GitOrigin-RevId: e78459f571c478b61223f01334759e501a54061b --- td/generate/scheme/td_api.tl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 9092f2f39..a8cf01fd2 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -378,7 +378,7 @@ inputChatPhotoPrevious chat_photo_id:int64 = InputChatPhoto; //@description A static photo in JPEG format @photo Photo to be set as profile photo. Only inputFileLocal and inputFileGenerated are allowed inputChatPhotoStatic photo:InputFile = InputChatPhoto; -//@description An animation in MPEG4 format; must be square, shorter than 10 seconds, have width between 160 and 800 and be at most 2MB in size +//@description An animation in MPEG4 format; must be square, at most 10 seconds long, have width between 160 and 800 and be at most 2MB in size //@animation Animation to be set as profile photo. Only inputFileLocal and inputFileGenerated are allowed //@main_frame_timestamp Timestamp of the frame, which will be used as static chat photo inputChatPhotoAnimation animation:InputFile main_frame_timestamp:double = InputChatPhoto; From d6f5675cb20e73d2d2cc9774745bd3b723db49d1 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 13 Sep 2020 00:51:24 +0300 Subject: [PATCH 14/22] Always use send_closure_later in *_message_ready_to_send to keep the relative message order. GitOrigin-RevId: 711dec50273bd457640d8515e583f5365ccc567d --- td/telegram/MessagesManager.cpp | 85 ++++++++++++++++++++------------- td/telegram/MessagesManager.h | 2 + 2 files changed, 53 insertions(+), 34 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 361fdb401..3f2993250 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -21329,25 +21329,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect auto content_type = content->get_type(); if (content_type == MessageContentType::Text) { CHECK(!is_edit); - const FormattedText *message_text = get_message_content_text(content); - CHECK(message_text != nullptr); - - int64 random_id = begin_send_message(dialog_id, m); - if (is_secret) { - CHECK(!m->message_id.is_scheduled()); - auto layer = td_->contacts_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id()); - send_closure(td_->create_net_actor(), &SendSecretMessageActor::send, dialog_id, - m->reply_to_random_id, m->ttl, message_text->text, - get_secret_input_media(content, td_, nullptr, BufferSlice(), layer), - get_input_secret_message_entities(message_text->entities, layer), m->via_bot_user_id, - m->media_album_id, m->disable_notification, random_id); - } else { - send_closure(td_->create_net_actor(), &SendMessageActor::send, get_message_flags(m), dialog_id, - m->reply_to_message_id, get_message_schedule_date(m), get_input_reply_markup(m->reply_markup), - get_input_message_entities(td_->contacts_manager_.get(), message_text->entities, "do_send_message"), - message_text->text, random_id, &m->send_query_ref, - get_sequence_dispatcher_id(dialog_id, content_type)); - } + send_closure_later(actor_id(this), &MessagesManager::on_text_message_ready_to_send, dialog_id, m->message_id); return; } @@ -21424,8 +21406,8 @@ void MessagesManager::on_message_media_uploaded(DialogId dialog_id, const Messag } if (m->media_album_id == 0) { - on_media_message_ready_to_send( - dialog_id, message_id, + send_closure_later( + actor_id(this), &MessagesManager::on_media_message_ready_to_send, dialog_id, message_id, PromiseCreator::lambda([this, dialog_id, input_media = std::move(input_media), file_id, thumbnail_file_id](Result result) mutable { if (result.is_error() || G()->close_flag()) { @@ -21498,8 +21480,8 @@ void MessagesManager::on_secret_message_media_uploaded(DialogId dialog_id, const */ // TODO use file_id, thumbnail_file_id, was_uploaded, was_thumbnail_uploaded, // invalidate partial remote location for file_id in case of failed upload even message has already been deleted - on_media_message_ready_to_send( - dialog_id, m->message_id, + send_closure_later( + actor_id(this), &MessagesManager::on_media_message_ready_to_send, dialog_id, m->message_id, PromiseCreator::lambda( [this, dialog_id, secret_input_media = std::move(secret_input_media)](Result result) mutable { if (result.is_error() || G()->close_flag()) { @@ -21651,18 +21633,18 @@ void MessagesManager::on_upload_message_media_finished(int64 media_album_id, Dia // send later, because some messages may be being deleted now for (auto request_message_id : request.message_ids) { LOG(INFO) << "Send on_media_message_ready_to_send for " << request_message_id << " in " << dialog_id; - send_closure_later(actor_id(this), &MessagesManager::on_media_message_ready_to_send, dialog_id, - request_message_id, - PromiseCreator::lambda([actor_id = actor_id(this), media_album_id](Result result) { - if (result.is_error() || G()->close_flag()) { - return; - } + auto promise = PromiseCreator::lambda([actor_id = actor_id(this), media_album_id](Result result) { + if (result.is_error() || G()->close_flag()) { + return; + } - auto m = result.move_as_ok(); - CHECK(m != nullptr); - CHECK(m->media_album_id == media_album_id); - send_closure_later(actor_id, &MessagesManager::do_send_message_group, media_album_id); - })); + auto m = result.move_as_ok(); + CHECK(m != nullptr); + CHECK(m->media_album_id == media_album_id); + send_closure_later(actor_id, &MessagesManager::do_send_message_group, media_album_id); + }); + send_closure_later(actor_id(this), &MessagesManager::on_media_message_ready_to_send, dialog_id, + request_message_id, std::move(promise)); } } } @@ -21766,6 +21748,41 @@ void MessagesManager::do_send_message_group(int64 media_album_id) { get_sequence_dispatcher_id(dialog_id, is_copy ? MessageContentType::None : MessageContentType::Photo)); } +void MessagesManager::on_text_message_ready_to_send(DialogId dialog_id, MessageId message_id) { + LOG(INFO) << "Ready to send " << message_id << " to " << dialog_id; + + auto m = get_message({dialog_id, message_id}); + if (m == nullptr) { + return; + } + + CHECK(message_id.is_yet_unsent()); + + auto content = m->content.get(); + CHECK(content != nullptr); + auto content_type = content->get_type(); + + const FormattedText *message_text = get_message_content_text(content); + CHECK(message_text != nullptr); + + int64 random_id = begin_send_message(dialog_id, m); + if (dialog_id.get_type() == DialogType::SecretChat) { + CHECK(!message_id.is_scheduled()); + auto layer = td_->contacts_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id()); + send_closure(td_->create_net_actor(), &SendSecretMessageActor::send, dialog_id, + m->reply_to_random_id, m->ttl, message_text->text, + get_secret_input_media(content, td_, nullptr, BufferSlice(), layer), + get_input_secret_message_entities(message_text->entities, layer), m->via_bot_user_id, + m->media_album_id, m->disable_notification, random_id); + } else { + send_closure(td_->create_net_actor(), &SendMessageActor::send, get_message_flags(m), dialog_id, + m->reply_to_message_id, get_message_schedule_date(m), get_input_reply_markup(m->reply_markup), + get_input_message_entities(td_->contacts_manager_.get(), message_text->entities, "do_send_message"), + message_text->text, random_id, &m->send_query_ref, + get_sequence_dispatcher_id(dialog_id, content_type)); + } +} + void MessagesManager::on_media_message_ready_to_send(DialogId dialog_id, MessageId message_id, Promise &&promise) { LOG(INFO) << "Ready to send " << message_id << " to " << dialog_id; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 59a8a2452..956b9f996 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1768,6 +1768,8 @@ class MessagesManager : public Actor { void do_send_message_group(int64 media_album_id); + void on_text_message_ready_to_send(DialogId dialog_id, MessageId message_id); + void on_media_message_ready_to_send(DialogId dialog_id, MessageId message_id, Promise &&promise); void on_yet_unsent_media_queue_updated(DialogId dialog_id); From 8c43f751cd09097185e7bfe54f5c87261b9baf1a Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 13 Sep 2020 01:28:14 +0300 Subject: [PATCH 15/22] Synchronously send media group to keep the relative message order. GitOrigin-RevId: 7f6f0f1b47dae56f3bc459f81fc2922fdc7b46dc --- td/telegram/MessagesManager.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 3f2993250..1b548e6d6 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -21630,10 +21630,12 @@ void MessagesManager::on_upload_message_media_finished(int64 media_album_id, Dia request.finished_count++; if (request.finished_count == request.message_ids.size() || request.results[pos].is_error()) { - // send later, because some messages may be being deleted now + // must use send_closure_later if some messages may be being deleted now + // but this function is called only through send_closure_later, so there should be no being deleted messages + // we must to use synchronous calls to keep the correct message order during copying of multiple messages for (auto request_message_id : request.message_ids) { LOG(INFO) << "Send on_media_message_ready_to_send for " << request_message_id << " in " << dialog_id; - auto promise = PromiseCreator::lambda([actor_id = actor_id(this), media_album_id](Result result) { + auto promise = PromiseCreator::lambda([this, media_album_id](Result result) { if (result.is_error() || G()->close_flag()) { return; } @@ -21641,10 +21643,12 @@ void MessagesManager::on_upload_message_media_finished(int64 media_album_id, Dia auto m = result.move_as_ok(); CHECK(m != nullptr); CHECK(m->media_album_id == media_album_id); - send_closure_later(actor_id, &MessagesManager::do_send_message_group, media_album_id); + do_send_message_group(media_album_id); + // send_closure_later(actor_id, &MessagesManager::do_send_message_group, media_album_id); }); - send_closure_later(actor_id(this), &MessagesManager::on_media_message_ready_to_send, dialog_id, - request_message_id, std::move(promise)); + // send_closure_later(actor_id(this), &MessagesManager::on_media_message_ready_to_send, dialog_id, + // request_message_id, std::move(promise)); + on_media_message_ready_to_send(dialog_id, request_message_id, std::move(promise)); } } } From c7a9e5980c3b931c34aa2c8a2fad94a464e95a26 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 13 Sep 2020 01:31:08 +0300 Subject: [PATCH 16/22] tg_cli: support custom message ID separators in deleteMessages. GitOrigin-RevId: f070685d2fee167e3679d57e84d70fff1f682f72 --- td/telegram/cli.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 22b10679f..09b2966d7 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2717,15 +2717,13 @@ class CliClient final : public Actor { } else if (op == "delf" || op == "DeleteFile") { string file_id = args; send_request(td_api::make_object(as_file_id(file_id))); - } else if (op == "dm") { + } else if (op == "dm" || op == "dmr") { string chat_id; string message_ids; - string revoke; - std::tie(chat_id, args) = split(args); - std::tie(message_ids, revoke) = split(args); + std::tie(chat_id, message_ids) = split(args); - send_request(td_api::make_object(as_chat_id(chat_id), as_message_ids(message_ids), - as_bool(revoke))); + send_request( + td_api::make_object(as_chat_id(chat_id), as_message_ids(message_ids), op == "dmr")); } else if (op == "fm" || op == "cm") { string chat_id; string from_chat_id; From fb0a43ee938ba4661f1db5f264a5d03b0e78f5b5 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 13 Sep 2020 17:52:39 +0300 Subject: [PATCH 17/22] Automatically update message interaction info when linked channel is changed. GitOrigin-RevId: 248afe64dbb6fe2e3e4fe72e474220e6c257d286 --- td/generate/scheme/td_api.tl | 2 +- td/telegram/ContactsManager.cpp | 33 ++++++++++++++++++++++++++++ td/telegram/MessagesManager.cpp | 39 ++++++++++++++++++++++++++++++++- td/telegram/MessagesManager.h | 6 +++++ 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a8cf01fd2..37635d079 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3106,7 +3106,7 @@ updateMessageContent chat_id:int53 message_id:int53 new_content:MessageContent = //@description A message was edited. Changes in the message content will come in a separate updateMessageContent @chat_id Chat identifier @message_id Message identifier @edit_date Point in time (Unix timestamp) when the message was edited @reply_markup New message reply markup; may be null updateMessageEdited chat_id:int53 message_id:int53 edit_date:int32 reply_markup:ReplyMarkup = Update; -//@description The information about interactions with a message has changed @chat_id Chat identifier @message_id Message identifier @interaction_info New information about interactions with the message +//@description The information about interactions with a message has changed @chat_id Chat identifier @message_id Message identifier @interaction_info New information about interactions with the message; may be null updateMessageInteractionInfo chat_id:int53 message_id:int53 interaction_info:messageInteractionInfo = Update; //@description The message content was opened. Updates voice note messages to "listened", video note messages to "viewed" and starts the TTL timer for self-destructing messages @chat_id Chat identifier @message_id Message identifier diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index ba801852c..b04c7a0dd 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -9744,6 +9744,14 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c } update_channel_full(channel, channel_id); + + if (linked_channel_id.is_valid()) { + auto linked_channel_full = get_channel_full_force(linked_channel_id, "on_get_chat_full"); + on_update_channel_full_linked_channel_id(linked_channel_full, linked_channel_id, channel_id); + if (linked_channel_full != nullptr) { + update_channel_full(linked_channel_full, linked_channel_id); + } + } } promise.set_value(Unit()); } @@ -11195,6 +11203,17 @@ ChannelId ContactsManager::get_linked_channel_id(ChannelId channel_id) const { void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *channel_full, ChannelId channel_id, ChannelId linked_channel_id) { + auto old_linked_channel_id = get_linked_channel_id(channel_id); + LOG(INFO) << "Uplate linked channel in " << channel_id << " from " << old_linked_channel_id << " to " + << linked_channel_id; + + if (channel_full != nullptr && channel_full->linked_channel_id != linked_channel_id && + channel_full->linked_channel_id.is_valid()) { + get_channel_force(channel_full->linked_channel_id); + get_channel_full_force(channel_full->linked_channel_id, "on_update_channel_full_linked_channel_id 0"); + } + auto old_linked_linked_channel_id = get_linked_channel_id(linked_channel_id); + remove_linked_channel_id(channel_id); remove_linked_channel_id(linked_channel_id); if (channel_id.is_valid() && linked_channel_id.is_valid()) { @@ -11250,6 +11269,20 @@ void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *chan c->is_changed = true; update_channel(c, channel_id); } + + if (old_linked_channel_id != linked_channel_id) { + // must be called after the linked channel is changed + td_->messages_manager_->on_dialog_linked_channel_updated(DialogId(channel_id), old_linked_channel_id, + linked_channel_id); + } + auto new_linked_linked_channel_id = get_linked_channel_id(linked_channel_id); + LOG(INFO) << "Uplate linked channel in " << linked_channel_id << " from " << old_linked_linked_channel_id << " to " + << new_linked_linked_channel_id; + if (old_linked_linked_channel_id != new_linked_linked_channel_id) { + // must be called after the linked channel is changed + td_->messages_manager_->on_dialog_linked_channel_updated(DialogId(linked_channel_id), old_linked_linked_channel_id, + new_linked_linked_channel_id); + } } void ContactsManager::on_update_channel_full_location(ChannelFull *channel_full, ChannelId channel_id, diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 1b548e6d6..a7ceea595 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -9645,6 +9645,22 @@ void MessagesManager::delete_dialog_history_from_server(DialogId dialog_id, Mess } } +void MessagesManager::find_discussed_messages(const Message *m, ChannelId old_channel_id, ChannelId new_channel_id, + vector &message_ids) { + if (m == nullptr) { + return; + } + + find_discussed_messages(m->left.get(), old_channel_id, new_channel_id, message_ids); + + if (!m->reply_info.is_empty() && m->reply_info.channel_id.is_valid() && + (m->reply_info.channel_id == old_channel_id || m->reply_info.channel_id == new_channel_id)) { + message_ids.push_back(m->message_id); + } + + find_discussed_messages(m->right.get(), old_channel_id, new_channel_id, message_ids); +} + void MessagesManager::find_messages_from_user(const Message *m, UserId user_id, vector &message_ids) { if (m == nullptr) { return; @@ -25449,6 +25465,7 @@ void MessagesManager::send_update_message_edited(DialogId dialog_id, const Messa } void MessagesManager::send_update_message_interaction_info(DialogId dialog_id, const Message *m) const { + CHECK(m != nullptr); if (td_->auth_manager_->is_bot()) { return; } @@ -26997,6 +27014,26 @@ void MessagesManager::on_dialog_user_is_deleted_updated(DialogId dialog_id, bool } } +void MessagesManager::on_dialog_linked_channel_updated(DialogId dialog_id, ChannelId old_linked_channel_id, + ChannelId new_linked_channel_id) const { + CHECK(dialog_id.get_type() == DialogType::Channel); + if (!is_broadcast_channel(dialog_id)) { + return; + } + auto d = get_dialog(dialog_id); // no need to create the dialog + if (d != nullptr && d->is_update_new_chat_sent) { + vector message_ids; + find_discussed_messages(d->messages.get(), old_linked_channel_id, new_linked_channel_id, message_ids); + LOG(INFO) << "Found discussion messages " << message_ids; + for (auto message_id : message_ids) { + send_update_message_interaction_info(dialog_id, get_message(d, message_id)); + if (message_id == d->last_message_id) { + send_update_chat_last_message_impl(d, "on_dialog_linked_channel_updated"); + } + } + } +} + DialogId MessagesManager::resolve_dialog_username(const string &username) const { auto cleaned_username = clean_username(username); auto it = resolved_usernames_.find(cleaned_username); @@ -29627,8 +29664,8 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq Message *top_m = get_message(d, m->top_reply_message_id); if (top_m != nullptr && is_active_message_reply_info(dialog_id, top_m->reply_info)) { top_m->reply_info.add_reply(m->sender_dialog_id.is_valid() ? m->sender_dialog_id : DialogId(m->sender_user_id)); - on_message_changed(d, top_m, true, "update_message_reply_count"); send_update_message_interaction_info(dialog_id, top_m); + on_message_changed(d, top_m, true, "update_message_reply_count"); } } } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 956b9f996..be15f8689 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -734,6 +734,9 @@ class MessagesManager : public Actor { void on_dialog_user_is_blocked_updated(DialogId dialog_id, bool is_blocked); void on_dialog_user_is_deleted_updated(DialogId dialog_id, bool is_deleted); + void on_dialog_linked_channel_updated(DialogId dialog_id, ChannelId old_linked_channel_id, + ChannelId new_linked_channel_id) const; + void on_resolved_username(const string &username, DialogId dialog_id); void drop_username(const string &username); @@ -1847,6 +1850,9 @@ class MessagesManager : public Actor { static MessageId find_message_by_date(const Message *m, int32 date); + static void find_discussed_messages(const Message *m, ChannelId old_channel_id, ChannelId new_channel_id, + vector &message_ids); + static void find_messages_from_user(const Message *m, UserId user_id, vector &message_ids); static void find_unread_mentions(const Message *m, vector &message_ids); From ed10f1851c08e113af32575017ea5c34e9ad9a07 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 13 Sep 2020 17:57:06 +0300 Subject: [PATCH 18/22] Keep reply_count only in discussion supergroups. GitOrigin-RevId: f9f603e89eba8dcb9a8b92574c6e15ecace9cb4e --- td/telegram/MessagesManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index a7ceea595..4dc5ee31e 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6170,7 +6170,7 @@ bool MessagesManager::is_active_message_reply_info(DialogId dialog_id, const Mes td_api::object_ptr MessagesManager::get_message_interaction_info_object( DialogId dialog_id, const Message *m) const { - bool is_active_reply_info = is_active_message_reply_info(dialog_id, m->reply_info); + bool is_active_reply_info = m->message_id.is_server() && is_active_message_reply_info(dialog_id, m->reply_info); if (m->view_count == 0 && m->forward_count == 0 && !is_active_reply_info) { return nullptr; } @@ -20553,7 +20553,8 @@ MessagesManager::Message *MessagesManager::get_message_to_send( if (is_channel_post) { return td_->contacts_manager_->get_channel_has_linked_channel(dialog_id.get_channel_id()); } - return !m->reply_to_message_id.is_valid(); + return !reply_to_message_id.is_valid() && + td_->contacts_manager_->get_channel_has_linked_channel(dialog_id.get_channel_id()); }()) { m->reply_info.reply_count = 0; } From 1cd9f5d8c9265a11214bee74328825ed9ef5b7ab Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 14 Sep 2020 01:12:24 +0300 Subject: [PATCH 19/22] Support generating of public links for comment messages. GitOrigin-RevId: 68d9a0260e60719f129e05d32fcbf756e93fa5d4 --- td/generate/scheme/td_api.tl | 5 +- td/generate/scheme/td_api.tlo | Bin 181364 -> 181400 bytes td/telegram/MessagesManager.cpp | 148 ++++++++++++++++++++++---------- td/telegram/MessagesManager.h | 2 +- td/telegram/Td.cpp | 13 ++- td/telegram/cli.cpp | 6 +- 6 files changed, 122 insertions(+), 52 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 37635d079..c1d8b475e 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3681,8 +3681,9 @@ removeNotificationGroup notification_group_id:int32 max_notification_id:int32 = //@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 if a link for a whole media album should be returned -getPublicMessageLink chat_id:int53 message_id:int53 for_album:Bool = PublicMessageLink; +//@for_album Pass true to create a link for a whole media album +//@for_comment Pass true to create a link to a message as a channel message comment +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 diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 200fafae9683a284b47bf4ad00def92386edd791..8df9db5605880192d8d261d38a0276f9e6a8eb8d 100644 GIT binary patch delta 64 zcmey;!9AmsyP<_~3sX%Z%i}vmg3}uknG~i^F=FzW{szRlpv1_^ot9q|pPZkYo0?ZL SS-?qVS^=ZLc9kTifFuAS=@%IQ delta 39 ucmbQy$^E5+yP<_~3sX%ZOJ@4&m(v>(nG~k09AxyF{szd}Zji*3kpuugG7mBU diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 4dc5ee31e..ee8a9f413 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -12298,6 +12298,9 @@ std::pair> MessagesManager::creat is_active_message_reply_info(dialog_id, reply_info)) { top_reply_message_id = message_id; } + if (top_reply_message_id.is_valid() && dialog_type != DialogType::Channel) { + top_reply_message_id = MessageId(); + } bool has_forward_info = message_info.forward_header != nullptr; @@ -15306,37 +15309,39 @@ void MessagesManager::get_message_force_from_server(Dialog *d, MessageId message LOG(INFO) << "Get " << message_id << " in " << d->dialog_id << " using " << to_string(input_message); auto dialog_type = d->dialog_id.get_type(); auto m = get_message_force(d, message_id, "get_message_force_from_server"); - if (m == nullptr && message_id.is_valid() && message_id.is_server()) { - if (d->last_new_message_id != MessageId() && message_id > d->last_new_message_id) { - // message will not be added to the dialog anyway - if (dialog_type == DialogType::Channel) { - // so we try to force channel difference first + if (m == nullptr) { + if (message_id.is_valid() && message_id.is_server()) { + if (d->last_new_message_id != MessageId() && message_id > d->last_new_message_id) { + // message will not be added to the dialog anyway + if (dialog_type == DialogType::Channel) { + // so we try to force channel difference first - // replied message can't be older than already added original message, but pinned message can be - LOG_CHECK(input_message == nullptr || input_message->get_id() == telegram_api::inputMessagePinned::ID) - << to_string(input_message) << " " << d->dialog_id << " " << message_id << " " << d->last_new_message_id - << " " << d->last_message_id << " " << d->first_database_message_id << " " << d->last_database_message_id - << " " << d->pinned_message_id << " " << d->last_read_all_mentions_message_id << " " - << d->max_unavailable_message_id << " " << d->last_clear_history_message_id << " " << d->order << " " - << d->deleted_last_message_id << " " << d->max_added_message_id << " " << d->pts << " " - << d->last_assigned_message_id << " " << d->debug_last_new_message_id << " " - << d->debug_first_database_message_id << " " << d->debug_last_database_message_id; - postponed_get_message_requests_[d->dialog_id].emplace_back(message_id, std::move(promise), - std::move(input_message)); - get_channel_difference(d->dialog_id, d->pts, true, "get_message"); - } else { - promise.set_value(Unit()); + // replied message can't be older than already added original message, but pinned message can be + LOG_CHECK(input_message == nullptr || input_message->get_id() == telegram_api::inputMessagePinned::ID) + << to_string(input_message) << " " << d->dialog_id << " " << message_id << " " << d->last_new_message_id + << " " << d->last_message_id << " " << d->first_database_message_id << " " << d->last_database_message_id + << " " << d->pinned_message_id << " " << d->last_read_all_mentions_message_id << " " + << d->max_unavailable_message_id << " " << d->last_clear_history_message_id << " " << d->order << " " + << d->deleted_last_message_id << " " << d->max_added_message_id << " " << d->pts << " " + << d->last_assigned_message_id << " " << d->debug_last_new_message_id << " " + << d->debug_first_database_message_id << " " << d->debug_last_database_message_id; + postponed_get_message_requests_[d->dialog_id].emplace_back(message_id, std::move(promise), + std::move(input_message)); + get_channel_difference(d->dialog_id, d->pts, true, "get_message"); + } else { + promise.set_value(Unit()); + } + return; } - return; - } - if (d->deleted_message_ids.count(message_id) == 0 && dialog_type != DialogType::SecretChat) { - return get_message_from_server({d->dialog_id, message_id}, std::move(promise), std::move(input_message)); - } - } else if (m == nullptr && message_id.is_valid_scheduled() && message_id.is_scheduled_server()) { - if (d->deleted_scheduled_server_message_ids.count(message_id.get_scheduled_server_message_id()) == 0 && - dialog_type != DialogType::SecretChat && input_message == nullptr) { - return get_message_from_server({d->dialog_id, message_id}, std::move(promise)); + if (d->deleted_message_ids.count(message_id) == 0 && dialog_type != DialogType::SecretChat) { + return get_message_from_server({d->dialog_id, message_id}, std::move(promise), std::move(input_message)); + } + } else if (message_id.is_valid_scheduled() && message_id.is_scheduled_server()) { + if (d->deleted_scheduled_server_message_ids.count(message_id.get_scheduled_server_message_id()) == 0 && + dialog_type != DialogType::SecretChat && input_message == nullptr) { + return get_message_from_server({d->dialog_id, message_id}, std::move(promise)); + } } } @@ -15571,42 +15576,95 @@ bool MessagesManager::is_message_edited_recently(FullMessageId full_message_id, } std::pair MessagesManager::get_public_message_link(FullMessageId full_message_id, bool for_group, - Promise &&promise) { + 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(6, "Chat not found")); + promise.set_error(Status::Error(400, "Chat not found")); return {}; } if (!have_input_peer(dialog_id, AccessRights::Read)) { - promise.set_error(Status::Error(6, "Can't access the chat")); + promise.set_error(Status::Error(400, "Can't access the chat")); return {}; } if (dialog_id.get_type() != DialogType::Channel || td_->contacts_manager_->get_channel_username(dialog_id.get_channel_id()).empty()) { promise.set_error(Status::Error( - 6, "Public message links are available only for messages in supergroups and channel chats with a username")); + 400, "Public message links are available only for messages in supergroups and channel chats with a username")); return {}; } auto *m = get_message_force(d, full_message_id.get_message_id(), "get_public_message_link"); if (m == nullptr) { - promise.set_error(Status::Error(6, "Message not found")); + promise.set_error(Status::Error(400, "Message not found")); return {}; } if (m->message_id.is_yet_unsent()) { - promise.set_error(Status::Error(6, "Message is yet unsent")); + promise.set_error(Status::Error(400, "Message is yet unsent")); return {}; } if (m->message_id.is_scheduled()) { - promise.set_error(Status::Error(6, "Message is scheduled")); + promise.set_error(Status::Error(400, "Message is scheduled")); return {}; } if (!m->message_id.is_server()) { - promise.set_error(Status::Error(6, "Message is local")); + promise.set_error(Status::Error(400, "Message is local")); return {}; } + if (m->media_album_id == 0) { + for_group = true; // default is true + } + + string comment_link; + if (!m->top_reply_message_id.is_valid()) { + for_comment = false; + } + if (d->deleted_message_ids.count(m->top_reply_message_id) != 0) { + for_comment = false; + } + if (for_comment) { + CHECK(dialog_id.get_type() == DialogType::Channel); // only channel messages can have top_reply_message_id + 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 || + !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) { + for_comment = false; + } else { + auto linked_dialog_id = top_m->forward_info->sender_dialog_id; + auto linked_message_id = top_m->forward_info->message_id; + auto linked_d = get_dialog(linked_dialog_id); + CHECK(linked_d != nullptr); + CHECK(linked_dialog_id.get_type() == DialogType::Channel); + if (!have_input_peer(linked_dialog_id, AccessRights::Read) || + td_->contacts_manager_->get_channel_username(linked_dialog_id.get_channel_id()).empty() || + linked_d->deleted_message_ids.count(linked_message_id) != 0) { + for_comment = false; + } else { + 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 {}; + } + + auto it = public_message_links_[for_group].find({linked_dialog_id, linked_message_id}); + if (it == public_message_links_[for_group].end()) { + td_->create_handler(std::move(promise)) + ->send(linked_dialog_id.get_channel_id(), linked_message_id, for_group, false); + return {}; + } + + comment_link = PSTRING() << it->second.first << (it->second.first.find('?') == string::npos ? '?' : '&') + << "comment_id=" << m->message_id.get_server_message_id().get(); + } + } + } + auto it = public_message_links_[for_group].find(full_message_id); if (it == public_message_links_[for_group].end()) { td_->create_handler(std::move(promise)) @@ -15615,7 +15673,11 @@ std::pair MessagesManager::get_public_message_link(FullMessageId } promise.set_value(Unit()); - return it->second; + if (for_comment) { + 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, @@ -15628,30 +15690,30 @@ string MessagesManager::get_message_link(FullMessageId full_message_id, 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(6, "Chat not found")); + promise.set_error(Status::Error(400, "Chat not found")); return {}; } if (!have_input_peer(dialog_id, AccessRights::Read)) { - promise.set_error(Status::Error(6, "Can't access the chat")); + promise.set_error(Status::Error(400, "Can't access the chat")); return {}; } if (dialog_id.get_type() != DialogType::Channel) { promise.set_error( - Status::Error(6, "Message links are available only for messages in supergroups and channel chats")); + 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(6, "Message not found")); + promise.set_error(Status::Error(400, "Message not found")); return {}; } if (m->message_id.is_scheduled()) { - promise.set_error(Status::Error(6, "Message is scheduled")); + promise.set_error(Status::Error(400, "Message is scheduled")); return {}; } if (!m->message_id.is_server()) { - promise.set_error(Status::Error(6, "Message is local")); + promise.set_error(Status::Error(400, "Message is local")); return {}; } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index be15f8689..1bf891e62 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -562,7 +562,7 @@ 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, + std::pair get_public_message_link(FullMessageId full_message_id, bool for_group, bool &for_comment, Promise &&promise); void on_get_public_message_link(FullMessageId full_message_id, bool for_group, string url, string html); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 1b2c6501e..e7e8e375f 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1093,13 +1093,14 @@ 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_, std::move(promise)); + td->messages_manager_->get_public_message_link(full_message_id_, for_group_, for_comment_, std::move(promise)); } void do_send_result() override { @@ -1107,10 +1108,13 @@ class GetPublicMessageLinkRequest : public RequestActor<> { } public: - GetPublicMessageLinkRequest(ActorShared td, uint64 request_id, int64 dialog_id, int64 message_id, bool for_group) + 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_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 } }; @@ -5100,7 +5104,8 @@ void Td::on_request(uint64 id, const td_api::getMessages &request) { 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_); + 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) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 09b2966d7..d9c871ba7 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2615,10 +2615,12 @@ class CliClient final : public Actor { string chat_id; string message_id; string for_album; + string for_comment; std::tie(chat_id, args) = split(args); - std::tie(message_id, for_album) = 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_album), as_bool(for_comment))); } else if (op == "gmlink") { string chat_id; string message_id; From e082b2ac490765a5c26ba2833d06fac46aa924df Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 14 Sep 2020 01:39:34 +0300 Subject: [PATCH 20/22] Store public message links separately for each dialog. GitOrigin-RevId: 2b227d07c8ec7c42cabd7af78ffde3ff07799f92 --- td/telegram/MessagesManager.cpp | 13 ++++++++----- td/telegram/MessagesManager.h | 5 ++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index ee8a9f413..8127db0f9 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -15652,8 +15652,9 @@ std::pair MessagesManager::get_public_message_link(FullMessageId return {}; } - auto it = public_message_links_[for_group].find({linked_dialog_id, linked_message_id}); - if (it == public_message_links_[for_group].end()) { + auto &links = public_message_links_[for_group][linked_dialog_id].links_; + auto it = links.find(linked_message_id); + if (it == links.end()) { td_->create_handler(std::move(promise)) ->send(linked_dialog_id.get_channel_id(), linked_message_id, for_group, false); return {}; @@ -15665,8 +15666,9 @@ std::pair MessagesManager::get_public_message_link(FullMessageId } } - auto it = public_message_links_[for_group].find(full_message_id); - if (it == public_message_links_[for_group].end()) { + 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 {}; @@ -15683,7 +15685,8 @@ std::pair MessagesManager::get_public_message_link(FullMessageId 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] = {std::move(url), std::move(html)}; + 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, Promise &&promise) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 1bf891e62..681f5fbdb 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2978,7 +2978,10 @@ class MessagesManager : public Actor { std::unordered_map found_fts_messages_; // random_id -> FoundMessages std::unordered_map found_message_public_forwards_; // random_id -> FoundMessages - std::unordered_map, FullMessageIdHash> public_message_links_[2]; + struct PublicMessageLinks { + std::unordered_map, MessageIdHash> links_; + }; + std::unordered_map public_message_links_[2]; std::unordered_map> chat_events_; // random_id -> chat events From d940b861133d4a20a43eeab2dca8e3270666b7b3 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 14 Sep 2020 01:44:55 +0300 Subject: [PATCH 21/22] Drop public message links from cache when dialog username changes. GitOrigin-RevId: 008652cfb854f5298c7e9522fc086c78f1a66ecd --- td/telegram/MessagesManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 8127db0f9..3fcc4b106 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -27325,6 +27325,10 @@ void MessagesManager::on_dialog_username_updated(DialogId dialog_id, const strin if (d != nullptr) { update_dialogs_hints(d); } + if (old_username != new_username) { + public_message_links_[0].erase(dialog_id); + public_message_links_[1].erase(dialog_id); + } if (!old_username.empty() && old_username != new_username) { resolved_usernames_.erase(clean_username(old_username)); inaccessible_resolved_usernames_.erase(clean_username(old_username)); From a6463970b1b6c88d81cd0360446248abb348f1b0 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 14 Sep 2020 02:23:02 +0300 Subject: [PATCH 22/22] Delete received empty channel messages. GitOrigin-RevId: f6754fb7381c2e72983874033ac1e2bbc2293c89 --- td/telegram/MessagesManager.cpp | 33 ++++++++++++++++++++++++++++----- td/telegram/MessagesManager.h | 9 ++++++--- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 3fcc4b106..ff9a1b94a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -454,6 +454,16 @@ class GetChannelMessagesQuery : public Td::ResultHandler { auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetChannelMessagesQuery"); LOG_IF(ERROR, !info.is_channel_messages) << "Receive ordinary messages in GetChannelMessagesQuery"; + vector empty_message_ids; + for (auto &message : info.messages) { + if (message->get_id() == telegram_api::messageEmpty::ID) { + auto message_id = MessagesManager::get_message_id(message, false); + if (message_id.is_valid()) { + empty_message_ids.push_back(message_id); + } + } + } + td->messages_manager_->on_get_empty_messages(DialogId(channel_id_), std::move(empty_message_ids)); td->messages_manager_->on_get_messages(std::move(info.messages), info.is_channel_messages, false, "GetChannelMessagesQuery"); @@ -6838,7 +6848,7 @@ void MessagesManager::process_channel_update(tl_object_ptr } auto dialog_id = DialogId(channel_id); - delete_dialog_messages_from_updates(dialog_id, message_ids); + delete_dialog_messages_from_updates(dialog_id, message_ids, false); break; } case telegram_api::updateEditChannelMessage::ID: { @@ -8332,6 +8342,12 @@ void MessagesManager::after_get_difference() { } } +void MessagesManager::on_get_empty_messages(DialogId dialog_id, vector empty_message_ids) { + if (!empty_message_ids.empty()) { + delete_dialog_messages_from_updates(dialog_id, std::move(empty_message_ids), true); + } +} + MessagesManager::MessagesInfo MessagesManager::on_get_messages( tl_object_ptr &&messages_ptr, const char *source) { CHECK(messages_ptr != nullptr); @@ -9087,7 +9103,8 @@ void MessagesManager::delete_messages_from_updates(const vector &mess } } -void MessagesManager::delete_dialog_messages_from_updates(DialogId dialog_id, const vector &message_ids) { +void MessagesManager::delete_dialog_messages_from_updates(DialogId dialog_id, const vector &message_ids, + bool skip_update_for_not_found_messages) { CHECK(dialog_id.get_type() == DialogType::Channel || dialog_id.get_type() == DialogType::SecretChat); Dialog *d = get_dialog_force(dialog_id); if (d == nullptr) { @@ -9105,7 +9122,13 @@ void MessagesManager::delete_dialog_messages_from_updates(DialogId dialog_id, co } auto message = delete_message(d, message_id, true, &need_update_dialog_pos, "updates"); - deleted_message_ids.push_back(message == nullptr ? message_id.get() : message->message_id.get()); + if (message == nullptr) { + if (!skip_update_for_not_found_messages) { + deleted_message_ids.push_back(message_id.get()); + } + } else { + deleted_message_ids.push_back(message->message_id.get()); + } } if (need_update_dialog_pos) { send_update_chat_last_message(d, "delete_dialog_messages_from_updates"); @@ -11030,7 +11053,7 @@ void MessagesManager::ttl_loop(double now) { } } for (auto &it : to_delete) { - delete_dialog_messages_from_updates(it.first, it.second); + delete_dialog_messages_from_updates(it.first, it.second, false); } ttl_update_timeout(now); } @@ -11733,7 +11756,7 @@ void MessagesManager::finish_delete_secret_messages(DialogId dialog_id, std::vec LOG(INFO) << "Skip deletion of service " << message_id; } } - delete_dialog_messages_from_updates(dialog_id, to_delete_message_ids); + delete_dialog_messages_from_updates(dialog_id, to_delete_message_ids, false); } void MessagesManager::delete_secret_chat_history(SecretChatId secret_chat_id, MessageId last_message_id, diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 681f5fbdb..dd6401861 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -194,6 +194,8 @@ class MessagesManager : public Actor { static vector get_scheduled_server_message_ids(const vector &message_ids); + static MessageId get_message_id(const tl_object_ptr &message_ptr, bool is_scheduled); + DialogId get_message_dialog_id(const tl_object_ptr &message_ptr) const; tl_object_ptr get_input_peer(DialogId dialog_id, AccessRights access_rights) const; @@ -214,6 +216,8 @@ class MessagesManager : public Actor { bool have_input_peer(DialogId dialog_id, AccessRights access_rights) const; + void on_get_empty_messages(DialogId dialog_id, vector empty_message_ids); + struct MessagesInfo { vector> messages; int32 total_count = 0; @@ -1634,8 +1638,6 @@ class MessagesManager : public Actor { static constexpr bool DROP_UPDATES = false; - static MessageId get_message_id(const tl_object_ptr &message_ptr, bool is_scheduled); - FullMessageId get_full_message_id(const tl_object_ptr &message_ptr, bool is_scheduled) const; static int32 get_message_date(const tl_object_ptr &message_ptr); @@ -1741,7 +1743,8 @@ class MessagesManager : public Actor { void delete_messages_from_updates(const vector &message_ids); - void delete_dialog_messages_from_updates(DialogId dialog_id, const vector &message_ids); + void delete_dialog_messages_from_updates(DialogId dialog_id, const vector &message_ids, + bool skip_update_for_not_found_messages); void do_forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, const vector &messages, const vector &message_ids, uint64 logevent_id);