Add class MessageQuote and use it in MessageInputReplyTo and RepliedMessageInfo.

This commit is contained in:
levlam 2024-04-25 15:52:19 +03:00
parent 275cf20362
commit 1f6fdd554a
15 changed files with 378 additions and 158 deletions

View File

@ -420,6 +420,7 @@ set(TDLIB_SOURCE
td/telegram/MessageImportManager.cpp td/telegram/MessageImportManager.cpp
td/telegram/MessageInputReplyTo.cpp td/telegram/MessageInputReplyTo.cpp
td/telegram/MessageOrigin.cpp td/telegram/MessageOrigin.cpp
td/telegram/MessageQuote.cpp
td/telegram/MessageReaction.cpp td/telegram/MessageReaction.cpp
td/telegram/MessageReplyHeader.cpp td/telegram/MessageReplyHeader.cpp
td/telegram/MessageReplyInfo.cpp td/telegram/MessageReplyInfo.cpp
@ -747,6 +748,7 @@ set(TDLIB_SOURCE
td/telegram/MessageInputReplyTo.h td/telegram/MessageInputReplyTo.h
td/telegram/MessageLinkInfo.h td/telegram/MessageLinkInfo.h
td/telegram/MessageOrigin.h td/telegram/MessageOrigin.h
td/telegram/MessageQuote.h
td/telegram/MessageReaction.h td/telegram/MessageReaction.h
td/telegram/MessageReplyHeader.h td/telegram/MessageReplyHeader.h
td/telegram/MessageReplyInfo.h td/telegram/MessageReplyInfo.h
@ -955,6 +957,7 @@ set(TDLIB_SOURCE
td/telegram/MessageForwardInfo.hpp td/telegram/MessageForwardInfo.hpp
td/telegram/MessageInputReplyTo.hpp td/telegram/MessageInputReplyTo.hpp
td/telegram/MessageOrigin.hpp td/telegram/MessageOrigin.hpp
td/telegram/MessageQuote.hpp
td/telegram/MessageReaction.hpp td/telegram/MessageReaction.hpp
td/telegram/MessageReplyInfo.hpp td/telegram/MessageReplyInfo.hpp
td/telegram/MinChannel.hpp td/telegram/MinChannel.hpp

View File

@ -372,6 +372,7 @@ function split_file($file, $chunks, $undo) {
'MessageId' => 'MessageId', 'MessageId' => 'MessageId',
'message_import_manager[_(-](?![.]get[(][)])|MessageImportManager' => 'MessageImportManager', 'message_import_manager[_(-](?![.]get[(][)])|MessageImportManager' => 'MessageImportManager',
'MessageLinkInfo' => 'MessageLinkInfo', 'MessageLinkInfo' => 'MessageLinkInfo',
'MessageQuote' => 'MessageQuote',
'MessageReaction|UnreadMessageReaction|[a-z_]*message[a-z_]*reaction' => 'MessageReaction', 'MessageReaction|UnreadMessageReaction|[a-z_]*message[a-z_]*reaction' => 'MessageReaction',
'[a-z_]*_message_sender' => 'MessageSender', '[a-z_]*_message_sender' => 'MessageSender',
'messages_manager[_(-](?![.]get[(][)])|MessagesManager' => 'MessagesManager', 'messages_manager[_(-](?![.]get[(][)])|MessagesManager' => 'MessagesManager',

View File

@ -650,7 +650,7 @@ MessageInputReplyTo BusinessConnectionManager::create_business_message_input_rep
} }
} }
} }
return MessageInputReplyTo{message_id, DialogId(), std::move(quote), quote_position}; return MessageInputReplyTo{message_id, DialogId(), {std::move(quote), quote_position}};
} }
default: default:
UNREACHABLE(); UNREACHABLE();

View File

