Add class ReactionType.
This commit is contained in:
parent
e695289557
commit
5558825d61
@ -444,6 +444,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PremiumGiftOption.cpp
|
||||
td/telegram/QueryCombiner.cpp
|
||||
td/telegram/QueryMerger.cpp
|
||||
td/telegram/ReactionType.cpp
|
||||
td/telegram/RecentDialogList.cpp
|
||||
td/telegram/ReplyMarkup.cpp
|
||||
td/telegram/ReportReason.cpp
|
||||
@ -734,6 +735,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PublicDialogType.h
|
||||
td/telegram/QueryCombiner.h
|
||||
td/telegram/QueryMerger.h
|
||||
td/telegram/ReactionType.h
|
||||
td/telegram/RecentDialogList.h
|
||||
td/telegram/ReplyMarkup.h
|
||||
td/telegram/ReportReason.h
|
||||
@ -838,6 +840,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/PollId.hpp
|
||||
td/telegram/PollManager.hpp
|
||||
td/telegram/PremiumGiftOption.hpp
|
||||
td/telegram/ReactionType.hpp
|
||||
td/telegram/ReplyMarkup.hpp
|
||||
td/telegram/RequestedDialogType.hpp
|
||||
td/telegram/ScopeNotificationSettings.hpp
|
||||
|
@ -28,10 +28,9 @@ ChatReactions::ChatReactions(telegram_api::object_ptr<telegram_api::ChatReaction
|
||||
}
|
||||
case telegram_api::chatReactionsSome::ID: {
|
||||
auto chat_reactions = move_tl_object_as<telegram_api::chatReactionsSome>(chat_reactions_ptr);
|
||||
reactions_ =
|
||||
transform(chat_reactions->reactions_, [](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) {
|
||||
return get_message_reaction_string(reaction);
|
||||
});
|
||||
reaction_types_ = transform(
|
||||
chat_reactions->reactions_,
|
||||
[](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) { return ReactionType(reaction); });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -51,9 +50,9 @@ ChatReactions::ChatReactions(td_api::object_ptr<td_api::ChatAvailableReactions>
|
||||
break;
|
||||
case td_api::chatAvailableReactionsSome::ID: {
|
||||
auto chat_reactions = move_tl_object_as<td_api::chatAvailableReactionsSome>(chat_reactions_ptr);
|
||||
reactions_ = transform(chat_reactions->reactions_, [](const td_api::object_ptr<td_api::ReactionType> &reaction) {
|
||||
return get_message_reaction_string(reaction);
|
||||
});
|
||||
reaction_types_ =
|
||||
transform(chat_reactions->reactions_,
|
||||
[](const td_api::object_ptr<td_api::ReactionType> &reaction) { return ReactionType(reaction); });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -61,30 +60,33 @@ ChatReactions::ChatReactions(td_api::object_ptr<td_api::ChatAvailableReactions>
|
||||
}
|
||||
}
|
||||
|
||||
ChatReactions ChatReactions::get_active_reactions(const FlatHashMap<string, size_t> &active_reaction_pos) const {
|
||||
ChatReactions ChatReactions::get_active_reactions(
|
||||
const FlatHashMap<ReactionType, size_t, ReactionTypeHash> &active_reaction_pos) const {
|
||||
ChatReactions result = *this;
|
||||
if (!reactions_.empty()) {
|
||||
if (!reaction_types_.empty()) {
|
||||
CHECK(!allow_all_);
|
||||
CHECK(!allow_custom_);
|
||||
td::remove_if(result.reactions_,
|
||||
[&](const string &reaction) { return !is_active_reaction(reaction, active_reaction_pos); });
|
||||
td::remove_if(result.reaction_types_, [&](const ReactionType &reaction_type) {
|
||||
return !reaction_type.is_active_reaction(active_reaction_pos);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ChatReactions::is_allowed_reaction(const string &reaction) const {
|
||||
bool ChatReactions::is_allowed_reaction_type(const ReactionType &reaction_type) const {
|
||||
CHECK(!allow_all_);
|
||||
if (allow_custom_ && is_custom_reaction(reaction)) {
|
||||
if (allow_custom_ && reaction_type.is_custom_reaction()) {
|
||||
return true;
|
||||
}
|
||||
return td::contains(reactions_, reaction);
|
||||
return td::contains(reaction_types_, reaction_type);
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::ChatAvailableReactions> ChatReactions::get_chat_available_reactions_object() const {
|
||||
if (allow_all_) {
|
||||
return td_api::make_object<td_api::chatAvailableReactionsAll>();
|
||||
}
|
||||
return td_api::make_object<td_api::chatAvailableReactionsSome>(transform(reactions_, get_reaction_type_object));
|
||||
return td_api::make_object<td_api::chatAvailableReactionsSome>(transform(
|
||||
reaction_types_, [](const ReactionType &reaction_type) { return reaction_type.get_reaction_type_object(); }));
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::ChatReactions> ChatReactions::get_input_chat_reactions() const {
|
||||
@ -95,15 +97,16 @@ telegram_api::object_ptr<telegram_api::ChatReactions> ChatReactions::get_input_c
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::chatReactionsAll>(flags, allow_custom_);
|
||||
}
|
||||
if (!reactions_.empty()) {
|
||||
return telegram_api::make_object<telegram_api::chatReactionsSome>(transform(reactions_, get_input_reaction));
|
||||
if (!reaction_types_.empty()) {
|
||||
return telegram_api::make_object<telegram_api::chatReactionsSome>(transform(
|
||||
reaction_types_, [](const ReactionType &reaction_type) { return reaction_type.get_input_reaction(); }));
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::chatReactionsNone>();
|
||||
}
|
||||
|
||||
bool operator==(const ChatReactions &lhs, const ChatReactions &rhs) {
|
||||
// don't compare allow_custom_
|
||||
return lhs.reactions_ == rhs.reactions_ && lhs.allow_all_ == rhs.allow_all_;
|
||||
return lhs.reaction_types_ == rhs.reaction_types_ && lhs.allow_all_ == rhs.allow_all_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const ChatReactions &reactions) {
|
||||
@ -113,7 +116,7 @@ StringBuilder &operator<<(StringBuilder &string_builder, const ChatReactions &re
|
||||
}
|
||||
return string_builder << "AllRegularReactions";
|
||||
}
|
||||
return string_builder << '[' << reactions.reactions_ << ']';
|
||||
return string_builder << '[' << reactions.reaction_types_ << ']';
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -6,6 +6,7 @@
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
@ -17,13 +18,13 @@
|
||||
namespace td {
|
||||
|
||||
struct ChatReactions {
|
||||
vector<string> reactions_;
|
||||
vector<ReactionType> reaction_types_;
|
||||
bool allow_all_ = false; // implies empty reactions
|
||||
bool allow_custom_ = false; // implies allow_all
|
||||
|
||||
ChatReactions() = default;
|
||||
|
||||
explicit ChatReactions(vector<string> &&reactions) : reactions_(std::move(reactions)) {
|
||||
explicit ChatReactions(vector<ReactionType> &&reactions) : reaction_types_(std::move(reactions)) {
|
||||
}
|
||||
|
||||
explicit ChatReactions(telegram_api::object_ptr<telegram_api::ChatReactions> &&chat_reactions_ptr);
|
||||
@ -33,28 +34,29 @@ struct ChatReactions {
|
||||
ChatReactions(bool allow_all, bool allow_custom) : allow_all_(allow_all), allow_custom_(allow_custom) {
|
||||
}
|
||||
|
||||
ChatReactions get_active_reactions(const FlatHashMap<string, size_t> &active_reaction_pos) const;
|
||||
ChatReactions get_active_reactions(
|
||||
const FlatHashMap<ReactionType, size_t, ReactionTypeHash> &active_reaction_pos) const;
|
||||
|
||||
bool is_allowed_reaction(const string &reaction) const;
|
||||
bool is_allowed_reaction_type(const ReactionType &reaction) const;
|
||||
|
||||
telegram_api::object_ptr<telegram_api::ChatReactions> get_input_chat_reactions() const;
|
||||
|
||||
td_api::object_ptr<td_api::ChatAvailableReactions> get_chat_available_reactions_object() const;
|
||||
|
||||
bool empty() const {
|
||||
return reactions_.empty() && !allow_all_;
|
||||
return reaction_types_.empty() && !allow_all_;
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const {
|
||||
bool has_reactions = !reactions_.empty();
|
||||
bool has_reactions = !reaction_types_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(allow_all_);
|
||||
STORE_FLAG(allow_custom_);
|
||||
STORE_FLAG(has_reactions);
|
||||
END_STORE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::store(reactions_, storer);
|
||||
td::store(reaction_types_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +69,7 @@ struct ChatReactions {
|
||||
PARSE_FLAG(has_reactions);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::parse(reactions_, parser);
|
||||
td::parse(reaction_types_, parser);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "td/telegram/net/PublicRsaKeyShared.h"
|
||||
#include "td/telegram/net/Session.h"
|
||||
#include "td/telegram/Premium.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/TdDb.h"
|
||||
@ -1402,9 +1403,9 @@ void ConfigManager::process_config(tl_object_ptr<telegram_api::config> config) {
|
||||
options.set_option_integer("notification_default_delay_ms", fix_timeout_ms(config->notify_default_delay_ms_));
|
||||
|
||||
if (is_from_main_dc && !options.have_option("default_reaction_need_sync")) {
|
||||
auto reaction_str = get_message_reaction_string(config->reactions_default_);
|
||||
if (!reaction_str.empty()) {
|
||||
options.set_option_string("default_reaction", reaction_str);
|
||||
ReactionType reaction_type(config->reactions_default_);
|
||||
if (!reaction_type.is_empty()) {
|
||||
options.set_option_string("default_reaction", reaction_type.get_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/MessageSender.h"
|
||||
#include "td/telegram/MessagesManager.h"
|
||||
#include "td/telegram/misc.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/ServerMessageId.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
@ -25,17 +24,11 @@
|
||||
#include "td/actor/SleepActor.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/as.h"
|
||||
#include "td/utils/base64.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/emoji.h"
|
||||
#include "td/utils/FlatHashSet.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/utf8.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
@ -49,81 +42,6 @@ static size_t get_max_reaction_count() {
|
||||
max(static_cast<int32>(1), static_cast<int32>(G()->get_option_integer(option_key, is_premium ? 3 : 1))));
|
||||
}
|
||||
|
||||
static int64 get_custom_emoji_id(const string &reaction) {
|
||||
auto r_decoded = base64_decode(Slice(&reaction[1], reaction.size() - 1));
|
||||
CHECK(r_decoded.is_ok());
|
||||
CHECK(r_decoded.ok().size() == 8);
|
||||
return as<int64>(r_decoded.ok().c_str());
|
||||
}
|
||||
|
||||
static string get_custom_emoji_string(int64 custom_emoji_id) {
|
||||
char s[8];
|
||||
as<int64>(&s) = custom_emoji_id;
|
||||
return PSTRING() << '#' << base64_encode(Slice(s, 8));
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::Reaction> get_input_reaction(const string &reaction) {
|
||||
if (reaction.empty()) {
|
||||
return telegram_api::make_object<telegram_api::reactionEmpty>();
|
||||
}
|
||||
if (is_custom_reaction(reaction)) {
|
||||
return telegram_api::make_object<telegram_api::reactionCustomEmoji>(get_custom_emoji_id(reaction));
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::reactionEmoji>(reaction);
|
||||
}
|
||||
|
||||
string get_message_reaction_string(const telegram_api::object_ptr<telegram_api::Reaction> &reaction) {
|
||||
if (reaction == nullptr) {
|
||||
return string();
|
||||
}
|
||||
switch (reaction->get_id()) {
|
||||
case telegram_api::reactionEmpty::ID:
|
||||
return string();
|
||||
case telegram_api::reactionEmoji::ID: {
|
||||
const string &emoji = static_cast<const telegram_api::reactionEmoji *>(reaction.get())->emoticon_;
|
||||
if (is_custom_reaction(emoji)) {
|
||||
return string();
|
||||
}
|
||||
return emoji;
|
||||
}
|
||||
case telegram_api::reactionCustomEmoji::ID:
|
||||
return get_custom_emoji_string(
|
||||
static_cast<const telegram_api::reactionCustomEmoji *>(reaction.get())->document_id_);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return string();
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::ReactionType> get_reaction_type_object(const string &reaction) {
|
||||
CHECK(!reaction.empty());
|
||||
if (is_custom_reaction(reaction)) {
|
||||
return td_api::make_object<td_api::reactionTypeCustomEmoji>(get_custom_emoji_id(reaction));
|
||||
}
|
||||
return td_api::make_object<td_api::reactionTypeEmoji>(reaction);
|
||||
}
|
||||
|
||||
string get_message_reaction_string(const td_api::object_ptr<td_api::ReactionType> &type) {
|
||||
if (type == nullptr) {
|
||||
return string();
|
||||
}
|
||||
switch (type->get_id()) {
|
||||
case td_api::reactionTypeEmoji::ID: {
|
||||
const string &emoji = static_cast<const td_api::reactionTypeEmoji *>(type.get())->emoji_;
|
||||
if (!check_utf8(emoji) || is_custom_reaction(emoji)) {
|
||||
return string();
|
||||
}
|
||||
return emoji;
|
||||
}
|
||||
case td_api::reactionTypeCustomEmoji::ID:
|
||||
return get_custom_emoji_string(
|
||||
static_cast<const td_api::reactionTypeCustomEmoji *>(type.get())->custom_emoji_id_);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return string();
|
||||
}
|
||||
}
|
||||
|
||||
class GetMessagesReactionsQuery final : public Td::ResultHandler {
|
||||
DialogId dialog_id_;
|
||||
vector<MessageId> message_ids_;
|
||||
@ -186,7 +104,7 @@ class SendReactionQuery final : public Td::ResultHandler {
|
||||
explicit SendReactionQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(FullMessageId full_message_id, vector<string> reactions, bool is_big, bool add_to_recent) {
|
||||
void send(FullMessageId full_message_id, vector<ReactionType> reaction_types, bool is_big, bool add_to_recent) {
|
||||
dialog_id_ = full_message_id.get_dialog_id();
|
||||
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read);
|
||||
@ -195,7 +113,7 @@ class SendReactionQuery final : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
int32 flags = 0;
|
||||
if (!reactions.empty()) {
|
||||
if (!reaction_types.empty()) {
|
||||
flags |= telegram_api::messages_sendReaction::REACTION_MASK;
|
||||
|
||||
if (is_big) {
|
||||
@ -208,9 +126,11 @@ class SendReactionQuery final : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::messages_sendReaction(flags, false /*ignored*/, false /*ignored*/, std::move(input_peer),
|
||||
telegram_api::messages_sendReaction(
|
||||
flags, false /*ignored*/, false /*ignored*/, std::move(input_peer),
|
||||
full_message_id.get_message_id().get_server_message_id().get(),
|
||||
transform(reactions, get_input_reaction)),
|
||||
transform(reaction_types,
|
||||
[](const ReactionType &reaction_type) { return reaction_type.get_input_reaction(); })),
|
||||
{{dialog_id_}, {full_message_id}}));
|
||||
}
|
||||
|
||||
@ -238,7 +158,7 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler {
|
||||
Promise<td_api::object_ptr<td_api::addedReactions>> promise_;
|
||||
DialogId dialog_id_;
|
||||
MessageId message_id_;
|
||||
string reaction_;
|
||||
ReactionType reaction_type_;
|
||||
string offset_;
|
||||
|
||||
public:
|
||||
@ -246,10 +166,10 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler {
|
||||
: promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(FullMessageId full_message_id, string reaction, string offset, int32 limit) {
|
||||
void send(FullMessageId full_message_id, ReactionType reaction_type, string offset, int32 limit) {
|
||||
dialog_id_ = full_message_id.get_dialog_id();
|
||||
message_id_ = full_message_id.get_message_id();
|
||||
reaction_ = std::move(reaction);
|
||||
reaction_type_ = std::move(reaction_type);
|
||||
offset_ = std::move(offset);
|
||||
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read);
|
||||
@ -258,7 +178,7 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
int32 flags = 0;
|
||||
if (!reaction_.empty()) {
|
||||
if (!reaction_type_.is_empty()) {
|
||||
flags |= telegram_api::messages_getMessageReactionsList::REACTION_MASK;
|
||||
}
|
||||
if (!offset_.empty()) {
|
||||
@ -268,7 +188,7 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler {
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::messages_getMessageReactionsList(flags, std::move(input_peer),
|
||||
message_id_.get_server_message_id().get(),
|
||||
get_input_reaction(reaction_), offset_, limit),
|
||||
reaction_type_.get_input_reaction(), offset_, limit),
|
||||
{{full_message_id}}));
|
||||
}
|
||||
|
||||
@ -292,29 +212,30 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::addedReaction>> reactions;
|
||||
FlatHashMap<string, vector<DialogId>> recent_reactions;
|
||||
FlatHashMap<ReactionType, vector<DialogId>, ReactionTypeHash> recent_reaction_types;
|
||||
for (const auto &reaction : ptr->reactions_) {
|
||||
DialogId dialog_id(reaction->peer_id_);
|
||||
auto reaction_str = get_message_reaction_string(reaction->reaction_);
|
||||
if (!dialog_id.is_valid() || (reaction_.empty() ? reaction_str.empty() : reaction_ != reaction_str)) {
|
||||
auto reaction_type = ReactionType(reaction->reaction_);
|
||||
if (!dialog_id.is_valid() ||
|
||||
(reaction_type_.is_empty() ? reaction_type.is_empty() : reaction_type_ != reaction_type)) {
|
||||
LOG(ERROR) << "Receive unexpected " << to_string(reaction);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (offset_.empty()) {
|
||||
recent_reactions[reaction_str].push_back(dialog_id);
|
||||
recent_reaction_types[reaction_type].push_back(dialog_id);
|
||||
}
|
||||
|
||||
auto message_sender = get_min_message_sender_object(td_, dialog_id, "GetMessageReactionsListQuery");
|
||||
if (message_sender != nullptr) {
|
||||
reactions.push_back(td_api::make_object<td_api::addedReaction>(get_reaction_type_object(reaction_str),
|
||||
reactions.push_back(td_api::make_object<td_api::addedReaction>(reaction_type.get_reaction_type_object(),
|
||||
std::move(message_sender), reaction->date_));
|
||||
}
|
||||
}
|
||||
|
||||
if (offset_.empty()) {
|
||||
td_->messages_manager_->on_get_message_reaction_list({dialog_id_, message_id_}, reaction_,
|
||||
std::move(recent_reactions), total_count);
|
||||
td_->messages_manager_->on_get_message_reaction_list({dialog_id_, message_id_}, reaction_type_,
|
||||
std::move(recent_reaction_types), total_count);
|
||||
}
|
||||
|
||||
promise_.set_value(
|
||||
@ -328,13 +249,13 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler {
|
||||
};
|
||||
|
||||
class SetDefaultReactionQuery final : public Td::ResultHandler {
|
||||
string reaction_;
|
||||
ReactionType reaction_type_;
|
||||
|
||||
public:
|
||||
void send(const string &reaction) {
|
||||
reaction_ = reaction;
|
||||
void send(const ReactionType &reaction_type) {
|
||||
reaction_type_ = reaction_type;
|
||||
send_query(
|
||||
G()->net_query_creator().create(telegram_api::messages_setDefaultReaction(get_input_reaction(reaction))));
|
||||
G()->net_query_creator().create(telegram_api::messages_setDefaultReaction(reaction_type.get_input_reaction())));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
@ -348,7 +269,7 @@ class SetDefaultReactionQuery final : public Td::ResultHandler {
|
||||
}
|
||||
|
||||
auto default_reaction = td_->option_manager_->get_option_string("default_reaction", "-");
|
||||
if (default_reaction != reaction_) {
|
||||
if (default_reaction != reaction_type_.get_string()) {
|
||||
send_set_default_reaction_query(td_);
|
||||
} else {
|
||||
td_->option_manager_->set_option_empty("default_reaction_needs_sync");
|
||||
@ -404,10 +325,10 @@ class ReportReactionQuery final : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
MessageReaction::MessageReaction(string reaction, int32 choose_count, bool is_chosen,
|
||||
MessageReaction::MessageReaction(ReactionType reaction_type, int32 choose_count, bool is_chosen,
|
||||
DialogId my_recent_chooser_dialog_id, vector<DialogId> &&recent_chooser_dialog_ids,
|
||||
vector<std::pair<ChannelId, MinChannel>> &&recent_chooser_min_channels)
|
||||
: reaction_(std::move(reaction))
|
||||
: reaction_type_(std::move(reaction_type))
|
||||
, choose_count_(choose_count)
|
||||
, is_chosen_(is_chosen)
|
||||
, my_recent_chooser_dialog_id_(my_recent_chooser_dialog_id)
|
||||
@ -453,7 +374,7 @@ void MessageReaction::update_recent_chooser_dialog_ids(const MessageReaction &ol
|
||||
return;
|
||||
}
|
||||
CHECK(is_chosen_ && old_reaction.is_chosen_);
|
||||
CHECK(reaction_ == old_reaction.reaction_);
|
||||
CHECK(reaction_type_ == old_reaction.reaction_type_);
|
||||
CHECK(old_reaction.recent_chooser_dialog_ids_.size() == MAX_RECENT_CHOOSERS + 1);
|
||||
for (size_t i = 0; i < MAX_RECENT_CHOOSERS; i++) {
|
||||
if (recent_chooser_dialog_ids_[i] != old_reaction.recent_chooser_dialog_ids_[i]) {
|
||||
@ -528,18 +449,18 @@ td_api::object_ptr<td_api::messageReaction> MessageReaction::get_message_reactio
|
||||
}
|
||||
}
|
||||
}
|
||||
return td_api::make_object<td_api::messageReaction>(get_reaction_type_object(reaction_), choose_count_, is_chosen_,
|
||||
std::move(recent_choosers));
|
||||
return td_api::make_object<td_api::messageReaction>(reaction_type_.get_reaction_type_object(), 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.my_recent_chooser_dialog_id_ == rhs.my_recent_chooser_dialog_id_ &&
|
||||
return lhs.reaction_type_ == rhs.reaction_type_ && lhs.choose_count_ == rhs.choose_count_ &&
|
||||
lhs.is_chosen_ == rhs.is_chosen_ && lhs.my_recent_chooser_dialog_id_ == rhs.my_recent_chooser_dialog_id_ &&
|
||||
lhs.recent_chooser_dialog_ids_ == rhs.recent_chooser_dialog_ids_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReaction &reaction) {
|
||||
string_builder << '[' << reaction.reaction_ << (reaction.is_chosen_ ? " X " : " x ") << reaction.choose_count_;
|
||||
string_builder << '[' << reaction.reaction_type_ << (reaction.is_chosen_ ? " X " : " x ") << reaction.choose_count_;
|
||||
if (!reaction.recent_chooser_dialog_ids_.empty()) {
|
||||
string_builder << " by " << reaction.recent_chooser_dialog_ids_;
|
||||
if (reaction.my_recent_chooser_dialog_id_.is_valid()) {
|
||||
@ -554,16 +475,17 @@ td_api::object_ptr<td_api::unreadReaction> UnreadMessageReaction::get_unread_rea
|
||||
if (sender_id == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return td_api::make_object<td_api::unreadReaction>(get_reaction_type_object(reaction_), std::move(sender_id),
|
||||
return td_api::make_object<td_api::unreadReaction>(reaction_type_.get_reaction_type_object(), std::move(sender_id),
|
||||
is_big_);
|
||||
}
|
||||
|
||||
bool operator==(const UnreadMessageReaction &lhs, const UnreadMessageReaction &rhs) {
|
||||
return lhs.reaction_ == rhs.reaction_ && lhs.sender_dialog_id_ == rhs.sender_dialog_id_ && lhs.is_big_ == rhs.is_big_;
|
||||
return lhs.reaction_type_ == rhs.reaction_type_ && lhs.sender_dialog_id_ == rhs.sender_dialog_id_ &&
|
||||
lhs.is_big_ == rhs.is_big_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const UnreadMessageReaction &unread_reaction) {
|
||||
return string_builder << '[' << unread_reaction.reaction_ << (unread_reaction.is_big_ ? " BY " : " by ")
|
||||
return string_builder << '[' << unread_reaction.reaction_type_ << (unread_reaction.is_big_ ? " BY " : " by ")
|
||||
<< unread_reaction.sender_dialog_id_ << ']';
|
||||
}
|
||||
|
||||
@ -591,18 +513,18 @@ unique_ptr<MessageReactions> MessageReactions::get_message_reactions(
|
||||
}
|
||||
}
|
||||
|
||||
FlatHashSet<string> reaction_strings;
|
||||
vector<std::pair<int32, string>> chosen_reaction_order;
|
||||
FlatHashSet<ReactionType, ReactionTypeHash> reaction_types;
|
||||
vector<std::pair<int32, ReactionType>> chosen_reaction_order;
|
||||
for (auto &reaction_count : reactions->results_) {
|
||||
auto reaction_str = get_message_reaction_string(reaction_count->reaction_);
|
||||
auto reaction_type = ReactionType(reaction_count->reaction_);
|
||||
if (reaction_count->count_ <= 0 || reaction_count->count_ >= MessageReaction::MAX_CHOOSE_COUNT ||
|
||||
reaction_str.empty()) {
|
||||
LOG(ERROR) << "Receive reaction " << reaction_str << " with invalid count " << reaction_count->count_;
|
||||
reaction_type.is_empty()) {
|
||||
LOG(ERROR) << "Receive reaction " << reaction_type << " with invalid count " << reaction_count->count_;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!reaction_strings.insert(reaction_str).second) {
|
||||
LOG(ERROR) << "Receive duplicate reaction " << reaction_str;
|
||||
if (!reaction_types.insert(reaction_type).second) {
|
||||
LOG(ERROR) << "Receive duplicate reaction " << reaction_type;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -611,15 +533,15 @@ unique_ptr<MessageReactions> MessageReactions::get_message_reactions(
|
||||
vector<DialogId> recent_chooser_dialog_ids;
|
||||
vector<std::pair<ChannelId, MinChannel>> recent_chooser_min_channels;
|
||||
for (auto &peer_reaction : reactions->recent_reactions_) {
|
||||
auto peer_reaction_str = get_message_reaction_string(peer_reaction->reaction_);
|
||||
if (peer_reaction_str == reaction_str) {
|
||||
auto peer_reaction_type = ReactionType(peer_reaction->reaction_);
|
||||
if (peer_reaction_type == reaction_type) {
|
||||
DialogId dialog_id(peer_reaction->peer_id_);
|
||||
if (!dialog_id.is_valid()) {
|
||||
LOG(ERROR) << "Receive invalid " << dialog_id << " as a recent chooser for reaction " << reaction_str;
|
||||
LOG(ERROR) << "Receive invalid " << dialog_id << " as a recent chooser for reaction " << reaction_type;
|
||||
continue;
|
||||
}
|
||||
if (!recent_choosers.insert(dialog_id).second) {
|
||||
LOG(ERROR) << "Receive duplicate " << dialog_id << " as a recent chooser for reaction " << reaction_str;
|
||||
LOG(ERROR) << "Receive duplicate " << dialog_id << " as a recent chooser for reaction " << reaction_type;
|
||||
continue;
|
||||
}
|
||||
if (!td->messages_manager_->have_dialog_info(dialog_id)) {
|
||||
@ -649,7 +571,7 @@ unique_ptr<MessageReactions> MessageReactions::get_message_reactions(
|
||||
my_recent_chooser_dialog_id = dialog_id;
|
||||
}
|
||||
if (peer_reaction->unread_) {
|
||||
result->unread_reactions_.emplace_back(std::move(peer_reaction_str), dialog_id, peer_reaction->big_);
|
||||
result->unread_reactions_.emplace_back(std::move(peer_reaction_type), dialog_id, peer_reaction->big_);
|
||||
}
|
||||
if (recent_chooser_dialog_ids.size() == MessageReaction::MAX_RECENT_CHOOSERS) {
|
||||
break;
|
||||
@ -659,32 +581,32 @@ unique_ptr<MessageReactions> MessageReactions::get_message_reactions(
|
||||
|
||||
bool is_chosen = (reaction_count->flags_ & telegram_api::reactionCount::CHOSEN_ORDER_MASK) != 0;
|
||||
if (is_chosen) {
|
||||
chosen_reaction_order.emplace_back(reaction_count->chosen_order_, reaction_str);
|
||||
chosen_reaction_order.emplace_back(reaction_count->chosen_order_, reaction_type);
|
||||
}
|
||||
result->reactions_.push_back({std::move(reaction_str), reaction_count->count_, is_chosen,
|
||||
result->reactions_.push_back({std::move(reaction_type), reaction_count->count_, is_chosen,
|
||||
my_recent_chooser_dialog_id, std::move(recent_chooser_dialog_ids),
|
||||
std::move(recent_chooser_min_channels)});
|
||||
}
|
||||
if (chosen_reaction_order.size() > 1) {
|
||||
std::sort(chosen_reaction_order.begin(), chosen_reaction_order.end());
|
||||
result->chosen_reaction_order_ =
|
||||
transform(chosen_reaction_order, [](const std::pair<int32, string> &order) { return order.second; });
|
||||
transform(chosen_reaction_order, [](const std::pair<int32, ReactionType> &order) { return order.second; });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageReaction *MessageReactions::get_reaction(const string &reaction) {
|
||||
MessageReaction *MessageReactions::get_reaction(const ReactionType &reaction_type) {
|
||||
for (auto &added_reaction : reactions_) {
|
||||
if (added_reaction.get_reaction() == reaction) {
|
||||
if (added_reaction.get_reaction_type() == reaction_type) {
|
||||
return &added_reaction;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const MessageReaction *MessageReactions::get_reaction(const string &reaction) const {
|
||||
const MessageReaction *MessageReactions::get_reaction(const ReactionType &reaction_type) const {
|
||||
for (auto &added_reaction : reactions_) {
|
||||
if (added_reaction.get_reaction() == reaction) {
|
||||
if (added_reaction.get_reaction_type() == reaction_type) {
|
||||
return &added_reaction;
|
||||
}
|
||||
}
|
||||
@ -698,12 +620,12 @@ void MessageReactions::update_from(const MessageReactions &old_reactions) {
|
||||
chosen_reaction_order_ = old_reactions.chosen_reaction_order_;
|
||||
for (const auto &old_reaction : old_reactions.reactions_) {
|
||||
if (old_reaction.is_chosen()) {
|
||||
auto *reaction = get_reaction(old_reaction.get_reaction());
|
||||
auto *reaction = get_reaction(old_reaction.get_reaction_type());
|
||||
if (reaction != nullptr) {
|
||||
reaction->update_from(old_reaction);
|
||||
}
|
||||
} else {
|
||||
td::remove(chosen_reaction_order_, old_reaction.get_reaction());
|
||||
td::remove(chosen_reaction_order_, old_reaction.get_reaction_type());
|
||||
}
|
||||
}
|
||||
unread_reactions_ = old_reactions.unread_reactions_;
|
||||
@ -714,7 +636,7 @@ void MessageReactions::update_from(const MessageReactions &old_reactions) {
|
||||
for (const auto &old_reaction : old_reactions.reactions_) {
|
||||
if (old_reaction.is_chosen() &&
|
||||
old_reaction.get_recent_chooser_dialog_ids().size() == MessageReaction::MAX_RECENT_CHOOSERS + 1) {
|
||||
auto *reaction = get_reaction(old_reaction.get_reaction());
|
||||
auto *reaction = get_reaction(old_reaction.get_reaction_type());
|
||||
if (reaction != nullptr && reaction->is_chosen()) {
|
||||
reaction->update_recent_chooser_dialog_ids(old_reaction);
|
||||
}
|
||||
@ -722,11 +644,11 @@ void MessageReactions::update_from(const MessageReactions &old_reactions) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MessageReactions::add_reaction(const string &reaction, bool is_big, DialogId my_dialog_id,
|
||||
bool MessageReactions::add_reaction(const ReactionType &reaction_type, bool is_big, DialogId my_dialog_id,
|
||||
bool have_recent_choosers) {
|
||||
vector<string> new_chosen_reaction_order = get_chosen_reactions();
|
||||
vector<ReactionType> new_chosen_reaction_order = get_chosen_reaction_types();
|
||||
|
||||
auto added_reaction = get_reaction(reaction);
|
||||
auto added_reaction = get_reaction(reaction_type);
|
||||
if (added_reaction == nullptr) {
|
||||
vector<DialogId> recent_chooser_dialog_ids;
|
||||
DialogId my_recent_chooser_dialog_id;
|
||||
@ -735,18 +657,18 @@ bool MessageReactions::add_reaction(const string &reaction, bool is_big, DialogI
|
||||
my_recent_chooser_dialog_id = my_dialog_id;
|
||||
}
|
||||
reactions_.push_back(
|
||||
{reaction, 1, true, my_recent_chooser_dialog_id, std::move(recent_chooser_dialog_ids), Auto()});
|
||||
new_chosen_reaction_order.emplace_back(reaction);
|
||||
{reaction_type, 1, true, my_recent_chooser_dialog_id, std::move(recent_chooser_dialog_ids), Auto()});
|
||||
new_chosen_reaction_order.emplace_back(reaction_type);
|
||||
} else if (!added_reaction->is_chosen()) {
|
||||
added_reaction->set_as_chosen(my_dialog_id, have_recent_choosers);
|
||||
new_chosen_reaction_order.emplace_back(reaction);
|
||||
new_chosen_reaction_order.emplace_back(reaction_type);
|
||||
} else if (!is_big) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto max_reaction_count = get_max_reaction_count();
|
||||
while (new_chosen_reaction_order.size() > max_reaction_count) {
|
||||
auto index = new_chosen_reaction_order[0] == reaction ? 1 : 0;
|
||||
auto index = new_chosen_reaction_order[0] == reaction_type ? 1 : 0;
|
||||
CHECK(static_cast<size_t>(index) < new_chosen_reaction_order.size());
|
||||
bool is_removed = do_remove_reaction(new_chosen_reaction_order[index]);
|
||||
CHECK(is_removed);
|
||||
@ -765,10 +687,10 @@ bool MessageReactions::add_reaction(const string &reaction, bool is_big, DialogI
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MessageReactions::remove_reaction(const string &reaction, DialogId my_dialog_id) {
|
||||
if (do_remove_reaction(reaction)) {
|
||||
bool MessageReactions::remove_reaction(const ReactionType &reaction_type, DialogId my_dialog_id) {
|
||||
if (do_remove_reaction(reaction_type)) {
|
||||
if (!chosen_reaction_order_.empty()) {
|
||||
bool is_removed = td::remove(chosen_reaction_order_, reaction);
|
||||
bool is_removed = td::remove(chosen_reaction_order_, reaction_type);
|
||||
CHECK(is_removed);
|
||||
|
||||
// if the user isn't a Premium user, then max_reaction_count could be reduced from 3 to 1
|
||||
@ -793,10 +715,10 @@ bool MessageReactions::remove_reaction(const string &reaction, DialogId my_dialo
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MessageReactions::do_remove_reaction(const string &reaction) {
|
||||
bool MessageReactions::do_remove_reaction(const ReactionType &reaction_type) {
|
||||
for (auto it = reactions_.begin(); it != reactions_.end(); ++it) {
|
||||
auto &message_reaction = *it;
|
||||
if (message_reaction.get_reaction() == reaction) {
|
||||
if (message_reaction.get_reaction_type() == reaction_type) {
|
||||
if (message_reaction.is_chosen()) {
|
||||
message_reaction.unset_as_chosen();
|
||||
if (message_reaction.is_empty()) {
|
||||
@ -810,21 +732,21 @@ bool MessageReactions::do_remove_reaction(const string &reaction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MessageReactions::sort_reactions(const FlatHashMap<string, size_t> &active_reaction_pos) {
|
||||
void MessageReactions::sort_reactions(const FlatHashMap<ReactionType, size_t, ReactionTypeHash> &active_reaction_pos) {
|
||||
std::sort(reactions_.begin(), reactions_.end(),
|
||||
[&active_reaction_pos](const MessageReaction &lhs, const MessageReaction &rhs) {
|
||||
if (lhs.get_choose_count() != rhs.get_choose_count()) {
|
||||
return lhs.get_choose_count() > rhs.get_choose_count();
|
||||
}
|
||||
auto lhs_it = active_reaction_pos.find(lhs.get_reaction());
|
||||
auto lhs_it = active_reaction_pos.find(lhs.get_reaction_type());
|
||||
auto lhs_pos = lhs_it != active_reaction_pos.end() ? lhs_it->second : active_reaction_pos.size();
|
||||
auto rhs_it = active_reaction_pos.find(rhs.get_reaction());
|
||||
auto rhs_it = active_reaction_pos.find(rhs.get_reaction_type());
|
||||
auto rhs_pos = rhs_it != active_reaction_pos.end() ? rhs_it->second : active_reaction_pos.size();
|
||||
if (lhs_pos != rhs_pos) {
|
||||
return lhs_pos < rhs_pos;
|
||||
}
|
||||
|
||||
return lhs.get_reaction() < rhs.get_reaction();
|
||||
return lhs.get_reaction_type() < rhs.get_reaction_type();
|
||||
});
|
||||
}
|
||||
|
||||
@ -856,21 +778,22 @@ void MessageReactions::fix_my_recent_chooser_dialog_id(DialogId my_dialog_id) {
|
||||
}
|
||||
}
|
||||
|
||||
vector<string> MessageReactions::get_chosen_reactions() const {
|
||||
vector<ReactionType> MessageReactions::get_chosen_reaction_types() const {
|
||||
if (!chosen_reaction_order_.empty()) {
|
||||
return chosen_reaction_order_;
|
||||
}
|
||||
|
||||
vector<string> reaction_order;
|
||||
vector<ReactionType> reaction_order;
|
||||
for (auto &reaction : reactions_) {
|
||||
if (reaction.is_chosen()) {
|
||||
reaction_order.push_back(reaction.get_reaction());
|
||||
reaction_order.push_back(reaction.get_reaction_type());
|
||||
}
|
||||
}
|
||||
return reaction_order;
|
||||
}
|
||||
|
||||
bool MessageReactions::are_consistent_with_list(const string &reaction, FlatHashMap<string, vector<DialogId>> reactions,
|
||||
bool MessageReactions::are_consistent_with_list(
|
||||
const ReactionType &reaction_type, FlatHashMap<ReactionType, vector<DialogId>, ReactionTypeHash> reaction_types,
|
||||
int32 total_count) const {
|
||||
auto are_consistent = [](const vector<DialogId> &lhs, const vector<DialogId> &rhs) {
|
||||
size_t i = 0;
|
||||
@ -881,27 +804,27 @@ bool MessageReactions::are_consistent_with_list(const string &reaction, FlatHash
|
||||
return i == max_i;
|
||||
};
|
||||
|
||||
if (reaction.empty()) {
|
||||
if (reaction_type.is_empty()) {
|
||||
// received list and total_count for all reactions
|
||||
int32 old_total_count = 0;
|
||||
for (const auto &message_reaction : reactions_) {
|
||||
CHECK(!message_reaction.get_reaction().empty());
|
||||
if (!are_consistent(reactions[message_reaction.get_reaction()],
|
||||
CHECK(!message_reaction.get_reaction_type().is_empty());
|
||||
if (!are_consistent(reaction_types[message_reaction.get_reaction_type()],
|
||||
message_reaction.get_recent_chooser_dialog_ids())) {
|
||||
return false;
|
||||
}
|
||||
old_total_count += message_reaction.get_choose_count();
|
||||
reactions.erase(message_reaction.get_reaction());
|
||||
reaction_types.erase(message_reaction.get_reaction_type());
|
||||
}
|
||||
return old_total_count == total_count && reactions.empty();
|
||||
return old_total_count == total_count && reaction_types.empty();
|
||||
}
|
||||
|
||||
// received list and total_count for a single reaction
|
||||
const auto *message_reaction = get_reaction(reaction);
|
||||
const auto *message_reaction = get_reaction(reaction_type);
|
||||
if (message_reaction == nullptr) {
|
||||
return reactions.count(reaction) == 0 && total_count == 0;
|
||||
return reaction_types.count(reaction_type) == 0 && total_count == 0;
|
||||
} else {
|
||||
return are_consistent(reactions[reaction], message_reaction->get_recent_chooser_dialog_ids()) &&
|
||||
return are_consistent(reaction_types[reaction_type], message_reaction->get_recent_chooser_dialog_ids()) &&
|
||||
message_reaction->get_choose_count() == total_count;
|
||||
}
|
||||
}
|
||||
@ -970,14 +893,6 @@ StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr<Messag
|
||||
return string_builder << *reactions;
|
||||
}
|
||||
|
||||
bool is_custom_reaction(const string &reaction) {
|
||||
return reaction[0] == '#';
|
||||
}
|
||||
|
||||
bool is_active_reaction(const string &reaction, const FlatHashMap<string, size_t> &active_reaction_pos) {
|
||||
return !reaction.empty() && (is_custom_reaction(reaction) || active_reaction_pos.count(reaction) > 0);
|
||||
}
|
||||
|
||||
void reload_message_reactions(Td *td, DialogId dialog_id, vector<MessageId> &&message_ids) {
|
||||
if (!td->messages_manager_->have_input_peer(dialog_id, AccessRights::Read) ||
|
||||
dialog_id.get_type() == DialogType::SecretChat || message_ids.empty()) {
|
||||
@ -998,14 +913,14 @@ void reload_message_reactions(Td *td, DialogId dialog_id, vector<MessageId> &&me
|
||||
td->create_handler<GetMessagesReactionsQuery>()->send(dialog_id, std::move(message_ids));
|
||||
}
|
||||
|
||||
void send_message_reaction(Td *td, FullMessageId full_message_id, vector<string> reactions, bool is_big,
|
||||
void send_message_reaction(Td *td, FullMessageId full_message_id, vector<ReactionType> reaction_types, bool is_big,
|
||||
bool add_to_recent, Promise<Unit> &&promise) {
|
||||
td->create_handler<SendReactionQuery>(std::move(promise))
|
||||
->send(full_message_id, std::move(reactions), is_big, add_to_recent);
|
||||
->send(full_message_id, std::move(reaction_types), is_big, add_to_recent);
|
||||
}
|
||||
|
||||
void get_message_added_reactions(Td *td, FullMessageId full_message_id, string reaction, string offset, int32 limit,
|
||||
Promise<td_api::object_ptr<td_api::addedReactions>> &&promise) {
|
||||
void get_message_added_reactions(Td *td, FullMessageId full_message_id, ReactionType reaction_type, string offset,
|
||||
int32 limit, Promise<td_api::object_ptr<td_api::addedReactions>> &&promise) {
|
||||
if (!td->messages_manager_->have_message_force(full_message_id, "get_message_added_reactions")) {
|
||||
return promise.set_error(Status::Error(400, "Message not found"));
|
||||
}
|
||||
@ -1025,19 +940,19 @@ void get_message_added_reactions(Td *td, FullMessageId full_message_id, string r
|
||||
}
|
||||
|
||||
td->create_handler<GetMessageReactionsListQuery>(std::move(promise))
|
||||
->send(full_message_id, std::move(reaction), std::move(offset), limit);
|
||||
->send(full_message_id, std::move(reaction_type), std::move(offset), limit);
|
||||
}
|
||||
|
||||
void set_default_reaction(Td *td, string reaction, Promise<Unit> &&promise) {
|
||||
if (reaction.empty()) {
|
||||
void set_default_reaction(Td *td, ReactionType reaction_type, Promise<Unit> &&promise) {
|
||||
if (reaction_type.is_empty()) {
|
||||
return promise.set_error(Status::Error(400, "Default reaction must be non-empty"));
|
||||
}
|
||||
if (!is_custom_reaction(reaction) && !td->stickers_manager_->is_active_reaction(reaction)) {
|
||||
if (!reaction_type.is_custom_reaction() && !td->stickers_manager_->is_active_reaction(reaction_type)) {
|
||||
return promise.set_error(Status::Error(400, "Can't set incative reaction as default"));
|
||||
}
|
||||
|
||||
if (td->option_manager_->get_option_string("default_reaction", "-") != reaction) {
|
||||
td->option_manager_->set_option_string("default_reaction", reaction);
|
||||
if (td->option_manager_->get_option_string("default_reaction", "-") != reaction_type.get_string()) {
|
||||
td->option_manager_->set_option_string("default_reaction", reaction_type.get_string());
|
||||
if (!td->option_manager_->get_option_boolean("default_reaction_needs_sync")) {
|
||||
td->option_manager_->set_option_boolean("default_reaction_needs_sync", true);
|
||||
send_set_default_reaction_query(td);
|
||||
@ -1047,14 +962,8 @@ void set_default_reaction(Td *td, string reaction, Promise<Unit> &&promise) {
|
||||
}
|
||||
|
||||
void send_set_default_reaction_query(Td *td) {
|
||||
td->create_handler<SetDefaultReactionQuery>()->send(td->option_manager_->get_option_string("default_reaction"));
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::updateDefaultReactionType> get_update_default_reaction_type(const string &default_reaction) {
|
||||
if (default_reaction.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return td_api::make_object<td_api::updateDefaultReactionType>(get_reaction_type_object(default_reaction));
|
||||
td->create_handler<SetDefaultReactionQuery>()->send(
|
||||
ReactionType(td->option_manager_->get_option_string("default_reaction")));
|
||||
}
|
||||
|
||||
void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId chooser_dialog_id,
|
||||
@ -1088,38 +997,16 @@ void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId ch
|
||||
td->create_handler<ReportReactionQuery>(std::move(promise))->send(dialog_id, message_id, chooser_dialog_id);
|
||||
}
|
||||
|
||||
vector<string> get_recent_reactions(Td *td) {
|
||||
vector<ReactionType> get_recent_reactions(Td *td) {
|
||||
return td->stickers_manager_->get_recent_reactions();
|
||||
}
|
||||
|
||||
vector<string> get_top_reactions(Td *td) {
|
||||
vector<ReactionType> get_top_reactions(Td *td) {
|
||||
return td->stickers_manager_->get_top_reactions();
|
||||
}
|
||||
|
||||
void add_recent_reaction(Td *td, const string &reaction) {
|
||||
td->stickers_manager_->add_recent_reaction(reaction);
|
||||
}
|
||||
|
||||
int64 get_reactions_hash(const vector<string> &reactions) {
|
||||
vector<uint64> numbers;
|
||||
for (auto &reaction : reactions) {
|
||||
if (is_custom_reaction(reaction)) {
|
||||
auto custom_emoji_id = static_cast<uint64>(get_custom_emoji_id(reaction));
|
||||
numbers.push_back(custom_emoji_id >> 32);
|
||||
numbers.push_back(custom_emoji_id & 0xFFFFFFFF);
|
||||
} else {
|
||||
auto emoji = remove_emoji_selectors(reaction);
|
||||
unsigned char hash[16];
|
||||
md5(emoji, {hash, sizeof(hash)});
|
||||
auto get = [hash](int num) {
|
||||
return static_cast<uint32>(hash[num]);
|
||||
};
|
||||
|
||||
numbers.push_back(0);
|
||||
numbers.push_back(static_cast<int32>((get(0) << 24) + (get(1) << 16) + (get(2) << 8) + get(3)));
|
||||
}
|
||||
}
|
||||
return get_vector_hash(numbers);
|
||||
void add_recent_reaction(Td *td, const ReactionType &reaction_type) {
|
||||
td->stickers_manager_->add_recent_reaction(reaction_type);
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "td/telegram/FullMessageId.h"
|
||||
#include "td/telegram/MessageId.h"
|
||||
#include "td/telegram/MinChannel.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
#include "td/telegram/UserId.h"
|
||||
@ -33,7 +34,7 @@ class MessageReaction {
|
||||
|
||||
static constexpr size_t MAX_RECENT_CHOOSERS = 3;
|
||||
|
||||
string reaction_;
|
||||
ReactionType reaction_type_;
|
||||
int32 choose_count_ = 0;
|
||||
bool is_chosen_ = false;
|
||||
DialogId my_recent_chooser_dialog_id_;
|
||||
@ -46,7 +47,7 @@ class MessageReaction {
|
||||
|
||||
friend struct MessageReactions;
|
||||
|
||||
MessageReaction(string reaction, int32 choose_count, bool is_chosen, DialogId my_recent_chooser_dialog_id,
|
||||
MessageReaction(ReactionType reaction_type, int32 choose_count, bool is_chosen, DialogId my_recent_chooser_dialog_id,
|
||||
vector<DialogId> &&recent_chooser_dialog_ids,
|
||||
vector<std::pair<ChannelId, MinChannel>> &&recent_chooser_min_channels);
|
||||
|
||||
@ -94,8 +95,8 @@ class MessageReaction {
|
||||
public:
|
||||
MessageReaction() = default;
|
||||
|
||||
const string &get_reaction() const {
|
||||
return reaction_;
|
||||
const ReactionType &get_reaction_type() const {
|
||||
return reaction_type_;
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
@ -114,7 +115,7 @@ inline bool operator!=(const MessageReaction &lhs, const MessageReaction &rhs) {
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReaction &reaction);
|
||||
|
||||
class UnreadMessageReaction {
|
||||
string reaction_;
|
||||
ReactionType reaction_type_;
|
||||
DialogId sender_dialog_id_;
|
||||
bool is_big_ = false;
|
||||
|
||||
@ -125,8 +126,8 @@ class UnreadMessageReaction {
|
||||
public:
|
||||
UnreadMessageReaction() = default;
|
||||
|
||||
UnreadMessageReaction(string reaction, DialogId sender_dialog_id, bool is_big)
|
||||
: reaction_(std::move(reaction)), sender_dialog_id_(sender_dialog_id), is_big_(is_big) {
|
||||
UnreadMessageReaction(ReactionType reaction_type, DialogId sender_dialog_id, bool is_big)
|
||||
: reaction_type_(std::move(reaction_type)), sender_dialog_id_(sender_dialog_id), is_big_(is_big) {
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::unreadReaction> get_unread_reaction_object(Td *td) const;
|
||||
@ -149,7 +150,7 @@ StringBuilder &operator<<(StringBuilder &string_builder, const UnreadMessageReac
|
||||
struct MessageReactions {
|
||||
vector<MessageReaction> reactions_;
|
||||
vector<UnreadMessageReaction> unread_reactions_;
|
||||
vector<string> chosen_reaction_order_;
|
||||
vector<ReactionType> chosen_reaction_order_;
|
||||
bool is_min_ = false;
|
||||
bool need_polling_ = true;
|
||||
bool can_get_added_reactions_ = false;
|
||||
@ -160,25 +161,26 @@ struct MessageReactions {
|
||||
tl_object_ptr<telegram_api::messageReactions> &&reactions,
|
||||
bool is_bot);
|
||||
|
||||
MessageReaction *get_reaction(const string &reaction);
|
||||
MessageReaction *get_reaction(const ReactionType &reaction_type);
|
||||
|
||||
const MessageReaction *get_reaction(const string &reaction) const;
|
||||
const MessageReaction *get_reaction(const ReactionType &reaction_type) const;
|
||||
|
||||
void update_from(const MessageReactions &old_reactions);
|
||||
|
||||
bool add_reaction(const string &reaction, bool is_big, DialogId my_dialog_id, bool have_recent_choosers);
|
||||
bool add_reaction(const ReactionType &reaction_type, bool is_big, DialogId my_dialog_id, bool have_recent_choosers);
|
||||
|
||||
bool remove_reaction(const string &reaction, DialogId my_dialog_id);
|
||||
bool remove_reaction(const ReactionType &reaction_type, DialogId my_dialog_id);
|
||||
|
||||
void sort_reactions(const FlatHashMap<string, size_t> &active_reaction_pos);
|
||||
void sort_reactions(const FlatHashMap<ReactionType, size_t, ReactionTypeHash> &active_reaction_pos);
|
||||
|
||||
void fix_chosen_reaction();
|
||||
|
||||
void fix_my_recent_chooser_dialog_id(DialogId my_dialog_id);
|
||||
|
||||
vector<string> get_chosen_reactions() const;
|
||||
vector<ReactionType> get_chosen_reaction_types() const;
|
||||
|
||||
bool are_consistent_with_list(const string &reaction, FlatHashMap<string, vector<DialogId>> reactions,
|
||||
bool are_consistent_with_list(const ReactionType &reaction_type,
|
||||
FlatHashMap<ReactionType, vector<DialogId>, ReactionTypeHash> reaction_types,
|
||||
int32 total_count) const;
|
||||
|
||||
vector<td_api::object_ptr<td_api::messageReaction>> get_message_reactions_object(Td *td, UserId my_user_id,
|
||||
@ -201,48 +203,32 @@ struct MessageReactions {
|
||||
void parse(ParserT &parser);
|
||||
|
||||
private:
|
||||
bool do_remove_reaction(const string &reaction);
|
||||
bool do_remove_reaction(const ReactionType &reaction_type);
|
||||
};
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReactions &reactions);
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr<MessageReactions> &reactions);
|
||||
|
||||
telegram_api::object_ptr<telegram_api::Reaction> get_input_reaction(const string &reaction);
|
||||
|
||||
td_api::object_ptr<td_api::ReactionType> get_reaction_type_object(const string &reaction);
|
||||
|
||||
string get_message_reaction_string(const telegram_api::object_ptr<telegram_api::Reaction> &reaction);
|
||||
|
||||
string get_message_reaction_string(const td_api::object_ptr<td_api::ReactionType> &type);
|
||||
|
||||
bool is_custom_reaction(const string &reaction);
|
||||
|
||||
bool is_active_reaction(const string &reaction, const FlatHashMap<string, size_t> &active_reaction_pos);
|
||||
|
||||
void reload_message_reactions(Td *td, DialogId dialog_id, vector<MessageId> &&message_ids);
|
||||
|
||||
void send_message_reaction(Td *td, FullMessageId full_message_id, vector<string> reactions, bool is_big,
|
||||
void send_message_reaction(Td *td, FullMessageId full_message_id, vector<ReactionType> reaction_types, bool is_big,
|
||||
bool add_to_recent, Promise<Unit> &&promise);
|
||||
|
||||
void get_message_added_reactions(Td *td, FullMessageId full_message_id, string reaction, string offset, int32 limit,
|
||||
Promise<td_api::object_ptr<td_api::addedReactions>> &&promise);
|
||||
void get_message_added_reactions(Td *td, FullMessageId full_message_id, ReactionType reaction_type, string offset,
|
||||
int32 limit, Promise<td_api::object_ptr<td_api::addedReactions>> &&promise);
|
||||
|
||||
void set_default_reaction(Td *td, string reaction, Promise<Unit> &&promise);
|
||||
void set_default_reaction(Td *td, ReactionType reaction_type, Promise<Unit> &&promise);
|
||||
|
||||
void send_set_default_reaction_query(Td *td);
|
||||
|
||||
td_api::object_ptr<td_api::updateDefaultReactionType> get_update_default_reaction_type(const string &default_reaction);
|
||||
|
||||
void report_message_reactions(Td *td, FullMessageId full_message_id, DialogId chooser_dialog_id,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
vector<string> get_recent_reactions(Td *td);
|
||||
vector<ReactionType> get_recent_reactions(Td *td);
|
||||
|
||||
vector<string> get_top_reactions(Td *td);
|
||||
vector<ReactionType> get_top_reactions(Td *td);
|
||||
|
||||
void add_recent_reaction(Td *td, const string &reaction);
|
||||
|
||||
int64 get_reactions_hash(const vector<string> &reactions);
|
||||
void add_recent_reaction(Td *td, const ReactionType &reaction_type);
|
||||
|
||||
} // namespace td
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "td/telegram/MessageReaction.h"
|
||||
#include "td/telegram/MinChannel.hpp"
|
||||
#include "td/telegram/ReactionType.hpp"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/common.h"
|
||||
@ -27,7 +28,7 @@ void MessageReaction::store(StorerT &storer) const {
|
||||
STORE_FLAG(has_recent_chooser_min_channels);
|
||||
STORE_FLAG(has_my_recent_chooser_dialog_id);
|
||||
END_STORE_FLAGS();
|
||||
td::store(reaction_, storer);
|
||||
td::store(reaction_type_, storer);
|
||||
td::store(choose_count_, storer);
|
||||
if (has_recent_chooser_dialog_ids) {
|
||||
td::store(recent_chooser_dialog_ids_, storer);
|
||||
@ -51,7 +52,7 @@ void MessageReaction::parse(ParserT &parser) {
|
||||
PARSE_FLAG(has_recent_chooser_min_channels);
|
||||
PARSE_FLAG(has_my_recent_chooser_dialog_id);
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(reaction_, parser);
|
||||
td::parse(reaction_type_, parser);
|
||||
td::parse(choose_count_, parser);
|
||||
if (has_recent_chooser_dialog_ids) {
|
||||
td::parse(recent_chooser_dialog_ids_, parser);
|
||||
@ -65,7 +66,7 @@ void MessageReaction::parse(ParserT &parser) {
|
||||
CHECK(td::contains(recent_chooser_dialog_ids_, my_recent_chooser_dialog_id_));
|
||||
}
|
||||
CHECK(!is_empty());
|
||||
CHECK(!reaction_.empty());
|
||||
CHECK(!reaction_type_.is_empty());
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
@ -73,7 +74,7 @@ void UnreadMessageReaction::store(StorerT &storer) const {
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(is_big_);
|
||||
END_STORE_FLAGS();
|
||||
td::store(reaction_, storer);
|
||||
td::store(reaction_type_, storer);
|
||||
td::store(sender_dialog_id_, storer);
|
||||
}
|
||||
|
||||
@ -82,9 +83,9 @@ void UnreadMessageReaction::parse(ParserT &parser) {
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(is_big_);
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(reaction_, parser);
|
||||
td::parse(reaction_type_, parser);
|
||||
td::parse(sender_dialog_id_, parser);
|
||||
CHECK(!reaction_.empty());
|
||||
CHECK(!reaction_type_.is_empty());
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
|
@ -5766,9 +5766,9 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
|
||||
if (has_available_reactions) {
|
||||
parse(available_reactions, parser);
|
||||
} else if (has_legacy_available_reactions) {
|
||||
vector<string> legacy_available_reactions;
|
||||
parse(legacy_available_reactions, parser);
|
||||
available_reactions = ChatReactions(std::move(legacy_available_reactions));
|
||||
vector<ReactionType> legacy_available_reaction_types;
|
||||
parse(legacy_available_reaction_types, parser);
|
||||
available_reactions = ChatReactions(std::move(legacy_available_reaction_types));
|
||||
}
|
||||
if (has_available_reactions_generation) {
|
||||
parse(available_reactions_generation, parser);
|
||||
@ -6846,8 +6846,9 @@ void MessagesManager::update_message_reactions(FullMessageId full_message_id,
|
||||
update_message_interaction_info(full_message_id, -1, -1, false, nullptr, true, std::move(reactions));
|
||||
}
|
||||
|
||||
void MessagesManager::on_get_message_reaction_list(FullMessageId full_message_id, const string &reaction,
|
||||
FlatHashMap<string, vector<DialogId>> reactions, int32 total_count) {
|
||||
void MessagesManager::on_get_message_reaction_list(
|
||||
FullMessageId full_message_id, const ReactionType &reaction_type,
|
||||
FlatHashMap<ReactionType, vector<DialogId>, ReactionTypeHash> reaction_types, int32 total_count) {
|
||||
const Message *m = get_message_force(full_message_id, "on_get_message_reaction_list");
|
||||
if (m == nullptr || m->reactions == nullptr) {
|
||||
return;
|
||||
@ -6855,7 +6856,7 @@ void MessagesManager::on_get_message_reaction_list(FullMessageId full_message_id
|
||||
|
||||
// it's impossible to use received reactions to update message reactions, because there is no way to find,
|
||||
// which reactions are chosen by the current user, so just reload message reactions for consistency
|
||||
if (m->reactions->are_consistent_with_list(reaction, std::move(reactions), total_count)) {
|
||||
if (m->reactions->are_consistent_with_list(reaction_type, std::move(reaction_types), total_count)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -8454,19 +8455,19 @@ void MessagesManager::hide_dialog_message_reactions(Dialog *d) {
|
||||
}
|
||||
}
|
||||
|
||||
void MessagesManager::set_active_reactions(vector<string> active_reactions) {
|
||||
if (active_reactions == active_reactions_) {
|
||||
void MessagesManager::set_active_reactions(vector<ReactionType> active_reaction_types) {
|
||||
if (active_reaction_types == active_reaction_types_) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Set active reactions to " << active_reactions;
|
||||
bool is_changed = active_reactions != active_reactions_;
|
||||
active_reactions_ = std::move(active_reactions);
|
||||
LOG(INFO) << "Set active reactions to " << active_reaction_types;
|
||||
bool is_changed = active_reaction_types != active_reaction_types_;
|
||||
active_reaction_types_ = std::move(active_reaction_types);
|
||||
|
||||
auto old_active_reaction_pos_ = std::move(active_reaction_pos_);
|
||||
active_reaction_pos_.clear();
|
||||
for (size_t i = 0; i < active_reactions_.size(); i++) {
|
||||
active_reaction_pos_[active_reactions_[i]] = i;
|
||||
for (size_t i = 0; i < active_reaction_types_.size(); i++) {
|
||||
active_reaction_pos_[active_reaction_types_[i]] = i;
|
||||
}
|
||||
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
@ -23787,22 +23788,22 @@ Result<td_api::object_ptr<td_api::availableReactions>> MessagesManager::get_mess
|
||||
LOG(INFO) << "Have available reactions " << available_reactions << " to be sorted by top reactions " << top_reactions
|
||||
<< " and recent reactions " << recent_reactions;
|
||||
if (active_reactions.allow_custom_ && active_reactions.allow_all_) {
|
||||
for (auto &reaction : recent_reactions) {
|
||||
if (is_custom_reaction(reaction)) {
|
||||
for (auto &reaction_type : recent_reactions) {
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
show_premium = true;
|
||||
}
|
||||
}
|
||||
for (auto &reaction : top_reactions) {
|
||||
if (is_custom_reaction(reaction)) {
|
||||
for (auto &reaction_type : top_reactions) {
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
show_premium = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlatHashSet<string> all_available_reactions;
|
||||
for (const auto &reaction : available_reactions.reactions_) {
|
||||
CHECK(!reaction.empty());
|
||||
all_available_reactions.insert(reaction);
|
||||
FlatHashSet<ReactionType, ReactionTypeHash> all_available_reaction_types;
|
||||
for (const auto &reaction_type : available_reactions.reaction_types_) {
|
||||
CHECK(!reaction_type.is_empty());
|
||||
all_available_reaction_types.insert(reaction_type);
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> top_reaction_objects;
|
||||
@ -23810,22 +23811,22 @@ Result<td_api::object_ptr<td_api::availableReactions>> MessagesManager::get_mess
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> popular_reaction_objects;
|
||||
vector<td_api::object_ptr<td_api::availableReaction>> last_reaction_objects;
|
||||
|
||||
FlatHashSet<string> added_custom_reactions;
|
||||
FlatHashSet<ReactionType, ReactionTypeHash> added_custom_reaction_types;
|
||||
auto add_reactions = [&](vector<td_api::object_ptr<td_api::availableReaction>> &reaction_objects,
|
||||
const vector<string> &reactions) {
|
||||
for (auto &reaction : reactions) {
|
||||
if (all_available_reactions.erase(reaction) != 0) {
|
||||
const vector<ReactionType> &reaction_types) {
|
||||
for (auto &reaction_type : reaction_types) {
|
||||
if (all_available_reaction_types.erase(reaction_type) != 0) {
|
||||
// add available reaction
|
||||
if (is_custom_reaction(reaction)) {
|
||||
added_custom_reactions.insert(reaction);
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
added_custom_reaction_types.insert(reaction_type);
|
||||
}
|
||||
reaction_objects.push_back(
|
||||
td_api::make_object<td_api::availableReaction>(get_reaction_type_object(reaction), false));
|
||||
} else if (is_custom_reaction(reaction) && available_reactions.allow_custom_ &&
|
||||
added_custom_reactions.insert(reaction).second) {
|
||||
td_api::make_object<td_api::availableReaction>(reaction_type.get_reaction_type_object(), false));
|
||||
} else if (reaction_type.is_custom_reaction() && available_reactions.allow_custom_ &&
|
||||
added_custom_reaction_types.insert(reaction_type).second) {
|
||||
// add implicitly available custom reaction
|
||||
reaction_objects.push_back(
|
||||
td_api::make_object<td_api::availableReaction>(get_reaction_type_object(reaction), !is_premium));
|
||||
td_api::make_object<td_api::availableReaction>(reaction_type.get_reaction_type_object(), !is_premium));
|
||||
} else {
|
||||
// skip the reaction
|
||||
}
|
||||
@ -23843,8 +23844,8 @@ Result<td_api::object_ptr<td_api::availableReactions>> MessagesManager::get_mess
|
||||
} else {
|
||||
add_reactions(top_reaction_objects, top_reactions);
|
||||
}
|
||||
add_reactions(last_reaction_objects, active_reactions_);
|
||||
add_reactions(last_reaction_objects, available_reactions.reactions_);
|
||||
add_reactions(last_reaction_objects, active_reaction_types_);
|
||||
add_reactions(last_reaction_objects, available_reactions.reaction_types_);
|
||||
|
||||
if (show_premium) {
|
||||
if (recent_reactions.empty()) {
|
||||
@ -23864,7 +23865,7 @@ Result<td_api::object_ptr<td_api::availableReactions>> MessagesManager::get_mess
|
||||
append(top_reaction_objects, std::move(last_reaction_objects));
|
||||
}
|
||||
|
||||
CHECK(all_available_reactions.empty());
|
||||
CHECK(all_available_reaction_types.empty());
|
||||
|
||||
return td_api::make_object<td_api::availableReactions>(
|
||||
std::move(top_reaction_objects), std::move(recent_reaction_objects), std::move(popular_reaction_objects),
|
||||
@ -23899,16 +23900,16 @@ ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d,
|
||||
}
|
||||
|
||||
if (active_reactions.allow_all_) {
|
||||
active_reactions.reactions_ = active_reactions_;
|
||||
active_reactions.reaction_types_ = active_reaction_types_;
|
||||
active_reactions.allow_all_ = false;
|
||||
}
|
||||
if (m->reactions != nullptr) {
|
||||
for (const auto &reaction : m->reactions->reactions_) {
|
||||
// an already used reaction can be added if it is an active reaction
|
||||
const string &reaction_str = reaction.get_reaction();
|
||||
if (can_use_reactions && is_active_reaction(reaction_str, active_reaction_pos_) &&
|
||||
!td::contains(active_reactions.reactions_, reaction_str)) {
|
||||
active_reactions.reactions_.push_back(reaction_str);
|
||||
const auto &reaction_type = reaction.get_reaction_type();
|
||||
if (can_use_reactions && reaction_type.is_active_reaction(active_reaction_pos_) &&
|
||||
!td::contains(active_reactions.reaction_types_, reaction_type)) {
|
||||
active_reactions.reaction_types_.push_back(reaction_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -23918,7 +23919,7 @@ ChatReactions MessagesManager::get_message_available_reactions(const Dialog *d,
|
||||
return active_reactions;
|
||||
}
|
||||
|
||||
void MessagesManager::add_message_reaction(FullMessageId full_message_id, string reaction, bool is_big,
|
||||
void MessagesManager::add_message_reaction(FullMessageId full_message_id, ReactionType reaction_type, bool is_big,
|
||||
bool add_to_recent, Promise<Unit> &&promise) {
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
Dialog *d = get_dialog_force(dialog_id, "add_message_reaction");
|
||||
@ -23931,7 +23932,7 @@ void MessagesManager::add_message_reaction(FullMessageId full_message_id, string
|
||||
return promise.set_error(Status::Error(400, "Message not found"));
|
||||
}
|
||||
|
||||
if (!get_message_available_reactions(d, m, true).is_allowed_reaction(reaction)) {
|
||||
if (!get_message_available_reactions(d, m, true).is_allowed_reaction_type(reaction_type)) {
|
||||
return promise.set_error(Status::Error(400, "The reaction isn't available for the message"));
|
||||
}
|
||||
|
||||
@ -23944,18 +23945,19 @@ void MessagesManager::add_message_reaction(FullMessageId full_message_id, string
|
||||
|
||||
auto my_dialog_id =
|
||||
d->default_send_message_as_dialog_id.is_valid() ? d->default_send_message_as_dialog_id : get_my_dialog_id();
|
||||
if (!m->reactions->add_reaction(reaction, is_big, my_dialog_id, have_recent_choosers)) {
|
||||
if (!m->reactions->add_reaction(reaction_type, is_big, my_dialog_id, have_recent_choosers)) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
if (add_to_recent) {
|
||||
add_recent_reaction(td_, reaction);
|
||||
add_recent_reaction(td_, reaction_type);
|
||||
}
|
||||
|
||||
set_message_reactions(d, m, is_big, add_to_recent, std::move(promise));
|
||||
}
|
||||
|
||||
void MessagesManager::remove_message_reaction(FullMessageId full_message_id, string reaction, Promise<Unit> &&promise) {
|
||||
void MessagesManager::remove_message_reaction(FullMessageId full_message_id, ReactionType reaction_type,
|
||||
Promise<Unit> &&promise) {
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
Dialog *d = get_dialog_force(dialog_id, "remove_message_reaction");
|
||||
if (d == nullptr) {
|
||||
@ -23967,13 +23969,13 @@ void MessagesManager::remove_message_reaction(FullMessageId full_message_id, str
|
||||
return promise.set_error(Status::Error(400, "Message not found"));
|
||||
}
|
||||
|
||||
if (reaction.empty()) {
|
||||
if (reaction_type.is_empty()) {
|
||||
return promise.set_error(Status::Error(400, "Invalid reaction specified"));
|
||||
}
|
||||
|
||||
auto my_dialog_id =
|
||||
d->default_send_message_as_dialog_id.is_valid() ? d->default_send_message_as_dialog_id : get_my_dialog_id();
|
||||
if (m->reactions == nullptr || !m->reactions->remove_reaction(reaction, my_dialog_id)) {
|
||||
if (m->reactions == nullptr || !m->reactions->remove_reaction(reaction_type, my_dialog_id)) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
@ -23999,7 +24001,7 @@ void MessagesManager::set_message_reactions(Dialog *d, Message *m, bool is_big,
|
||||
send_closure(actor_id, &MessagesManager::on_set_message_reactions, full_message_id, std::move(result),
|
||||
std::move(promise));
|
||||
});
|
||||
send_message_reaction(td_, full_message_id, m->reactions->get_chosen_reactions(), is_big, add_to_recent,
|
||||
send_message_reaction(td_, full_message_id, m->reactions->get_chosen_reaction_types(), is_big, add_to_recent,
|
||||
std::move(query_promise));
|
||||
}
|
||||
|
||||
@ -33833,7 +33835,7 @@ void MessagesManager::set_dialog_available_reactions(
|
||||
|
||||
ChatReactions available_reactions(std::move(available_reactions_ptr), !is_broadcast_channel(dialog_id));
|
||||
auto active_reactions = get_active_reactions(available_reactions);
|
||||
if (active_reactions.reactions_.size() != available_reactions.reactions_.size()) {
|
||||
if (active_reactions.reaction_types_.size() != available_reactions.reaction_types_.size()) {
|
||||
return promise.set_error(Status::Error(400, "Invalid reactions specified"));
|
||||
}
|
||||
available_reactions = std::move(active_reactions);
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "td/telegram/NotificationSettingsScope.h"
|
||||
#include "td/telegram/OrderedMessage.h"
|
||||
#include "td/telegram/Photo.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/RecentDialogList.h"
|
||||
#include "td/telegram/ReplyMarkup.h"
|
||||
#include "td/telegram/RestrictionReason.h"
|
||||
@ -355,8 +356,9 @@ class MessagesManager final : public Actor {
|
||||
|
||||
void try_reload_message_reactions(DialogId dialog_id, bool is_finished);
|
||||
|
||||
void on_get_message_reaction_list(FullMessageId full_message_id, const string &reaction,
|
||||
FlatHashMap<string, vector<DialogId>> reactions, int32 total_count);
|
||||
void on_get_message_reaction_list(FullMessageId full_message_id, const ReactionType &reaction_type,
|
||||
FlatHashMap<ReactionType, vector<DialogId>, ReactionTypeHash> reaction_types,
|
||||
int32 total_count);
|
||||
|
||||
void on_update_message_interaction_info(FullMessageId full_message_id, int32 view_count, int32 forward_count,
|
||||
bool has_reply_info,
|
||||
@ -566,7 +568,7 @@ class MessagesManager final : public Actor {
|
||||
|
||||
void set_dialog_description(DialogId dialog_id, const string &description, Promise<Unit> &&promise);
|
||||
|
||||
void set_active_reactions(vector<string> active_reactions);
|
||||
void set_active_reactions(vector<ReactionType> active_reaction_types);
|
||||
|
||||
void set_dialog_available_reactions(DialogId dialog_id,
|
||||
td_api::object_ptr<td_api::ChatAvailableReactions> &&available_reactions_ptr,
|
||||
@ -856,10 +858,10 @@ class MessagesManager final : public Actor {
|
||||
Result<td_api::object_ptr<td_api::availableReactions>> get_message_available_reactions(FullMessageId full_message_id,
|
||||
int32 row_size);
|
||||
|
||||
void add_message_reaction(FullMessageId full_message_id, string reaction, bool is_big, bool add_to_recent,
|
||||
void add_message_reaction(FullMessageId full_message_id, ReactionType reaction_type, bool is_big, bool add_to_recent,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void remove_message_reaction(FullMessageId full_message_id, string reaction, Promise<Unit> &&promise);
|
||||
void remove_message_reaction(FullMessageId full_message_id, ReactionType reaction_type, Promise<Unit> &&promise);
|
||||
|
||||
void get_message_public_forwards(FullMessageId full_message_id, string offset, int32 limit,
|
||||
Promise<td_api::object_ptr<td_api::foundMessages>> &&promise);
|
||||
@ -3697,8 +3699,8 @@ class MessagesManager final : public Actor {
|
||||
|
||||
FlatHashMap<FullMessageId, int32, FullMessageIdHash> pending_read_reactions_;
|
||||
|
||||
vector<string> active_reactions_;
|
||||
FlatHashMap<string, size_t> active_reaction_pos_;
|
||||
vector<ReactionType> active_reaction_types_;
|
||||
FlatHashMap<ReactionType, size_t, ReactionTypeHash> active_reaction_pos_;
|
||||
|
||||
FlatHashMap<PendingGetHistoryQuery, vector<Promise<Unit>>, PendingGetHistoryQueryHash> get_history_queries_;
|
||||
|
||||
|
@ -17,10 +17,10 @@
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/JsonValue.h"
|
||||
#include "td/telegram/LanguagePackManager.h"
|
||||
#include "td/telegram/MessageReaction.h"
|
||||
#include "td/telegram/net/MtprotoHeader.h"
|
||||
#include "td/telegram/net/NetQueryDispatcher.h"
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
#include "td/telegram/StorageManager.h"
|
||||
@ -315,7 +315,7 @@ bool OptionManager::is_internal_option(Slice name) {
|
||||
|
||||
td_api::object_ptr<td_api::Update> OptionManager::get_internal_option_update(Slice name) const {
|
||||
if (name == "default_reaction") {
|
||||
return get_update_default_reaction_type(get_option_string(name));
|
||||
return ReactionType(get_option_string(name)).get_update_default_reaction_type();
|
||||
}
|
||||
if (name == "otherwise_relogin_days") {
|
||||
auto days = narrow_cast<int32>(get_option_integer(name));
|
||||
|
154
td/telegram/ReactionType.cpp
Normal file
154
td/telegram/ReactionType.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
//
|
||||
// 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/ReactionType.h"
|
||||
|
||||
#include "td/telegram/misc.h"
|
||||
|
||||
#include "td/utils/as.h"
|
||||
#include "td/utils/base64.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/emoji.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
#include "td/utils/utf8.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
static int64 get_custom_emoji_id(const string &reaction) {
|
||||
auto r_decoded = base64_decode(Slice(&reaction[1], reaction.size() - 1));
|
||||
CHECK(r_decoded.is_ok());
|
||||
CHECK(r_decoded.ok().size() == 8);
|
||||
return as<int64>(r_decoded.ok().c_str());
|
||||
}
|
||||
|
||||
static string get_custom_emoji_string(int64 custom_emoji_id) {
|
||||
char s[8];
|
||||
as<int64>(&s) = custom_emoji_id;
|
||||
return PSTRING() << '#' << base64_encode(Slice(s, 8));
|
||||
}
|
||||
|
||||
ReactionType::ReactionType(string &&emoji) : reaction_(std::move(emoji)) {
|
||||
}
|
||||
|
||||
ReactionType::ReactionType(const telegram_api::object_ptr<telegram_api::Reaction> &reaction) {
|
||||
if (reaction == nullptr) {
|
||||
return;
|
||||
}
|
||||
switch (reaction->get_id()) {
|
||||
case telegram_api::reactionEmpty::ID:
|
||||
break;
|
||||
case telegram_api::reactionEmoji::ID:
|
||||
reaction_ = static_cast<const telegram_api::reactionEmoji *>(reaction.get())->emoticon_;
|
||||
if (is_custom_reaction()) {
|
||||
reaction_ = string();
|
||||
}
|
||||
break;
|
||||
case telegram_api::reactionCustomEmoji::ID:
|
||||
reaction_ =
|
||||
get_custom_emoji_string(static_cast<const telegram_api::reactionCustomEmoji *>(reaction.get())->document_id_);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ReactionType::ReactionType(const td_api::object_ptr<td_api::ReactionType> &type) {
|
||||
if (type == nullptr) {
|
||||
return;
|
||||
}
|
||||
switch (type->get_id()) {
|
||||
case td_api::reactionTypeEmoji::ID: {
|
||||
const string &emoji = static_cast<const td_api::reactionTypeEmoji *>(type.get())->emoji_;
|
||||
if (!check_utf8(emoji)) {
|
||||
break;
|
||||
}
|
||||
reaction_ = emoji;
|
||||
if (is_custom_reaction()) {
|
||||
reaction_ = string();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case td_api::reactionTypeCustomEmoji::ID:
|
||||
reaction_ =
|
||||
get_custom_emoji_string(static_cast<const td_api::reactionTypeCustomEmoji *>(type.get())->custom_emoji_id_);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
telegram_api::object_ptr<telegram_api::Reaction> ReactionType::get_input_reaction() const {
|
||||
if (is_empty()) {
|
||||
return telegram_api::make_object<telegram_api::reactionEmpty>();
|
||||
}
|
||||
if (is_custom_reaction()) {
|
||||
return telegram_api::make_object<telegram_api::reactionCustomEmoji>(get_custom_emoji_id(reaction_));
|
||||
}
|
||||
return telegram_api::make_object<telegram_api::reactionEmoji>(reaction_);
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::ReactionType> ReactionType::get_reaction_type_object() const {
|
||||
CHECK(!is_empty());
|
||||
if (is_custom_reaction()) {
|
||||
return td_api::make_object<td_api::reactionTypeCustomEmoji>(get_custom_emoji_id(reaction_));
|
||||
}
|
||||
return td_api::make_object<td_api::reactionTypeEmoji>(reaction_);
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::updateDefaultReactionType> ReactionType::get_update_default_reaction_type() const {
|
||||
if (is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return td_api::make_object<td_api::updateDefaultReactionType>(get_reaction_type_object());
|
||||
}
|
||||
|
||||
bool ReactionType::is_custom_reaction() const {
|
||||
return reaction_[0] == '#';
|
||||
}
|
||||
|
||||
bool ReactionType::is_active_reaction(
|
||||
const FlatHashMap<ReactionType, size_t, ReactionTypeHash> &active_reaction_pos) const {
|
||||
return !reaction_.empty() && (is_custom_reaction() || active_reaction_pos.count(*this) > 0);
|
||||
}
|
||||
|
||||
bool operator<(const ReactionType &lhs, const ReactionType &rhs) {
|
||||
return lhs.reaction_ < rhs.reaction_;
|
||||
}
|
||||
|
||||
bool operator==(const ReactionType &lhs, const ReactionType &rhs) {
|
||||
return lhs.reaction_ == rhs.reaction_;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const ReactionType &reaction_type) {
|
||||
return string_builder << reaction_type.reaction_;
|
||||
}
|
||||
|
||||
int64 get_reaction_types_hash(const vector<ReactionType> &reaction_types) {
|
||||
vector<uint64> numbers;
|
||||
for (auto &reaction_type : reaction_types) {
|
||||
if (reaction_type.is_custom_reaction()) {
|
||||
auto custom_emoji_id = static_cast<uint64>(get_custom_emoji_id(reaction_type.get_string()));
|
||||
numbers.push_back(custom_emoji_id >> 32);
|
||||
numbers.push_back(custom_emoji_id & 0xFFFFFFFF);
|
||||
} else {
|
||||
auto emoji = remove_emoji_selectors(reaction_type.get_string());
|
||||
unsigned char hash[16];
|
||||
md5(emoji, {hash, sizeof(hash)});
|
||||
auto get = [hash](int num) {
|
||||
return static_cast<uint32>(hash[num]);
|
||||
};
|
||||
|
||||
numbers.push_back(0);
|
||||
numbers.push_back(static_cast<int32>((get(0) << 24) + (get(1) << 16) + (get(2) << 8) + get(3)));
|
||||
}
|
||||
}
|
||||
return get_vector_hash(numbers);
|
||||
}
|
||||
|
||||
} // namespace td
|
85
td/telegram/ReactionType.h
Normal file
85
td/telegram/ReactionType.h
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// 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/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/FlatHashMap.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
class Dependencies;
|
||||
|
||||
class Td;
|
||||
|
||||
class ReactionType {
|
||||
string reaction_;
|
||||
|
||||
friend bool operator<(const ReactionType &lhs, const ReactionType &rhs);
|
||||
|
||||
friend bool operator==(const ReactionType &lhs, const ReactionType &rhs);
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &string_builder, const ReactionType &reaction_type);
|
||||
|
||||
friend struct ReactionTypeHash;
|
||||
|
||||
public:
|
||||
ReactionType() = default;
|
||||
|
||||
explicit ReactionType(string &&emoji);
|
||||
|
||||
explicit ReactionType(const telegram_api::object_ptr<telegram_api::Reaction> &reaction);
|
||||
|
||||
explicit ReactionType(const td_api::object_ptr<td_api::ReactionType> &type);
|
||||
|
||||
telegram_api::object_ptr<telegram_api::Reaction> get_input_reaction() const;
|
||||
|
||||
td_api::object_ptr<td_api::ReactionType> get_reaction_type_object() const;
|
||||
|
||||
td_api::object_ptr<td_api::updateDefaultReactionType> get_update_default_reaction_type() const;
|
||||
|
||||
bool is_custom_reaction() const;
|
||||
|
||||
bool is_active_reaction(const FlatHashMap<ReactionType, size_t, ReactionTypeHash> &active_reaction_pos) const;
|
||||
|
||||
bool is_empty() const {
|
||||
return reaction_.empty();
|
||||
}
|
||||
|
||||
const string &get_string() const {
|
||||
return reaction_;
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
struct ReactionTypeHash {
|
||||
uint32 operator()(const ReactionType &reaction_type) const {
|
||||
return Hash<string>()(reaction_type.reaction_);
|
||||
}
|
||||
};
|
||||
|
||||
bool operator<(const ReactionType &lhs, const ReactionType &rhs);
|
||||
|
||||
bool operator==(const ReactionType &lhs, const ReactionType &rhs);
|
||||
|
||||
inline bool operator!=(const ReactionType &lhs, const ReactionType &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const ReactionType &reaction_type);
|
||||
|
||||
int64 get_reaction_types_hash(const vector<ReactionType> &reaction_types);
|
||||
|
||||
} // namespace td
|
27
td/telegram/ReactionType.hpp
Normal file
27
td/telegram/ReactionType.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// 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/ReactionType.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
template <class StorerT>
|
||||
void ReactionType::store(StorerT &storer) const {
|
||||
CHECK(!is_empty());
|
||||
td::store(reaction_, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void ReactionType::parse(ParserT &parser) {
|
||||
td::parse(reaction_, parser);
|
||||
}
|
||||
|
||||
} // namespace td
|
@ -1812,12 +1812,13 @@ void StickersManager::init() {
|
||||
|
||||
td_api::object_ptr<td_api::emojiReaction> StickersManager::get_emoji_reaction_object(const string &emoji) const {
|
||||
for (auto &reaction : reactions_.reactions_) {
|
||||
if (reaction.reaction_ == emoji) {
|
||||
if (reaction.reaction_type_.get_string() == emoji) {
|
||||
return td_api::make_object<td_api::emojiReaction>(
|
||||
reaction.reaction_, reaction.title_, reaction.is_active_, get_sticker_object(reaction.static_icon_),
|
||||
get_sticker_object(reaction.appear_animation_), get_sticker_object(reaction.select_animation_),
|
||||
get_sticker_object(reaction.activate_animation_), get_sticker_object(reaction.effect_animation_),
|
||||
get_sticker_object(reaction.around_animation_), get_sticker_object(reaction.center_animation_));
|
||||
reaction.reaction_type_.get_string(), reaction.title_, reaction.is_active_,
|
||||
get_sticker_object(reaction.static_icon_), get_sticker_object(reaction.appear_animation_),
|
||||
get_sticker_object(reaction.select_animation_), get_sticker_object(reaction.activate_animation_),
|
||||
get_sticker_object(reaction.effect_animation_), get_sticker_object(reaction.around_animation_),
|
||||
get_sticker_object(reaction.center_animation_));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
@ -1833,47 +1834,47 @@ void StickersManager::get_emoji_reaction(const string &emoji,
|
||||
promise.set_value(get_emoji_reaction_object(emoji));
|
||||
}
|
||||
|
||||
vector<string> StickersManager::get_recent_reactions() {
|
||||
vector<ReactionType> StickersManager::get_recent_reactions() {
|
||||
load_recent_reactions();
|
||||
return recent_reactions_.reactions_;
|
||||
return recent_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
vector<string> StickersManager::get_top_reactions() {
|
||||
vector<ReactionType> StickersManager::get_top_reactions() {
|
||||
load_top_reactions();
|
||||
return top_reactions_.reactions_;
|
||||
return top_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
void StickersManager::add_recent_reaction(const string &reaction) {
|
||||
void StickersManager::add_recent_reaction(const ReactionType &reaction_type) {
|
||||
load_recent_reactions();
|
||||
|
||||
auto &reactions = recent_reactions_.reactions_;
|
||||
if (!reactions.empty() && reactions[0] == reaction) {
|
||||
auto &reactions = recent_reactions_.reaction_types_;
|
||||
if (!reactions.empty() && reactions[0] == reaction_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::find(reactions.begin(), reactions.end(), reaction);
|
||||
auto it = std::find(reactions.begin(), reactions.end(), reaction_type);
|
||||
if (it == reactions.end()) {
|
||||
if (static_cast<int32>(reactions.size()) == MAX_RECENT_REACTIONS) {
|
||||
reactions.back() = reaction;
|
||||
reactions.back() = reaction_type;
|
||||
} else {
|
||||
reactions.push_back(reaction);
|
||||
reactions.push_back(reaction_type);
|
||||
}
|
||||
it = reactions.end() - 1;
|
||||
}
|
||||
std::rotate(reactions.begin(), it, it + 1);
|
||||
|
||||
recent_reactions_.hash_ = get_reactions_hash(reactions);
|
||||
recent_reactions_.hash_ = get_reaction_types_hash(reactions);
|
||||
}
|
||||
|
||||
void StickersManager::clear_recent_reactions(Promise<Unit> &&promise) {
|
||||
load_recent_reactions();
|
||||
|
||||
if (recent_reactions_.reactions_.empty()) {
|
||||
if (recent_reactions_.reaction_types_.empty()) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
recent_reactions_.hash_ = 0;
|
||||
recent_reactions_.reactions_.clear();
|
||||
recent_reactions_.reaction_types_.clear();
|
||||
|
||||
td_->create_handler<ClearRecentReactionsQuery>(std::move(promise))->send();
|
||||
}
|
||||
@ -4139,12 +4140,13 @@ void StickersManager::on_get_special_sticker_set(const SpecialStickerSetType &ty
|
||||
|
||||
td_api::object_ptr<td_api::updateActiveEmojiReactions> StickersManager::get_update_active_emoji_reactions_object()
|
||||
const {
|
||||
return td_api::make_object<td_api::updateActiveEmojiReactions>(vector<string>(active_reactions_));
|
||||
return td_api::make_object<td_api::updateActiveEmojiReactions>(
|
||||
transform(active_reaction_types_, [](const ReactionType &reaction_type) { return reaction_type.get_string(); }));
|
||||
}
|
||||
|
||||
void StickersManager::save_active_reactions() {
|
||||
LOG(INFO) << "Save " << active_reactions_.size() << " active reactions";
|
||||
G()->td_db()->get_binlog_pmc()->set("active_reactions", log_event_store(active_reactions_).as_slice().str());
|
||||
LOG(INFO) << "Save " << active_reaction_types_.size() << " active reactions";
|
||||
G()->td_db()->get_binlog_pmc()->set("active_reactions", log_event_store(active_reaction_types_).as_slice().str());
|
||||
}
|
||||
|
||||
void StickersManager::save_reactions() {
|
||||
@ -4154,34 +4156,34 @@ void StickersManager::save_reactions() {
|
||||
}
|
||||
|
||||
void StickersManager::save_recent_reactions() {
|
||||
LOG(INFO) << "Save " << recent_reactions_.reactions_.size() << " recent reactions";
|
||||
LOG(INFO) << "Save " << recent_reactions_.reaction_types_.size() << " recent reactions";
|
||||
are_recent_reactions_loaded_from_database_ = true;
|
||||
G()->td_db()->get_binlog_pmc()->set("recent_reactions", log_event_store(recent_reactions_).as_slice().str());
|
||||
}
|
||||
|
||||
void StickersManager::save_top_reactions() {
|
||||
LOG(INFO) << "Save " << top_reactions_.reactions_.size() << " top reactions";
|
||||
LOG(INFO) << "Save " << top_reactions_.reaction_types_.size() << " top reactions";
|
||||
are_top_reactions_loaded_from_database_ = true;
|
||||
G()->td_db()->get_binlog_pmc()->set("top_reactions", log_event_store(top_reactions_).as_slice().str());
|
||||
}
|
||||
|
||||
void StickersManager::load_active_reactions() {
|
||||
LOG(INFO) << "Loading active reactions";
|
||||
string active_reactions = G()->td_db()->get_binlog_pmc()->get("active_reactions");
|
||||
if (active_reactions.empty()) {
|
||||
string active_reaction_types = G()->td_db()->get_binlog_pmc()->get("active_reactions");
|
||||
if (active_reaction_types.empty()) {
|
||||
return reload_reactions();
|
||||
}
|
||||
|
||||
auto status = log_event_parse(active_reactions_, active_reactions);
|
||||
auto status = log_event_parse(active_reaction_types_, active_reaction_types);
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << "Can't load active reactions: " << status;
|
||||
active_reactions_ = {};
|
||||
active_reaction_types_ = {};
|
||||
return reload_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << active_reactions_.size() << " active reactions";
|
||||
LOG(INFO) << "Successfully loaded " << active_reaction_types_.size() << " active reactions";
|
||||
|
||||
td_->messages_manager_->set_active_reactions(vector<string>(active_reactions_));
|
||||
td_->messages_manager_->set_active_reactions(active_reaction_types_);
|
||||
|
||||
send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object());
|
||||
}
|
||||
@ -4204,8 +4206,8 @@ void StickersManager::load_reactions() {
|
||||
LOG(ERROR) << "Can't load available reactions: " << status;
|
||||
return reload_reactions();
|
||||
}
|
||||
for (auto &reaction : new_reactions.reactions_) {
|
||||
if (!reaction.is_valid()) {
|
||||
for (auto &reaction_type : new_reactions.reactions_) {
|
||||
if (!reaction_type.is_valid()) {
|
||||
LOG(ERROR) << "Loaded invalid reaction";
|
||||
return reload_reactions();
|
||||
}
|
||||
@ -4236,7 +4238,7 @@ void StickersManager::load_recent_reactions() {
|
||||
return reload_recent_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << recent_reactions_.reactions_.size() << " recent reactions";
|
||||
LOG(INFO) << "Successfully loaded " << recent_reactions_.reaction_types_.size() << " recent reactions";
|
||||
}
|
||||
|
||||
void StickersManager::load_top_reactions() {
|
||||
@ -4258,26 +4260,26 @@ void StickersManager::load_top_reactions() {
|
||||
return reload_top_reactions();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << top_reactions_.reactions_.size() << " top reactions";
|
||||
LOG(INFO) << "Successfully loaded " << top_reactions_.reaction_types_.size() << " top reactions";
|
||||
}
|
||||
|
||||
void StickersManager::update_active_reactions() {
|
||||
vector<string> active_reactions;
|
||||
vector<ReactionType> active_reaction_types;
|
||||
for (auto &reaction : reactions_.reactions_) {
|
||||
if (reaction.is_active_) {
|
||||
active_reactions.emplace_back(reaction.reaction_);
|
||||
active_reaction_types.emplace_back(reaction.reaction_type_);
|
||||
}
|
||||
}
|
||||
if (active_reactions == active_reactions_) {
|
||||
if (active_reaction_types == active_reaction_types_) {
|
||||
return;
|
||||
}
|
||||
active_reactions_ = active_reactions;
|
||||
active_reaction_types_ = active_reaction_types;
|
||||
|
||||
save_active_reactions();
|
||||
|
||||
send_closure(G()->td(), &Td::send_update, get_update_active_emoji_reactions_object());
|
||||
|
||||
td_->messages_manager_->set_active_reactions(std::move(active_reactions));
|
||||
td_->messages_manager_->set_active_reactions(std::move(active_reaction_types));
|
||||
}
|
||||
|
||||
void StickersManager::on_get_available_reactions(
|
||||
@ -4311,7 +4313,7 @@ void StickersManager::on_get_available_reactions(
|
||||
Reaction reaction;
|
||||
reaction.is_active_ = !available_reaction->inactive_;
|
||||
reaction.is_premium_ = available_reaction->premium_;
|
||||
reaction.reaction_ = std::move(available_reaction->reaction_);
|
||||
reaction.reaction_type_ = ReactionType(std::move(available_reaction->reaction_));
|
||||
reaction.title_ = std::move(available_reaction->title_);
|
||||
reaction.static_icon_ =
|
||||
on_get_sticker_document(std::move(available_reaction->static_icon_), StickerFormat::Webp).second;
|
||||
@ -4329,11 +4331,11 @@ void StickersManager::on_get_available_reactions(
|
||||
on_get_sticker_document(std::move(available_reaction->center_icon_), StickerFormat::Tgs).second;
|
||||
|
||||
if (!reaction.is_valid()) {
|
||||
LOG(ERROR) << "Receive invalid reaction " << reaction.reaction_;
|
||||
LOG(ERROR) << "Receive invalid reaction " << reaction.reaction_type_;
|
||||
continue;
|
||||
}
|
||||
if (reaction.is_premium_) {
|
||||
LOG(ERROR) << "Receive premium reaction " << reaction.reaction_;
|
||||
LOG(ERROR) << "Receive premium reaction " << reaction.reaction_type_;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -4364,21 +4366,20 @@ void StickersManager::on_get_recent_reactions(tl_object_ptr<telegram_api::messag
|
||||
|
||||
CHECK(constructor_id == telegram_api::messages_reactions::ID);
|
||||
auto reactions = move_tl_object_as<telegram_api::messages_reactions>(reactions_ptr);
|
||||
auto new_reactions =
|
||||
transform(reactions->reactions_, [](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) {
|
||||
return get_message_reaction_string(reaction);
|
||||
});
|
||||
if (new_reactions == recent_reactions_.reactions_ && recent_reactions_.hash_ == reactions->hash_) {
|
||||
auto new_reaction_types = transform(
|
||||
reactions->reactions_,
|
||||
[](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) { return ReactionType(reaction); });
|
||||
if (new_reaction_types == recent_reactions_.reaction_types_ && recent_reactions_.hash_ == reactions->hash_) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
recent_reactions_.reactions_ = std::move(new_reactions);
|
||||
recent_reactions_.reaction_types_ = std::move(new_reaction_types);
|
||||
recent_reactions_.hash_ = reactions->hash_;
|
||||
|
||||
auto expected_hash = get_reactions_hash(recent_reactions_.reactions_);
|
||||
auto expected_hash = get_reaction_types_hash(recent_reactions_.reaction_types_);
|
||||
if (recent_reactions_.hash_ != expected_hash) {
|
||||
LOG(ERROR) << "Receive hash " << recent_reactions_.hash_ << " instead of " << expected_hash << " for reactions "
|
||||
<< recent_reactions_.reactions_;
|
||||
<< recent_reactions_.reaction_types_;
|
||||
}
|
||||
|
||||
save_recent_reactions();
|
||||
@ -4401,15 +4402,14 @@ void StickersManager::on_get_top_reactions(tl_object_ptr<telegram_api::messages_
|
||||
|
||||
CHECK(constructor_id == telegram_api::messages_reactions::ID);
|
||||
auto reactions = move_tl_object_as<telegram_api::messages_reactions>(reactions_ptr);
|
||||
auto new_reactions =
|
||||
transform(reactions->reactions_, [](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) {
|
||||
return get_message_reaction_string(reaction);
|
||||
});
|
||||
if (new_reactions == top_reactions_.reactions_ && top_reactions_.hash_ == reactions->hash_) {
|
||||
auto new_reaction_types = transform(
|
||||
reactions->reactions_,
|
||||
[](const telegram_api::object_ptr<telegram_api::Reaction> &reaction) { return ReactionType(reaction); });
|
||||
if (new_reaction_types == top_reactions_.reaction_types_ && top_reactions_.hash_ == reactions->hash_) {
|
||||
LOG(INFO) << "Top reactions are not modified";
|
||||
return;
|
||||
}
|
||||
top_reactions_.reactions_ = std::move(new_reactions);
|
||||
top_reactions_.reaction_types_ = std::move(new_reaction_types);
|
||||
top_reactions_.hash_ = reactions->hash_;
|
||||
|
||||
save_top_reactions();
|
||||
@ -7229,9 +7229,9 @@ void StickersManager::send_update_animated_emoji_clicked(FullMessageId full_mess
|
||||
full_message_id.get_message_id().get(), get_sticker_object(sticker_id, false, true)));
|
||||
}
|
||||
|
||||
bool StickersManager::is_active_reaction(const string &reaction) const {
|
||||
bool StickersManager::is_active_reaction(const ReactionType &reaction_type) const {
|
||||
for (auto &supported_reaction : reactions_.reactions_) {
|
||||
if (supported_reaction.reaction_ == reaction) {
|
||||
if (supported_reaction.reaction_type_ == reaction_type) {
|
||||
return supported_reaction.is_active_;
|
||||
}
|
||||
}
|
||||
@ -10412,7 +10412,7 @@ void StickersManager::get_current_state(vector<td_api::object_ptr<td_api::Update
|
||||
return;
|
||||
}
|
||||
|
||||
if (!active_reactions_.empty()) {
|
||||
if (!active_reaction_types_.empty()) {
|
||||
updates.push_back(get_update_active_emoji_reactions_object());
|
||||
}
|
||||
for (int32 type = 0; type < MAX_STICKER_TYPE; type++) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "td/telegram/FullMessageId.h"
|
||||
#include "td/telegram/PhotoFormat.h"
|
||||
#include "td/telegram/PhotoSize.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/SecretInputMedia.h"
|
||||
#include "td/telegram/SpecialStickerSetType.h"
|
||||
#include "td/telegram/StickerFormat.h"
|
||||
@ -146,7 +147,7 @@ class StickersManager final : public Actor {
|
||||
|
||||
Status on_animated_emoji_message_clicked(string &&emoji, FullMessageId full_message_id, string data);
|
||||
|
||||
bool is_active_reaction(const string &reaction) const;
|
||||
bool is_active_reaction(const ReactionType &reaction_type) const;
|
||||
|
||||
void create_sticker(FileId file_id, FileId premium_animation_file_id, string minithumbnail, PhotoSize thumbnail,
|
||||
Dimensions dimensions, tl_object_ptr<telegram_api::documentAttributeSticker> sticker,
|
||||
@ -195,11 +196,11 @@ class StickersManager final : public Actor {
|
||||
|
||||
void get_emoji_reaction(const string &emoji, Promise<td_api::object_ptr<td_api::emojiReaction>> &&promise);
|
||||
|
||||
vector<string> get_recent_reactions();
|
||||
vector<ReactionType> get_recent_reactions();
|
||||
|
||||
vector<string> get_top_reactions();
|
||||
vector<ReactionType> get_top_reactions();
|
||||
|
||||
void add_recent_reaction(const string &reaction);
|
||||
void add_recent_reaction(const ReactionType &reaction_type);
|
||||
|
||||
void clear_recent_reactions(Promise<Unit> &&promise);
|
||||
|
||||
@ -584,7 +585,7 @@ class StickersManager final : public Actor {
|
||||
};
|
||||
|
||||
struct Reaction {
|
||||
string reaction_;
|
||||
ReactionType reaction_type_;
|
||||
string title_;
|
||||
bool is_active_ = false;
|
||||
bool is_premium_ = false;
|
||||
@ -598,7 +599,7 @@ class StickersManager final : public Actor {
|
||||
|
||||
bool is_valid() const {
|
||||
return static_icon_.is_valid() && appear_animation_.is_valid() && select_animation_.is_valid() &&
|
||||
activate_animation_.is_valid() && effect_animation_.is_valid() && !reaction_.empty();
|
||||
activate_animation_.is_valid() && effect_animation_.is_valid() && !reaction_type_.is_empty();
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
@ -623,7 +624,7 @@ class StickersManager final : public Actor {
|
||||
struct ReactionList {
|
||||
int64 hash_ = 0;
|
||||
bool is_being_reloaded_ = false;
|
||||
vector<string> reactions_;
|
||||
vector<ReactionType> reaction_types_;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
@ -1178,7 +1179,7 @@ class StickersManager final : public Actor {
|
||||
FlatHashMap<FileId, std::pair<UserId, Promise<Unit>>, FileIdHash> being_uploaded_files_;
|
||||
|
||||
Reactions reactions_;
|
||||
vector<string> active_reactions_;
|
||||
vector<ReactionType> active_reaction_types_;
|
||||
|
||||
ReactionList recent_reactions_;
|
||||
ReactionList top_reactions_;
|
||||
|
@ -476,7 +476,7 @@ void StickersManager::Reaction::store(StorerT &storer) const {
|
||||
STORE_FLAG(has_center_animation);
|
||||
STORE_FLAG(is_premium_);
|
||||
END_STORE_FLAGS();
|
||||
td::store(reaction_, storer);
|
||||
td::store(reaction_type_, storer);
|
||||
td::store(title_, storer);
|
||||
stickers_manager->store_sticker(static_icon_, false, storer, "Reaction");
|
||||
stickers_manager->store_sticker(appear_animation_, false, storer, "Reaction");
|
||||
@ -502,7 +502,7 @@ void StickersManager::Reaction::parse(ParserT &parser) {
|
||||
PARSE_FLAG(has_center_animation);
|
||||
PARSE_FLAG(is_premium_);
|
||||
END_PARSE_FLAGS();
|
||||
td::parse(reaction_, parser);
|
||||
td::parse(reaction_type_, parser);
|
||||
td::parse(title_, parser);
|
||||
static_icon_ = stickers_manager->parse_sticker(false, parser);
|
||||
appear_animation_ = stickers_manager->parse_sticker(false, parser);
|
||||
@ -545,24 +545,24 @@ void StickersManager::Reactions::parse(ParserT &parser) {
|
||||
|
||||
template <class StorerT>
|
||||
void StickersManager::ReactionList::store(StorerT &storer) const {
|
||||
bool has_reactions = !reactions_.empty();
|
||||
bool has_reaction_types = !reaction_types_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(has_reactions);
|
||||
STORE_FLAG(has_reaction_types);
|
||||
END_STORE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::store(reactions_, storer);
|
||||
if (has_reaction_types) {
|
||||
td::store(reaction_types_, storer);
|
||||
td::store(hash_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void StickersManager::ReactionList::parse(ParserT &parser) {
|
||||
bool has_reactions;
|
||||
bool has_reaction_types;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(has_reactions);
|
||||
PARSE_FLAG(has_reaction_types);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::parse(reactions_, parser);
|
||||
if (has_reaction_types) {
|
||||
td::parse(reaction_types_, parser);
|
||||
td::parse(hash_, parser);
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +107,7 @@
|
||||
#include "td/telegram/Premium.h"
|
||||
#include "td/telegram/PrivacyManager.h"
|
||||
#include "td/telegram/PublicDialogType.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/ReportReason.h"
|
||||
#include "td/telegram/RequestActor.h"
|
||||
#include "td/telegram/ScopeNotificationSettings.h"
|
||||
@ -5350,7 +5351,7 @@ void Td::on_request(uint64 id, td_api::addMessageReaction &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
messages_manager_->add_message_reaction({DialogId(request.chat_id_), MessageId(request.message_id_)},
|
||||
get_message_reaction_string(request.reaction_type_), request.is_big_,
|
||||
ReactionType(request.reaction_type_), request.is_big_,
|
||||
request.update_recent_reactions_, std::move(promise));
|
||||
}
|
||||
|
||||
@ -5358,7 +5359,7 @@ void Td::on_request(uint64 id, td_api::removeMessageReaction &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
messages_manager_->remove_message_reaction({DialogId(request.chat_id_), MessageId(request.message_id_)},
|
||||
get_message_reaction_string(request.reaction_type_), std::move(promise));
|
||||
ReactionType(request.reaction_type_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getMessageAddedReactions &request) {
|
||||
@ -5366,14 +5367,14 @@ void Td::on_request(uint64 id, td_api::getMessageAddedReactions &request) {
|
||||
CLEAN_INPUT_STRING(request.offset_);
|
||||
CREATE_REQUEST_PROMISE();
|
||||
get_message_added_reactions(this, {DialogId(request.chat_id_), MessageId(request.message_id_)},
|
||||
get_message_reaction_string(request.reaction_type_), std::move(request.offset_),
|
||||
request.limit_, std::move(promise));
|
||||
ReactionType(request.reaction_type_), std::move(request.offset_), request.limit_,
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::setDefaultReactionType &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
set_default_reaction(this, get_message_reaction_string(request.reaction_type_), std::move(promise));
|
||||
set_default_reaction(this, ReactionType(request.reaction_type_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getMessagePublicForwards &request) {
|
||||
|
Loading…
Reference in New Issue
Block a user