Add MessageReactions.

This commit is contained in:
levlam 2022-01-20 22:54:34 +03:00
parent aed0fc247d
commit 739d2b292d
8 changed files with 431 additions and 18 deletions

View File

@ -356,6 +356,7 @@ set(TDLIB_SOURCE
td/telegram/MessageContentType.cpp
td/telegram/MessageEntity.cpp
td/telegram/MessageId.cpp
td/telegram/MessageReaction.cpp
td/telegram/MessageReplyInfo.cpp
td/telegram/MessagesDb.cpp
td/telegram/MessageSearchFilter.cpp
@ -561,6 +562,7 @@ set(TDLIB_SOURCE
td/telegram/MessageEntity.h
td/telegram/MessageId.h
td/telegram/MessageLinkInfo.h
td/telegram/MessageReaction.h
td/telegram/MessageReplyInfo.h
td/telegram/MessageThreadInfo.h
td/telegram/MessagesDb.h
@ -677,6 +679,7 @@ set(TDLIB_SOURCE
td/telegram/Game.hpp
td/telegram/InputMessageText.hpp
td/telegram/MessageEntity.hpp
td/telegram/MessageReaction.hpp
td/telegram/MessageReplyInfo.hpp
td/telegram/MinChannel.hpp
td/telegram/NotificationSettings.hpp

View File

@ -754,11 +754,19 @@ messageForwardInfo origin:MessageForwardOrigin date:int32 public_service_announc
//@last_message_id Identifier of the last reply to the message
messageReplyInfo reply_count:int32 recent_replier_ids:vector<MessageSender> last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 last_message_id:int53 = MessageReplyInfo;
//@description Contains information about a reaction to a message
//@reaction Text representation of the reaction
//@choose_count Number of times the reaction was chosen
//@is_chosen True, if the reaction is chosen by the user
//@recent_chooser_user_ids Identifiers of at most 3 recent users, chosen the reaction
messageReaction reaction:string choose_count:int32 is_chosen:Bool recent_chooser_user_ids:vector<int53> = MessageReaction;
//@description Contains information about interactions with a message
//@view_count Number of times the message was viewed
//@forward_count Number of times the message was forwarded
//@reply_info Information about direct or indirect replies to the message; may be null. Currently, available only in channels with a discussion supergroup and discussion supergroups for messages, which are not replies itself
messageInteractionInfo view_count:int32 forward_count:int32 reply_info:messageReplyInfo = MessageInteractionInfo;
//@reactions The list of reactions chosen for the message
messageInteractionInfo view_count:int32 forward_count:int32 reply_info:messageReplyInfo reactions:vector<messageReaction> = MessageInteractionInfo;
//@class MessageSendingState @description Contains information about the sending state of the message

View File

@ -3085,7 +3085,7 @@ class GetBroadcastStatsQuery final : public Td::ResultHandler {
for (auto &info : result->recent_message_interactions_) {
td_->messages_manager_->on_update_message_interaction_info({DialogId(channel_id_), MessageId(info->message_id_)},
info->view_count_, info->forward_count_, false,
nullptr);
nullptr, false, nullptr);
}
promise_.set_value(std::move(result));
}

View File

@ -0,0 +1,143 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// 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/MessageReaction.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/Td.h"
#include "td/utils/algorithm.h"
#include "td/utils/logging.h"
#include <unordered_set>
namespace td {
td_api::object_ptr<td_api::messageReaction> MessageReaction::get_message_reaction_object(Td *td) const {
CHECK(!is_empty());
vector<int64> recent_choosers;
for (auto user_id : recent_chooser_user_ids_) {
if (td->contacts_manager_->have_min_user(user_id)) {
recent_choosers.push_back(td->contacts_manager_->get_user_id_object(user_id, "get_message_reaction_object"));
} else {
LOG(ERROR) << "Skip unknown reacted " << user_id;
}
}
return td_api::make_object<td_api::messageReaction>(reaction_, choose_count_, is_chosen_, std::move(recent_choosers));
}
bool operator==(const MessageReaction &lhs, const MessageReaction &rhs) {
return lhs.reaction_ == rhs.reaction_ && lhs.choose_count_ == rhs.choose_count_ && lhs.is_chosen_ == rhs.is_chosen_ &&
lhs.recent_chooser_user_ids_ == rhs.recent_chooser_user_ids_;
}
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReaction &reaction) {
string_builder << '[' << reaction.reaction_ << (reaction.is_chosen_ ? " X " : " x ") << reaction.choose_count_;
if (!reaction.recent_chooser_user_ids_.empty()) {
string_builder << " by " << reaction.recent_chooser_user_ids_;
}
return string_builder << ']';
}
unique_ptr<MessageReactions> MessageReactions::get_message_reactions(
Td *td, tl_object_ptr<telegram_api::messageReactions> &&reactions, bool is_bot) {
if (reactions == nullptr || is_bot) {
return nullptr;
}
auto result = make_unique<MessageReactions>();
result->can_see_all_choosers_ = reactions->can_see_list_;
result->is_min_ = reactions->min_;
std::unordered_set<string> reaction_strings;
for (auto &reaction_count : reactions->results_) {
if (reaction_count->count_ <= 0 || reaction_count->count_ >= MessageReaction::MAX_CHOOSE_COUNT) {
LOG(ERROR) << "Receive reaction " << reaction_count->reaction_ << " with invalid count "
<< reaction_count->count_;
continue;
}
if (!reaction_strings.insert(reaction_count->reaction_).second) {
LOG(ERROR) << "Receive duplicate reaction " << reaction_count->reaction_;
continue;
}
vector<UserId> recent_chooser_user_ids;
for (auto &user_reaction : reactions->recent_reactons_) {
if (user_reaction->reaction_ == reaction_count->reaction_) {
UserId user_id(user_reaction->user_id_);
if (!user_id.is_valid()) {
LOG(ERROR) << "Receive invalid " << user_id;
continue;
}
if (td::contains(recent_chooser_user_ids, user_id)) {
LOG(ERROR) << "Receive duplicate " << user_id;
continue;
}
if (!td->contacts_manager_->have_min_user(user_id)) {
LOG(ERROR) << "Have no info about " << user_id;
continue;
}
recent_chooser_user_ids.push_back(user_id);
if (recent_chooser_user_ids.size() == MessageReaction::MAX_RECENT_CHOOSERS) {
break;
}
}
}
result->reactions_.emplace_back(std::move(reaction_count->reaction_), reaction_count->count_,
reaction_count->chosen_, std::move(recent_chooser_user_ids));
}
return result;
}
void MessageReactions::update_from(const MessageReactions &old_reactions) {
if (old_reactions.has_pending_reaction_) {
// we will ignore all updates, received while there is a pending reaction, so there are no reasons to update
return;
}
CHECK(!has_pending_reaction_);
if (is_min_ && !old_reactions.is_min_) {
// chosen reaction was known, keep it
is_min_ = false;
for (const auto &old_reaction : old_reactions.reactions_) {
if (old_reaction.is_chosen()) {
for (auto &reaction : reactions_) {
if (reaction.get_reaction() == old_reaction.get_reaction()) {
reaction.set_is_chosen(true);
}
}
}
}
}
}
bool MessageReactions::need_update_message_reactions(const MessageReactions *old_reactions,
const MessageReactions *new_reactions) {
if (old_reactions == nullptr) {
// add reactions
return new_reactions != nullptr;
}
if (old_reactions->has_pending_reaction_) {
// ignore all updates, received while there is a pending reaction
return false;
}
if (new_reactions == nullptr) {
// remove reactions when they are disabled
return true;
}
// has_pending_reaction_ and old_chosen_reaction_ don't affect visible state
// compare all other fields
return old_reactions->reactions_ != new_reactions->reactions_ || old_reactions->is_min_ != new_reactions->is_min_ ||
old_reactions->can_see_all_choosers_ != new_reactions->can_see_all_choosers_ ||
old_reactions->need_polling_ != new_reactions->need_polling_;
}
} // namespace td

View File

@ -0,0 +1,106 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// 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/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Td;
class MessageReaction {
string reaction_;
int32 choose_count_ = 0;
bool is_chosen_ = false;
vector<UserId> recent_chooser_user_ids_;
friend bool operator==(const MessageReaction &lhs, const MessageReaction &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const MessageReaction &message_reaction);
public:
static constexpr size_t MAX_RECENT_CHOOSERS = 3;
static constexpr int32 MAX_CHOOSE_COUNT = 2147483640;
MessageReaction() = default;
MessageReaction(string &&reaction, int32 choose_count, bool is_chosen, vector<UserId> &&recent_chooser_user_ids)
: reaction_(std::move(reaction))
, choose_count_(choose_count)
, is_chosen_(is_chosen)
, recent_chooser_user_ids_(std::move(recent_chooser_user_ids)) {
}
bool is_empty() const {
return choose_count_ <= 0;
}
const string &get_reaction() const {
return reaction_;
}
bool is_chosen() const {
return is_chosen_;
}
void set_is_chosen(bool is_chosen) {
is_chosen_ = is_chosen;
}
const vector<UserId> &get_recent_chooser_user_ids() const {
return recent_chooser_user_ids_;
}
td_api::object_ptr<td_api::messageReaction> get_message_reaction_object(Td *td) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
bool operator==(const MessageReaction &lhs, const MessageReaction &rhs);
inline bool operator!=(const MessageReaction &lhs, const MessageReaction &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReaction &message_reaction);
struct MessageReactions {
vector<MessageReaction> reactions_;
bool is_min_ = false;
bool need_polling_ = true;
bool can_see_all_choosers_ = false;
bool has_pending_reaction_ = false;
string old_chosen_reaction_;
MessageReactions() = default;
static unique_ptr<MessageReactions> get_message_reactions(Td *td,
tl_object_ptr<telegram_api::messageReactions> &&reactions,
bool is_bot);
void update_from(const MessageReactions &old_reactions);
static bool need_update_message_reactions(const MessageReactions *old_reactions,
const MessageReactions *new_reactions);
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
} // namespace td

View File

@ -0,0 +1,86 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// 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/MessageReaction.h"
#include "td/utils/common.h"
#include "td/utils/tl_helpers.h"
namespace td {
template <class StorerT>
void MessageReaction::store(StorerT &storer) const {
CHECK(!is_empty());
bool has_recent_chooser_user_ids = !recent_chooser_user_ids_.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(is_chosen_);
STORE_FLAG(has_recent_chooser_user_ids);
END_STORE_FLAGS();
td::store(reaction_, storer);
td::store(choose_count_, storer);
if (has_recent_chooser_user_ids) {
td::store(recent_chooser_user_ids_, storer);
}
}
template <class ParserT>
void MessageReaction::parse(ParserT &parser) {
bool has_recent_chooser_user_ids;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_chosen_);
PARSE_FLAG(has_recent_chooser_user_ids);
END_PARSE_FLAGS();
td::parse(reaction_, parser);
td::parse(choose_count_, parser);
if (has_recent_chooser_user_ids) {
td::parse(recent_chooser_user_ids_, parser);
}
CHECK(!is_empty());
}
template <class StorerT>
void MessageReactions::store(StorerT &storer) const {
bool has_reactions = !reactions_.empty();
bool has_old_chosen_reaction = !old_chosen_reaction_.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(is_min_);
STORE_FLAG(need_polling_);
STORE_FLAG(can_see_all_choosers_);
STORE_FLAG(has_pending_reaction_);
STORE_FLAG(has_reactions);
STORE_FLAG(has_old_chosen_reaction);
END_STORE_FLAGS();
if (has_reactions) {
td::store(reactions_, storer);
}
if (has_old_chosen_reaction) {
td::store(old_chosen_reaction_, storer);
}
}
template <class ParserT>
void MessageReactions::parse(ParserT &parser) {
bool has_reactions;
bool has_old_chosen_reaction;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_min_);
PARSE_FLAG(need_polling_);
PARSE_FLAG(can_see_all_choosers_);
PARSE_FLAG(has_pending_reaction_);
PARSE_FLAG(has_reactions);
PARSE_FLAG(has_old_chosen_reaction);
END_PARSE_FLAGS();
if (has_reactions) {
td::parse(reactions_, parser);
}
if (has_old_chosen_reaction) {
td::parse(old_chosen_reaction_, parser);
}
}
} // namespace td

