diff --git a/CMakeLists.txt b/CMakeLists.txt index 24c365497..e266ca3c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,7 @@ set(TDLIB_SOURCE td/telegram/CallManager.cpp td/telegram/CallbackQueriesManager.cpp td/telegram/ChannelParticipantFilter.cpp + td/telegram/ChatReactions.cpp td/telegram/ClientActor.cpp td/telegram/ConfigManager.cpp td/telegram/ConnectionState.cpp @@ -505,6 +506,7 @@ set(TDLIB_SOURCE td/telegram/ChannelParticipantFilter.h td/telegram/ChannelType.h td/telegram/ChatId.h + td/telegram/ChatReactions.h td/telegram/ClientActor.h td/telegram/ConfigManager.h td/telegram/ConnectionState.h diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index dea413588..88c76f6b8 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1069,6 +1069,15 @@ chatSourcePublicServiceAnnouncement type:string text:string = ChatSource; chatPosition list:ChatList order:int64 is_pinned:Bool source:ChatSource = ChatPosition; +//@class ChatAvailableReactions @description Describes reactions available in the chat + +//@description All reactions are available in the chat +chatAvailableReactionsAll = ChatAvailableReactions; + +//@description Only specific reactions are available in the chat @reactions The list of reactions +chatAvailableReactionsSome reactions:vector = ChatAvailableReactions; + + //@description Describes a video chat //@group_call_id Group call identifier of an active video chat; 0 if none. Full information about the video chat can be received through the method getGroupCall //@has_participants True, if the video chat has participants @@ -1099,7 +1108,7 @@ videoChat group_call_id:int32 has_participants:Bool default_participant_id:Messa //@unread_mention_count Number of unread messages with a mention/reply in the chat //@unread_reaction_count Number of messages with unread reactions in the chat //@notification_settings Notification settings for the chat -//@available_reactions List of reactions, available in the chat +//@available_reactions Types of reaction, available in the chat //@message_ttl Current message Time To Live setting (self-destruct timer) for the chat; 0 if not defined. TTL is counted from the time message or its content is viewed in secret chats and from the send date in other chats //@theme_name If non-empty, name of a theme, set for the chat //@action_bar Information about actions which must be possible to do through the chat action bar; may be null @@ -1108,7 +1117,7 @@ videoChat group_call_id:int32 has_participants:Bool default_participant_id:Messa //@reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat //@draft_message A draft of a message in the chat; may be null //@client_data Application-specific data associated with the chat. (For example, the chat scroll position or local chat notification settings can be stored here.) Persistent if the message database is used -chat id:int53 type:ChatType title:string photo:chatPhotoInfo permissions:chatPermissions last_message:message positions:vector message_sender_id:MessageSender has_protected_content:Bool is_marked_as_unread:Bool is_blocked:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 unread_reaction_count:int32 notification_settings:chatNotificationSettings available_reactions:vector message_ttl:int32 theme_name:string action_bar:ChatActionBar video_chat:videoChat pending_join_requests:chatJoinRequestsInfo reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat; +chat id:int53 type:ChatType title:string photo:chatPhotoInfo permissions:chatPermissions last_message:message positions:vector message_sender_id:MessageSender has_protected_content:Bool is_marked_as_unread:Bool is_blocked:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 unread_reaction_count:int32 notification_settings:chatNotificationSettings available_reactions:ChatAvailableReactions message_ttl:int32 theme_name:string action_bar:ChatActionBar video_chat:videoChat pending_join_requests:chatJoinRequestsInfo reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat; //@description Represents a list of chats @total_count Approximate total number of chats found @chat_ids List of chat identifiers chats total_count:int32 chat_ids:vector = Chats; @@ -2832,7 +2841,7 @@ chatEventMemberPromoted user_id:int53 old_status:ChatMemberStatus new_status:Cha chatEventMemberRestricted member_id:MessageSender old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction; //@description The chat available reactions were changed @old_available_reactions Previous chat available reactions @new_available_reactions New chat available reactions -chatEventAvailableReactionsChanged old_available_reactions:vector new_available_reactions:vector = ChatEventAction; +chatEventAvailableReactionsChanged old_available_reactions:ChatAvailableReactions new_available_reactions:ChatAvailableReactions = ChatEventAction; //@description The chat description was changed @old_description Previous chat description @new_description New chat description chatEventDescriptionChanged old_description:string new_description:string = ChatEventAction; @@ -4247,8 +4256,8 @@ updateChatReadOutbox chat_id:int53 last_read_outbox_message_id:int53 = Update; //@description The chat action bar was changed @chat_id Chat identifier @action_bar The new value of the action bar; may be null updateChatActionBar chat_id:int53 action_bar:ChatActionBar = Update; -//@description The chat available reactions were changed @chat_id Chat identifier @available_reactions The new list of reactions, available in the chat -updateChatAvailableReactions chat_id:int53 available_reactions:vector = Update; +//@description The chat available reactions were changed @chat_id Chat identifier @available_reactions The new reactions, available in the chat +updateChatAvailableReactions chat_id:int53 available_reactions:ChatAvailableReactions = Update; //@description A chat draft has changed. Be aware that the update may come in the currently opened chat but with old content of the draft. If the user has changed the content of the draft, this update mustn't be applied @chat_id Chat identifier @draft_message The new draft message; may be null @positions The new chat positions in the chat lists updateChatDraftMessage chat_id:int53 draft_message:draftMessage positions:vector = Update; @@ -5434,8 +5443,8 @@ toggleChatIsMarkedAsUnread chat_id:int53 is_marked_as_unread:Bool = Ok; //@description Changes the value of the default disable_notification parameter, used when a message is sent to a chat @chat_id Chat identifier @default_disable_notification New value of default_disable_notification toggleChatDefaultDisableNotification chat_id:int53 default_disable_notification:Bool = Ok; -//@description Changes reactions, available in a chat. Available for basic groups, supergroups, and channels. Requires can_change_info administrator right @chat_id Identifier of the chat @available_reactions New list of reactions, available in the chat. All reactions must be active -setChatAvailableReactions chat_id:int53 available_reactions:vector = Ok; +//@description Changes reactions, available in a chat. Available for basic groups, supergroups, and channels. Requires can_change_info administrator right @chat_id Identifier of the chat @available_reactions Reactions available in the chat. All emoji reactions must be active +setChatAvailableReactions chat_id:int53 available_reactions:ChatAvailableReactions = Ok; //@description Changes application-specific data associated with a chat @chat_id Chat identifier @client_data New value of client_data setChatClientData chat_id:int53 client_data:string = Ok; diff --git a/td/telegram/AvailableReaction.cpp b/td/telegram/AvailableReaction.cpp index 045a15903..1b0304dae 100644 --- a/td/telegram/AvailableReaction.cpp +++ b/td/telegram/AvailableReaction.cpp @@ -22,32 +22,22 @@ AvailableReactionType get_reaction_type(const vector &availab return AvailableReactionType::Unavailable; } -vector get_active_reactions(const vector &available_reactions, - const vector &active_reactions) { +ChatReactions get_active_reactions(const ChatReactions &available_reactions, + const vector &active_reactions) { if (available_reactions.empty()) { // fast path return available_reactions; } - if (available_reactions.size() == active_reactions.size()) { - size_t i; - for (i = 0; i < available_reactions.size(); i++) { - if (available_reactions[i] != active_reactions[i].reaction_) { - break; - } - } - if (i == available_reactions.size()) { - // fast path - return available_reactions; - } - } + CHECK(!available_reactions.allow_all_); + CHECK(!available_reactions.allow_custom_); vector result; for (const auto &active_reaction : active_reactions) { - if (td::contains(available_reactions, active_reaction.reaction_)) { + if (td::contains(available_reactions.reactions_, active_reaction.reaction_)) { result.push_back(active_reaction.reaction_); } } - return result; + return ChatReactions(std::move(result)); } bool operator==(const AvailableReaction &lhs, const AvailableReaction &rhs) { diff --git a/td/telegram/AvailableReaction.h b/td/telegram/AvailableReaction.h index a5a56e3b7..becd0c782 100644 --- a/td/telegram/AvailableReaction.h +++ b/td/telegram/AvailableReaction.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/ChatReactions.h" #include "td/telegram/td_api.h" #include "td/utils/common.h" @@ -29,7 +30,7 @@ enum class AvailableReactionType : int32 { Unavailable, Available, NeedsPremium AvailableReactionType get_reaction_type(const vector &reactions, const string &reaction); -vector get_active_reactions(const vector &available_reactions, - const vector &active_reactions); +ChatReactions get_active_reactions(const ChatReactions &available_reactions, + const vector &active_reactions); } // namespace td diff --git a/td/telegram/ChatReactions.cpp b/td/telegram/ChatReactions.cpp new file mode 100644 index 000000000..8e9e4d87d --- /dev/null +++ b/td/telegram/ChatReactions.cpp @@ -0,0 +1,99 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/ChatReactions.h" + +#include "td/telegram/MessageReaction.h" + +#include "td/utils/algorithm.h" + +namespace td { + +ChatReactions::ChatReactions(telegram_api::object_ptr &&chat_reactions_ptr) { + if (chat_reactions_ptr == nullptr) { + return; + } + switch (chat_reactions_ptr->get_id()) { + case telegram_api::chatReactionsNone::ID: + break; + case telegram_api::chatReactionsAll::ID: { + auto chat_reactions = move_tl_object_as(chat_reactions_ptr); + allow_all_ = true; + allow_custom_ = chat_reactions->allow_custom_; + break; + } + case telegram_api::chatReactionsSome::ID: { + auto chat_reactions = move_tl_object_as(chat_reactions_ptr); + reactions_ = + transform(chat_reactions->reactions_, [](const telegram_api::object_ptr &reaction) { + return get_message_reaction_string(reaction); + }); + break; + } + default: + UNREACHABLE(); + } +} + +ChatReactions::ChatReactions(td_api::object_ptr &&chat_reactions_ptr, + bool allow_custom) { + if (chat_reactions_ptr == nullptr) { + return; + } + switch (chat_reactions_ptr->get_id()) { + case td_api::chatAvailableReactionsAll::ID: + allow_all_ = true; + allow_custom_ = allow_custom; + break; + case td_api::chatAvailableReactionsSome::ID: { + auto chat_reactions = move_tl_object_as(chat_reactions_ptr); + reactions_ = transform(chat_reactions->reactions_, [](const td_api::object_ptr &reaction) { + return get_message_reaction_string(reaction); + }); + break; + } + default: + UNREACHABLE(); + } +} + +td_api::object_ptr ChatReactions::get_chat_available_reactions_object() const { + if (allow_all_) { + return td_api::make_object(); + } + return td_api::make_object(transform(reactions_, get_reaction_type_object)); +} + +telegram_api::object_ptr ChatReactions::get_input_chat_reactions() const { + if (allow_all_) { + int32 flags = 0; + if (allow_custom_) { + flags |= telegram_api::chatReactionsAll::ALLOW_CUSTOM_MASK; + } + return telegram_api::make_object(flags, false /*ignored*/); + } + if (!reactions_.empty()) { + return telegram_api::make_object(transform(reactions_, get_input_reaction)); + } + return telegram_api::make_object(); +} + +bool operator==(const ChatReactions &lhs, const ChatReactions &rhs) { + // don't compare allow_custom_ + return lhs.reactions_ == rhs.reactions_ && lhs.allow_all_ == rhs.allow_all_; +} + +StringBuilder &operator<<(StringBuilder &string_builder, const ChatReactions &reactions) { + if (reactions.allow_all_) { + if (reactions.allow_custom_) { + return string_builder << "AllReactions"; + } + return string_builder << "AllRegularReactions"; + } + return string_builder << '[' << reactions.reactions_ << ']'; +} + +} // namespace td diff --git a/td/telegram/ChatReactions.h b/td/telegram/ChatReactions.h new file mode 100644 index 000000000..5a52c22b5 --- /dev/null +++ b/td/telegram/ChatReactions.h @@ -0,0 +1,78 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +#include "td/utils/common.h" +#include "td/utils/StringBuilder.h" +#include "td/utils/tl_helpers.h" + +namespace td { + +struct ChatReactions { + vector reactions_; + bool allow_all_ = false; // implies empty reactions + bool allow_custom_ = false; // implies allow_all + + ChatReactions() = default; + + explicit ChatReactions(vector &&reactions) : reactions_(std::move(reactions)) { + } + + explicit ChatReactions(telegram_api::object_ptr &&chat_reactions_ptr); + + ChatReactions(td_api::object_ptr &&chat_reactions_ptr, bool allow_custom); + + ChatReactions(bool allow_all, bool allow_custom) : allow_all_(allow_all), allow_custom_(allow_custom) { + } + + telegram_api::object_ptr get_input_chat_reactions() const; + + td_api::object_ptr get_chat_available_reactions_object() const; + + bool empty() const { + return reactions_.empty() && !allow_all_; + } + + template + void store(StorerT &storer) const { + bool has_reactions = !reactions_.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); + } + } + + template + void parse(ParserT &parser) { + bool has_reactions; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(allow_all_); + PARSE_FLAG(allow_custom_); + PARSE_FLAG(has_reactions); + END_PARSE_FLAGS(); + if (has_reactions) { + td::parse(reactions_, parser); + } + } +}; + +bool operator==(const ChatReactions &lhs, const ChatReactions &rhs); + +inline bool operator!=(const ChatReactions &lhs, const ChatReactions &rhs) { + return !(lhs == rhs); +} + +StringBuilder &operator<<(StringBuilder &string_builder, const ChatReactions &reactions); + +} // namespace td diff --git a/td/telegram/DialogEventLog.cpp b/td/telegram/DialogEventLog.cpp index 76763f1f4..ff7c8928f 100644 --- a/td/telegram/DialogEventLog.cpp +++ b/td/telegram/DialogEventLog.cpp @@ -7,6 +7,7 @@ #include "td/telegram/DialogEventLog.h" #include "td/telegram/ChannelId.h" +#include "td/telegram/ChatReactions.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/DialogInviteLink.h" #include "td/telegram/DialogLocation.h" @@ -346,7 +347,11 @@ static td_api::object_ptr get_chat_event_action_object( } case telegram_api::channelAdminLogEventActionChangeAvailableReactions::ID: { auto action = move_tl_object_as(action_ptr); - return nullptr; + ChatReactions old_available_reactions(std::move(action->prev_value_)); + ChatReactions new_available_reactions(std::move(action->new_value_)); + return td_api::make_object( + old_available_reactions.get_chat_available_reactions_object(), + new_available_reactions.get_chat_available_reactions_object()); } default: UNREACHABLE(); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index d06d945ce..7966a0850 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1427,14 +1427,14 @@ class SetChatAvailableReactionsQuery final : public Td::ResultHandler { explicit SetChatAvailableReactionsQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(DialogId dialog_id, vector available_reactions) { + void send(DialogId dialog_id, const ChatReactions &available_reactions) { dialog_id_ = dialog_id; auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write); if (input_peer == nullptr) { return on_error(Status::Error(400, "Can't access the chat")); } send_query(G()->net_query_creator().create(telegram_api::messages_setChatAvailableReactions( - std::move(input_peer), make_tl_object()))); + std::move(input_peer), available_reactions.get_input_chat_reactions()))); } void on_result(BufferSlice packet) final { @@ -5208,9 +5208,10 @@ void MessagesManager::Dialog::store(StorerT &storer) const { bool has_pending_join_requests = pending_join_request_count != 0; bool has_action_bar = action_bar != nullptr; bool has_default_send_message_as_dialog_id = default_send_message_as_dialog_id.is_valid(); - bool has_available_reactions = !available_reactions.empty(); + bool has_legacy_available_reactions = false; bool has_available_reactions_generation = available_reactions_generation != 0; bool has_have_full_history_source = have_full_history && have_full_history_source != 0; + bool has_available_reactions = !available_reactions.empty(); BEGIN_STORE_FLAGS(); STORE_FLAG(has_draft_message); STORE_FLAG(has_last_database_message); @@ -5287,10 +5288,11 @@ void MessagesManager::Dialog::store(StorerT &storer) const { STORE_FLAG(has_action_bar); STORE_FLAG(has_default_send_message_as_dialog_id); STORE_FLAG(need_drop_default_send_message_as_dialog_id); - STORE_FLAG(has_available_reactions); + STORE_FLAG(has_legacy_available_reactions); STORE_FLAG(is_available_reactions_inited); STORE_FLAG(has_available_reactions_generation); STORE_FLAG(has_have_full_history_source); + STORE_FLAG(has_available_reactions); END_STORE_FLAGS(); } @@ -5448,9 +5450,10 @@ void MessagesManager::Dialog::parse(ParserT &parser) { bool action_bar_can_invite_members = false; bool has_action_bar = false; bool has_default_send_message_as_dialog_id = false; - bool has_available_reactions = false; + bool has_legacy_available_reactions = false; bool has_available_reactions_generation = false; bool has_have_full_history_source = false; + bool has_available_reactions = false; BEGIN_PARSE_FLAGS(); PARSE_FLAG(has_draft_message); PARSE_FLAG(has_last_database_message); @@ -5542,10 +5545,11 @@ void MessagesManager::Dialog::parse(ParserT &parser) { PARSE_FLAG(has_action_bar); PARSE_FLAG(has_default_send_message_as_dialog_id); PARSE_FLAG(need_drop_default_send_message_as_dialog_id); - PARSE_FLAG(has_available_reactions); + PARSE_FLAG(has_legacy_available_reactions); PARSE_FLAG(is_available_reactions_inited); PARSE_FLAG(has_available_reactions_generation); PARSE_FLAG(has_have_full_history_source); + PARSE_FLAG(has_available_reactions); END_PARSE_FLAGS(); } else { need_repair_action_bar = false; @@ -5696,6 +5700,10 @@ void MessagesManager::Dialog::parse(ParserT &parser) { } if (has_available_reactions) { parse(available_reactions, parser); + } else if (has_legacy_available_reactions) { + vector legacy_available_reactions; + parse(legacy_available_reactions, parser); + available_reactions = ChatReactions(std::move(legacy_available_reactions)); } if (has_available_reactions_generation) { parse(available_reactions_generation, parser); @@ -8130,11 +8138,10 @@ void MessagesManager::on_update_dialog_available_reactions( return; } - vector legacy_available_reactions; - set_dialog_available_reactions(d, std::move(legacy_available_reactions)); + set_dialog_available_reactions(d, ChatReactions(std::move(available_reactions))); } -void MessagesManager::set_dialog_available_reactions(Dialog *d, vector &&available_reactions) { +void MessagesManager::set_dialog_available_reactions(Dialog *d, ChatReactions &&available_reactions) { CHECK(!td_->auth_manager_->is_bot()); CHECK(d != nullptr); switch (d->dialog_id.get_type()) { @@ -8276,15 +8283,15 @@ void MessagesManager::set_active_reactions(vector active_reac }); } -vector MessagesManager::get_active_reactions(const vector &available_reactions) const { +ChatReactions MessagesManager::get_active_reactions(const ChatReactions &available_reactions) const { return ::td::get_active_reactions(available_reactions, active_reactions_); } -vector MessagesManager::get_dialog_active_reactions(const Dialog *d) const { +ChatReactions MessagesManager::get_dialog_active_reactions(const Dialog *d) const { CHECK(d != nullptr); switch (d->dialog_id.get_type()) { case DialogType::User: - return transform(active_reactions_, [](auto &reaction) { return reaction.reaction_; }); + return ChatReactions(true, true); case DialogType::Chat: case DialogType::Channel: return get_active_reactions(d->available_reactions); @@ -8310,7 +8317,7 @@ vector MessagesManager::get_message_active_reactions(const Dialog *d, co return vector(); } } - return get_dialog_active_reactions(d); + return get_dialog_active_reactions(d).reactions_; } bool MessagesManager::need_poll_dialog_message_reactions(const Dialog *d) { @@ -21432,6 +21439,7 @@ td_api::object_ptr MessagesManager::get_chat_object(const Dialog * auto can_delete = can_delete_dialog(d); // TODO hide/show draft message when can_send_message(dialog_id) changes auto draft_message = can_send_message(d->dialog_id).is_ok() ? get_draft_message_object(d->draft_message) : nullptr; + auto available_reactions = get_dialog_active_reactions(d).get_chat_available_reactions_object(); return make_tl_object( d->dialog_id.get(), get_chat_type_object(d->dialog_id), get_dialog_title(d->dialog_id), get_chat_photo_info_object(td_->file_manager_.get(), get_dialog_photo(d->dialog_id)), @@ -21443,7 +21451,7 @@ td_api::object_ptr MessagesManager::get_chat_object(const Dialog * can_report_dialog(d->dialog_id), d->notification_settings.silent_send_message, d->server_unread_count + d->local_unread_count, d->last_read_inbox_message_id.get(), d->last_read_outbox_message_id.get(), d->unread_mention_count, d->unread_reaction_count, - get_chat_notification_settings_object(&d->notification_settings), get_dialog_active_reactions(d), + get_chat_notification_settings_object(&d->notification_settings), std::move(available_reactions), d->message_ttl.get_message_ttl_object(), get_dialog_theme_name(d), get_chat_action_bar_object(d), get_video_chat_object(d), get_chat_join_requests_info_object(d), d->reply_markup_message_id.get(), std::move(draft_message), d->client_data); @@ -31047,9 +31055,10 @@ void MessagesManager::send_update_chat_available_reactions(const Dialog *d) { CHECK(d != nullptr); LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in send_update_chat_available_reactions"; + auto available_reactions = get_dialog_active_reactions(d).get_chat_available_reactions_object(); send_closure( G()->td(), &Td::send_update, - td_api::make_object(d->dialog_id.get(), get_dialog_active_reactions(d))); + td_api::make_object(d->dialog_id.get(), std::move(available_reactions))); } void MessagesManager::send_update_secret_chats_with_user_theme(const Dialog *d) const { @@ -33735,15 +33744,17 @@ void MessagesManager::set_dialog_title(DialogId dialog_id, const string &title, td_->create_handler(std::move(promise))->send(dialog_id, new_title); } -void MessagesManager::set_dialog_available_reactions(DialogId dialog_id, vector available_reactions, - Promise &&promise) { +void MessagesManager::set_dialog_available_reactions( + DialogId dialog_id, td_api::object_ptr &&available_reactions_ptr, + Promise &&promise) { Dialog *d = get_dialog_force(dialog_id, "set_dialog_available_reactions"); if (d == nullptr) { return promise.set_error(Status::Error(400, "Chat not found")); } + ChatReactions available_reactions(std::move(available_reactions_ptr), !is_broadcast_channel(dialog_id)); auto active_reactions = get_active_reactions(available_reactions); - if (active_reactions.size() != available_reactions.size()) { + if (active_reactions.reactions_.size() != available_reactions.reactions_.size()) { return promise.set_error(Status::Error(400, "Invalid reactions specified")); } available_reactions = std::move(active_reactions); @@ -33776,7 +33787,7 @@ void MessagesManager::set_dialog_available_reactions(DialogId dialog_id, vector< bool is_changed = d->available_reactions != available_reactions; - set_dialog_available_reactions(d, vector(available_reactions)); + set_dialog_available_reactions(d, ChatReactions(available_reactions)); if (!is_changed) { return promise.set_value(Unit()); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index cf4ed9c35..92a04675c 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -10,6 +10,7 @@ #include "td/telegram/AffectedHistory.h" #include "td/telegram/AvailableReaction.h" #include "td/telegram/ChannelId.h" +#include "td/telegram/ChatReactions.h" #include "td/telegram/DialogAction.h" #include "td/telegram/DialogDate.h" #include "td/telegram/DialogDb.h" @@ -539,7 +540,9 @@ class MessagesManager final : public Actor { void set_active_reactions(vector active_reactions); - void set_dialog_available_reactions(DialogId dialog_id, vector available_reactions, Promise &&promise); + void set_dialog_available_reactions(DialogId dialog_id, + td_api::object_ptr &&available_reactions_ptr, + Promise &&promise); void set_dialog_permissions(DialogId dialog_id, const td_api::object_ptr &permissions, Promise &&promise); @@ -1265,7 +1268,7 @@ class MessagesManager final : public Actor { MessageId last_pinned_message_id; MessageId reply_markup_message_id; DialogNotificationSettings notification_settings; - vector available_reactions; + ChatReactions available_reactions; uint32 available_reactions_generation = 0; MessageTtl message_ttl; unique_ptr draft_message; @@ -2683,15 +2686,15 @@ class MessagesManager final : public Actor { void on_set_message_reaction(FullMessageId full_message_id, Result result, Promise promise); - void set_dialog_available_reactions(Dialog *d, vector &&available_reactions); + void set_dialog_available_reactions(Dialog *d, ChatReactions &&available_reactions); void set_dialog_next_available_reactions_generation(Dialog *d, uint32 generation); void hide_dialog_message_reactions(Dialog *d); - vector get_active_reactions(const vector &available_reactions) const; + ChatReactions get_active_reactions(const ChatReactions &available_reactions) const; - vector get_dialog_active_reactions(const Dialog *d) const; + ChatReactions get_dialog_active_reactions(const Dialog *d) const; vector get_message_active_reactions(const Dialog *d, const Message *m) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 842601ae1..04fe52167 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6092,9 +6092,6 @@ void Td::on_request(uint64 id, const td_api::toggleBotIsAddedToAttachmentMenu &r } void Td::on_request(uint64 id, td_api::setChatAvailableReactions &request) { - for (auto &reaction : request.available_reactions_) { - CLEAN_INPUT_STRING(reaction); - } CREATE_OK_REQUEST_PROMISE(); messages_manager_->set_dialog_available_reactions(DialogId(request.chat_id_), std::move(request.available_reactions_), std::move(promise)); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 5251f1d51..ca4790c73 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -724,7 +724,7 @@ class CliClient final : public Actor { return td_api::make_object(to_double(latitude), to_double(longitude), to_double(accuracy)); } - td_api::object_ptr as_reaction_type(Slice type) const { + static td_api::object_ptr as_reaction_type(Slice type) { type = trim(type); if (type.empty()) { return nullptr; @@ -4523,7 +4523,15 @@ class CliClient final : public Actor { ChatId chat_id; string available_reactions; get_args(args, chat_id, available_reactions); - send_request(td_api::make_object(chat_id, autosplit_str(available_reactions))); + td_api::object_ptr chat_available_reactions; + if (available_reactions == "all") { + chat_available_reactions = td_api::make_object(); + } else if (!available_reactions.empty()) { + auto reactions = transform(autosplit_str(available_reactions), as_reaction_type); + chat_available_reactions = td_api::make_object(std::move(reactions)); + } + send_request( + td_api::make_object(chat_id, std::move(chat_available_reactions))); } else if (op == "scd") { ChatId chat_id; string description;