From 43deaf45021052c774db9347b82cc637e2590d5b Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 30 Oct 2022 00:35:37 +0300 Subject: [PATCH] Add td_api::deleteForumTopic. --- td/generate/scheme/td_api.tl | 5 ++ td/telegram/ForumTopicManager.cpp | 19 +++++ td/telegram/ForumTopicManager.h | 2 + td/telegram/MessagesManager.cpp | 115 ++++++++++++++++++++++++++++++ td/telegram/MessagesManager.h | 8 +++ td/telegram/Td.cpp | 7 ++ td/telegram/Td.h | 2 + td/telegram/TdDb.cpp | 1 + td/telegram/cli.cpp | 5 ++ td/telegram/logevent/LogEvent.h | 1 + 10 files changed, 165 insertions(+) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 3472791f6..e40fe5bcc 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5315,6 +5315,11 @@ editForumTopic chat_id:int53 message_thread_id:int53 title:string icon_custom_em //@is_closed Pass true to close the topic; pass false to reopen it toggleForumTopicIsClosed chat_id:int53 message_thread_id:int53 is_closed:Bool = Ok; +//@description Deletes all messages in a forum topic; requires can_delete_messages administrator rights in the supergroup unless the user is creator of the topic, the topic has no messages from other users and has at most 11 messages +//@chat_id Identifier of the chat +//@message_thread_id Message thread identifier of the forum topic +deleteForumTopic chat_id:int53 message_thread_id:int53 = Ok; + //@description Returns information about a emoji reaction. Returns a 404 error if the reaction is not found @emoji Text representation of the reaction getEmojiReaction emoji:string = EmojiReaction; diff --git a/td/telegram/ForumTopicManager.cpp b/td/telegram/ForumTopicManager.cpp index cf65425ed..8602674ea 100644 --- a/td/telegram/ForumTopicManager.cpp +++ b/td/telegram/ForumTopicManager.cpp @@ -261,6 +261,25 @@ void ForumTopicManager::toggle_forum_topic_is_closed(DialogId dialog_id, Message td_->create_handler(std::move(promise))->send(channel_id, top_thread_message_id, is_closed); } +void ForumTopicManager::delete_forum_topic(DialogId dialog_id, MessageId top_thread_message_id, + Promise &&promise) { + TRY_STATUS_PROMISE(promise, is_forum(dialog_id)); + auto channel_id = dialog_id.get_channel_id(); + + if (!top_thread_message_id.is_valid() || !top_thread_message_id.is_server()) { + return promise.set_error(Status::Error(400, "Invalid message thread identifier specified")); + } + + if (!td_->contacts_manager_->get_channel_permissions(channel_id).can_delete_messages()) { + auto topic_info = get_topic_info(dialog_id, top_thread_message_id); + if (topic_info != nullptr && !topic_info->is_outgoing()) { + return promise.set_error(Status::Error(400, "Not enough rights to delete the topic")); + } + } + + td_->messages_manager_->delete_topic_history(dialog_id, top_thread_message_id, std::move(promise)); +} + void ForumTopicManager::on_forum_topic_edited(DialogId dialog_id, MessageId top_thread_message_id, const ForumTopicEditedData &edited_data) { auto topic_info = get_topic_info(dialog_id, top_thread_message_id); diff --git a/td/telegram/ForumTopicManager.h b/td/telegram/ForumTopicManager.h index 5ca356019..a469a148d 100644 --- a/td/telegram/ForumTopicManager.h +++ b/td/telegram/ForumTopicManager.h @@ -43,6 +43,8 @@ class ForumTopicManager final : public Actor { void toggle_forum_topic_is_closed(DialogId dialog_id, MessageId top_thread_message_id, bool is_closed, Promise &&promise); + void delete_forum_topic(DialogId dialog_id, MessageId top_thread_message_id, Promise &&promise); + void on_forum_topic_edited(DialogId dialog_id, MessageId top_thread_message_id, const ForumTopicEditedData &edited_data); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 0c84bbb85..a4b6b21c2 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -3015,6 +3015,40 @@ class DeleteHistoryQuery final : public Td::ResultHandler { } }; +class DeleteTopicHistoryQuery final : public Td::ResultHandler { + Promise promise_; + ChannelId channel_id_; + + public: + explicit DeleteTopicHistoryQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, MessageId top_thread_message_id) { + CHECK(dialog_id.get_type() == DialogType::Channel); + channel_id_ = dialog_id.get_channel_id(); + + auto input_channel = td_->contacts_manager_->get_input_channel(channel_id_); + CHECK(input_channel != nullptr); + + send_query(G()->net_query_creator().create(telegram_api::channels_deleteTopicHistory( + std::move(input_channel), top_thread_message_id.get_server_message_id().get()))); + } + + 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()); + } + + promise_.set_value(AffectedHistory(result_ptr.move_as_ok())); + } + + void on_error(Status status) final { + td_->contacts_manager_->on_get_channel_error(channel_id_, status, "DeleteTopicHistoryQuery"); + promise_.set_error(std::move(status)); + } +}; + class DeleteChannelHistoryQuery final : public Td::ResultHandler { Promise promise_; ChannelId channel_id_; @@ -11503,6 +11537,68 @@ void MessagesManager::delete_dialog_history_on_server(DialogId dialog_id, Messag } } +void MessagesManager::delete_topic_history(DialogId dialog_id, MessageId top_thread_message_id, + Promise &&promise) { + Dialog *d = get_dialog_force(dialog_id, "delete_dialog_history"); + if (d == nullptr) { + return promise.set_error(Status::Error(400, "Chat not found")); + } + + if (!have_input_peer(dialog_id, AccessRights::Read)) { + return promise.set_error(Status::Error(400, "Chat info not found")); + } + + // auto old_order = d->order; + // delete_all_dialog_topic_messages(d, top_thread_message_id); + + delete_topic_history_on_server(dialog_id, top_thread_message_id, 0, std::move(promise)); +} + +class MessagesManager::DeleteTopicHistoryOnServerLogEvent { + public: + DialogId dialog_id_; + MessageId top_thread_message_id_; + + template + void store(StorerT &storer) const { + BEGIN_STORE_FLAGS(); + END_STORE_FLAGS(); + td::store(dialog_id_, storer); + td::store(top_thread_message_id_, storer); + } + + template + void parse(ParserT &parser) { + BEGIN_PARSE_FLAGS(); + END_PARSE_FLAGS(); + td::parse(dialog_id_, parser); + td::parse(top_thread_message_id_, parser); + } +}; + +uint64 MessagesManager::save_delete_topic_history_on_server_log_event(DialogId dialog_id, + MessageId top_thread_message_id) { + DeleteTopicHistoryOnServerLogEvent log_event{dialog_id, top_thread_message_id}; + return binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::DeleteTopicHistoryOnServer, + get_log_event_storer(log_event)); +} + +void MessagesManager::delete_topic_history_on_server(DialogId dialog_id, MessageId top_thread_message_id, + uint64 log_event_id, Promise &&promise) { + if (log_event_id == 0 && G()->parameters().use_message_db) { + log_event_id = save_delete_topic_history_on_server_log_event(dialog_id, top_thread_message_id); + } + + auto new_promise = get_erase_log_event_promise(log_event_id, std::move(promise)); + promise = std::move(new_promise); // to prevent self-move + + 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)); +} + void MessagesManager::delete_all_call_messages(bool revoke, Promise &&promise) { delete_all_call_messages_on_server(revoke, 0, std::move(promise)); } @@ -40158,6 +40254,25 @@ void MessagesManager::on_binlog_events(vector &&events) { log_event.revoke_, true, event.id_, Auto()); break; } + case LogEvent::HandlerType::DeleteTopicHistoryOnServer: { + if (!G()->parameters().use_message_db) { + binlog_erase(G()->td_db()->get_binlog(), event.id_); + break; + } + + DeleteTopicHistoryOnServerLogEvent log_event; + log_event_parse(log_event, event.data_).ensure(); + + auto dialog_id = log_event.dialog_id_; + Dialog *d = get_dialog_force(dialog_id, "DeleteTopicHistoryOnServerLogEvent"); + if (d == nullptr || !have_input_peer(dialog_id, AccessRights::Read)) { + binlog_erase(G()->td_db()->get_binlog(), event.id_); + break; + } + + delete_topic_history_on_server(dialog_id, log_event.top_thread_message_id_, event.id_, Auto()); + break; + } case LogEvent::HandlerType::DeleteAllCallMessagesOnServer: { DeleteAllCallMessagesOnServerLogEvent log_event; log_event_parse(log_event, event.data_).ensure(); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 437169781..5e5c8fb7f 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -401,6 +401,8 @@ class MessagesManager final : public Actor { void delete_dialog_history(DialogId dialog_id, bool remove_from_dialog_list, bool revoke, Promise &&promise); + void delete_topic_history(DialogId dialog_id, MessageId top_thread_message_id, Promise &&promise); + void delete_all_call_messages(bool revoke, Promise &&promise); void delete_dialog_messages_by_sender(DialogId dialog_id, DialogId sender_dialog_id, Promise &&promise); @@ -1767,6 +1769,7 @@ class MessagesManager final : public Actor { class DeleteMessageLogEvent; class DeleteMessagesOnServerLogEvent; class DeleteScheduledMessagesOnServerLogEvent; + class DeleteTopicHistoryOnServerLogEvent; class ForwardMessagesLogEvent; class GetChannelDifferenceLogEvent; class ReadAllDialogMentionsOnServerLogEvent; @@ -2154,6 +2157,9 @@ class MessagesManager final : public Actor { void delete_dialog_history_on_server(DialogId dialog_id, MessageId max_message_id, bool remove_from_dialog_list, bool revoke, bool allow_error, uint64 log_event_id, Promise &&promise); + void delete_topic_history_on_server(DialogId dialog_id, MessageId top_thread_message_id, uint64 log_event_id, + Promise &&promise); + void delete_all_call_messages_on_server(bool revoke, uint64 log_event_id, Promise &&promise); void block_message_sender_from_replies_on_server(MessageId message_id, bool need_delete_message, @@ -3310,6 +3316,8 @@ class MessagesManager final : public Actor { static uint64 save_delete_dialog_history_on_server_log_event(DialogId dialog_id, MessageId max_message_id, bool remove_from_dialog_list, bool revoke); + static uint64 save_delete_topic_history_on_server_log_event(DialogId dialog_id, MessageId top_thread_message_id); + static uint64 save_delete_all_call_messages_on_server_log_event(bool revoke); static uint64 save_block_message_sender_from_replies_on_server_log_event(MessageId message_id, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f1d0b4a0d..d9a5879f2 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5539,6 +5539,13 @@ void Td::on_request(uint64 id, const td_api::toggleForumTopicIsClosed &request) request.is_closed_, std::move(promise)); } +void Td::on_request(uint64 id, const td_api::deleteForumTopic &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + forum_topic_manager_->delete_forum_topic(DialogId(request.chat_id_), MessageId(request.message_thread_id_), + std::move(promise)); +} + void Td::on_request(uint64 id, td_api::setGameScore &request) { CHECK_IS_BOT(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 1d7bebd87..7450a419f 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -738,6 +738,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::toggleForumTopicIsClosed &request); + void on_request(uint64 id, const td_api::deleteForumTopic &request); + void on_request(uint64 id, td_api::setGameScore &request); void on_request(uint64 id, td_api::setInlineGameScore &request); diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index 4dfe42c99..989487fbc 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -108,6 +108,7 @@ Status init_binlog(Binlog &binlog, string path, BinlogKeyValue &binlog_p case LogEvent::HandlerType::DeleteAllCallMessagesOnServer: case LogEvent::HandlerType::DeleteDialogMessagesByDateOnServer: case LogEvent::HandlerType::ReadAllDialogReactionsOnServer: + case LogEvent::HandlerType::DeleteTopicHistoryOnServer: events.to_messages_manager.push_back(event.clone()); break; case LogEvent::HandlerType::UpdateScopeNotificationSettingsOnServer: diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 5c46586eb..95cda7b15 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3877,6 +3877,11 @@ class CliClient final : public Actor { bool is_closed; get_args(args, chat_id, message_thread_id, is_closed); send_request(td_api::make_object(chat_id, message_thread_id, is_closed)); + } else if (op == "dft") { + ChatId 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 == "gallm") { send_request(td_api::make_object()); } else if (op == "sbsm") { diff --git a/td/telegram/logevent/LogEvent.h b/td/telegram/logevent/LogEvent.h index 2a4fee9b0..349ea8608 100644 --- a/td/telegram/logevent/LogEvent.h +++ b/td/telegram/logevent/LogEvent.h @@ -101,6 +101,7 @@ class LogEvent { DeleteAllCallMessagesOnServer = 0x122, DeleteDialogMessagesByDateOnServer = 0x123, ReadAllDialogReactionsOnServer = 0x124, + DeleteTopicHistoryOnServer = 0x125, GetChannelDifference = 0x140, AddMessagePushNotification = 0x200, EditMessagePushNotification = 0x201,