@ -10,6 +10,7 @@
#include "td/telegram/InputMessageText.hpp" #include "td/telegram/InputMessageText.hpp"
#include "td/telegram/MessageInputReplyTo.hpp" #include "td/telegram/MessageInputReplyTo.hpp"
#include "td/telegram/MessageQuote.h"
#include "td/telegram/Version.h" #include "td/telegram/Version.h"
#include "td/utils/tl_helpers.h" #include "td/utils/tl_helpers.h"
@ -59,7 +60,7 @@ void DraftMessage::parse(ParserT &parser) {
if (has_legacy_reply_to_message_id) { if (has_legacy_reply_to_message_id) {
MessageId legacy_reply_to_message_id; MessageId legacy_reply_to_message_id;
td::parse(legacy_reply_to_message_id, parser); td::parse(legacy_reply_to_message_id, parser);
message_input_reply_to_ = MessageInputReplyTo{legacy_reply_to_message_id, DialogId(), FormattedText(), 0}; message_input_reply_to_ = MessageInputReplyTo{legacy_reply_to_message_id, DialogId(), MessageQuote()};
} }
if (has_input_message_text) { if (has_input_message_text) {
td::parse(input_message_text_, parser); td::parse(input_message_text_, parser);

View File

@ -55,12 +55,7 @@ MessageInputReplyTo::MessageInputReplyTo(Td *td,
message_id_ = message_id; message_id_ = message_id;
dialog_id_ = dialog_id; dialog_id_ = dialog_id;
if (!reply_to->quote_text_.empty()) { quote_ = MessageQuote(td, reply_to);
quote_ = get_formatted_text(td->user_manager_.get(), std::move(reply_to->quote_text_),
std::move(reply_to->quote_entities_), true, true, false, "inputReplyToMessage");
remove_unallowed_quote_entities(quote_);
quote_position_ = max(0, reply_to->quote_offset_);
}
break; break;
} }
default: default:
@ -70,7 +65,7 @@ MessageInputReplyTo::MessageInputReplyTo(Td *td,
void MessageInputReplyTo::add_dependencies(Dependencies &dependencies) const { void MessageInputReplyTo::add_dependencies(Dependencies &dependencies) const {
dependencies.add_dialog_and_dependencies(dialog_id_); dependencies.add_dialog_and_dependencies(dialog_id_);
add_formatted_text_dependencies(dependencies, &quote_); // just in case quote_.add_dependencies(dependencies);
dependencies.add_dialog_and_dependencies(story_full_id_.get_dialog_id()); // just in case dependencies.add_dialog_and_dependencies(story_full_id_.get_dialog_id()); // just in case
} }
@ -108,19 +103,11 @@ telegram_api::object_ptr<telegram_api::InputReplyTo> MessageInputReplyTo::get_in
} }
flags |= telegram_api::inputReplyToMessage::REPLY_TO_PEER_ID_MASK; flags |= telegram_api::inputReplyToMessage::REPLY_TO_PEER_ID_MASK;
} }
if (!quote_.text.empty()) { auto result = telegram_api::make_object<telegram_api::inputReplyToMessage>(
flags |= telegram_api::inputReplyToMessage::QUOTE_TEXT_MASK;
}
auto quote_entities = get_input_message_entities(td->user_manager_.get(), quote_.entities, "get_input_reply_to");
if (!quote_entities.empty()) {
flags |= telegram_api::inputReplyToMessage::QUOTE_ENTITIES_MASK;
}
if (quote_position_ != 0) {
flags |= telegram_api::inputReplyToMessage::QUOTE_OFFSET_MASK;
}
return telegram_api::make_object<telegram_api::inputReplyToMessage>(
flags, reply_to_message_id.get_server_message_id().get(), top_thread_message_id.get_server_message_id().get(), flags, reply_to_message_id.get_server_message_id().get(), top_thread_message_id.get_server_message_id().get(),
std::move(input_peer), quote_.text, std::move(quote_entities), quote_position_); std::move(input_peer), string(), Auto(), 0);
quote_.update_input_reply_to_message(td, result.get());
return result;
} }
// only for draft messages // only for draft messages
@ -133,13 +120,9 @@ td_api::object_ptr<td_api::InputMessageReplyTo> MessageInputReplyTo::get_input_m
if (!message_id_.is_valid() && !message_id_.is_valid_scheduled()) { if (!message_id_.is_valid() && !message_id_.is_valid_scheduled()) {
return nullptr; return nullptr;
} }
td_api::object_ptr<td_api::inputTextQuote> quote;
if (!quote_.text.empty()) {
quote = td_api::make_object<td_api::inputTextQuote>(get_formatted_text_object(quote_, true, -1), quote_position_);
}
return td_api::make_object<td_api::inputMessageReplyToMessage>( return td_api::make_object<td_api::inputMessageReplyToMessage>(
td->dialog_manager_->get_chat_id_object(dialog_id_, "inputMessageReplyToMessage"), message_id_.get(), td->dialog_manager_->get_chat_id_object(dialog_id_, "inputMessageReplyToMessage"), message_id_.get(),
std::move(quote)); quote_.get_input_text_quote_object());
} }
MessageId MessageInputReplyTo::get_same_chat_reply_to_message_id() const { MessageId MessageInputReplyTo::get_same_chat_reply_to_message_id() const {
@ -156,8 +139,7 @@ MessageFullId MessageInputReplyTo::get_reply_message_full_id(DialogId owner_dial
bool operator==(const MessageInputReplyTo &lhs, const MessageInputReplyTo &rhs) { bool operator==(const MessageInputReplyTo &lhs, const MessageInputReplyTo &rhs) {
return lhs.message_id_ == rhs.message_id_ && lhs.dialog_id_ == rhs.dialog_id_ && return lhs.message_id_ == rhs.message_id_ && lhs.dialog_id_ == rhs.dialog_id_ &&
lhs.story_full_id_ == rhs.story_full_id_ && lhs.quote_ == rhs.quote_ && lhs.story_full_id_ == rhs.story_full_id_ && lhs.quote_ == rhs.quote_;
lhs.quote_position_ == rhs.quote_position_;
} }
bool operator!=(const MessageInputReplyTo &lhs, const MessageInputReplyTo &rhs) { bool operator!=(const MessageInputReplyTo &lhs, const MessageInputReplyTo &rhs) {
@ -170,13 +152,7 @@ StringBuilder &operator<<(StringBuilder &string_builder, const MessageInputReply
if (input_reply_to.dialog_id_ != DialogId()) { if (input_reply_to.dialog_id_ != DialogId()) {
string_builder << " in " << input_reply_to.dialog_id_; string_builder << " in " << input_reply_to.dialog_id_;
} }
if (!input_reply_to.quote_.text.empty()) { return string_builder << input_reply_to.quote_;
string_builder << " with " << input_reply_to.quote_.text.size() << " quoted bytes";
if (input_reply_to.quote_position_ != 0) {
string_builder << " at position " << input_reply_to.quote_position_;
}
}
return string_builder;
} }
if (input_reply_to.story_full_id_.is_valid()) { if (input_reply_to.story_full_id_.is_valid()) {
return string_builder << input_reply_to.story_full_id_; return string_builder << input_reply_to.story_full_id_;

View File

@ -7,9 +7,9 @@
#pragma once #pragma once
#include "td/telegram/DialogId.h" #include "td/telegram/DialogId.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageFullId.h" #include "td/telegram/MessageFullId.h"
#include "td/telegram/MessageId.h" #include "td/telegram/MessageId.h"
#include "td/telegram/MessageQuote.h"
#include "td/telegram/StoryFullId.h" #include "td/telegram/StoryFullId.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
@ -26,8 +26,7 @@ class Td;
class MessageInputReplyTo { class MessageInputReplyTo {
MessageId message_id_; MessageId message_id_;
DialogId dialog_id_; DialogId dialog_id_;
FormattedText quote_; MessageQuote quote_;
int32 quote_position_ = 0;
// or // or
StoryFullId story_full_id_; StoryFullId story_full_id_;
@ -45,12 +44,8 @@ class MessageInputReplyTo {
MessageInputReplyTo &operator=(MessageInputReplyTo &&) = default; MessageInputReplyTo &operator=(MessageInputReplyTo &&) = default;
~MessageInputReplyTo(); ~MessageInputReplyTo();
MessageInputReplyTo(MessageId message_id, DialogId dialog_id, FormattedText &&quote, int32 quote_position) MessageInputReplyTo(MessageId message_id, DialogId dialog_id, MessageQuote quote)
: message_id_(message_id) : message_id_(message_id), dialog_id_(dialog_id), quote_(std::move(quote)) {
, dialog_id_(dialog_id)
, quote_(std::move(quote))
, quote_position_(max(0, quote_position)) {
remove_unallowed_quote_entities(quote_);
} }
explicit MessageInputReplyTo(StoryFullId story_full_id) : story_full_id_(story_full_id) { explicit MessageInputReplyTo(StoryFullId story_full_id) : story_full_id_(story_full_id) {
@ -67,12 +62,11 @@ class MessageInputReplyTo {
} }
bool has_quote() const { bool has_quote() const {
return !quote_.text.empty(); return !quote_.is_empty();
} }
void set_quote(FormattedText &&quote, int32 quote_position) { void set_quote(MessageQuote quote) {
quote_ = std::move(quote); quote_ = std::move(quote);
quote_position_ = max(0, quote_position);
} }
StoryFullId get_story_full_id() const { StoryFullId get_story_full_id() const {
@ -83,7 +77,7 @@ class MessageInputReplyTo {
if (story_full_id_.is_valid()) { if (story_full_id_.is_valid()) {
return MessageInputReplyTo(story_full_id_); return MessageInputReplyTo(story_full_id_);
} }
return MessageInputReplyTo(message_id_, dialog_id_, FormattedText(quote_), quote_position_); return MessageInputReplyTo(message_id_, dialog_id_, quote_.clone());
} }
void add_dependencies(Dependencies &dependencies) const; void add_dependencies(Dependencies &dependencies) const;

View File

@ -9,6 +9,8 @@
#include "td/telegram/MessageInputReplyTo.h" #include "td/telegram/MessageInputReplyTo.h"
#include "td/telegram/MessageOrigin.hpp" #include "td/telegram/MessageOrigin.hpp"
#include "td/telegram/MessageQuote.h"
#include "td/telegram/MessageQuote.hpp"
#include "td/utils/tl_helpers.h" #include "td/utils/tl_helpers.h"
@ -18,15 +20,15 @@ template <class StorerT>
void MessageInputReplyTo::store(StorerT &storer) const { void MessageInputReplyTo::store(StorerT &storer) const {
bool has_message_id = message_id_.is_valid(); bool has_message_id = message_id_.is_valid();
bool has_story_full_id = story_full_id_.is_valid(); bool has_story_full_id = story_full_id_.is_valid();
bool has_quote = !quote_.text.empty();
bool has_dialog_id = dialog_id_.is_valid(); bool has_dialog_id = dialog_id_.is_valid();
bool has_quote_position = quote_position_ != 0; bool has_quote = !quote_.is_empty();
BEGIN_STORE_FLAGS(); BEGIN_STORE_FLAGS();
STORE_FLAG(has_message_id); STORE_FLAG(has_message_id);
STORE_FLAG(has_story_full_id); STORE_FLAG(has_story_full_id);
STORE_FLAG(has_quote); STORE_FLAG(false);
STORE_FLAG(has_dialog_id); STORE_FLAG(has_dialog_id);
STORE_FLAG(has_quote_position); STORE_FLAG(false);
STORE_FLAG(has_quote);
END_STORE_FLAGS(); END_STORE_FLAGS();
if (has_message_id) { if (has_message_id) {
td::store(message_id_, storer); td::store(message_id_, storer);
@ -34,14 +36,11 @@ void MessageInputReplyTo::store(StorerT &storer) const {
if (has_story_full_id) { if (has_story_full_id) {
td::store(story_full_id_, storer); td::store(story_full_id_, storer);
} }
if (has_quote) {
td::store(quote_, storer);
}
if (has_dialog_id) { if (has_dialog_id) {
td::store(dialog_id_, storer); td::store(dialog_id_, storer);
} }
if (has_quote_position) { if (has_quote) {
td::store(quote_position_, storer); td::store(quote_, storer);
} }
} }
@ -49,15 +48,17 @@ template <class ParserT>
void MessageInputReplyTo::parse(ParserT &parser) { void MessageInputReplyTo::parse(ParserT &parser) {
bool has_message_id; bool has_message_id;
bool has_story_full_id; bool has_story_full_id;
bool has_quote; bool has_quote_legacy;
bool has_dialog_id; bool has_dialog_id;
bool has_quote_position; bool has_quote_position_legacy;
bool has_quote;
BEGIN_PARSE_FLAGS(); BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_message_id); PARSE_FLAG(has_message_id);
PARSE_FLAG(has_story_full_id); PARSE_FLAG(has_story_full_id);
PARSE_FLAG(has_quote); PARSE_FLAG(has_quote_legacy);
PARSE_FLAG(has_dialog_id); PARSE_FLAG(has_dialog_id);
PARSE_FLAG(has_quote_position); PARSE_FLAG(has_quote_position_legacy);
PARSE_FLAG(has_quote);
END_PARSE_FLAGS(); END_PARSE_FLAGS();
if (has_message_id) { if (has_message_id) {
td::parse(message_id_, parser); td::parse(message_id_, parser);
@ -65,15 +66,21 @@ void MessageInputReplyTo::parse(ParserT &parser) {
if (has_story_full_id) { if (has_story_full_id) {
td::parse(story_full_id_, parser); td::parse(story_full_id_, parser);
} }
if (has_quote) { FormattedText quote_legacy;
td::parse(quote_, parser); if (has_quote_legacy) {
remove_unallowed_quote_entities(quote_); td::parse(quote_legacy, parser);
} }
if (has_dialog_id) { if (has_dialog_id) {
td::parse(dialog_id_, parser); td::parse(dialog_id_, parser);
} }
if (has_quote_position) { int32 quote_position_legacy = 0;
td::parse(quote_position_, parser); if (has_quote_position_legacy) {
td::parse(quote_position_legacy, parser);
}
if (has_quote) {
td::parse(quote_, parser);
} else if (has_quote_legacy) {
quote_ = MessageQuote(std::move(quote_legacy), quote_position_legacy);
} }
} }

View File

@ -0,0 +1,137 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
//
// 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/MessageQuote.h"
#include "td/telegram/Dependencies.h"
#include "td/telegram/OptionManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserManager.h"
#include "td/utils/logging.h"
namespace td {
MessageQuote::~MessageQuote() = default;
MessageQuote::MessageQuote(Td *td,
telegram_api::object_ptr<telegram_api::inputReplyToMessage> &input_reply_to_message) {
CHECK(input_reply_to_message != nullptr);
if (input_reply_to_message->quote_text_.empty()) {
return;
}
text_ =
get_formatted_text(td->user_manager_.get(), std::move(input_reply_to_message->quote_text_),
std::move(input_reply_to_message->quote_entities_), true, true, false, "inputReplyToMessage");
remove_unallowed_quote_entities(text_);
position_ = max(0, input_reply_to_message->quote_offset_);
}
MessageQuote::MessageQuote(Td *td, telegram_api::object_ptr<telegram_api::messageReplyHeader> &reply_header) {
CHECK(reply_header != nullptr);
if (reply_header->quote_text_.empty()) {
return;
}
text_ = get_formatted_text(td->user_manager_.get(), std::move(reply_header->quote_text_),
std::move(reply_header->quote_entities_), true, true, false, "messageReplyHeader");
remove_unallowed_quote_entities(text_);
position_ = max(0, reply_header->quote_offset_);
is_manual_ = reply_header->quote_;
}
MessageQuote MessageQuote::clone(bool ignore_is_manual) const {
return {FormattedText(text_), position_, ignore_is_manual ? true : is_manual_};
}
MessageQuote MessageQuote::create_automatic_quote(Td *td, FormattedText &&text) {
remove_unallowed_quote_entities(text);
truncate_formatted_text(
text, static_cast<size_t>(td->option_manager_->get_option_integer("message_reply_quote_length_max")));
return MessageQuote(std::move(text), 0, false);
}
int MessageQuote::need_quote_changed_warning(const MessageQuote &old_quote, const MessageQuote &new_quote) {
if (old_quote.position_ != new_quote.position_ &&
max(old_quote.position_, new_quote.position_) <
static_cast<int32>(min(old_quote.text_.text.size(), new_quote.text_.text.size()))) {
// quote position can't change
return 1;
}
if (old_quote.is_manual_ != new_quote.is_manual_) {
// quote manual property can't change
return 1;
}
if (old_quote.text_ != new_quote.text_) {
if (old_quote.is_manual_) {
return 1;
}
// automatic quote can change if the original message was edited
return -1;
}
return 0;
}
void MessageQuote::add_dependencies(Dependencies &dependencies) const {
add_formatted_text_dependencies(dependencies, &text_); // just in case
}
void MessageQuote::update_input_reply_to_message(Td *td,
telegram_api::inputReplyToMessage *input_reply_to_message) const {
CHECK(input_reply_to_message != nullptr);
if (is_empty()) {
return;
}
CHECK(is_manual_);
input_reply_to_message->flags_ |= telegram_api::inputReplyToMessage::QUOTE_TEXT_MASK;
input_reply_to_message->quote_text_ = text_.text;
input_reply_to_message->quote_entities_ =
get_input_message_entities(td->user_manager_.get(), text_.entities, "update_input_reply_to_message");
if (!input_reply_to_message->quote_entities_.empty()) {
input_reply_to_message->flags_ |= telegram_api::inputReplyToMessage::QUOTE_ENTITIES_MASK;
}
if (position_ != 0) {
input_reply_to_message->flags_ |= telegram_api::inputReplyToMessage::QUOTE_OFFSET_MASK;
input_reply_to_message->quote_offset_ = position_;
}
}
// only for draft messages
td_api::object_ptr<td_api::inputTextQuote> MessageQuote::get_input_text_quote_object() const {
if (is_empty()) {
return nullptr;
}
CHECK(is_manual_);
return td_api::make_object<td_api::inputTextQuote>(get_formatted_text_object(text_, true, -1), position_);
}
td_api::object_ptr<td_api::textQuote> MessageQuote::get_text_quote_object() const {
if (is_empty()) {
return nullptr;
}
return td_api::make_object<td_api::textQuote>(get_formatted_text_object(text_, true, -1), position_, is_manual_);
}
bool operator==(const MessageQuote &lhs, const MessageQuote &rhs) {
return lhs.text_ == rhs.text_ && lhs.position_ == rhs.position_ && lhs.is_manual_ == rhs.is_manual_;
}
bool operator!=(const MessageQuote &lhs, const MessageQuote &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const MessageQuote &quote) {
if (!quote.is_empty()) {
string_builder << " with " << quote.text_.text.size() << (!quote.is_manual_ ? " automatically" : "")
<< " quoted bytes";
if (quote.position_ != 0) {
string_builder << " at position " << quote.position_;
}
}
return string_builder;
}
} // namespace td

View File

@ -0,0 +1,83 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
//
// 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/MessageEntity.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Dependencies;
class Td;
class MessageQuote {
FormattedText text_;
int32 position_ = 0;
bool is_manual_ = true;
friend bool operator==(const MessageQuote &lhs, const MessageQuote &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const MessageQuote &quote);
public:
MessageQuote() = default;
MessageQuote(const MessageQuote &) = delete;
MessageQuote &operator=(const MessageQuote &) = delete;
MessageQuote(MessageQuote &&) = default;
MessageQuote &operator=(MessageQuote &&) = default;
~MessageQuote();
MessageQuote(FormattedText &&text, int32 position, bool is_manual = true)
: text_(std::move(text)), position_(max(0, position)), is_manual_(is_manual) {
remove_unallowed_quote_entities(text_);
}
MessageQuote(Td *td, telegram_api::object_ptr<telegram_api::inputReplyToMessage> &input_reply_to_message);
MessageQuote(Td *td, telegram_api::object_ptr<telegram_api::messageReplyHeader> &reply_header);
static MessageQuote create_automatic_quote(Td *td, FormattedText &&text);
static int need_quote_changed_warning(const MessageQuote &old_quote, const MessageQuote &new_quote);
bool is_empty() const {
return text_.text.empty();
}
bool is_manual() const {
return is_manual_;
}
MessageQuote clone(bool ignore_is_manual = false) const;
void add_dependencies(Dependencies &dependencies) const;
void update_input_reply_to_message(Td *td, telegram_api::inputReplyToMessage *input_reply_to_message) const;
td_api::object_ptr<td_api::inputTextQuote> get_input_text_quote_object() const;
td_api::object_ptr<td_api::textQuote> get_text_quote_object() const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
bool operator==(const MessageQuote &lhs, const MessageQuote &rhs);
bool operator!=(const MessageQuote &lhs, const MessageQuote &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const MessageQuote &quote);
} // namespace td

View File

@ -0,0 +1,50 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
//
// 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/MessageQuote.h"
#include "td/utils/tl_helpers.h"
namespace td {
template <class StorerT>
void MessageQuote::store(StorerT &storer) const {
bool has_text = !text_.text.empty();
bool has_position = position_ != 0;
BEGIN_STORE_FLAGS();
STORE_FLAG(has_text);
STORE_FLAG(has_position);
STORE_FLAG(is_manual_);
END_STORE_FLAGS();
if (has_text) {
td::store(text_, storer);
}
if (has_position) {
td::store(position_, storer);
}
}
template <class ParserT>
void MessageQuote::parse(ParserT &parser) {
bool has_text;
bool has_position;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_text);
PARSE_FLAG(has_position);
PARSE_FLAG(is_manual_);
END_PARSE_FLAGS();
if (has_text) {
td::parse(text_, parser);
remove_unallowed_quote_entities(text_);
}
if (has_position) {
td::parse(position_, parser);
}
}
} // namespace td

View File

@ -49,6 +49,7 @@
#include "td/telegram/MessageForwardInfo.h" #include "td/telegram/MessageForwardInfo.h"
#include "td/telegram/MessageForwardInfo.hpp" #include "td/telegram/MessageForwardInfo.hpp"
#include "td/telegram/MessageOrigin.hpp" #include "td/telegram/MessageOrigin.hpp"
#include "td/telegram/MessageQuote.h"
#include "td/telegram/MessageReaction.h" #include "td/telegram/MessageReaction.h"
#include "td/telegram/MessageReaction.hpp" #include "td/telegram/MessageReaction.hpp"
#include "td/telegram/MessageReplyInfo.hpp" #include "td/telegram/MessageReplyInfo.hpp"
@ -4632,7 +4633,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
if (reply_to_story_full_id.is_valid()) { if (reply_to_story_full_id.is_valid()) {
input_reply_to = MessageInputReplyTo(reply_to_story_full_id); input_reply_to = MessageInputReplyTo(reply_to_story_full_id);
} else if (legacy_reply_to_message_id.is_valid()) { } else if (legacy_reply_to_message_id.is_valid()) {
input_reply_to = MessageInputReplyTo{legacy_reply_to_message_id, DialogId(), FormattedText(), 0}; input_reply_to = MessageInputReplyTo{legacy_reply_to_message_id, DialogId(), MessageQuote()};
} }
} }
if (has_replied_message_info) { if (has_replied_message_info) {
@ -23097,7 +23098,7 @@ MessageInputReplyTo MessagesManager::create_message_input_reply_to(
} }
if (reply_to == nullptr) { if (reply_to == nullptr) {
if (!for_draft && top_thread_message_id.is_valid() && top_thread_message_id.is_server()) { if (!for_draft && top_thread_message_id.is_valid() && top_thread_message_id.is_server()) {
return MessageInputReplyTo{top_thread_message_id, DialogId(), FormattedText(), 0}; return MessageInputReplyTo{top_thread_message_id, DialogId(), MessageQuote()};
} }
return {}; return {};
} }
@ -23125,7 +23126,7 @@ MessageInputReplyTo MessagesManager::create_message_input_reply_to(
if (!message_id.is_valid()) { if (!message_id.is_valid()) {
if (!for_draft && message_id == MessageId() && top_thread_message_id.is_valid() && if (!for_draft && message_id == MessageId() && top_thread_message_id.is_valid() &&
top_thread_message_id.is_server()) { top_thread_message_id.is_server()) {
return MessageInputReplyTo{top_thread_message_id, DialogId(), FormattedText(), 0}; return MessageInputReplyTo{top_thread_message_id, DialogId(), MessageQuote()};
} }
return {}; return {};
} }
@ -23169,10 +23170,10 @@ MessageInputReplyTo MessagesManager::create_message_input_reply_to(
(reply_d->notification_info != nullptr && (reply_d->notification_info != nullptr &&
message_id <= reply_d->notification_info->max_push_notification_message_id_)) { message_id <= reply_d->notification_info->max_push_notification_message_id_)) {
// allow to reply yet unreceived server message in the same chat // allow to reply yet unreceived server message in the same chat
return MessageInputReplyTo{message_id, reply_dialog_id, std::move(quote), quote_position}; return MessageInputReplyTo{message_id, reply_dialog_id, MessageQuote{std::move(quote), quote_position}};
} }
if (!for_draft && top_thread_message_id.is_valid() && top_thread_message_id.is_server()) { if (!for_draft && top_thread_message_id.is_valid() && top_thread_message_id.is_server()) {
return MessageInputReplyTo{top_thread_message_id, DialogId(), FormattedText(), 0}; return MessageInputReplyTo{top_thread_message_id, DialogId(), MessageQuote()};
} }
LOG(INFO) << "Can't find " << message_id << " in " << reply_d->dialog_id; LOG(INFO) << "Can't find " << message_id << " in " << reply_d->dialog_id;
@ -23184,7 +23185,7 @@ MessageInputReplyTo MessagesManager::create_message_input_reply_to(
LOG(INFO) << "Can't reply in another chat " << m->message_id << " in " << reply_d->dialog_id; LOG(INFO) << "Can't reply in another chat " << m->message_id << " in " << reply_d->dialog_id;
return {}; return {};
} }
return MessageInputReplyTo{m->message_id, reply_dialog_id, std::move(quote), quote_position}; return MessageInputReplyTo{m->message_id, reply_dialog_id, MessageQuote{std::move(quote), quote_position}};
} }
default: default:
UNREACHABLE(); UNREACHABLE();
@ -23276,7 +23277,7 @@ void MessagesManager::cancel_send_message_query(DialogId dialog_id, Message *m)
CHECK(input_reply_to != nullptr); CHECK(input_reply_to != nullptr);
CHECK(input_reply_to->get_reply_message_full_id(reply_d->dialog_id) == MessageFullId(dialog_id, m->message_id)); CHECK(input_reply_to->get_reply_message_full_id(reply_d->dialog_id) == MessageFullId(dialog_id, m->message_id));
set_message_reply(reply_d, replied_m, set_message_reply(reply_d, replied_m,
MessageInputReplyTo{replied_m->top_thread_message_id, DialogId(), FormattedText(), 0}, true); MessageInputReplyTo{replied_m->top_thread_message_id, DialogId(), MessageQuote()}, true);
} }
replied_yet_unsent_messages_.erase(it); replied_yet_unsent_messages_.erase(it);
} }
@ -26505,7 +26506,7 @@ Result<td_api::object_ptr<td_api::messages>> MessagesManager::forward_messages(
if (!input_reply_to.is_valid() && copied_message.original_reply_to_message_id.is_valid() && is_secret) { if (!input_reply_to.is_valid() && copied_message.original_reply_to_message_id.is_valid() && is_secret) {
auto it = forwarded_message_id_to_new_message_id.find(copied_message.original_reply_to_message_id); auto it = forwarded_message_id_to_new_message_id.find(copied_message.original_reply_to_message_id);
if (it != forwarded_message_id_to_new_message_id.end()) { if (it != forwarded_message_id_to_new_message_id.end()) {
input_reply_to = MessageInputReplyTo{it->second, DialogId(), FormattedText(), 0}; input_reply_to = MessageInputReplyTo{it->second, DialogId(), MessageQuote()};
} }
} }
@ -26597,7 +26598,7 @@ Result<td_api::object_ptr<td_api::messages>> MessagesManager::send_quick_reply_s
if (content.original_reply_to_message_id_.is_valid()) { if (content.original_reply_to_message_id_.is_valid()) {
auto it = original_message_id_to_new_message_id.find(content.original_reply_to_message_id_); auto it = original_message_id_to_new_message_id.find(content.original_reply_to_message_id_);
if (it != original_message_id_to_new_message_id.end()) { if (it != original_message_id_to_new_message_id.end()) {
input_reply_to = MessageInputReplyTo{it->second, DialogId(), FormattedText(), 0}; input_reply_to = MessageInputReplyTo{it->second, DialogId(), MessageQuote()};
} }
} }
@ -26795,7 +26796,7 @@ Result<vector<MessageId>> MessagesManager::resend_messages(DialogId dialog_id, v
auto r_quote = get_formatted_text(td_, td_->dialog_manager_->get_my_dialog_id(), std::move(quote->text_), auto r_quote = get_formatted_text(td_, td_->dialog_manager_->get_my_dialog_id(), std::move(quote->text_),
td_->auth_manager_->is_bot(), true, true, true); td_->auth_manager_->is_bot(), true, true, true);
if (r_quote.is_ok()) { if (r_quote.is_ok()) {
message->input_reply_to.set_quote(r_quote.move_as_ok(), quote->position_); message->input_reply_to.set_quote(MessageQuote{r_quote.move_as_ok(), quote->position_});
} }
} else if (need_drop_reply) { } else if (need_drop_reply) {
message->input_reply_to = {}; message->input_reply_to = {};
@ -36969,7 +36970,7 @@ void MessagesManager::restore_message_reply_to_message_id(Dialog *d, Message *m)
if (message_id.is_valid() || message_id.is_valid_scheduled()) { if (message_id.is_valid() || message_id.is_valid_scheduled()) {
update_message_reply_to_message_id(d, m, message_id, false); update_message_reply_to_message_id(d, m, message_id, false);
} else { } else {
set_message_reply(d, m, MessageInputReplyTo{m->top_thread_message_id, DialogId(), FormattedText(), 0}, false); set_message_reply(d, m, MessageInputReplyTo{m->top_thread_message_id, DialogId(), MessageQuote()}, false);
} }
} }

View File

@ -22,6 +22,7 @@
#include "td/telegram/MessageContentType.h" #include "td/telegram/MessageContentType.h"
#include "td/telegram/MessageCopyOptions.h" #include "td/telegram/MessageCopyOptions.h"
#include "td/telegram/MessageInputReplyTo.h" #include "td/telegram/MessageInputReplyTo.h"
#include "td/telegram/MessageQuote.h"
#include "td/telegram/MessageReplyHeader.h" #include "td/telegram/MessageReplyHeader.h"
#include "td/telegram/MessageSelfDestructType.h" #include "td/telegram/MessageSelfDestructType.h"
#include "td/telegram/misc.h" #include "td/telegram/misc.h"
@ -248,7 +249,7 @@ class QuickReplyManager::SendQuickReplyMessageQuery final : public Td::ResultHan
flags |= telegram_api::messages_sendMessage::INVERT_MEDIA_MASK; flags |= telegram_api::messages_sendMessage::INVERT_MEDIA_MASK;
} }
auto reply_to = auto reply_to =
MessageInputReplyTo(m->reply_to_message_id, DialogId(), Auto(), 0).get_input_reply_to(td_, MessageId()); MessageInputReplyTo(m->reply_to_message_id, DialogId(), MessageQuote()).get_input_reply_to(td_, MessageId());
if (reply_to != nullptr) { if (reply_to != nullptr) {
flags |= telegram_api::messages_sendMessage::REPLY_TO_MASK; flags |= telegram_api::messages_sendMessage::REPLY_TO_MASK;
} }
@ -304,7 +305,7 @@ class QuickReplyManager::SendQuickReplyInlineMessageQuery final : public Td::Res
flags |= telegram_api::messages_sendInlineBotResult::HIDE_VIA_MASK; flags |= telegram_api::messages_sendInlineBotResult::HIDE_VIA_MASK;
} }
auto reply_to = auto reply_to =
MessageInputReplyTo(m->reply_to_message_id, DialogId(), Auto(), 0).get_input_reply_to(td_, MessageId()); MessageInputReplyTo(m->reply_to_message_id, DialogId(), MessageQuote()).get_input_reply_to(td_, MessageId());
if (reply_to != nullptr) { if (reply_to != nullptr) {
flags |= telegram_api::messages_sendInlineBotResult::REPLY_TO_MASK; flags |= telegram_api::messages_sendInlineBotResult::REPLY_TO_MASK;
} }
@ -364,7 +365,7 @@ class QuickReplyManager::SendQuickReplyMediaQuery final : public Td::ResultHandl
flags |= telegram_api::messages_sendMedia::INVERT_MEDIA_MASK; flags |= telegram_api::messages_sendMedia::INVERT_MEDIA_MASK;
} }
auto reply_to = auto reply_to =
MessageInputReplyTo(m->reply_to_message_id, DialogId(), Auto(), 0).get_input_reply_to(td_, MessageId()); MessageInputReplyTo(m->reply_to_message_id, DialogId(), MessageQuote()).get_input_reply_to(td_, MessageId());
if (reply_to != nullptr) { if (reply_to != nullptr) {
flags |= telegram_api::messages_sendMedia::REPLY_TO_MASK; flags |= telegram_api::messages_sendMedia::REPLY_TO_MASK;
} }

View File

@ -114,12 +114,8 @@ RepliedMessageInfo::RepliedMessageInfo(Td *td, tl_object_ptr<telegram_api::messa
} }
} }
} }
if ((!origin_.is_empty() || message_id_ != MessageId()) && !reply_header->quote_text_.empty()) { if (!origin_.is_empty() || message_id_ != MessageId()) {
is_quote_manual_ = reply_header->quote_; quote_ = MessageQuote(td, reply_header);
quote_ = get_formatted_text(td->user_manager_.get(), std::move(reply_header->quote_text_),
std::move(reply_header->quote_entities_), true, true, false, "RepliedMessageInfo");
remove_unallowed_quote_entities(quote_);
quote_position_ = max(0, reply_header->quote_offset_);
} }
} }
@ -128,10 +124,8 @@ RepliedMessageInfo::RepliedMessageInfo(Td *td, const MessageInputReplyTo &input_
return; return;
} }
message_id_ = input_reply_to.message_id_; message_id_ = input_reply_to.message_id_;
if (!input_reply_to.quote_.text.empty()) { if (!input_reply_to.quote_.is_empty()) {
quote_ = input_reply_to.quote_; quote_ = input_reply_to.quote_.clone();
quote_position_ = input_reply_to.quote_position_;
is_quote_manual_ = true;
} }
if (input_reply_to.dialog_id_ != DialogId()) { if (input_reply_to.dialog_id_ != DialogId()) {
auto info = auto info =
@ -145,11 +139,8 @@ RepliedMessageInfo::RepliedMessageInfo(Td *td, const MessageInputReplyTo &input_
content_ = std::move(info.content_); content_ = std::move(info.content_);
auto content_text = get_message_content_text_mutable(content_.get()); auto content_text = get_message_content_text_mutable(content_.get());
if (content_text != nullptr) { if (content_text != nullptr) {
if (!is_quote_manual_) { if (!quote_.is_manual()) {
quote_ = std::move(*content_text); quote_ = MessageQuote::create_automatic_quote(td, std::move(*content_text));
remove_unallowed_quote_entities(quote_);
truncate_formatted_text(
quote_, static_cast<size_t>(td->option_manager_->get_option_integer("message_reply_quote_length_max")));
} }
*content_text = FormattedText(); *content_text = FormattedText();
} }
@ -175,9 +166,7 @@ RepliedMessageInfo RepliedMessageInfo::clone(Td *td) const {
result.content_ = dup_message_content(td, td->dialog_manager_->get_my_dialog_id(), content_.get(), result.content_ = dup_message_content(td, td->dialog_manager_->get_my_dialog_id(), content_.get(),
MessageContentDupType::Forward, MessageCopyOptions()); MessageContentDupType::Forward, MessageCopyOptions());
} }
result.quote_ = quote_; result.quote_ = quote_.clone();
result.quote_position_ = quote_position_;
result.is_quote_manual_ = is_quote_manual_;
return result; return result;
} }
@ -198,22 +187,9 @@ bool RepliedMessageInfo::need_reply_changed_warning(
// only signature can change in the message origin // only signature can change in the message origin
return true; return true;
} }
if (old_info.quote_position_ != new_info.quote_position_ && auto need_quote_warning = MessageQuote::need_quote_changed_warning(old_info.quote_, new_info.quote_);
max(old_info.quote_position_, new_info.quote_position_) < if (need_quote_warning != 0) {
static_cast<int32>(min(old_info.quote_.text.size(), new_info.quote_.text.size()))) { return need_quote_warning > 0;
// quote position can't change
return true;
}
if (old_info.is_quote_manual_ != new_info.is_quote_manual_) {
// quote manual property can't change
return true;
}
if (old_info.quote_ != new_info.quote_) {
if (old_info.is_quote_manual_) {
return true;
}
// automatic quote can change if the original message was edited
return false;
} }
if (old_info.dialog_id_ != new_info.dialog_id_ && old_info.dialog_id_ != DialogId() && if (old_info.dialog_id_ != new_info.dialog_id_ && old_info.dialog_id_ != DialogId() &&
new_info.dialog_id_ != DialogId()) { new_info.dialog_id_ != DialogId()) {
@ -269,7 +245,7 @@ vector<UserId> RepliedMessageInfo::get_min_user_ids(Td *td) const {
user_ids.push_back(dialog_id_.get_user_id()); user_ids.push_back(dialog_id_.get_user_id());
} }
origin_.add_user_ids(user_ids); origin_.add_user_ids(user_ids);
// not supported server-side: add_formatted_text_user_ids(user_ids, &quote_); // not supported server-side: quote_.add_user_ids(user_ids);
if (content_ != nullptr) { if (content_ != nullptr) {
append(user_ids, get_message_content_min_user_ids(td, content_.get())); append(user_ids, get_message_content_min_user_ids(td, content_.get()));
} }
@ -291,7 +267,7 @@ vector<ChannelId> RepliedMessageInfo::get_min_channel_ids(Td *td) const {
void RepliedMessageInfo::add_dependencies(Dependencies &dependencies, bool is_bot) const { void RepliedMessageInfo::add_dependencies(Dependencies &dependencies, bool is_bot) const {
dependencies.add_dialog_and_dependencies(dialog_id_); dependencies.add_dialog_and_dependencies(dialog_id_);
origin_.add_dependencies(dependencies); origin_.add_dependencies(dependencies);
add_formatted_text_dependencies(dependencies, &quote_); quote_.add_dependencies(dependencies);
if (content_ != nullptr) { if (content_ != nullptr) {
add_message_content_dependencies(dependencies, content_.get(), is_bot); add_message_content_dependencies(dependencies, content_.get(), is_bot);
} }
@ -309,12 +285,6 @@ td_api::object_ptr<td_api::messageReplyToMessage> RepliedMessageInfo::get_messag
chat_id = 0; chat_id = 0;
} }
td_api::object_ptr<td_api::textQuote> quote;
if (!quote_.text.empty()) {
quote = td_api::make_object<td_api::textQuote>(get_formatted_text_object(quote_, true, -1), quote_position_,
is_quote_manual_);
}
td_api::object_ptr<td_api::MessageOrigin> origin; td_api::object_ptr<td_api::MessageOrigin> origin;
if (!origin_.is_empty()) { if (!origin_.is_empty()) {
origin = origin_.get_message_origin_object(td); origin = origin_.get_message_origin_object(td);
@ -341,15 +311,14 @@ td_api::object_ptr<td_api::messageReplyToMessage> RepliedMessageInfo::get_messag
} }
} }
return td_api::make_object<td_api::messageReplyToMessage>(chat_id, message_id_.get(), std::move(quote), return td_api::make_object<td_api::messageReplyToMessage>(chat_id, message_id_.get(), quote_.get_text_quote_object(),
std::move(origin), origin_date_, std::move(content)); std::move(origin), origin_date_, std::move(content));
} }
MessageInputReplyTo RepliedMessageInfo::get_input_reply_to() const { MessageInputReplyTo RepliedMessageInfo::get_input_reply_to() const {
CHECK(!is_external()); CHECK(!is_external());
if (message_id_.is_valid()) { if (message_id_.is_valid()) {
FormattedText quote = quote_; return MessageInputReplyTo(message_id_, dialog_id_, quote_.clone(true));
return MessageInputReplyTo(message_id_, dialog_id_, std::move(quote), quote_position_);
} }
return {}; return {};
} }
@ -388,8 +357,7 @@ void RepliedMessageInfo::unregister_content(Td *td) const {
bool operator==(const RepliedMessageInfo &lhs, const RepliedMessageInfo &rhs) { bool operator==(const RepliedMessageInfo &lhs, const RepliedMessageInfo &rhs) {
if (!(lhs.message_id_ == rhs.message_id_ && lhs.dialog_id_ == rhs.dialog_id_ && if (!(lhs.message_id_ == rhs.message_id_ && lhs.dialog_id_ == rhs.dialog_id_ &&
lhs.origin_date_ == rhs.origin_date_ && lhs.origin_ == rhs.origin_ && lhs.quote_ == rhs.quote_ && lhs.origin_date_ == rhs.origin_date_ && lhs.origin_ == rhs.origin_ && lhs.quote_ == rhs.quote_)) {
lhs.quote_position_ == rhs.quote_position_ && lhs.is_quote_manual_ == rhs.is_quote_manual_)) {
return false; return false;
} }
bool need_update = false; bool need_update = false;
@ -413,13 +381,7 @@ StringBuilder &operator<<(StringBuilder &string_builder, const RepliedMessageInf
if (info.origin_date_ != 0) { if (info.origin_date_ != 0) {
string_builder << " sent at " << info.origin_date_ << " by " << info.origin_; string_builder << " sent at " << info.origin_date_ << " by " << info.origin_;
} }
if (!info.quote_.text.empty()) { string_builder << info.quote_;
string_builder << " with " << info.quote_.text.size() << (info.is_quote_manual_ ? " manually" : "")
<< " quoted bytes";
if (info.quote_position_ != 0) {
string_builder << " at position " << info.quote_position_;
}
}
if (info.content_ != nullptr) { if (info.content_ != nullptr) {
string_builder << " and content of the type " << info.content_->get_type(); string_builder << " and content of the type " << info.content_->get_type();
} }

View File

@ -10,11 +10,11 @@
#include "td/telegram/DialogId.h" #include "td/telegram/DialogId.h"
#include "td/telegram/files/FileId.h" #include "td/telegram/files/FileId.h"
#include "td/telegram/MessageContent.h" #include "td/telegram/MessageContent.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageFullId.h" #include "td/telegram/MessageFullId.h"
#include "td/telegram/MessageId.h" #include "td/telegram/MessageId.h"
#include "td/telegram/MessageInputReplyTo.h" #include "td/telegram/MessageInputReplyTo.h"
#include "td/telegram/MessageOrigin.h" #include "td/telegram/MessageOrigin.h"
#include "td/telegram/MessageQuote.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h" #include "td/telegram/UserId.h"
@ -36,9 +36,7 @@ class RepliedMessageInfo {
int32 origin_date_ = 0; // for replies in other chats int32 origin_date_ = 0; // for replies in other chats
MessageOrigin origin_; // for replies in other chats MessageOrigin origin_; // for replies in other chats
unique_ptr<MessageContent> content_; // for replies in other chats unique_ptr<MessageContent> content_; // for replies in other chats
FormattedText quote_; MessageQuote quote_;
int32 quote_position_ = 0;
bool is_quote_manual_ = false;
friend bool operator==(const RepliedMessageInfo &lhs, const RepliedMessageInfo &rhs); friend bool operator==(const RepliedMessageInfo &lhs, const RepliedMessageInfo &rhs);

View File

@ -22,18 +22,18 @@ void RepliedMessageInfo::store(StorerT &storer) const {
bool has_dialog_id = dialog_id_.is_valid(); bool has_dialog_id = dialog_id_.is_valid();
bool has_origin_date = origin_date_ != 0; bool has_origin_date = origin_date_ != 0;
bool has_origin = !origin_.is_empty(); bool has_origin = !origin_.is_empty();
bool has_quote = !quote_.text.empty();
bool has_content = content_ != nullptr; bool has_content = content_ != nullptr;
bool has_quote_position = quote_position_ != 0; bool has_quote = !quote_.is_empty();
BEGIN_STORE_FLAGS(); BEGIN_STORE_FLAGS();
STORE_FLAG(has_message_id); STORE_FLAG(has_message_id);
STORE_FLAG(has_dialog_id); STORE_FLAG(has_dialog_id);
STORE_FLAG(has_origin_date); STORE_FLAG(has_origin_date);
STORE_FLAG(has_origin); STORE_FLAG(has_origin);
STORE_FLAG(has_quote); STORE_FLAG(false);
STORE_FLAG(is_quote_manual_); STORE_FLAG(false);
STORE_FLAG(has_content); STORE_FLAG(has_content);
STORE_FLAG(has_quote_position); STORE_FLAG(false);
STORE_FLAG(has_quote);
END_STORE_FLAGS(); END_STORE_FLAGS();
if (has_message_id) { if (has_message_id) {
td::store(message_id_, storer); td::store(message_id_, storer);
@ -47,14 +47,11 @@ void RepliedMessageInfo::store(StorerT &storer) const {
if (has_origin) { if (has_origin) {
td::store(origin_, storer); td::store(origin_, storer);
} }
if (has_quote) {
td::store(quote_, storer);
}
if (has_content) { if (has_content) {
store_message_content(content_.get(), storer); store_message_content(content_.get(), storer);
} }
if (has_quote_position) { if (has_quote) {
td::store(quote_position_, storer); td::store(quote_, storer);
} }
} }
@ -64,18 +61,21 @@ void RepliedMessageInfo::parse(ParserT &parser) {
bool has_dialog_id; bool has_dialog_id;
bool has_origin_date; bool has_origin_date;
bool has_origin; bool has_origin;
bool has_quote; bool has_quote_legacy;
bool is_quote_manual_legacy;
bool has_content; bool has_content;
bool has_quote_position; bool has_quote_position_legacy;
bool has_quote;
BEGIN_PARSE_FLAGS(); BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_message_id); PARSE_FLAG(has_message_id);
PARSE_FLAG(has_dialog_id); PARSE_FLAG(has_dialog_id);
PARSE_FLAG(has_origin_date); PARSE_FLAG(has_origin_date);
PARSE_FLAG(has_origin); PARSE_FLAG(has_origin);
PARSE_FLAG(has_quote); PARSE_FLAG(has_quote_legacy);
PARSE_FLAG(is_quote_manual_); PARSE_FLAG(is_quote_manual_legacy);
PARSE_FLAG(has_content); PARSE_FLAG(has_content);
PARSE_FLAG(has_quote_position); PARSE_FLAG(has_quote_position_legacy);
PARSE_FLAG(has_quote);
END_PARSE_FLAGS(); END_PARSE_FLAGS();
if (has_message_id) { if (has_message_id) {
td::parse(message_id_, parser); td::parse(message_id_, parser);
@ -89,15 +89,21 @@ void RepliedMessageInfo::parse(ParserT &parser) {
if (has_origin) { if (has_origin) {
td::parse(origin_, parser); td::parse(origin_, parser);
} }
if (has_quote) { FormattedText quote_legacy;
td::parse(quote_, parser); if (has_quote_legacy) {
remove_unallowed_quote_entities(quote_); td::parse(quote_legacy, parser);
} }
if (has_content) { if (has_content) {
parse_message_content(content_, parser); parse_message_content(content_, parser);
} }
if (has_quote_position) { int32 quote_position_legacy = 0;
td::parse(quote_position_, parser); if (has_quote_position_legacy) {
td::parse(quote_position_legacy, parser);
}
if (has_quote) {
td::parse(quote_, parser);
} else if (has_quote_legacy) {
quote_ = MessageQuote(std::move(quote_legacy), quote_position_legacy, is_quote_manual_legacy);
} }
} }