Use MessageSender for recent reaction choosers.

This commit is contained in:
levlam 2022-01-21 13:15:27 +03:00
parent 7c4d333a77
commit 05a069d221
5 changed files with 107 additions and 39 deletions

View File

@ -758,8 +758,8 @@ messageReplyInfo reply_count:int32 recent_replier_ids:vector<MessageSender> last
//@reaction Text representation of the reaction //@reaction Text representation of the reaction
//@choose_count Number of times the reaction was chosen //@choose_count Number of times the reaction was chosen
//@is_chosen True, if the reaction is chosen by the user //@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 //@recent_chooser_ids Identifiers of at most 3 recent message senders, chosen the reaction; available in basic groups and supergroups
messageReaction reaction:string choose_count:int32 is_chosen:Bool recent_chooser_user_ids:vector<int53> = MessageReaction; messageReaction reaction:string choose_count:int32 is_chosen:Bool recent_chooser_ids:vector<MessageSender> = MessageReaction;
//@description Contains information about interactions with a message //@description Contains information about interactions with a message
//@view_count Number of times the message was viewed //@view_count Number of times the message was viewed

View File

@ -7,6 +7,7 @@
#include "td/telegram/MessageReaction.h" #include "td/telegram/MessageReaction.h"
#include "td/telegram/ContactsManager.h" #include "td/telegram/ContactsManager.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/utils/algorithm.h" #include "td/utils/algorithm.h"
@ -19,12 +20,30 @@ namespace td {
td_api::object_ptr<td_api::messageReaction> MessageReaction::get_message_reaction_object(Td *td) const { td_api::object_ptr<td_api::messageReaction> MessageReaction::get_message_reaction_object(Td *td) const {
CHECK(!is_empty()); CHECK(!is_empty());
vector<int64> recent_choosers; vector<td_api::object_ptr<td_api::MessageSender>> recent_choosers;
for (auto user_id : recent_chooser_user_ids_) { for (auto dialog_id : recent_chooser_dialog_ids_) {
if (td->contacts_manager_->have_min_user(user_id)) { auto dialog_type = dialog_id.get_type();
recent_choosers.push_back(td->contacts_manager_->get_user_id_object(user_id, "get_message_reaction_object")); if (dialog_type == DialogType::User) {
auto user_id = dialog_id.get_user_id();
if (td->contacts_manager_->have_min_user(user_id)) {
recent_choosers.push_back(td_api::make_object<td_api::messageSenderUser>(
td->contacts_manager_->get_user_id_object(user_id, "get_message_reaction_object")));
} else {
LOG(ERROR) << "Skip unknown reacted " << user_id;
}
} else { } else {
LOG(ERROR) << "Skip unknown reacted " << user_id; if (!td->messages_manager_->have_dialog(dialog_id) &&
(td->messages_manager_->have_dialog_info(dialog_id) ||
(dialog_type == DialogType::Channel &&
td->contacts_manager_->have_min_channel(dialog_id.get_channel_id())))) {
LOG(INFO) << "Force creation of " << dialog_id;
td->messages_manager_->force_create_dialog(dialog_id, "get_message_reaction_object", true);
}
if (td->messages_manager_->have_dialog(dialog_id)) {
recent_choosers.push_back(td_api::make_object<td_api::messageSenderChat>(dialog_id.get()));
} else {
LOG(ERROR) << "Skip unknown reacted " << dialog_id;
}
} }
} }
return td_api::make_object<td_api::messageReaction>(reaction_, choose_count_, is_chosen_, std::move(recent_choosers)); return td_api::make_object<td_api::messageReaction>(reaction_, choose_count_, is_chosen_, std::move(recent_choosers));
@ -32,13 +51,13 @@ td_api::object_ptr<td_api::messageReaction> MessageReaction::get_message_reactio
bool operator==(const MessageReaction &lhs, const MessageReaction &rhs) { 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_ && 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_; lhs.recent_chooser_dialog_ids_ == rhs.recent_chooser_dialog_ids_;
} }
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReaction &reaction) { StringBuilder &operator<<(StringBuilder &string_builder, const MessageReaction &reaction) {
string_builder << '[' << reaction.reaction_ << (reaction.is_chosen_ ? " X " : " x ") << reaction.choose_count_; string_builder << '[' << reaction.reaction_ << (reaction.is_chosen_ ? " X " : " x ") << reaction.choose_count_;
if (!reaction.recent_chooser_user_ids_.empty()) { if (!reaction.recent_chooser_dialog_ids_.empty()) {
string_builder << " by " << reaction.recent_chooser_user_ids_; string_builder << " by " << reaction.recent_chooser_dialog_ids_;
} }
return string_builder << ']'; return string_builder << ']';
} }
@ -54,6 +73,7 @@ unique_ptr<MessageReactions> MessageReactions::get_message_reactions(
result->is_min_ = reactions->min_; result->is_min_ = reactions->min_;
std::unordered_set<string> reaction_strings; std::unordered_set<string> reaction_strings;
std::unordered_set<DialogId, DialogIdHash> recent_choosers;
for (auto &reaction_count : reactions->results_) { for (auto &reaction_count : reactions->results_) {
if (reaction_count->count_ <= 0 || reaction_count->count_ >= MessageReaction::MAX_CHOOSE_COUNT) { if (reaction_count->count_ <= 0 || reaction_count->count_ >= MessageReaction::MAX_CHOOSE_COUNT) {
LOG(ERROR) << "Receive reaction " << reaction_count->reaction_ << " with invalid count " LOG(ERROR) << "Receive reaction " << reaction_count->reaction_ << " with invalid count "
@ -66,32 +86,51 @@ unique_ptr<MessageReactions> MessageReactions::get_message_reactions(
continue; continue;
} }
vector<UserId> recent_chooser_user_ids; vector<DialogId> recent_chooser_dialog_ids;
vector<std::pair<ChannelId, MinChannel>> recent_chooser_min_channels;
for (auto &user_reaction : reactions->recent_reactons_) { for (auto &user_reaction : reactions->recent_reactons_) {
if (user_reaction->reaction_ == reaction_count->reaction_) { if (user_reaction->reaction_ == reaction_count->reaction_) {
UserId user_id(user_reaction->user_id_); DialogId dialog_id(UserId(user_reaction->user_id_));
if (!user_id.is_valid()) { if (!dialog_id.is_valid()) {
LOG(ERROR) << "Receive invalid " << user_id; LOG(ERROR) << "Receive invalid " << dialog_id << " as a recent chooser";
continue; continue;
} }
if (td::contains(recent_chooser_user_ids, user_id)) { if (!recent_choosers.insert(dialog_id).second) {
LOG(ERROR) << "Receive duplicate " << user_id; LOG(ERROR) << "Receive duplicate " << dialog_id << " as a recent chooser";
continue; continue;
} }
if (!td->contacts_manager_->have_min_user(user_id)) { if (!td->messages_manager_->have_dialog_info(dialog_id)) {
LOG(ERROR) << "Have no info about " << user_id; auto dialog_type = dialog_id.get_type();
continue; if (dialog_type == DialogType::User) {
auto user_id = dialog_id.get_user_id();
if (!td->contacts_manager_->have_min_user(user_id)) {
LOG(ERROR) << "Have no info about " << user_id;
continue;
}
} else if (dialog_type == DialogType::Channel) {
auto channel_id = dialog_id.get_channel_id();
auto min_channel = td->contacts_manager_->get_min_channel(channel_id);
if (min_channel == nullptr) {
LOG(ERROR) << "Have no info about reacted " << channel_id;
continue;
}
recent_chooser_min_channels.emplace_back(channel_id, *min_channel);
} else {
LOG(ERROR) << "Have no info about reacted " << dialog_id;
continue;
}
} }
recent_chooser_user_ids.push_back(user_id); recent_chooser_dialog_ids.push_back(dialog_id);
if (recent_chooser_user_ids.size() == MessageReaction::MAX_RECENT_CHOOSERS) { if (recent_chooser_dialog_ids.size() == MessageReaction::MAX_RECENT_CHOOSERS) {
break; break;
} }
} }
} }
result->reactions_.emplace_back(std::move(reaction_count->reaction_), reaction_count->count_, result->reactions_.emplace_back(std::move(reaction_count->reaction_), reaction_count->count_,
reaction_count->chosen_, std::move(recent_chooser_user_ids)); reaction_count->chosen_, std::move(recent_chooser_dialog_ids),
std::move(recent_chooser_min_channels));
} }
return result; return result;
} }

View File

@ -6,13 +6,17 @@
// //
#pragma once #pragma once
#include "td/telegram/ChannelId.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/MinChannel.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/utils/common.h" #include "td/utils/common.h"
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
#include <utility>
namespace td { namespace td {
class Td; class Td;
@ -21,7 +25,8 @@ class MessageReaction {
string reaction_; string reaction_;
int32 choose_count_ = 0; int32 choose_count_ = 0;
bool is_chosen_ = false; bool is_chosen_ = false;
vector<UserId> recent_chooser_user_ids_; vector<DialogId> recent_chooser_dialog_ids_;
vector<std::pair<ChannelId, MinChannel>> recent_chooser_min_channels_;
friend bool operator==(const MessageReaction &lhs, const MessageReaction &rhs); friend bool operator==(const MessageReaction &lhs, const MessageReaction &rhs);
@ -33,11 +38,13 @@ class MessageReaction {
MessageReaction() = default; MessageReaction() = default;
MessageReaction(string &&reaction, int32 choose_count, bool is_chosen, vector<UserId> &&recent_chooser_user_ids) MessageReaction(string &&reaction, int32 choose_count, bool is_chosen, vector<DialogId> &&recent_chooser_dialog_ids,
vector<std::pair<ChannelId, MinChannel>> &&recent_chooser_min_channels)
: reaction_(std::move(reaction)) : reaction_(std::move(reaction))
, choose_count_(choose_count) , choose_count_(choose_count)
, is_chosen_(is_chosen) , is_chosen_(is_chosen)
, recent_chooser_user_ids_(std::move(recent_chooser_user_ids)) { , recent_chooser_dialog_ids_(std::move(recent_chooser_dialog_ids))
, recent_chooser_min_channels_(std::move(recent_chooser_min_channels)) {
} }
bool is_empty() const { bool is_empty() const {
@ -56,8 +63,12 @@ class MessageReaction {
is_chosen_ = is_chosen; is_chosen_ = is_chosen;
} }
const vector<UserId> &get_recent_chooser_user_ids() const { const vector<DialogId> &get_recent_chooser_dialog_ids() const {
return recent_chooser_user_ids_; return recent_chooser_dialog_ids_;
}
const vector<std::pair<ChannelId, MinChannel>> &get_recent_chooser_min_channels() const {
return recent_chooser_min_channels_;
} }
td_api::object_ptr<td_api::messageReaction> get_message_reaction_object(Td *td) const; td_api::object_ptr<td_api::messageReaction> get_message_reaction_object(Td *td) const;

View File

@ -16,29 +16,39 @@ namespace td {
template <class StorerT> template <class StorerT>
void MessageReaction::store(StorerT &storer) const { void MessageReaction::store(StorerT &storer) const {
CHECK(!is_empty()); CHECK(!is_empty());
bool has_recent_chooser_user_ids = !recent_chooser_user_ids_.empty(); bool has_recent_chooser_dialog_ids = !recent_chooser_dialog_ids_.empty();
bool has_recent_chooser_min_channels = !recent_chooser_min_channels_.empty();
BEGIN_STORE_FLAGS(); BEGIN_STORE_FLAGS();
STORE_FLAG(is_chosen_); STORE_FLAG(is_chosen_);
STORE_FLAG(has_recent_chooser_user_ids); STORE_FLAG(has_recent_chooser_dialog_ids);
STORE_FLAG(has_recent_chooser_min_channels);
END_STORE_FLAGS(); END_STORE_FLAGS();
td::store(reaction_, storer); td::store(reaction_, storer);
td::store(choose_count_, storer); td::store(choose_count_, storer);
if (has_recent_chooser_user_ids) { if (has_recent_chooser_dialog_ids) {
td::store(recent_chooser_user_ids_, storer); td::store(recent_chooser_dialog_ids_, storer);
}
if (has_recent_chooser_min_channels) {
td::store(recent_chooser_min_channels_, storer);
} }
} }
template <class ParserT> template <class ParserT>
void MessageReaction::parse(ParserT &parser) { void MessageReaction::parse(ParserT &parser) {
bool has_recent_chooser_user_ids; bool has_recent_chooser_dialog_ids;
bool has_recent_chooser_min_channels;
BEGIN_PARSE_FLAGS(); BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_chosen_); PARSE_FLAG(is_chosen_);
PARSE_FLAG(has_recent_chooser_user_ids); PARSE_FLAG(has_recent_chooser_dialog_ids);
PARSE_FLAG(has_recent_chooser_min_channels);
END_PARSE_FLAGS(); END_PARSE_FLAGS();
td::parse(reaction_, parser); td::parse(reaction_, parser);
td::parse(choose_count_, parser); td::parse(choose_count_, parser);
if (has_recent_chooser_user_ids) { if (has_recent_chooser_dialog_ids) {
td::parse(recent_chooser_user_ids_, parser); td::parse(recent_chooser_dialog_ids_, parser);
}
if (has_recent_chooser_min_channels) {
td::parse(recent_chooser_min_channels_, parser);
} }
CHECK(!is_empty()); CHECK(!is_empty());
} }

View File

@ -24421,7 +24421,7 @@ void MessagesManager::add_message_dependencies(Dependencies &dependencies, const
add_dialog_and_dependencies(dependencies, m->forward_info->from_dialog_id); add_dialog_and_dependencies(dependencies, m->forward_info->from_dialog_id);
} }
for (const auto &replier_min_channel : m->reply_info.replier_min_channels) { for (const auto &replier_min_channel : m->reply_info.replier_min_channels) {
LOG(INFO) << "Add min " << replier_min_channel.first; LOG(INFO) << "Add min replied " << replier_min_channel.first;
td_->contacts_manager_->add_min_channel(replier_min_channel.first, replier_min_channel.second); td_->contacts_manager_->add_min_channel(replier_min_channel.first, replier_min_channel.second);
} }
for (auto recent_replier_dialog_id : m->reply_info.recent_replier_dialog_ids) { for (auto recent_replier_dialog_id : m->reply_info.recent_replier_dialog_ids) {
@ -24431,8 +24431,16 @@ void MessagesManager::add_message_dependencies(Dependencies &dependencies, const
} }
if (m->reactions != nullptr) { if (m->reactions != nullptr) {
for (const auto &reaction : m->reactions->reactions_) { for (const auto &reaction : m->reactions->reactions_) {
const auto &user_ids = reaction.get_recent_chooser_user_ids(); for (const auto &recent_chooser_min_channel : reaction.get_recent_chooser_min_channels()) {
dependencies.user_ids.insert(user_ids.begin(), user_ids.end()); LOG(INFO) << "Add min reacted " << recent_chooser_min_channel.first;
td_->contacts_manager_->add_min_channel(recent_chooser_min_channel.first, recent_chooser_min_channel.second);
}
const auto &dialog_ids = reaction.get_recent_chooser_dialog_ids();
for (auto dialog_id : dialog_ids) {
// don't load the dialog itself
// it will be created in get_message_reaction_object if needed
add_dialog_dependencies(dependencies, dialog_id);
}
} }
} }
add_message_content_dependencies(dependencies, m->content.get()); add_message_content_dependencies(dependencies, m->content.get());