From b0ad4e5e6268a927b5ef645ef60de90a1aaff197 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 5 Jan 2022 16:23:35 +0300 Subject: [PATCH] Add td_api::setChatAvailableReactions. --- td/generate/scheme/td_api.tl | 11 ++-- td/telegram/MessagesManager.cpp | 102 +++++++++++++++++++++++++++++--- td/telegram/MessagesManager.h | 2 + td/telegram/Td.cpp | 9 +++ td/telegram/Td.h | 2 + td/telegram/cli.cpp | 6 ++ 6 files changed, 120 insertions(+), 12 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index c807ce425..d77aa41a1 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -672,7 +672,7 @@ supergroup id:int53 username:string date:int32 status:ChatMemberStatus member_co //@is_all_history_available True, if new chat members will have access to old messages. In public or discussion groups and both public and private channels, old messages are always available, so this option affects only private supergroups without a linked chat. The value of this field is only available for chat administrators //@sticker_set_id Identifier of the supergroup sticker set; 0 if none //@location Location to which the supergroup is connected; may be null -//@invite_link Primary invite link for this chat; may be null. For chat administrators with can_invite_users right only +//@invite_link Primary invite link for the chat; may be null. For chat administrators with can_invite_users right only //@bot_commands List of commands of bots in the group //@upgraded_from_basic_group_id Identifier of the basic group from which supergroup was upgraded; 0 if none //@upgraded_from_max_message_id Identifier of the last message in the basic group from which supergroup was upgraded; 0 if none @@ -979,8 +979,8 @@ videoChat group_call_id:int32 has_participants:Bool default_participant_id:Messa //@last_read_inbox_message_id Identifier of the last read incoming message //@last_read_outbox_message_id Identifier of the last read outgoing message //@unread_mention_count Number of unread messages with a mention/reply in the chat -//@notification_settings Notification settings for this chat -//@available_reactions List of reactions available for this chat +//@notification_settings Notification settings for the chat +//@available_reactions List of reactions, 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 @@ -3740,7 +3740,7 @@ 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 +//@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 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 @@ -4802,6 +4802,9 @@ 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 +setChatAvailableReactions chat_id:int53 available_reactions:vector = 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/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 958bfda3a..f152e3303 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1360,6 +1360,48 @@ class EditDialogTitleQuery final : public Td::ResultHandler { } }; +class SetChatAvailableReactionsQuery final : public Td::ResultHandler { + Promise promise_; + DialogId dialog_id_; + + public: + explicit SetChatAvailableReactionsQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, vector 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), std::move(available_reactions)))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(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 SetChatAvailableReactionsQuery: " << to_string(ptr); + td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); + } + + void on_error(Status status) final { + if (status.message() == "CHAT_NOT_MODIFIED") { + if (!td_->auth_manager_->is_bot()) { + promise_.set_value(Unit()); + return; + } + } else { + td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "SetChatAvailableReactionsQuery"); + } + promise_.set_error(std::move(status)); + } +}; + class SetChatThemeQuery final : public Td::ResultHandler { Promise promise_; DialogId dialog_id_; @@ -32121,8 +32163,6 @@ void MessagesManager::on_updated_dialog_folder_id(DialogId dialog_id, uint64 gen void MessagesManager::set_dialog_photo(DialogId dialog_id, const tl_object_ptr &input_photo, Promise &&promise) { - LOG(INFO) << "Receive setChatPhoto request to change photo of " << dialog_id; - if (!have_dialog_force(dialog_id, "set_dialog_photo")) { return promise.set_error(Status::Error(400, "Chat not found")); } @@ -32236,8 +32276,6 @@ void MessagesManager::upload_dialog_photo(DialogId dialog_id, FileId file_id, bo } void MessagesManager::set_dialog_title(DialogId dialog_id, const string &title, Promise &&promise) { - LOG(INFO) << "Receive setChatTitle request to change title of " << dialog_id << " to \"" << title << '"'; - if (!have_dialog_force(dialog_id, "set_dialog_title")) { return promise.set_error(Status::Error(400, "Chat not found")); } @@ -32282,6 +32320,57 @@ 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) { + const Dialog *d = get_dialog_force(dialog_id, "set_dialog_available_reactions"); + if (d == nullptr) { + return promise.set_error(Status::Error(400, "Chat not found")); + } + + if (get_active_reactions(td_, available_reactions) != available_reactions) { + return promise.set_error(Status::Error(400, "Invalid reactions specified")); + } + std::unordered_set unique_reactions{available_reactions.begin(), available_reactions.end()}; + if (unique_reactions.size() != available_reactions.size()) { + return promise.set_error(Status::Error(400, "Duplicate reactions specified")); + } + + switch (dialog_id.get_type()) { + case DialogType::User: + return promise.set_error(Status::Error(400, "Can't change private chat available reactions")); + case DialogType::Chat: { + auto chat_id = dialog_id.get_chat_id(); + auto status = td_->contacts_manager_->get_chat_permissions(chat_id); + if (!status.can_change_info_and_settings() || + (td_->auth_manager_->is_bot() && !td_->contacts_manager_->is_appointed_chat_administrator(chat_id))) { + return promise.set_error(Status::Error(400, "Not enough rights to change chat available reactions")); + } + break; + } + case DialogType::Channel: { + auto status = td_->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id()); + if (!status.can_change_info_and_settings()) { + return promise.set_error(Status::Error(400, "Not enough rights to change chat available reactions")); + } + break; + } + case DialogType::SecretChat: + return promise.set_error(Status::Error(400, "Can't change secret chat available reactions")); + case DialogType::None: + default: + UNREACHABLE(); + } + + // TODO this can be wrong if there were previous requests to change available reactions + if (d->available_reactions == available_reactions) { + return promise.set_value(Unit()); + } + + // TODO invoke after + td_->create_handler(std::move(promise)) + ->send(dialog_id, std::move(available_reactions)); +} + void MessagesManager::set_dialog_message_ttl(DialogId dialog_id, int32 ttl, Promise &&promise) { if (ttl < 0) { return promise.set_error(Status::Error(400, "Message auto-delete time can't be negative")); @@ -32472,7 +32561,7 @@ void MessagesManager::set_dialog_theme(DialogId dialog_id, const string &theme_n } // TODO this can be wrong if there were previous change theme requests - if (d->theme_name == theme_name) { + if (get_dialog_theme_name(d) == theme_name) { return promise.set_value(Unit()); } @@ -32481,9 +32570,6 @@ void MessagesManager::set_dialog_theme(DialogId dialog_id, const string &theme_n } void MessagesManager::set_dialog_description(DialogId dialog_id, const string &description, Promise &&promise) { - LOG(INFO) << "Receive setChatDescription request to set description of " << dialog_id << " to \"" << description - << '"'; - if (!have_dialog_force(dialog_id, "set_dialog_description")) { return promise.set_error(Status::Error(400, "Chat not found")); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 10add23df..ddc11e06b 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -504,6 +504,8 @@ class MessagesManager final : public Actor { void set_dialog_description(DialogId dialog_id, const string &description, Promise &&promise); + void set_dialog_available_reactions(DialogId dialog_id, vector available_reactions, Promise &&promise); + void set_dialog_permissions(DialogId dialog_id, const td_api::object_ptr &permissions, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 8b98d49c1..ea581b055 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6011,6 +6011,15 @@ void Td::on_request(uint64 id, const td_api::setPinnedChats &request) { transform(request.chat_ids_, [](int64 chat_id) { return DialogId(chat_id); }))); } +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)); +} + void Td::on_request(uint64 id, td_api::setChatClientData &request) { answer_ok_query( id, messages_manager_->set_dialog_client_data(DialogId(request.chat_id_), std::move(request.client_data_))); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 73f3fa71e..ded7a025a 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -837,6 +837,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::setPinnedChats &request); + void on_request(uint64 id, td_api::setChatAvailableReactions &request); + void on_request(uint64 id, td_api::setChatClientData &request); void on_request(uint64 id, td_api::setChatDescription &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 5c7b2439e..9883e8d19 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4164,6 +4164,12 @@ class CliClient final : public Actor { get_args(args, supergroup_id, sign_messages); send_request( td_api::make_object(as_supergroup_id(supergroup_id), sign_messages)); + } else if (op == "scar") { + ChatId chat_id; + string available_reactions; + get_args(args, chat_id, available_reactions); + send_request( + td_api::make_object(chat_id, full_split(available_reactions, ' '))); } else if (op == "scd") { ChatId chat_id; string description;