From 1901eafe8a6554e7bbbc18e868b0768711f26ca5 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 26 Jan 2022 15:25:03 +0300 Subject: [PATCH] Add td_api::getMessageAvailableReactions. --- td/generate/scheme/td_api.tl | 8 +++++++ td/telegram/MessageReaction.cpp | 16 ++++++++++---- td/telegram/MessageReaction.h | 2 ++ td/telegram/MessagesManager.cpp | 39 +++++++++++++++++++++++++++++++++ td/telegram/MessagesManager.h | 2 ++ td/telegram/Td.cpp | 12 ++++++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 5 +++++ 8 files changed, 82 insertions(+), 4 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 230789c11..66b076105 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2393,6 +2393,9 @@ chosenReaction reaction:string chooser_id:MessageSender = ChosenReaction; //@description Represents a list of chosen reactions for a message @total_count The total count of found reactions @reactions The list of chosen reactions @next_offset The offset for the next request. If empty, there are no more results chosenReactions total_count:int32 reactions:vector next_offset:string = ChosenReactions; +//@description Represents a list of reactions @reactions List of reactions +availableReactions reactions:vector = AvailableReactions; + //@description Contains stickers which must be used for reaction animation rendering //@reaction Text representation of the reaction @@ -4598,6 +4601,11 @@ editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup = editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok; +//@description Returns reactions, which can be set for a message. The list can change after updateReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message +//@chat_id Identifier of the chat to which the message belongs +//@message_id Identifier of the message +getMessageAvailableReactions chat_id:int53 message_id:int53 = AvailableReactions; + //@description Changes chosen reaction for a message //@chat_id Identifier of the chat to which the message belongs //@message_id Identifier of the message diff --git a/td/telegram/MessageReaction.cpp b/td/telegram/MessageReaction.cpp index d6c14eaa9..58b7b2d12 100644 --- a/td/telegram/MessageReaction.cpp +++ b/td/telegram/MessageReaction.cpp @@ -262,6 +262,15 @@ unique_ptr MessageReactions::get_message_reactions( return result; } +MessageReaction *MessageReactions::get_reaction(const string &reaction) { + for (auto &chosen_reaction : reactions_) { + if (chosen_reaction.get_reaction() == reaction) { + return &chosen_reaction; + } + } + return nullptr; +} + void MessageReactions::update_from(const MessageReactions &old_reactions) { if (old_reactions.has_pending_reaction_) { // we will ignore all updates, received while there is a pending reaction, so there are no reasons to update @@ -274,10 +283,9 @@ void MessageReactions::update_from(const MessageReactions &old_reactions) { is_min_ = false; for (const auto &old_reaction : old_reactions.reactions_) { if (old_reaction.is_chosen()) { - for (auto &reaction : reactions_) { - if (reaction.get_reaction() == old_reaction.get_reaction()) { - reaction.set_is_chosen(true, DialogId(), false); - } + auto *reaction = get_reaction(old_reaction.get_reaction()); + if (reaction != nullptr) { + reaction->set_is_chosen(true, DialogId(), false); } } } diff --git a/td/telegram/MessageReaction.h b/td/telegram/MessageReaction.h index 06fed6f81..e077f4a9a 100644 --- a/td/telegram/MessageReaction.h +++ b/td/telegram/MessageReaction.h @@ -107,6 +107,8 @@ struct MessageReactions { tl_object_ptr &&reactions, bool is_bot); + MessageReaction *get_reaction(const string &reaction); + void update_from(const MessageReactions &old_reactions); void sort(const std::unordered_map &active_reaction_pos); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 90dc510df..8c4885435 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -23758,6 +23758,45 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id } } +Result> MessagesManager::get_message_available_reactions(FullMessageId full_message_id) { + auto dialog_id = full_message_id.get_dialog_id(); + Dialog *d = get_dialog_force(dialog_id, "get_message_available_reactions"); + if (d == nullptr) { + return Status::Error(400, "Chat not found"); + } + + Message *m = get_message_force(d, full_message_id.get_message_id(), "get_message_available_reactions"); + if (m == nullptr) { + return Status::Error(400, "Message not found"); + } + + if (!m->message_id.is_valid() || !m->message_id.is_server() || get_active_reactions(d->available_reactions).empty()) { + return vector(); + } + + vector result; + int64 reactions_uniq_max = G()->shared_config().get_option_integer("reactions_uniq_max", 11); + bool can_add_new_reactions = + m->reactions == nullptr || static_cast(m->reactions->reactions_.size()) < reactions_uniq_max; + // can add only active available reactions or remove previously set reaction + for (const auto &active_reaction : active_reactions_) { + // can add the reaction if it has already been used for the message or is available in the chat + if ((m->reactions != nullptr && m->reactions->get_reaction(active_reaction) != nullptr) || + (can_add_new_reactions && td::contains(d->available_reactions, active_reaction))) { + result.push_back(active_reaction); + } + } + if (m->reactions != nullptr) { + for (const auto &reaction : m->reactions->reactions_) { + if (reaction.is_chosen() && !td::contains(result, reaction.get_reaction())) { + CHECK(!td::contains(active_reactions_, reaction.get_reaction())); + result.push_back(reaction.get_reaction()); + } + } + } + return result; +} + void MessagesManager::set_message_reaction(FullMessageId full_message_id, string reaction, Promise &&promise) { auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog_force(dialog_id, "set_message_reaction"); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c1695476b..f1869adcd 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -780,6 +780,8 @@ class MessagesManager final : public Actor { vector get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result, Promise &&promise); + Result> get_message_available_reactions(FullMessageId full_message_id); + void set_message_reaction(FullMessageId full_message_id, string reaction, Promise &&promise); void get_message_public_forwards(FullMessageId full_message_id, string offset, int32 limit, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 237536454..fd3850533 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5242,6 +5242,18 @@ void Td::on_request(uint64 id, const td_api::getChatScheduledMessages &request) CREATE_REQUEST(GetChatScheduledMessagesRequest, request.chat_id_); } +void Td::on_request(uint64 id, const td_api::getMessageAvailableReactions &request) { + CHECK_IS_USER(); + auto r_reactions = + messages_manager_->get_message_available_reactions({DialogId(request.chat_id_), MessageId(request.message_id_)}); + if (r_reactions.is_error()) { + send_closure(actor_id(this), &Td::send_error, id, r_reactions.move_as_error()); + } else { + send_closure(actor_id(this), &Td::send_result, id, + td_api::make_object(r_reactions.move_as_ok())); + } +} + void Td::on_request(uint64 id, td_api::setMessageReaction &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.reaction_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 99d24ec8e..d2b9e4348 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -645,6 +645,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getChatScheduledMessages &request); + void on_request(uint64 id, const td_api::getMessageAvailableReactions &request); + void on_request(uint64 id, td_api::setMessageReaction &request); void on_request(uint64 id, td_api::getMessageChosenReactions &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 12c49cf14..511cf551f 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2079,6 +2079,11 @@ class CliClient final : public Actor { ChatId chat_id; get_args(args, chat_id); send_request(td_api::make_object(chat_id)); + } else if (op == "gmar") { + ChatId chat_id; + MessageId message_id; + get_args(args, chat_id, message_id); + send_request(td_api::make_object(chat_id, message_id)); } else if (op == "react") { ChatId chat_id; MessageId message_id;