View File

@ -33,6 +33,8 @@
#include "td/telegram/MessageContent.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageEntity.hpp"
#include "td/telegram/MessageReaction.h"
#include "td/telegram/MessageReaction.hpp"
#include "td/telegram/MessageReplyInfo.hpp"
#include "td/telegram/MessagesDb.h"
#include "td/telegram/MessageSender.h"
@ -1919,7 +1921,7 @@ class GetMessagesViewsQuery final : public Td::ResultHandler {
auto view_count = (flags & telegram_api::messageViews::VIEWS_MASK) != 0 ? info->views_ : 0;
auto forward_count = (flags & telegram_api::messageViews::FORWARDS_MASK) != 0 ? info->forwards_ : 0;
td_->messages_manager_->on_update_message_interaction_info(full_message_id, view_count, forward_count, true,
std::move(info->replies_));
std::move(info->replies_), false, nullptr);
}
}
@ -4891,6 +4893,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
bool has_max_reply_media_timestamp = max_reply_media_timestamp >= 0;
bool are_message_media_timestamp_entities_found = true;
bool has_flags3 = true;
bool has_reactions = reactions != nullptr;
BEGIN_STORE_FLAGS();
STORE_FLAG(is_channel_post);
STORE_FLAG(is_outgoing);
@ -4961,6 +4964,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
BEGIN_STORE_FLAGS();
STORE_FLAG(noforwards);
STORE_FLAG(has_explicit_sender);
STORE_FLAG(has_reactions);
END_STORE_FLAGS();
}
@ -5079,6 +5083,9 @@ void MessagesManager::Message::store(StorerT &storer) const {
if (has_max_reply_media_timestamp) {
store(max_reply_media_timestamp, storer);
}
if (has_reactions) {
store(reactions, storer);
}
}
// do not forget to resolve message dependencies
@ -5122,6 +5129,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
bool has_ttl_period = false;
bool has_max_reply_media_timestamp = false;
bool has_flags3 = false;
bool has_reactions = false;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_channel_post);
PARSE_FLAG(is_outgoing);
@ -5192,6 +5200,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
BEGIN_PARSE_FLAGS();
PARSE_FLAG(noforwards);
PARSE_FLAG(has_explicit_sender);
PARSE_FLAG(has_reactions);
END_PARSE_FLAGS();
}
@ -5317,6 +5326,9 @@ void MessagesManager::Message::parse(ParserT &parser) {
if (has_max_reply_media_timestamp) {
parse(max_reply_media_timestamp, parser);
}
if (has_reactions) {
parse(reactions, parser);
}
CHECK(content != nullptr);
is_content_secret |=
@ -6787,7 +6799,7 @@ void MessagesManager::on_update_message_view_count(FullMessageId full_message_id
LOG(ERROR) << "Receive " << view_count << " views in updateChannelMessageViews for " << full_message_id;
return;
}
update_message_interaction_info(full_message_id, view_count, -1, false, nullptr);
update_message_interaction_info(full_message_id, view_count, -1, false, nullptr, false, nullptr);
}
void MessagesManager::on_update_message_forward_count(FullMessageId full_message_id, int32 forward_count) {
@ -6795,17 +6807,20 @@ void MessagesManager::on_update_message_forward_count(FullMessageId full_message
LOG(ERROR) << "Receive " << forward_count << " forwards in updateChannelMessageForwards for " << full_message_id;
return;
}
update_message_interaction_info(full_message_id, -1, forward_count, false, nullptr);
update_message_interaction_info(full_message_id, -1, forward_count, false, nullptr, false, nullptr);
}
void MessagesManager::on_update_message_interaction_info(FullMessageId full_message_id, int32 view_count,
int32 forward_count, bool has_reply_info,
tl_object_ptr<telegram_api::messageReplies> &&reply_info) {
tl_object_ptr<telegram_api::messageReplies> &&reply_info,
bool has_reactions,
tl_object_ptr<telegram_api::messageReactions> &&reactions) {
if (view_count < 0 || forward_count < 0) {
LOG(ERROR) << "Receive " << view_count << "/" << forward_count << " interaction counters for " << full_message_id;
return;
}
update_message_interaction_info(full_message_id, view_count, forward_count, has_reply_info, std::move(reply_info));
update_message_interaction_info(full_message_id, view_count, forward_count, has_reply_info, std::move(reply_info),
has_reactions, std::move(reactions));
}
void MessagesManager::on_pending_message_views_timeout(DialogId dialog_id) {
@ -6835,7 +6850,9 @@ void MessagesManager::on_pending_message_views_timeout(DialogId dialog_id) {
void MessagesManager::update_message_interaction_info(FullMessageId full_message_id, int32 view_count,
int32 forward_count, bool has_reply_info,
tl_object_ptr<telegram_api::messageReplies> &&reply_info) {
tl_object_ptr<telegram_api::messageReplies> &&reply_info,
bool has_reactions,
tl_object_ptr<telegram_api::messageReactions> &&reactions) {
auto dialog_id = full_message_id.get_dialog_id();
Dialog *d = get_dialog_force(dialog_id, "update_message_interaction_info");
if (d == nullptr) {
@ -6863,9 +6880,11 @@ void MessagesManager::update_message_interaction_info(FullMessageId full_message
if (new_reply_info.is_empty() && !is_empty_reply_info) {
has_reply_info = false;
}
auto new_reactions = MessageReactions::get_message_reactions(td_, std::move(reactions), td_->auth_manager_->is_bot());
if (update_message_interaction_info(dialog_id, m, view_count, forward_count, has_reply_info,
std::move(new_reply_info), "update_message_interaction_info")) {
std::move(new_reply_info), has_reactions, std::move(new_reactions),
"update_message_interaction_info")) {
on_message_changed(d, m, true, "update_message_interaction_info");
}
}
@ -6916,6 +6935,11 @@ bool MessagesManager::is_visible_message_reply_info(DialogId dialog_id, const Me
return is_active_message_reply_info(dialog_id, m->reply_info);
}
bool MessagesManager::is_visible_message_reactions(DialogId dialog_id, const Message *m) const {
// TODO hide message reactions if reactions are disabled in the chat
return true;
}
void MessagesManager::on_message_reply_info_changed(DialogId dialog_id, const Message *m) const {
if (td_->auth_manager_->is_bot()) {
return;
@ -6929,7 +6953,9 @@ void MessagesManager::on_message_reply_info_changed(DialogId dialog_id, const Me
td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_interaction_info_object(
DialogId dialog_id, const Message *m) const {
bool is_visible_reply_info = is_visible_message_reply_info(dialog_id, m);
if (m->view_count == 0 && m->forward_count == 0 && !is_visible_reply_info) {
bool has_reactions =
is_visible_message_reactions(dialog_id, m) && m->reactions != nullptr && !m->reactions->reactions_.empty();
if (m->view_count == 0 && m->forward_count == 0 && !is_visible_reply_info && !has_reactions) {
return nullptr;
}
if (m->message_id.is_scheduled() && (m->forward_info == nullptr || is_broadcast_channel(dialog_id))) {
@ -6945,12 +6971,21 @@ td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_
CHECK(reply_info != nullptr);
}
return td_api::make_object<td_api::messageInteractionInfo>(m->view_count, m->forward_count, std::move(reply_info));
vector<td_api::object_ptr<td_api::messageReaction>> reactions;
if (has_reactions) {
reactions = transform(m->reactions->reactions_, [td = td_](const MessageReaction &reaction) {
return reaction.get_message_reaction_object(td);
});
}
return td_api::make_object<td_api::messageInteractionInfo>(m->view_count, m->forward_count, std::move(reply_info),
std::move(reactions));
}
bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count,
int32 forward_count, bool has_reply_info,
MessageReplyInfo &&reply_info, const char *source) {
MessageReplyInfo &&reply_info, bool has_reactions,
unique_ptr<MessageReactions> &&reactions, const char *source) {
CHECK(m != nullptr);
m->interaction_info_update_date = G()->unix_time(); // doesn't force message saving
if (m->message_id.is_valid_scheduled()) {
@ -6968,7 +7003,13 @@ bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Messag
}
}
}
if (view_count > m->view_count || forward_count > m->forward_count || need_update_reply_info) {
if (has_reactions && reactions != nullptr && m->reactions != nullptr) {
reactions->update_from(*m->reactions);
}
bool need_update_reactions =
has_reactions && MessageReactions::need_update_message_reactions(m->reactions.get(), reactions.get());
if (view_count > m->view_count || forward_count > m->forward_count || need_update_reply_info ||
need_update_reactions) {
LOG(DEBUG) << "Update interaction info of " << FullMessageId{dialog_id, m->message_id} << " from " << m->view_count
<< '/' << m->forward_count << "/" << m->reply_info << " to " << view_count << '/' << forward_count << "/"
<< reply_info;
@ -6995,6 +7036,10 @@ bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Messag
}
need_update |= is_visible_message_reply_info(dialog_id, m);
}
if (need_update_reactions) {
m->reactions = std::move(reactions);
need_update |= is_visible_message_reactions(dialog_id, m);
}
if (need_update) {
send_update_message_interaction_info(dialog_id, m);
}
@ -13702,6 +13747,9 @@ MessagesManager::MessageInfo MessagesManager::parse_telegram_api_message(
if (message->flags_ & MESSAGE_FLAG_HAS_REPLY_INFO) {
message_info.reply_info = std::move(message->replies_);
}
if (message->flags_ & MESSAGE_FLAG_HAS_REACTIONS) {
message_info.reactions = std::move(message->reactions_);
}
if (message->flags_ & MESSAGE_FLAG_HAS_EDIT_DATE) {
message_info.edit_date = message->edit_date_;
}
@ -13959,6 +14007,8 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
if (top_thread_message_id.is_valid() && dialog_type != DialogType::Channel) {
top_thread_message_id = MessageId();
}
auto reactions =
MessageReactions::get_message_reactions(td_, std::move(message_info.reactions), td_->auth_manager_->is_bot());
bool has_forward_info = message_info.forward_header != nullptr;
@ -14003,6 +14053,7 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
message->view_count = view_count;
message->forward_count = forward_count;
message->reply_info = std::move(reply_info);
message->reactions = std::move(reactions);
message->legacy_layer = (is_legacy ? MTPROTO_LAYER : 0);
message->content = std::move(message_info.content);
message->reply_markup = get_reply_markup(std::move(message_info.reply_markup), td_->auth_manager_->is_bot(), false,
@ -24373,6 +24424,12 @@ void MessagesManager::add_message_dependencies(Dependencies &dependencies, const
// it will be created in get_message_reply_info_object if needed
add_dialog_dependencies(dependencies, recent_replier_dialog_id);
}
if (m->reactions != nullptr) {
for (const auto &reaction : m->reactions->reactions_) {
const auto &user_ids = reaction.get_recent_chooser_user_ids();
dependencies.user_ids.insert(user_ids.begin(), user_ids.end());
}
}
add_message_content_dependencies(dependencies, m->content.get());
add_reply_markup_dependencies(dependencies, m->reply_markup.get());
}
@ -34731,7 +34788,8 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr
need_send_update = true;
}
if (update_message_interaction_info(dialog_id, old_message, new_message->view_count, new_message->forward_count, true,
std::move(new_message->reply_info), "update_message")) {
std::move(new_message->reply_info), true, std::move(new_message->reactions),
"update_message")) {
need_send_update = true;
}
if (old_message->noforwards != new_message->noforwards) {

View File

@ -91,6 +91,7 @@ class DialogFilter;
class DraftMessage;
struct InputMessageContent;
class MessageContent;
struct MessageReactions;
class MultiSequenceDispatcher;
class Td;
@ -115,6 +116,7 @@ class MessagesManager final : public Actor {
static constexpr int32 MESSAGE_FLAG_HAS_MEDIA_ALBUM_ID = 1 << 17;
static constexpr int32 MESSAGE_FLAG_IS_FROM_SCHEDULED = 1 << 18;
static constexpr int32 MESSAGE_FLAG_IS_LEGACY = 1 << 19;
static constexpr int32 MESSAGE_FLAG_HAS_REACTIONS = 1 << 20;
static constexpr int32 MESSAGE_FLAG_HIDE_EDIT_DATE = 1 << 21;
static constexpr int32 MESSAGE_FLAG_IS_RESTRICTED = 1 << 22;
static constexpr int32 MESSAGE_FLAG_HAS_REPLY_INFO = 1 << 23;
@ -335,8 +337,9 @@ class MessagesManager final : public Actor {
void on_update_message_forward_count(FullMessageId full_message_id, int32 forward_count);
void on_update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count,
bool has_reply_info,
tl_object_ptr<telegram_api::messageReplies> &&reply_info);
bool has_reply_info, tl_object_ptr<telegram_api::messageReplies> &&reply_info,
bool has_reactions,
tl_object_ptr<telegram_api::messageReactions> &&reactions);
void on_update_live_location_viewed(FullMessageId full_message_id);
@ -996,6 +999,7 @@ class MessagesManager final : public Actor {
int32 view_count = 0;
int32 forward_count = 0;
tl_object_ptr<telegram_api::messageReplies> reply_info;
tl_object_ptr<telegram_api::messageReactions> reactions;
int32 flags = 0;
int32 edit_date = 0;
vector<RestrictionReason> restriction_reasons;
@ -1128,6 +1132,7 @@ class MessagesManager final : public Actor {
int32 view_count = 0;
int32 forward_count = 0;
MessageReplyInfo reply_info;
unique_ptr<MessageReactions> reactions;
unique_ptr<DraftMessage> thread_draft_message;
int32 interaction_info_update_date = 0;
@ -2083,12 +2088,15 @@ class MessagesManager final : public Actor {
void on_pending_message_views_timeout(DialogId dialog_id);
void update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count,
bool has_reply_info, tl_object_ptr<telegram_api::messageReplies> &&reply_info);
bool has_reply_info, tl_object_ptr<telegram_api::messageReplies> &&reply_info,
bool has_reactions, tl_object_ptr<telegram_api::messageReactions> &&reactions);
bool is_active_message_reply_info(DialogId dialog_id, const MessageReplyInfo &info) const;
bool is_visible_message_reply_info(DialogId dialog_id, const Message *m) const;
bool is_visible_message_reactions(DialogId dialog_id, const Message *m) const;
void on_message_reply_info_changed(DialogId dialog_id, const Message *m) const;
Result<FullMessageId> get_top_thread_full_message_id(DialogId dialog_id, const Message *m) const;
@ -2097,7 +2105,8 @@ class MessagesManager final : public Actor {
const Message *m) const;
bool update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count, int32 forward_count,
bool has_reply_info, MessageReplyInfo &&reply_info, const char *source);
bool has_reply_info, MessageReplyInfo &&reply_info, bool has_reactions,
unique_ptr<MessageReactions> &&reactions, const char *source);
bool update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, const char *source);