diff options
| author | levlam <levlam@telegram.org> | 2026-07-01 15:51:44 +0300 |
|---|---|---|
| committer | levlam <levlam@telegram.org> | 2026-07-01 15:51:44 +0300 |
| commit | 406d07ba55c7f763de39803fa1a042d85d1a2850 (patch) | |
| tree | 7a96beb9ade8899cdda7b3d69c1910f14f0d1f8c | |
| parent | 0f090ec07c81b2cfe5a75339243c2a5700c063ca (diff) | |
Support deletion of ephemeral messages.
| -rw-r--r-- | td/telegram/MessageQueryManager.cpp | 108 | ||||
| -rw-r--r-- | td/telegram/MessageQueryManager.h | 9 | ||||
| -rw-r--r-- | td/telegram/MessagesManager.cpp | 19 | ||||
| -rw-r--r-- | td/telegram/TdDb.cpp | 1 | ||||
| -rw-r--r-- | td/telegram/logevent/LogEvent.h | 1 |
5 files changed, 133 insertions, 5 deletions
diff --git a/td/telegram/MessageQueryManager.cpp b/td/telegram/MessageQueryManager.cpp index ef44bbfa4..74b29ff96 100644 --- a/td/telegram/MessageQueryManager.cpp +++ b/td/telegram/MessageQueryManager.cpp @@ -1662,6 +1662,45 @@ class DeleteScheduledMessagesQuery final : public Td::ResultHandler { } }; +class DeleteEphemeralMessageQuery final : public Td::ResultHandler { + Promise<Unit> promise_; + DialogId dialog_id_; + + public: + explicit DeleteEphemeralMessageQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, DialogId receiver_dialog_id, EphemeralMessageId ephemeral_message_id) { + dialog_id_ = dialog_id; + + auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Read); + if (input_peer == nullptr || receiver_dialog_id.get_type() != DialogType::User) { + return on_error(Status::Error(400, "Can't access the chat")); + } + auto r_input_user = td_->user_manager_->get_input_user(receiver_dialog_id.get_user_id()); + if (r_input_user.is_error()) { + return on_error(Status::Error(400, "Can't access the user")); + } + send_query(G()->net_query_creator().create(telegram_api::ephemeral_deleteMessage( + std::move(input_peer), r_input_user.move_as_ok(), ephemeral_message_id.get()))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result<telegram_api::ephemeral_deleteMessage>(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + promise_.set_value(Unit()); + } + + void on_error(Status status) final { + if (!td_->dialog_manager_->on_get_dialog_error(dialog_id_, status, "DeleteEphemeralMessageQuery")) { + LOG(ERROR) << "Receive error for delete ephemeral messages: " << status; + } + promise_.set_error(std::move(status)); + } +}; + class DeleteTopicHistoryQuery final : public Td::ResultHandler { Promise<AffectedHistory> promise_; DialogId dialog_id_; @@ -3684,6 +3723,53 @@ void MessageQueryManager::delete_scheduled_messages_on_server(DialogId dialog_id td_->create_handler<DeleteScheduledMessagesQuery>(std::move(promise))->send(dialog_id, std::move(message_ids)); } +class MessageQueryManager::DeleteEphemeralMessageOnServerLogEvent { + public: + DialogId dialog_id_; + DialogId receiver_dialog_id_; + EphemeralMessageId ephemeral_message_id_; + + template <class StorerT> + void store(StorerT &storer) const { + td::store(dialog_id_, storer); + td::store(receiver_dialog_id_, storer); + td::store(ephemeral_message_id_, storer); + } + + template <class ParserT> + void parse(ParserT &parser) { + td::parse(dialog_id_, parser); + td::parse(receiver_dialog_id_, parser); + td::parse(ephemeral_message_id_, parser); + } +}; + +uint64 MessageQueryManager::save_delete_ephemeral_message_on_server_log_event(DialogId dialog_id, + DialogId receiver_dialog_id, + EphemeralMessageId ephemeral_message_id) { + DeleteEphemeralMessageOnServerLogEvent log_event{dialog_id, receiver_dialog_id, ephemeral_message_id}; + return binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::DeleteEphemeralMessageOnServer, + get_log_event_storer(log_event)); +} + +void MessageQueryManager::delete_ephemeral_message_on_server(DialogId dialog_id, DialogId receiver_dialog_id, + EphemeralMessageId ephemeral_message_id, + uint64 log_event_id, Promise<Unit> &&promise) { + LOG(INFO) << "Delete " << ephemeral_message_id << " from " << receiver_dialog_id << " in " << dialog_id + << " from server"; + + if (log_event_id == 0 && G()->use_message_database()) { + log_event_id = + save_delete_ephemeral_message_on_server_log_event(dialog_id, receiver_dialog_id, ephemeral_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 + + td_->create_handler<DeleteEphemeralMessageQuery>(std::move(promise)) + ->send(dialog_id, receiver_dialog_id, ephemeral_message_id); +} + void MessageQueryManager::delete_topic_history(DialogId dialog_id, ForumTopicId forum_topic_id, Promise<Unit> &&promise) { TRY_STATUS_PROMISE( @@ -4261,6 +4347,28 @@ void MessageQueryManager::on_binlog_events(vector<BinlogEvent> &&events) { delete_scheduled_messages_on_server(dialog_id, std::move(log_event.message_ids_), event.id_, Auto()); break; } + case LogEvent::HandlerType::DeleteEphemeralMessageOnServer: { + if (!have_old_message_database) { + binlog_erase(G()->td_db()->get_binlog(), event.id_); + break; + } + + DeleteEphemeralMessageOnServerLogEvent log_event; + log_event_parse(log_event, event.get_data()).ensure(); + + auto dialog_id = log_event.dialog_id_; + if (!td_->dialog_manager_->have_dialog_force(dialog_id, "DeleteEphemeralMessageOnServerLogEvent") || + !td_->dialog_manager_->have_input_peer(dialog_id, true, AccessRights::Read)) { + binlog_erase(G()->td_db()->get_binlog(), event.id_); + break; + } + + td_->messages_manager_->on_delete_ephemeral_messages(dialog_id, {log_event.ephemeral_message_id_}); + + delete_ephemeral_message_on_server(dialog_id, log_event.receiver_dialog_id_, log_event.ephemeral_message_id_, + event.id_, Auto()); + break; + } case LogEvent::HandlerType::DeleteTopicHistoryOnServer: { if (!have_old_message_database) { binlog_erase(G()->td_db()->get_binlog(), event.id_); diff --git a/td/telegram/MessageQueryManager.h b/td/telegram/MessageQueryManager.h index 7f0c04502..777b5c50f 100644 --- a/td/telegram/MessageQueryManager.h +++ b/td/telegram/MessageQueryManager.h @@ -12,6 +12,7 @@ #include "td/telegram/DialogId.h" #include "td/telegram/DialogListId.h" #include "td/telegram/EmojiGameInfo.h" +#include "td/telegram/EphemeralMessageId.h" #include "td/telegram/files/FileId.h" #include "td/telegram/files/FileSourceId.h" #include "td/telegram/files/FileUploadId.h" @@ -211,6 +212,10 @@ class MessageQueryManager final : public Actor { void delete_scheduled_messages_on_server(DialogId dialog_id, vector<MessageId> message_ids, uint64 log_event_id, Promise<Unit> &&promise); + void delete_ephemeral_message_on_server(DialogId dialog_id, DialogId receiver_dialog_id, + EphemeralMessageId ephemeral_message_id, uint64 log_event_id, + Promise<Unit> &&promise); + void delete_topic_history(DialogId dialog_id, ForumTopicId forum_topic_id, Promise<Unit> &&promise); void delete_reactions_by_sender(DialogId dialog_id, DialogId sender_dialog_id, Promise<Unit> &&promise); @@ -261,6 +266,7 @@ class MessageQueryManager final : public Actor { class DeleteDialogMessagesByDateOnServerLogEvent; class DeleteMessagesOnServerLogEvent; class DeleteScheduledMessagesOnServerLogEvent; + class DeleteEphemeralMessageOnServerLogEvent; class DeleteTopicHistoryOnServerLogEvent; class ReadAllDialogMentionsOnServerLogEvent; class ReadAllDialogReactionsOnServerLogEvent; @@ -352,6 +358,9 @@ class MessageQueryManager final : public Actor { static uint64 save_delete_scheduled_messages_on_server_log_event(DialogId dialog_id, const vector<MessageId> &message_ids); + static uint64 save_delete_ephemeral_message_on_server_log_event(DialogId dialog_id, DialogId receiver_dialog_id, + EphemeralMessageId ephemeral_message_id); + static uint64 save_delete_topic_history_on_server_log_event(DialogId dialog_id, ForumTopicId forum_topic_id); static uint64 save_read_all_dialog_mentions_on_server_log_event(DialogId dialog_id); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 3a8383bf0..20350179f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8370,8 +8370,9 @@ bool MessagesManager::can_revoke_message(DialogId dialog_id, const Message *m) c if (m == nullptr) { return true; } - if (m->message_id.is_local()) { - return false; + auto dialog_type = dialog_id.get_type(); + if (m->message_id.is_local() && dialog_type != DialogType::SecretChat) { + return m->ephemeral_message_id.is_valid(); } if (dialog_id == td_->dialog_manager_->get_my_dialog_id()) { return false; @@ -8386,7 +8387,7 @@ bool MessagesManager::can_revoke_message(DialogId dialog_id, const Message *m) c const int32 DEFAULT_REVOKE_TIME_LIMIT = td_->auth_manager_->is_bot() ? 2 * 86400 : std::numeric_limits<int32>::max(); auto content_type = m->content->get_type(); - switch (dialog_id.get_type()) { + switch (dialog_type) { case DialogType::User: { bool can_revoke_incoming = td_->option_manager_->get_option_boolean("revoke_pm_inbox", true); int64 revoke_time_limit = @@ -8435,8 +8436,8 @@ void MessagesManager::delete_messages(DialogId dialog_id, const vector<MessageId vector<MessageId> message_ids; message_ids.reserve(input_message_ids.size()); vector<MessageId> deleted_server_message_ids; - vector<MessageId> deleted_scheduled_server_message_ids; + vector<std::pair<DialogId, EphemeralMessageId>> deleted_ephemeral_message_ids; for (auto message_id : input_message_ids) { if (!message_id.is_valid() && !message_id.is_valid_scheduled()) { return promise.set_error(400, "Invalid message identifier"); @@ -8450,6 +8451,10 @@ void MessagesManager::delete_messages(DialogId dialog_id, const vector<MessageId if (m->message_id.is_scheduled_server()) { deleted_scheduled_server_message_ids.push_back(m->message_id); } + } else if (is_ephemeral_message(m)) { + if (m->ephemeral_message_id.is_valid() && m->receiver_user_id.is_valid()) { + deleted_ephemeral_message_ids.emplace_back(DialogId(m->receiver_user_id), m->ephemeral_message_id); + } } else { if (m->message_id.is_server() || is_secret) { deleted_server_message_ids.push_back(m->message_id); @@ -8464,7 +8469,7 @@ void MessagesManager::delete_messages(DialogId dialog_id, const vector<MessageId if (!can_delete_message(dialog_id, m)) { return promise.set_error(400, "Message can't be deleted"); } - if (is_bot && !message_id.is_scheduled() && message_id.is_server() && !can_revoke_message(dialog_id, m)) { + if (is_bot && message_id.is_server() && !can_revoke_message(dialog_id, m)) { return promise.set_error(400, "Message can't be deleted for everyone"); } } @@ -8477,6 +8482,10 @@ void MessagesManager::delete_messages(DialogId dialog_id, const vector<MessageId mpas.get_promise()); td_->message_query_manager_->delete_scheduled_messages_on_server( dialog_id, std::move(deleted_scheduled_server_message_ids), 0, mpas.get_promise()); + for (auto &it : deleted_ephemeral_message_ids) { + td_->message_query_manager_->delete_ephemeral_message_on_server(dialog_id, it.first, it.second, 0, + mpas.get_promise()); + } lock.set_value(Unit()); do_delete_dialog_messages(d, message_ids, false, DELETE_MESSAGE_USER_REQUEST_SOURCE); diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index 839f627b0..c49ad458b 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -114,6 +114,7 @@ Status init_binlog(Binlog &binlog, string path, BinlogKeyValue<Binlog> &binlog_p case LogEvent::HandlerType::ReadMessageContentsOnServer: case LogEvent::HandlerType::UnpinAllDialogMessagesOnServer: case LogEvent::HandlerType::ReadAllPollVotesOnServer: + case LogEvent::HandlerType::DeleteEphemeralMessageOnServer: events.to_message_query_manager.push_back(event.clone()); break; case LogEvent::HandlerType::SendMessage: diff --git a/td/telegram/logevent/LogEvent.h b/td/telegram/logevent/LogEvent.h index 2afe70aad..ebb53adc3 100644 --- a/td/telegram/logevent/LogEvent.h +++ b/td/telegram/logevent/LogEvent.h @@ -106,6 +106,7 @@ class LogEvent { SendQuickReplyShortcutMessages = 0x128, UpdateReactionNotificationSettingsOnServer = 0x129, ReadAllPollVotesOnServer = 0x12a, + DeleteEphemeralMessageOnServer = 0x12b, GetChannelDifference = 0x140, AddMessagePushNotification = 0x200, EditMessagePushNotification = 0x201, |
