Add td_api::setMessageReaction.
This commit is contained in:
parent
ebb78d3c1b
commit
ce19ad822b
@ -4587,6 +4587,12 @@ editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup =
|
||||
editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok;
|
||||
|
||||
|
||||
//@description Changes chosen reaction for a message
|
||||
//@chat_id Identifier of the chat to which the message belongs
|
||||
//@message_id Identifier of the message
|
||||
//@reaction Text representation of the chosen reaction, or an empty string to remove reaction
|
||||
setMessageReaction chat_id:int53 message_id:int53 reaction:string = Ok;
|
||||
|
||||
//@description Returns reactions chosen for a message, along with their source
|
||||
//@chat_id Identifier of the chat to which the message belongs
|
||||
//@message_id Identifier of the message
|
||||
|
@ -5649,6 +5649,10 @@ bool is_unsent_animated_emoji_click(Td *td, DialogId dialog_id, const DialogActi
|
||||
return !td->stickers_manager_->is_sent_animated_emoji_click(dialog_id, remove_emoji_modifiers(emoji));
|
||||
}
|
||||
|
||||
bool is_active_reaction(Td *td, const string &reaction) {
|
||||
return td->stickers_manager_->is_active_reaction(reaction);
|
||||
}
|
||||
|
||||
void on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date) {
|
||||
send_closure(G()->top_dialog_manager(), &TopDialogManager::on_dialog_used, category, dialog_id, date);
|
||||
}
|
||||
|
@ -248,6 +248,8 @@ void on_sent_message_content(Td *td, const MessageContent *content);
|
||||
|
||||
bool is_unsent_animated_emoji_click(Td *td, DialogId dialog_id, const DialogAction &action);
|
||||
|
||||
bool is_active_reaction(Td *td, const string &reaction);
|
||||
|
||||
void on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date);
|
||||
|
||||
void update_used_hashtags(Td *td, const MessageContent *content);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/MessagesManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/UpdatesManager.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/buffer.h"
|
||||
@ -18,6 +19,50 @@
|
||||
|
||||
namespace td {
|
||||
|
||||
class SendReactionQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
DialogId dialog_id_;
|
||||
MessageId message_id_;
|
||||
|
||||
public:
|
||||
explicit SendReactionQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(FullMessageId full_message_id, string reaction) {
|
||||
dialog_id_ = full_message_id.get_dialog_id();
|
||||
message_id_ = full_message_id.get_message_id();
|
||||
|
||||
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read);
|
||||
if (input_peer == nullptr) {
|
||||
return on_error(Status::Error(400, "Can't access the chat"));
|
||||
}
|
||||
|
||||
int32 flags = 0;
|
||||
if (!reaction.empty()) {
|
||||
flags |= telegram_api::messages_sendReaction::REACTION_MASK;
|
||||
}
|
||||
|
||||
send_query(G()->net_query_creator().create(telegram_api::messages_sendReaction(
|
||||
flags, std::move(input_peer), message_id_.get_server_message_id().get(), reaction)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_sendReaction>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for SendReactionQuery: " << to_string(ptr);
|
||||
td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "SendReactionQuery");
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class GetMessageReactionsListQuery final : public Td::ResultHandler {
|
||||
Promise<td_api::object_ptr<td_api::chosenReactions>> promise_;
|
||||
DialogId dialog_id_;
|
||||
@ -95,6 +140,19 @@ class GetMessageReactionsListQuery final : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
void MessageReaction::set_is_chosen(bool is_chosen, DialogId chooser_dialog_id) {
|
||||
if (is_chosen_ == is_chosen) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_chosen_ = is_chosen;
|
||||
|
||||
if (chooser_dialog_id.is_valid()) {
|
||||
choose_count_ += is_chosen_ ? 1 : -1;
|
||||
// TODO update recent_chooser_dialog_ids_, but only if not broadcast
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::messageReaction> MessageReaction::get_message_reaction_object(Td *td) const {
|
||||
CHECK(!is_empty());
|
||||
|
||||
@ -250,13 +308,17 @@ bool MessageReactions::need_update_message_reactions(const MessageReactions *old
|
||||
return true;
|
||||
}
|
||||
|
||||
// has_pending_reaction_ and old_chosen_reaction_ don't affect visible state
|
||||
// has_pending_reaction_ doesn't affect visible state
|
||||
// compare all other fields
|
||||
return old_reactions->reactions_ != new_reactions->reactions_ || old_reactions->is_min_ != new_reactions->is_min_ ||
|
||||
old_reactions->can_see_all_choosers_ != new_reactions->can_see_all_choosers_ ||
|
||||
old_reactions->need_polling_ != new_reactions->need_polling_;
|
||||
}
|
||||
|
||||
void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, Promise<Unit> &&promise) {
|
||||
td->create_handler<SendReactionQuery>(std::move(promise))->send(full_message_id, std::move(reaction));
|
||||
}
|
||||
|
||||
void get_message_chosen_reactions(Td *td, FullMessageId full_message_id, string reaction, string offset, int32 limit,
|
||||
Promise<td_api::object_ptr<td_api::chosenReactions>> &&promise) {
|
||||
if (!td->messages_manager_->have_message_force(full_message_id, "get_message_chosen_reactions")) {
|
||||
@ -264,7 +326,8 @@ void get_message_chosen_reactions(Td *td, FullMessageId full_message_id, string
|
||||
}
|
||||
|
||||
auto message_id = full_message_id.get_message_id();
|
||||
if (!message_id.is_valid() || !message_id.is_server()) {
|
||||
if (full_message_id.get_dialog_id().get_type() == DialogType::SecretChat || !message_id.is_valid() ||
|
||||
!message_id.is_server()) {
|
||||
return promise.set_value(td_api::make_object<td_api::chosenReactions>(0, Auto(), string()));
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ class MessageReaction {
|
||||
|
||||
MessageReaction() = default;
|
||||
|
||||
MessageReaction(string &&reaction, int32 choose_count, bool is_chosen, vector<DialogId> &&recent_chooser_dialog_ids,
|
||||
MessageReaction(string reaction, int32 choose_count, bool is_chosen, vector<DialogId> &&recent_chooser_dialog_ids,
|
||||
vector<std::pair<ChannelId, MinChannel>> &&recent_chooser_min_channels)
|
||||
: reaction_(std::move(reaction))
|
||||
, choose_count_(choose_count)
|
||||
@ -62,9 +62,7 @@ class MessageReaction {
|
||||
return is_chosen_;
|
||||
}
|
||||
|
||||
void set_is_chosen(bool is_chosen) {
|
||||
is_chosen_ = is_chosen;
|
||||
}
|
||||
void set_is_chosen(bool is_chosen, DialogId chooser_dialog_id = DialogId());
|
||||
|
||||
const vector<DialogId> &get_recent_chooser_dialog_ids() const {
|
||||
return recent_chooser_dialog_ids_;
|
||||
@ -97,7 +95,6 @@ struct MessageReactions {
|
||||
bool need_polling_ = true;
|
||||
bool can_see_all_choosers_ = false;
|
||||
bool has_pending_reaction_ = false;
|
||||
string old_chosen_reaction_;
|
||||
|
||||
MessageReactions() = default;
|
||||
|
||||
@ -117,6 +114,8 @@ struct MessageReactions {
|
||||
void parse(ParserT &parser);
|
||||
};
|
||||
|
||||
void set_message_reaction(Td *td, FullMessageId full_message_id, string reaction, Promise<Unit> &&promise);
|
||||
|
||||
void get_message_chosen_reactions(Td *td, FullMessageId full_message_id, string reaction, string offset, int32 limit,
|
||||
Promise<td_api::object_ptr<td_api::chosenReactions>> &&promise);
|
||||
|
||||
|
@ -56,41 +56,31 @@ void MessageReaction::parse(ParserT &parser) {
|
||||
template <class StorerT>
|
||||
void MessageReactions::store(StorerT &storer) const {
|
||||
bool has_reactions = !reactions_.empty();
|
||||
bool has_old_chosen_reaction = !old_chosen_reaction_.empty();
|
||||
BEGIN_STORE_FLAGS();
|
||||
STORE_FLAG(is_min_);
|
||||
STORE_FLAG(need_polling_);
|
||||
STORE_FLAG(can_see_all_choosers_);
|
||||
STORE_FLAG(has_pending_reaction_);
|
||||
STORE_FLAG(has_reactions);
|
||||
STORE_FLAG(has_old_chosen_reaction);
|
||||
END_STORE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::store(reactions_, storer);
|
||||
}
|
||||
if (has_old_chosen_reaction) {
|
||||
td::store(old_chosen_reaction_, storer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void MessageReactions::parse(ParserT &parser) {
|
||||
bool has_reactions;
|
||||
bool has_old_chosen_reaction;
|
||||
BEGIN_PARSE_FLAGS();
|
||||
PARSE_FLAG(is_min_);
|
||||
PARSE_FLAG(need_polling_);
|
||||
PARSE_FLAG(can_see_all_choosers_);
|
||||
PARSE_FLAG(has_pending_reaction_);
|
||||
PARSE_FLAG(has_reactions);
|
||||
PARSE_FLAG(has_old_chosen_reaction);
|
||||
END_PARSE_FLAGS();
|
||||
if (has_reactions) {
|
||||
td::parse(reactions_, parser);
|
||||
}
|
||||
if (has_old_chosen_reaction) {
|
||||
td::parse(old_chosen_reaction_, parser);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -23720,6 +23720,72 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id
|
||||
}
|
||||
}
|
||||
|
||||
void MessagesManager::set_message_reaction(FullMessageId full_message_id, string reaction, Promise<Unit> &&promise) {
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
Dialog *d = get_dialog_force(dialog_id, "set_message_reaction");
|
||||
if (d == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||
}
|
||||
|
||||
Message *m = get_message_force(d, full_message_id.get_message_id(), "set_message_reaction");
|
||||
if (m == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Message not found"));
|
||||
}
|
||||
|
||||
if (full_message_id.get_dialog_id().get_type() == DialogType::SecretChat || !m->message_id.is_valid() ||
|
||||
!m->message_id.is_server()) {
|
||||
return promise.set_error(Status::Error(400, "Message can't have reactions"));
|
||||
}
|
||||
|
||||
if (!reaction.empty() && !is_active_reaction(td_, reaction)) {
|
||||
return promise.set_error(Status::Error(400, "Invalid reaction specified"));
|
||||
}
|
||||
|
||||
if (m->reactions == nullptr) {
|
||||
if (reaction.empty()) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
m->reactions = make_unique<MessageReactions>();
|
||||
}
|
||||
|
||||
bool is_found = false;
|
||||
for (auto it = m->reactions->reactions_.begin(); it != m->reactions->reactions_.end();) {
|
||||
auto &message_reaction = *it;
|
||||
if (message_reaction.is_chosen()) {
|
||||
if (message_reaction.get_reaction() == reaction) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
message_reaction.set_is_chosen(false);
|
||||
if (message_reaction.is_empty()) {
|
||||
it = m->reactions->reactions_.erase(it);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (message_reaction.get_reaction() == reaction) {
|
||||
message_reaction.set_is_chosen(true);
|
||||
is_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
// m->reactions->has_pending_reaction_ = true;
|
||||
if (!is_found && !reaction.empty()) {
|
||||
// TODO place to the correct position
|
||||
vector<DialogId> recent_chooser_dialog_ids;
|
||||
if (!is_broadcast_channel(dialog_id)) {
|
||||
recent_chooser_dialog_ids.push_back(get_my_dialog_id());
|
||||
}
|
||||
m->reactions->reactions_.emplace_back(reaction, 1, true, std::move(recent_chooser_dialog_ids), Auto());
|
||||
}
|
||||
|
||||
send_update_message_interaction_info(dialog_id, m);
|
||||
on_message_changed(d, m, true, "set_message_reaction");
|
||||
|
||||
::td::set_message_reaction(td_, full_message_id, std::move(reaction), std::move(promise));
|
||||
}
|
||||
|
||||
void MessagesManager::get_message_public_forwards(FullMessageId full_message_id, string offset, int32 limit,
|
||||
Promise<td_api::object_ptr<td_api::foundMessages>> &&promise) {
|
||||
auto dc_id_promise = PromiseCreator::lambda([actor_id = actor_id(this), full_message_id, offset = std::move(offset),
|
||||
|
@ -780,6 +780,8 @@ class MessagesManager final : public Actor {
|
||||
vector<MessageId> get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void set_message_reaction(FullMessageId full_message_id, string reaction, 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);
|
||||
|
||||
|
@ -5244,10 +5244,18 @@ void Td::on_request(uint64 id, const td_api::getChatScheduledMessages &request)
|
||||
CREATE_REQUEST(GetChatScheduledMessagesRequest, request.chat_id_);
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::setMessageReaction &request) {
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.reaction_);
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
messages_manager_->set_message_reaction({DialogId(request.chat_id_), MessageId(request.message_id_)},
|
||||
std::move(request.reaction_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getMessageChosenReactions &request) {
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.offset_);
|
||||
CLEAN_INPUT_STRING(request.reaction_);
|
||||
CLEAN_INPUT_STRING(request.offset_);
|
||||
CREATE_REQUEST_PROMISE();
|
||||
get_message_chosen_reactions(this, {DialogId(request.chat_id_), MessageId(request.message_id_)},
|
||||
std::move(request.reaction_), std::move(request.offset_), request.limit_,
|
||||
|
@ -645,6 +645,8 @@ class Td final : public Actor {
|
||||
|
||||
void on_request(uint64 id, const td_api::getChatScheduledMessages &request);
|
||||
|
||||
void on_request(uint64 id, td_api::setMessageReaction &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getMessageChosenReactions &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getMessagePublicForwards &request);
|
||||
|
@ -2058,6 +2058,12 @@ class CliClient final : public Actor {
|
||||
ChatId chat_id;
|
||||
get_args(args, chat_id);
|
||||
send_request(td_api::make_object<td_api::getChatScheduledMessages>(chat_id));
|
||||
} else if (op == "react") {
|
||||
ChatId chat_id;
|
||||
MessageId message_id;
|
||||
string reaction;
|
||||
get_args(args, chat_id, message_id, reaction);
|
||||
send_request(td_api::make_object<td_api::setMessageReaction>(chat_id, message_id, reaction));
|
||||
} else if (op == "gmcr") {
|
||||
ChatId chat_id;
|
||||
MessageId message_id;
|
||||
|
Loading…
Reference in New Issue
Block a user