diff --git a/CMakeLists.txt b/CMakeLists.txt index 298a1f679..1e50486f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -454,6 +454,7 @@ set(TDLIB_SOURCE td/telegram/ReactionManager.cpp td/telegram/ReactionType.cpp td/telegram/RecentDialogList.cpp + td/telegram/RepliedMessageInfo.cpp td/telegram/ReplyMarkup.cpp td/telegram/ReportReason.cpp td/telegram/RequestedDialogType.cpp @@ -763,6 +764,7 @@ set(TDLIB_SOURCE td/telegram/ReactionManager.h td/telegram/ReactionType.h td/telegram/RecentDialogList.h + td/telegram/RepliedMessageInfo.h td/telegram/ReplyMarkup.h td/telegram/ReportReason.h td/telegram/RequestActor.h diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index ca98d1a85..56aad77a3 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -5716,8 +5716,8 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const } unique_ptr get_action_message_content(Td *td, tl_object_ptr &&action_ptr, - DialogId owner_dialog_id, DialogId reply_in_dialog_id, - MessageId reply_to_message_id) { + DialogId owner_dialog_id, + const RepliedMessageInfo &replied_message_info) { CHECK(action_ptr != nullptr); switch (action_ptr->get_id()) { @@ -5812,12 +5812,7 @@ unique_ptr get_action_message_content(Td *td, tl_object_ptr(std::move(action->title_), chat_id); } case telegram_api::messageActionPinMessage::ID: { - if (reply_in_dialog_id.is_valid() && reply_in_dialog_id != owner_dialog_id) { - LOG(ERROR) << "Receive pinned message with " << reply_to_message_id << " in " << owner_dialog_id - << " in another " << reply_in_dialog_id; - reply_to_message_id = MessageId(); - reply_in_dialog_id = DialogId(); - } + auto reply_to_message_id = replied_message_info.get_same_chat_reply_to_message_id(); if (!reply_to_message_id.is_valid()) { // possible in basic groups LOG(INFO) << "Receive pinned message with " << reply_to_message_id << " in " << owner_dialog_id; @@ -5826,12 +5821,7 @@ unique_ptr get_action_message_content(Td *td, tl_object_ptr(reply_to_message_id); } case telegram_api::messageActionGameScore::ID: { - if (reply_in_dialog_id.is_valid() && reply_in_dialog_id != owner_dialog_id) { - LOG(ERROR) << "Receive game score with " << reply_to_message_id << " in " << owner_dialog_id << " in another " - << reply_in_dialog_id; - reply_to_message_id = MessageId(); - reply_in_dialog_id = DialogId(); - } + auto reply_to_message_id = replied_message_info.get_same_chat_reply_to_message_id(); if (!reply_to_message_id.is_valid()) { // possible in basic groups LOG(INFO) << "Receive game score with " << reply_to_message_id << " in " << owner_dialog_id; @@ -5856,20 +5846,20 @@ unique_ptr get_action_message_content(Td *td, tl_object_ptr(action_ptr); - if (!reply_to_message_id.is_valid()) { - if (reply_to_message_id != MessageId()) { - LOG(ERROR) << "Receive successful payment message with " << reply_to_message_id << " in " << owner_dialog_id; + auto message_full_id = replied_message_info.get_reply_message_full_id(); + if (!message_full_id.get_message_id().is_valid()) { + if (message_full_id.get_message_id() != MessageId()) { + LOG(ERROR) << "Receive successful payment message with " << message_full_id << " in " << owner_dialog_id; } - reply_in_dialog_id = DialogId(); - reply_to_message_id = MessageId(); + message_full_id = {}; } if (action->total_amount_ <= 0 || !check_currency_amount(action->total_amount_)) { LOG(ERROR) << "Receive invalid total amount " << action->total_amount_; action->total_amount_ = 0; } return td::make_unique( - reply_in_dialog_id, reply_to_message_id, std::move(action->currency_), action->total_amount_, - std::move(action->invoice_slug_), action->recurring_used_, action->recurring_init_); + message_full_id.get_dialog_id(), message_full_id.get_message_id(), std::move(action->currency_), + action->total_amount_, std::move(action->invoice_slug_), action->recurring_used_, action->recurring_init_); } case telegram_api::messageActionPaymentSentMe::ID: { if (!td->auth_manager_->is_bot()) { @@ -6069,17 +6059,15 @@ unique_ptr get_action_message_content(Td *td, tl_object_ptr(MessageId(), std::move(background_info)); } case telegram_api::messageActionSetSameChatWallPaper::ID: { - if (reply_in_dialog_id.is_valid() && reply_in_dialog_id != owner_dialog_id) { - LOG(ERROR) << "Receive old background message with " << reply_to_message_id << " in " << owner_dialog_id - << " in another " << reply_in_dialog_id; - reply_to_message_id = MessageId(); - reply_in_dialog_id = DialogId(); - } auto action = move_tl_object_as(action_ptr); BackgroundInfo background_info(td, std::move(action->wallpaper_)); if (!background_info.is_valid()) { break; } + auto reply_to_message_id = replied_message_info.get_same_chat_reply_to_message_id(); + if (!reply_to_message_id.is_valid()) { + reply_to_message_id = MessageId(); + } return make_unique(reply_to_message_id, std::move(background_info)); } case telegram_api::messageActionGiveawayLaunch::ID: diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index f26dba201..fe5431561 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -18,6 +18,7 @@ #include "td/telegram/MessageFullId.h" #include "td/telegram/MessageId.h" #include "td/telegram/Photo.h" +#include "td/telegram/RepliedMessageInfo.h" #include "td/telegram/ReplyMarkup.h" #include "td/telegram/secret_api.h" #include "td/telegram/SecretInputMedia.h" @@ -221,8 +222,8 @@ unique_ptr dup_message_content(Td *td, DialogId dialog_id, const MessageContentDupType type, MessageCopyOptions &©_options); unique_ptr get_action_message_content(Td *td, tl_object_ptr &&action_ptr, - DialogId owner_dialog_id, DialogId reply_in_dialog_id, - MessageId reply_to_message_id); + DialogId owner_dialog_id, + const RepliedMessageInfo &replied_message_info); tl_object_ptr get_message_content_object(const MessageContent *content, Td *td, DialogId dialog_id, int32 message_date, diff --git a/td/telegram/MessageReplyHeader.cpp b/td/telegram/MessageReplyHeader.cpp index a4730c4d2..715df65ee 100644 --- a/td/telegram/MessageReplyHeader.cpp +++ b/td/telegram/MessageReplyHeader.cpp @@ -34,68 +34,24 @@ MessageReplyHeader::MessageReplyHeader(Td *td, tl_object_ptrget_id() == telegram_api::messageReplyHeader::ID); auto reply_header = telegram_api::move_object_as(reply_header_ptr); - if (reply_header->reply_to_scheduled_) { - reply_to_message_id_ = MessageId(ScheduledServerMessageId(reply_header->reply_to_msg_id_), date); - if (message_id.is_scheduled()) { - auto reply_to_peer_id = std::move(reply_header->reply_to_peer_id_); - if (reply_to_peer_id != nullptr) { - reply_in_dialog_id_ = DialogId(reply_to_peer_id); - LOG(ERROR) << "Receive reply to " << MessageFullId{reply_in_dialog_id_, reply_to_message_id_} << " in " - << MessageFullId{dialog_id, message_id}; - reply_to_message_id_ = MessageId(); - reply_in_dialog_id_ = DialogId(); - } - } else { - LOG(ERROR) << "Receive reply to " << reply_to_message_id_ << " in " << MessageFullId{dialog_id, message_id}; - reply_to_message_id_ = MessageId(); - } - if (reply_header->reply_from_ != nullptr || reply_header->reply_media_ != nullptr || - !reply_header->quote_text_.empty() || !reply_header->quote_entities_.empty()) { - LOG(ERROR) << "Receive reply from other chat " << to_string(reply_header) << " in " - << MessageFullId{dialog_id, message_id}; - } - } else { - if (reply_header->reply_to_msg_id_ != 0) { - reply_to_message_id_ = MessageId(ServerMessageId(reply_header->reply_to_msg_id_)); - auto reply_to_peer_id = std::move(reply_header->reply_to_peer_id_); - if (reply_to_peer_id != nullptr) { - reply_in_dialog_id_ = DialogId(reply_to_peer_id); - if (!reply_in_dialog_id_.is_valid()) { - LOG(ERROR) << "Receive reply in invalid " << to_string(reply_to_peer_id); - reply_to_message_id_ = MessageId(); - reply_in_dialog_id_ = DialogId(); - } - if (reply_in_dialog_id_ == dialog_id) { - reply_in_dialog_id_ = DialogId(); // just in case - } - } - if (!reply_to_message_id_.is_valid()) { - LOG(ERROR) << "Receive " << to_string(reply_header) << " in " << MessageFullId{dialog_id, message_id}; - reply_to_message_id_ = MessageId(); - reply_in_dialog_id_ = DialogId(); - } - } else if (reply_header->reply_to_peer_id_ != nullptr) { - LOG(ERROR) << "Receive " << to_string(reply_header) << " in " << MessageFullId{dialog_id, message_id}; - } - if (reply_header->reply_from_ != nullptr) { - reply_date_ = reply_header->reply_from_->date_; - if (reply_header->reply_from_->channel_post_ != 0) { - LOG(ERROR) << "Receive " << to_string(reply_header) << " in " << MessageFullId{dialog_id, message_id}; - } else { - auto r_reply_origin = MessageOrigin::get_message_origin(td, std::move(reply_header->reply_from_)); - if (r_reply_origin.is_error()) { - reply_date_ = 0; - } - } - } - } + if (!message_id.is_scheduled() && can_have_thread) { if ((reply_header->flags_ & telegram_api::messageReplyHeader::REPLY_TO_TOP_ID_MASK) != 0) { top_thread_message_id_ = MessageId(ServerMessageId(reply_header->reply_to_top_id_)); - } else if (reply_to_message_id_.is_valid() && !reply_in_dialog_id_.is_valid() && reply_date_ == 0) { - top_thread_message_id_ = reply_to_message_id_; } - is_topic_message_ = top_thread_message_id_.is_valid() && reply_header->forum_topic_; + is_topic_message_ = reply_header->forum_topic_; + } + + replied_message_info_ = RepliedMessageInfo(td, std::move(reply_header), dialog_id, message_id, date); + + if (!message_id.is_scheduled() && can_have_thread && !top_thread_message_id_.is_valid()) { + auto same_chat_reply_to_message_id = replied_message_info_.get_same_chat_reply_to_message_id(); + if (same_chat_reply_to_message_id.is_valid()) { + CHECK(same_chat_reply_to_message_id.is_server()); + top_thread_message_id_ = same_chat_reply_to_message_id; + } else { + is_topic_message_ = false; + } } } diff --git a/td/telegram/MessageReplyHeader.h b/td/telegram/MessageReplyHeader.h index 667d072cb..0feeedf19 100644 --- a/td/telegram/MessageReplyHeader.h +++ b/td/telegram/MessageReplyHeader.h @@ -6,9 +6,8 @@ // #pragma once -#include "td/telegram/DialogId.h" #include "td/telegram/MessageId.h" -#include "td/telegram/MessageOrigin.h" +#include "td/telegram/RepliedMessageInfo.h" #include "td/telegram/StoryFullId.h" #include "td/telegram/telegram_api.h" @@ -19,10 +18,8 @@ namespace td { class Td; struct MessageReplyHeader { - MessageId reply_to_message_id_; - DialogId reply_in_dialog_id_; - int32 reply_date_ = 0; // for replies in other chats - MessageOrigin reply_origin_; // for replies in other chats + RepliedMessageInfo replied_message_info_; + MessageId top_thread_message_id_; bool is_topic_message_ = false; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index eed6ca800..74e037e5a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -61,6 +61,7 @@ #include "td/telegram/PollId.h" #include "td/telegram/PublicDialogType.h" #include "td/telegram/ReactionManager.h" +#include "td/telegram/RepliedMessageInfo.h" #include "td/telegram/ReplyMarkup.h" #include "td/telegram/ReplyMarkup.hpp" #include "td/telegram/ReportReason.h" @@ -14024,17 +14025,17 @@ void MessagesManager::on_get_secret_message(SecretChatId secret_chat_id, UserId auto lock_promise = pending_secret_message->load_data_multipromise.get_promise(); if ((message->flags_ & secret_api::decryptedMessage::REPLY_TO_RANDOM_ID_MASK) != 0) { - message_info.reply_header.reply_to_message_id_ = - get_message_id_by_random_id(d, message->reply_to_random_id_, "on_get_secret_message"); - if (!message_info.reply_header.reply_to_message_id_.is_valid()) { + auto reply_to_message_id = get_message_id_by_random_id(d, message->reply_to_random_id_, "on_get_secret_message"); + if (!reply_to_message_id.is_valid()) { auto dialog_it = pending_secret_message_ids_.find(message_info.dialog_id); if (dialog_it != pending_secret_message_ids_.end()) { auto message_it = dialog_it->second.find(message->reply_to_random_id_); if (message_it != dialog_it->second.end()) { - message_info.reply_header.reply_to_message_id_ = message_it->second; + reply_to_message_id = message_it->second; } } } + message_info.reply_header.replied_message_info_ = RepliedMessageInfo(reply_to_message_id); } if (!clean_input_string(message->via_bot_name_)) { @@ -14318,10 +14319,8 @@ MessagesManager::MessageInfo MessagesManager::parse_telegram_api_message( message_info.reply_header = MessageReplyHeader(td_, std::move(message->reply_to_), message_info.dialog_id, message_info.message_id, message_info.date, can_have_thread); message_info.content = get_action_message_content(td_, std::move(message->action_), message_info.dialog_id, - message_info.reply_header.reply_in_dialog_id_, - message_info.reply_header.reply_to_message_id_); - message_info.reply_header.reply_in_dialog_id_ = DialogId(); - message_info.reply_header.reply_to_message_id_ = MessageId(); + message_info.reply_header.replied_message_info_); + message_info.reply_header.replied_message_info_ = RepliedMessageInfo(); message_info.reply_header.story_full_id_ = StoryFullId(); break; } @@ -14428,8 +14427,9 @@ std::pair> MessagesManager::creat date = 1; } - MessageId reply_to_message_id = message_info.reply_header.reply_to_message_id_; - DialogId reply_in_dialog_id = message_info.reply_header.reply_in_dialog_id_; + auto reply_message_full_id = message_info.reply_header.replied_message_info_.get_reply_message_full_id(); + MessageId reply_to_message_id = reply_message_full_id.get_message_id(); + DialogId reply_in_dialog_id = reply_message_full_id.get_dialog_id(); MessageId top_thread_message_id = message_info.reply_header.top_thread_message_id_; bool is_topic_message = message_info.reply_header.is_topic_message_; fix_server_reply_to_message_id(dialog_id, message_id, reply_in_dialog_id, reply_to_message_id); diff --git a/td/telegram/RepliedMessageInfo.cpp b/td/telegram/RepliedMessageInfo.cpp new file mode 100644 index 000000000..ac06a0fec --- /dev/null +++ b/td/telegram/RepliedMessageInfo.cpp @@ -0,0 +1,87 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/RepliedMessageInfo.h" + +#include "td/telegram/MessageFullId.h" +#include "td/telegram/ScheduledServerMessageId.h" +#include "td/telegram/ServerMessageId.h" +#include "td/telegram/StoryId.h" +#include "td/telegram/UserId.h" + +#include "td/utils/logging.h" + +namespace td { + +RepliedMessageInfo::RepliedMessageInfo(Td *td, tl_object_ptr &&reply_header, + DialogId dialog_id, MessageId message_id, int32 date) { + CHECK(reply_header != nullptr); + if (reply_header->reply_to_scheduled_) { + reply_to_message_id_ = MessageId(ScheduledServerMessageId(reply_header->reply_to_msg_id_), date); + if (message_id.is_scheduled()) { + auto reply_to_peer_id = std::move(reply_header->reply_to_peer_id_); + if (reply_to_peer_id != nullptr) { + reply_in_dialog_id_ = DialogId(reply_to_peer_id); + LOG(ERROR) << "Receive reply to " << MessageFullId{reply_in_dialog_id_, reply_to_message_id_} << " in " + << MessageFullId{dialog_id, message_id}; + reply_to_message_id_ = MessageId(); + reply_in_dialog_id_ = DialogId(); + } + } else { + LOG(ERROR) << "Receive reply to " << reply_to_message_id_ << " in " << MessageFullId{dialog_id, message_id}; + reply_to_message_id_ = MessageId(); + } + if (reply_header->reply_from_ != nullptr || reply_header->reply_media_ != nullptr || + !reply_header->quote_text_.empty() || !reply_header->quote_entities_.empty()) { + LOG(ERROR) << "Receive reply from other chat " << to_string(reply_header) << " in " + << MessageFullId{dialog_id, message_id}; + } + } else { + if (reply_header->reply_to_msg_id_ != 0) { + reply_to_message_id_ = MessageId(ServerMessageId(reply_header->reply_to_msg_id_)); + auto reply_to_peer_id = std::move(reply_header->reply_to_peer_id_); + if (reply_to_peer_id != nullptr) { + reply_in_dialog_id_ = DialogId(reply_to_peer_id); + if (!reply_in_dialog_id_.is_valid()) { + LOG(ERROR) << "Receive reply in invalid " << to_string(reply_to_peer_id); + reply_to_message_id_ = MessageId(); + reply_in_dialog_id_ = DialogId(); + } + if (reply_in_dialog_id_ == dialog_id) { + reply_in_dialog_id_ = DialogId(); // just in case + } + } + if (!reply_to_message_id_.is_valid()) { + LOG(ERROR) << "Receive " << to_string(reply_header) << " in " << MessageFullId{dialog_id, message_id}; + reply_to_message_id_ = MessageId(); + reply_in_dialog_id_ = DialogId(); + } + } else if (reply_header->reply_to_peer_id_ != nullptr) { + LOG(ERROR) << "Receive " << to_string(reply_header) << " in " << MessageFullId{dialog_id, message_id}; + } + if (reply_header->reply_from_ != nullptr) { + reply_date_ = reply_header->reply_from_->date_; + if (reply_header->reply_from_->channel_post_ != 0) { + LOG(ERROR) << "Receive " << to_string(reply_header) << " in " << MessageFullId{dialog_id, message_id}; + } else { + auto r_reply_origin = MessageOrigin::get_message_origin(td, std::move(reply_header->reply_from_)); + if (r_reply_origin.is_error()) { + reply_date_ = 0; + } + } + } + } +} + +MessageId RepliedMessageInfo::get_same_chat_reply_to_message_id() const { + return is_same_chat_reply() ? reply_to_message_id_ : MessageId(); +} + +MessageFullId RepliedMessageInfo::get_reply_message_full_id() const { + return {reply_in_dialog_id_, reply_to_message_id_}; +} + +} // namespace td diff --git a/td/telegram/RepliedMessageInfo.h b/td/telegram/RepliedMessageInfo.h new file mode 100644 index 000000000..165259d52 --- /dev/null +++ b/td/telegram/RepliedMessageInfo.h @@ -0,0 +1,44 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/DialogId.h" +#include "td/telegram/MessageId.h" +#include "td/telegram/MessageOrigin.h" +#include "td/telegram/telegram_api.h" + +#include "td/utils/common.h" + +namespace td { + +class Td; + +class RepliedMessageInfo { + public: + MessageId reply_to_message_id_; + DialogId reply_in_dialog_id_; // DialogId() if reply is to a message in the same chat + int32 reply_date_ = 0; // for replies in other chats + MessageOrigin reply_origin_; // for replies in other chats + + RepliedMessageInfo() = default; + + explicit RepliedMessageInfo(MessageId reply_to_message_id) : reply_to_message_id_(reply_to_message_id) { + } + + RepliedMessageInfo(Td *td, tl_object_ptr &&reply_header, DialogId dialog_id, + MessageId message_id, int32 date); + + bool is_same_chat_reply() const { + return reply_in_dialog_id_ == DialogId() && reply_date_ == 0; + } + + MessageId get_same_chat_reply_to_message_id() const; + + MessageFullId get_reply_message_full_id() const; +}; + +} // namespace td