diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 385111b16..7c748859e 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3811,16 +3811,16 @@ updateSupergroup supergroup:supergroup = Update; //@description Some data of a secret chat has changed. This update is guaranteed to come before the secret chat identifier is returned to the application @secret_chat New data about the secret chat updateSecretChat secret_chat:secretChat = Update; -//@description Some data from userFullInfo has been changed @user_id User identifier @user_full_info New full information about the user +//@description Some data in userFullInfo has been changed @user_id User identifier @user_full_info New full information about the user updateUserFullInfo user_id:int53 user_full_info:userFullInfo = Update; -//@description Some data from basicGroupFullInfo has been changed @basic_group_id Identifier of a basic group @basic_group_full_info New full information about the group +//@description Some data in basicGroupFullInfo has been changed @basic_group_id Identifier of a basic group @basic_group_full_info New full information about the group updateBasicGroupFullInfo basic_group_id:int53 basic_group_full_info:basicGroupFullInfo = Update; -//@description Some data from supergroupFullInfo has been changed @supergroup_id Identifier of the supergroup or channel @supergroup_full_info New full information about the supergroup +//@description Some data in supergroupFullInfo has been changed @supergroup_id Identifier of the supergroup or channel @supergroup_full_info New full information about the supergroup updateSupergroupFullInfo supergroup_id:int53 supergroup_full_info:supergroupFullInfo = Update; -//@description Service notification from the server. Upon receiving this the application must show a popup with the content of the notification +//@description A service notification from the server was received. Upon receiving this the application must show a popup with the content of the notification //@type Notification type. If type begins with "AUTH_KEY_DROP_", then two buttons "Cancel" and "Log out" must be shown under notification; if user presses the second, all local data must be destroyed using Destroy method //@content Notification content updateServiceNotification type:string content:MessageContent = Update; @@ -4439,8 +4439,8 @@ addLocalMessage chat_id:int53 sender_id:MessageSender reply_to_message_id:int53 //@description Deletes messages @chat_id Chat identifier @message_ids Identifiers of the messages to be deleted @revoke Pass true to try to delete messages for all chat members. Always true for supergroups, channels and secret chats deleteMessages chat_id:int53 message_ids:vector revoke:Bool = Ok; -//@description Deletes all messages sent by the specified user to a chat. Supported only for supergroups; requires can_delete_messages administrator privileges @chat_id Chat identifier @user_id User identifier -deleteChatMessagesFromUser chat_id:int53 user_id:int53 = Ok; +//@description Deletes all messages sent by the specified message sender in a chat. Supported only for supergroups; requires can_delete_messages administrator privileges @chat_id Chat identifier @sender_id Identifier of the sender of messages to delete +deleteChatMessagesBySender chat_id:int53 sender_id:MessageSender = Ok; //@description Deletes all messages between the specified dates in a chat. Supported only for private chats and basic groups. Messages sent in the last 30 seconds will not be deleted //@chat_id Chat identifier @min_date The minimum date of the messages to delete @max_date The maximum date of the messages to delete @revoke Pass true to try to delete chat messages for all users; private chats only diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index fb9391ce6..3e9bb328f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -2831,24 +2831,24 @@ class BlockFromRepliesQuery final : public Td::ResultHandler { } }; -class DeleteUserHistoryQuery final : public Td::ResultHandler { +class DeleteParticipantHistoryQuery final : public Td::ResultHandler { Promise promise_; ChannelId channel_id_; public: - explicit DeleteUserHistoryQuery(Promise &&promise) : promise_(std::move(promise)) { + explicit DeleteParticipantHistoryQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(ChannelId channel_id, UserId user_id) { + void send(ChannelId channel_id, DialogId sender_dialog_id) { channel_id_ = channel_id; auto input_channel = td_->contacts_manager_->get_input_channel(channel_id_); if (input_channel == nullptr) { return promise_.set_error(Status::Error(400, "Chat is not accessible")); } - auto input_peer = td_->contacts_manager_->get_input_peer_user(user_id, AccessRights::Know); + auto input_peer = td_->messages_manager_->get_input_peer(sender_dialog_id, AccessRights::Know); if (input_peer == nullptr) { - return promise_.set_error(Status::Error(400, "User is not accessible")); + return promise_.set_error(Status::Error(400, "Message sender is not accessible")); } send_query(G()->net_query_creator().create( @@ -2865,7 +2865,7 @@ class DeleteUserHistoryQuery final : public Td::ResultHandler { } void on_error(Status status) final { - td_->contacts_manager_->on_get_channel_error(channel_id_, status, "DeleteUserHistoryQuery"); + td_->contacts_manager_->on_get_channel_error(channel_id_, status, "DeleteParticipantHistoryQuery"); promise_.set_error(std::move(status)); } }; @@ -10760,11 +10760,12 @@ void MessagesManager::find_unloadable_messages(const Dialog *d, int32 unload_bef find_unloadable_messages(d, unload_before_date, m->right.get(), message_ids, left_to_unload); } -void MessagesManager::delete_dialog_messages_from_user(DialogId dialog_id, UserId user_id, Promise &&promise) { +void MessagesManager::delete_dialog_messages_by_sender(DialogId dialog_id, DialogId sender_dialog_id, + Promise &&promise) { bool is_bot = td_->auth_manager_->is_bot(); CHECK(!is_bot); - Dialog *d = get_dialog_force(dialog_id, "delete_dialog_messages_from_user"); + Dialog *d = get_dialog_force(dialog_id, "delete_dialog_messages_by_sender"); if (d == nullptr) { return promise.set_error(Status::Error(400, "Chat not found")); } @@ -10773,8 +10774,8 @@ void MessagesManager::delete_dialog_messages_from_user(DialogId dialog_id, UserI return promise.set_error(Status::Error(400, "Not enough rights")); } - if (!td_->contacts_manager_->have_input_user(user_id)) { - return promise.set_error(Status::Error(400, "User not found")); + if (!have_input_peer(sender_dialog_id, AccessRights::Know)) { + return promise.set_error(Status::Error(400, "Message sender not found")); } ChannelId channel_id; @@ -10783,7 +10784,8 @@ void MessagesManager::delete_dialog_messages_from_user(DialogId dialog_id, UserI case DialogType::User: case DialogType::Chat: case DialogType::SecretChat: - return promise.set_error(Status::Error(400, "All messages from a user can be deleted only in supergroup chats")); + return promise.set_error( + Status::Error(400, "All messages from a sender can be deleted only in supergroup chats")); case DialogType::Channel: { channel_id = dialog_id.get_channel_id(); auto channel_type = td_->contacts_manager_->get_channel_type(channel_id); @@ -10804,73 +10806,87 @@ void MessagesManager::delete_dialog_messages_from_user(DialogId dialog_id, UserI } CHECK(channel_id.is_valid()); - if (G()->parameters().use_message_db) { - LOG(INFO) << "Delete all messages from " << user_id << " in " << dialog_id << " from database"; - G()->td_db()->get_messages_db_async()->delete_dialog_messages_from_user(dialog_id, user_id, + if (sender_dialog_id.get_type() == DialogType::SecretChat) { + return promise.set_value(Unit()); + } + + if (G()->parameters().use_message_db && sender_dialog_id.get_type() == DialogType::User) { + LOG(INFO) << "Delete all messages from " << sender_dialog_id << " in " << dialog_id << " from database"; + G()->td_db()->get_messages_db_async()->delete_dialog_messages_from_user(dialog_id, sender_dialog_id.get_user_id(), Auto()); // TODO Promise } vector message_ids; - find_messages(d->messages.get(), message_ids, [user_id](const Message *m) { return m->sender_user_id == user_id; }); + find_messages(d->messages.get(), message_ids, [sender_dialog_id](const Message *m) { + return sender_dialog_id == (m->sender_dialog_id.is_valid() ? m->sender_dialog_id : DialogId(m->sender_user_id)); + }); vector deleted_message_ids; bool need_update_dialog_pos = false; for (auto message_id : message_ids) { auto m = get_message(d, message_id); CHECK(m != nullptr); - CHECK(m->sender_user_id == user_id); CHECK(m->message_id == message_id); if (can_delete_channel_message(channel_status, m, is_bot)) { - auto p = delete_message(d, message_id, true, &need_update_dialog_pos, "delete messages from user"); + auto p = delete_message(d, message_id, true, &need_update_dialog_pos, "delete_dialog_messages_by_sender"); CHECK(p.get() == m); deleted_message_ids.push_back(p->message_id.get()); } } if (need_update_dialog_pos) { - send_update_chat_last_message(d, "delete_messages_from_user"); + send_update_chat_last_message(d, "delete_dialog_messages_by_sender"); } send_update_delete_messages(dialog_id, std::move(deleted_message_ids), true, false); - delete_all_channel_messages_from_user_on_server(channel_id, user_id, 0, std::move(promise)); + delete_all_channel_messages_by_sender_on_server(channel_id, sender_dialog_id, 0, std::move(promise)); } class MessagesManager::DeleteAllChannelMessagesFromUserOnServerLogEvent { public: ChannelId channel_id_; - UserId user_id_; + DialogId sender_dialog_id_; template void store(StorerT &storer) const { td::store(channel_id_, storer); - td::store(user_id_, storer); + td::store(sender_dialog_id_, storer); } template void parse(ParserT &parser) { td::parse(channel_id_, parser); - td::parse(user_id_, parser); + if (parser.version() >= static_cast(Version::AddKeyboardButtonFlags)) { + td::parse(sender_dialog_id_, parser); + } else { + UserId user_id; + td::parse(user_id, parser); + sender_dialog_id_ = DialogId(user_id); + } } }; -uint64 MessagesManager::save_delete_all_channel_messages_from_user_on_server_log_event(ChannelId channel_id, - UserId user_id) { - DeleteAllChannelMessagesFromUserOnServerLogEvent log_event{channel_id, user_id}; +uint64 MessagesManager::save_delete_all_channel_messages_by_sender_on_server_log_event(ChannelId channel_id, + DialogId sender_dialog_id) { + DeleteAllChannelMessagesFromUserOnServerLogEvent log_event{channel_id, sender_dialog_id}; return binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::DeleteAllChannelMessagesFromUserOnServer, get_log_event_storer(log_event)); } -void MessagesManager::delete_all_channel_messages_from_user_on_server(ChannelId channel_id, UserId user_id, +void MessagesManager::delete_all_channel_messages_by_sender_on_server(ChannelId channel_id, DialogId sender_dialog_id, uint64 log_event_id, Promise &&promise) { if (log_event_id == 0 && G()->parameters().use_chat_info_db) { - log_event_id = save_delete_all_channel_messages_from_user_on_server_log_event(channel_id, user_id); + log_event_id = save_delete_all_channel_messages_by_sender_on_server_log_event(channel_id, sender_dialog_id); } - AffectedHistoryQuery query = [td = td_, user_id](DialogId dialog_id, Promise &&query_promise) { - td->create_handler(std::move(query_promise))->send(dialog_id.get_channel_id(), user_id); + AffectedHistoryQuery query = [td = td_, sender_dialog_id](DialogId dialog_id, + Promise &&query_promise) { + td->create_handler(std::move(query_promise)) + ->send(dialog_id.get_channel_id(), sender_dialog_id); }; - run_affected_history_query_until_complete(DialogId(channel_id), std::move(query), false, + run_affected_history_query_until_complete(DialogId(channel_id), std::move(query), + sender_dialog_id.get_type() != DialogType::User, get_erase_log_event_promise(log_event_id, std::move(promise))); } @@ -37389,14 +37405,15 @@ void MessagesManager::on_binlog_events(vector &&events) { break; } - auto user_id = log_event.user_id_; - if (!td_->contacts_manager_->have_user_force(user_id)) { - LOG(ERROR) << "Can't find user " << user_id; + auto sender_dialog_id = log_event.sender_dialog_id_; + if (!td_->messages_manager_->have_dialog_info_force(sender_dialog_id) || + !td_->messages_manager_->have_input_peer(sender_dialog_id, AccessRights::Know)) { + LOG(ERROR) << "Can't find " << sender_dialog_id; binlog_erase(G()->td_db()->get_binlog(), event.id_); break; } - delete_all_channel_messages_from_user_on_server(channel_id, user_id, event.id_, Auto()); + delete_all_channel_messages_by_sender_on_server(channel_id, sender_dialog_id, event.id_, Auto()); break; } case LogEvent::HandlerType::DeleteDialogMessagesByDateOnServer: { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 45a018a05..ae29b6109 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -364,7 +364,7 @@ class MessagesManager final : public Actor { void delete_all_call_messages(bool revoke, Promise &&promise); - void delete_dialog_messages_from_user(DialogId dialog_id, UserId user_id, Promise &&promise); + void delete_dialog_messages_by_sender(DialogId dialog_id, DialogId sender_dialog_id, Promise &&promise); void delete_dialog_messages_by_date(DialogId dialog_id, int32 min_date, int32 max_date, bool revoke, Promise &&promise); @@ -2012,8 +2012,8 @@ class MessagesManager final : public Actor { bool need_delete_all_messages, bool report_spam, uint64 log_event_id, Promise &&promise); - void delete_all_channel_messages_from_user_on_server(ChannelId channel_id, UserId user_id, uint64 log_event_id, - Promise &&promise); + void delete_all_channel_messages_by_sender_on_server(ChannelId channel_id, DialogId sender_dialog_id, + uint64 log_event_id, Promise &&promise); void delete_dialog_messages_by_date_on_server(DialogId dialog_id, int32 min_date, int32 max_date, bool revoke, uint64 log_event_id, Promise &&promise); @@ -3111,7 +3111,8 @@ class MessagesManager final : public Actor { bool need_delete_all_messages, bool report_spam); - static uint64 save_delete_all_channel_messages_from_user_on_server_log_event(ChannelId channel_id, UserId user_id); + static uint64 save_delete_all_channel_messages_by_sender_on_server_log_event(ChannelId channel_id, + DialogId sender_dialog_id); static uint64 save_delete_dialog_messages_by_date_on_server_log_event(DialogId dialog_id, int32 min_date, int32 max_date, bool revoke); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 5ee599328..7f7083b10 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5451,10 +5451,12 @@ void Td::on_request(uint64 id, const td_api::deleteMessages &request) { request.revoke_, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::deleteChatMessagesFromUser &request) { +void Td::on_request(uint64 id, const td_api::deleteChatMessagesBySender &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - messages_manager_->delete_dialog_messages_from_user(DialogId(request.chat_id_), UserId(request.user_id_), + TRY_RESULT_PROMISE(promise, participant_dialog_id, + get_message_sender_dialog_id(this, request.sender_id_, false, false)); + messages_manager_->delete_dialog_messages_by_sender(DialogId(request.chat_id_), participant_dialog_id, std::move(promise)); } diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 1e8993171..99bb7bf6e 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -652,7 +652,7 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::deleteMessages &request); - void on_request(uint64 id, const td_api::deleteChatMessagesFromUser &request); + void on_request(uint64 id, const td_api::deleteChatMessagesBySender &request); void on_request(uint64 id, const td_api::deleteChatMessagesByDate &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 0d78b1253..2fb10af44 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3771,11 +3771,12 @@ class CliClient final : public Actor { get_args(args, chat_id, min_date, max_date, revoke); send_request( td_api::make_object(as_chat_id(chat_id), min_date, max_date, revoke)); - } else if (op == "dmfu") { + } else if (op == "dcmbs") { string chat_id; - string user_id; - get_args(args, chat_id, user_id); - send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id))); + string sender_id; + get_args(args, chat_id, sender_id); + send_request( + td_api::make_object(as_chat_id(chat_id), as_message_sender(sender_id))); } else if (op == "cnbgc") { string user_ids_string; string title;