From 342f446631b4c603edd33a470dceacbca47e5caa Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 31 Oct 2022 19:44:01 +0300 Subject: [PATCH] Support unpinning of all messages in a message thread. --- td/generate/scheme/td_api.tl | 9 +++--- td/telegram/MessagesManager.cpp | 51 ++++++++++++++++++++++----------- td/telegram/MessagesManager.h | 2 +- td/telegram/Td.cpp | 3 +- td/telegram/cli.cpp | 5 ++-- 5 files changed, 46 insertions(+), 24 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 74efab177..bbf2cca92 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5554,10 +5554,10 @@ getExternalLinkInfo link:string = LoginUrlInfo; getExternalLink link:string allow_write_access:Bool = HttpUrl; -//@description Marks all mentions in a chat as read @chat_id Chat identifier @message_thread_id If not 0, a message thread identifier in which mentions are marked as read; for forum supergroups only +//@description Marks all mentions in a chat or a forum topic as read @chat_id Chat identifier @message_thread_id If not 0, a message thread identifier in which mentions are marked as read; for forum supergroups only readAllChatMentions chat_id:int53 message_thread_id:int53 = Ok; -//@description Marks all reactions in a chat as read @chat_id Chat identifier @message_thread_id If not 0, a message thread identifier in which reactions are marked as read; for forum supergroups only +//@description Marks all reactions in a chat or a forum topic as read @chat_id Chat identifier @message_thread_id If not 0, a message thread identifier in which reactions are marked as read; for forum supergroups only readAllChatReactions chat_id:int53 message_thread_id:int53 = Ok; @@ -5686,8 +5686,9 @@ pinChatMessage chat_id:int53 message_id:int53 disable_notification:Bool only_for //@description Removes a pinned message from a chat; requires can_pin_messages rights in the group or can_edit_messages rights in the channel @chat_id Identifier of the chat @message_id Identifier of the removed pinned message unpinChatMessage chat_id:int53 message_id:int53 = Ok; -//@description Removes all pinned messages from a chat; requires can_pin_messages rights in the group or can_edit_messages rights in the channel @chat_id Identifier of the chat -unpinAllChatMessages chat_id:int53 = Ok; +//@description Removes all pinned messages from a chat or a forum topic; requires can_pin_messages rights in the group or can_edit_messages rights in the channel @chat_id Identifier of the chat +//@message_thread_id If not 0, a message thread identifier in which messages will be unpinned; for forum supergroups only +unpinAllChatMessages chat_id:int53 message_thread_id:int53 = Ok; //@description Adds the current user as a new member to a chat. Private and secret chats can't be joined using this method. May return an error with a message "INVITE_REQUEST_SENT" if only a join request was created @chat_id Chat identifier diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 362256d21..d11b2289b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -641,7 +641,7 @@ class UnpinAllMessagesQuery final : public Td::ResultHandler { explicit UnpinAllMessagesQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(DialogId dialog_id) { + void send(DialogId dialog_id, MessageId top_thread_message_id) { dialog_id_ = dialog_id; auto input_peer = td_->messages_manager_->get_input_peer(dialog_id_, AccessRights::Write); @@ -651,8 +651,11 @@ class UnpinAllMessagesQuery final : public Td::ResultHandler { } int32 flags = 0; - send_query( - G()->net_query_creator().create(telegram_api::messages_unpinAllMessages(flags, std::move(input_peer), 0))); + if (top_thread_message_id.is_valid()) { + flags |= telegram_api::messages_unpinAllMessages::TOP_MSG_ID_MASK; + } + send_query(G()->net_query_creator().create(telegram_api::messages_unpinAllMessages( + flags, std::move(input_peer), top_thread_message_id.get_server_message_id().get()))); } void on_result(BufferSlice packet) final { @@ -26400,7 +26403,7 @@ Status MessagesManager::can_use_top_thread_message_id(Dialog *d, MessageId top_t } if (!top_thread_message_id.is_valid() || !top_thread_message_id.is_server()) { - return Status::Error(400, "Invalid message thread ID specified"); + return Status::Error(400, "Invalid message thread identifier specified"); } if (d->dialog_id.get_type() != DialogType::Channel || is_broadcast_channel(d->dialog_id)) { return Status::Error(400, "Chat doesn't have threads"); @@ -34752,25 +34755,41 @@ void MessagesManager::pin_dialog_message(DialogId dialog_id, MessageId message_i ->send(dialog_id, message_id, is_unpin, disable_notification, only_for_self); } -void MessagesManager::unpin_all_dialog_messages(DialogId dialog_id, Promise &&promise) { +void MessagesManager::unpin_all_dialog_messages(DialogId dialog_id, MessageId top_thread_message_id, + Promise &&promise) { auto d = get_dialog_force(dialog_id, "unpin_all_dialog_messages"); if (d == nullptr) { return promise.set_error(Status::Error(400, "Chat not found")); } TRY_STATUS_PROMISE(promise, can_pin_messages(dialog_id)); + TRY_STATUS_PROMISE(promise, can_use_top_thread_message_id(d, top_thread_message_id, MessageId())); - vector message_ids; - find_messages(d->messages.get(), message_ids, [](const Message *m) { return m->is_pinned; }); + if (!td_->auth_manager_->is_bot()) { + vector message_ids; + find_messages(d->messages.get(), message_ids, [top_thread_message_id](const Message *m) { + return m->is_pinned && (!top_thread_message_id.is_valid() || m->top_thread_message_id == top_thread_message_id); + }); - vector deleted_message_ids; - for (auto message_id : message_ids) { - auto m = get_message(d, message_id); - CHECK(m != nullptr); + vector deleted_message_ids; + for (auto message_id : message_ids) { + auto m = get_message(d, message_id); + CHECK(m != nullptr); - m->is_pinned = false; - send_closure(G()->td(), &Td::send_update, - make_tl_object(d->dialog_id.get(), m->message_id.get(), m->is_pinned)); - on_message_changed(d, m, true, "unpin_all_dialog_messages"); + m->is_pinned = false; + send_closure( + G()->td(), &Td::send_update, + make_tl_object(d->dialog_id.get(), m->message_id.get(), m->is_pinned)); + on_message_changed(d, m, true, "unpin_all_dialog_messages"); + } + } + + if (top_thread_message_id.is_valid()) { + AffectedHistoryQuery query = [td = td_, top_thread_message_id](DialogId dialog_id, + Promise &&query_promise) { + td->create_handler(std::move(query_promise))->send(dialog_id, top_thread_message_id); + }; + run_affected_history_query_until_complete(dialog_id, std::move(query), true, std::move(promise)); + return; } set_dialog_last_pinned_message_id(d, MessageId()); @@ -34810,7 +34829,7 @@ void MessagesManager::unpin_all_dialog_messages_on_server(DialogId dialog_id, ui } AffectedHistoryQuery query = [td = td_](DialogId dialog_id, Promise &&query_promise) { - td->create_handler(std::move(query_promise))->send(dialog_id); + td->create_handler(std::move(query_promise))->send(dialog_id, MessageId()); }; run_affected_history_query_until_complete(dialog_id, std::move(query), true, get_erase_log_event_promise(log_event_id, std::move(promise))); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 5e5c8fb7f..90d654bac 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -563,7 +563,7 @@ class MessagesManager final : public Actor { void pin_dialog_message(DialogId dialog_id, MessageId message_id, bool disable_notification, bool only_for_self, bool is_unpin, Promise &&promise); - void unpin_all_dialog_messages(DialogId dialog_id, Promise &&promise); + void unpin_all_dialog_messages(DialogId dialog_id, MessageId top_thread_message_id, Promise &&promise); void get_dialog_info_full(DialogId dialog_id, Promise &&promise, const char *source); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index bb2abc1ee..d9daf9ac5 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6197,7 +6197,8 @@ void Td::on_request(uint64 id, const td_api::unpinChatMessage &request) { void Td::on_request(uint64 id, const td_api::unpinAllChatMessages &request) { CREATE_OK_REQUEST_PROMISE(); - messages_manager_->unpin_all_dialog_messages(DialogId(request.chat_id_), std::move(promise)); + messages_manager_->unpin_all_dialog_messages(DialogId(request.chat_id_), MessageId(request.message_thread_id_), + std::move(promise)); } void Td::on_request(uint64 id, const td_api::joinChat &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 95cda7b15..bcd65c881 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4697,8 +4697,9 @@ class CliClient final : public Actor { send_request(td_api::make_object(chat_id, message_id)); } else if (op == "uacm") { ChatId chat_id; - get_args(args, chat_id); - send_request(td_api::make_object(chat_id)); + MessageThreadId message_thread_id; + get_args(args, chat_id, message_thread_id); + send_request(td_api::make_object(chat_id, message_thread_id)); } else if (op == "grib") { send_request(td_api::make_object()); } else if (op == "spc" || op == "su") {