From 860903e2d332aa2b4458f33aaa74cc9f3b3da3ae Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 11 Jul 2026 22:35:20 +0300 Subject: Add td_api::editEphemeralMessage. --- td/generate/scheme/td_api.tl | 11 +++- td/telegram/MessageQueryManager.cpp | 114 ++++++++++++++++++++++++++++++++++++ td/telegram/MessageQueryManager.h | 5 ++ td/telegram/MessagesManager.cpp | 2 +- td/telegram/Requests.cpp | 8 +++ td/telegram/Requests.h | 2 + 6 files changed, 140 insertions(+), 2 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0b894ed9b..c408cce05 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -12198,7 +12198,7 @@ editMessageCaption chat_id:int53 message_id:int53 reply_markup:ReplyMarkup capti //@reply_markup The new message reply markup; pass null if none editMessageReplyMarkup chat_id:int53 message_id:int53 reply_markup:ReplyMarkup = Message; -//@description Edits the text of an inline text or game message sent via a bot; for bots only +//@description Edits the text of an inline text or game message sent via the bot; for bots only //@inline_message_id Inline message identifier //@reply_markup The new message reply markup; pass null if none //@input_message_content New text content of the message. Must be of type inputMessageText or inputMessageRichMessage; file upload isn't supported @@ -12229,6 +12229,15 @@ editInlineMessageCaption inline_message_id:string reply_markup:ReplyMarkup capti //@reply_markup The new message reply markup; pass null if none editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup = Ok; +//@description Edits the text, caption or reply markup of an ephemeral message sent by the bot; for bots only +//@chat_id The chat the message belongs to +//@receiver_user_id Identifier of the user who received the message +//@ephemeral_message_id Identifier of the ephemeral message +//@reply_markup The new message reply markup; pass null if none +//@input_message_content New content of the message; pass null to edit only reply markup. Must be one of the following types: inputMessageText, inputMessageAnimation, +//-inputMessageAudio, inputMessageDocument, inputMessagePhoto, inputMessageSticker, inputMessageVideo, inputMessageVideoNote, inputMessageVoiceNote +editEphemeralMessage chat_id:int53 receiver_user_id:int53 ephemeral_message_id:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = Ok; + //@description Edits the time when a scheduled message will be sent. Scheduling state of all messages in the same album or forwarded together with the message will be also changed //@chat_id The chat the message belongs to //@message_id Identifier of the message. Use messageProperties.can_edit_scheduling_state to check whether the message is suitable diff --git a/td/telegram/MessageQueryManager.cpp b/td/telegram/MessageQueryManager.cpp index fc25b62b5..69bdffdc5 100644 --- a/td/telegram/MessageQueryManager.cpp +++ b/td/telegram/MessageQueryManager.cpp @@ -1341,6 +1341,68 @@ class BlockFromRepliesQuery final : public Td::ResultHandler { } }; +class EditEphemeralMessageQuery final : public Td::ResultHandler { + Promise promise_; + + public: + explicit EditEphemeralMessageQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, UserId receiver_user_id, EphemeralMessageId ephemeral_message_id, bool force_edit_text, + const FormattedText *text, bool disable_web_page_preview, InputMedia &&input_media, bool invert_media, + const unique_ptr &reply_markup) { + // file upload isn't supported, so only previously uploaded files or URLs can be used in the InputMedia + CHECK(!FileManager::extract_was_uploaded(input_media)); + + int32 flags = 0; + auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Write); + CHECK(input_peer != nullptr); + auto r_input_user = td_->user_manager_->get_input_user(receiver_user_id); + if (r_input_user.is_error()) { + return on_error(Status::Error(400, "Can't access the user")); + } + auto input_reply_markup = get_input_reply_markup(td_->user_manager_.get(), reply_markup); + if (input_reply_markup != nullptr) { + flags |= telegram_api::ephemeral_editMessage::REPLY_MARKUP_MASK; + } + vector> entities; + if (force_edit_text || (text != nullptr && !text->text.empty())) { + flags |= telegram_api::ephemeral_editMessage::MESSAGE_MASK; + + entities = get_input_message_entities(td_->user_manager_.get(), text, "EditEphemeralMessageQuery"); + if (!entities.empty()) { + flags |= telegram_api::ephemeral_editMessage::ENTITIES_MASK; + } + } + if (input_media.media_ != nullptr) { + flags |= telegram_api::ephemeral_editMessage::MEDIA_MASK; + } + if (input_media.rich_message_ != nullptr) { + // flags |= telegram_api::ephemeral_editMessage::RICH_MESSAGE_MASK; + } + send_query(G()->net_query_creator().create(telegram_api::ephemeral_editMessage( + flags, std::move(input_peer), r_input_user.move_as_ok(), ephemeral_message_id.get(), + text == nullptr ? string() : text->text, std::move(input_media.media_), std::move(entities), + std::move(input_reply_markup)))); + } + + 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 EditEphemeralMessageQuery: " << to_string(ptr); + td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); + } + + void on_error(Status status) final { + LOG(INFO) << "Receive error for EditInlineMessageQuery: " << status; + promise_.set_error(std::move(status)); + } +}; + class DeletePhoneCallHistoryQuery final : public Td::ResultHandler { Promise promise_; @@ -3288,6 +3350,58 @@ void MessageQueryManager::block_message_sender_from_replies_on_server(MessageId ->send(message_id, need_delete_message, need_delete_all_messages, report_spam); } +void MessageQueryManager::edit_ephemeral_message( + DialogId dialog_id, UserId receiver_user_id, EphemeralMessageId ephemeral_message_id, + td_api::object_ptr &&reply_markup, + td_api::object_ptr &&input_message_content, Promise &&promise) { + auto is_bot = td_->auth_manager_->is_bot(); + CHECK(is_bot); + + TRY_STATUS_PROMISE(promise, td_->dialog_manager_->check_dialog_access(dialog_id, false, AccessRights::Write, + "edit_ephemeral_message_text")); + TRY_RESULT_PROMISE(promise, new_reply_markup, get_inline_reply_markup(std::move(reply_markup), is_bot, true)); + if (input_message_content == nullptr) { + td_->create_handler(std::move(promise)) + ->send(dialog_id, receiver_user_id, ephemeral_message_id, false, nullptr, false, InputMedia(), false, + new_reply_markup); + return; + } + int32 new_message_content_type = input_message_content->get_id(); + if (new_message_content_type == td_api::inputMessageText::ID) { + TRY_RESULT_PROMISE(promise, input_message_text, + process_input_message_text(td_, dialog_id, std::move(input_message_content), is_bot)); + td_->create_handler(std::move(promise)) + ->send(dialog_id, receiver_user_id, ephemeral_message_id, true, &input_message_text.text, + input_message_text.disable_web_page_preview, input_message_text.get_input_media_web_page(), + input_message_text.show_above_text, new_reply_markup); + } + + if (new_message_content_type != td_api::inputMessageAnimation::ID && + new_message_content_type != td_api::inputMessageAudio::ID && + new_message_content_type != td_api::inputMessageDocument::ID && + new_message_content_type != td_api::inputMessagePhoto::ID && + new_message_content_type != td_api::inputMessageVideo::ID) { + return promise.set_error(400, "Invalid message content type specified"); + } + + TRY_RESULT_PROMISE(promise, content, + get_input_message_content(dialog_id, std::move(input_message_content), td_, false)); + if (!content.ttl.is_empty()) { + return promise.set_error(400, "Can't enable self-destruction for media"); + } + + auto input_media = + get_message_content_input_media(content.content.get(), td_, MessageSelfDestructType(), string(), true, -1); + if (input_media.is_empty()) { + return promise.set_error(400, "File upload isn't allowed"); + } + + const FormattedText *caption = get_message_content_caption(content.content.get()); + td_->create_handler(std::move(promise)) + ->send(dialog_id, receiver_user_id, ephemeral_message_id, true, caption, false, std::move(input_media), + content.invert_media, new_reply_markup); +} + void MessageQueryManager::delete_dialog_messages_by_sender(DialogId dialog_id, DialogId sender_dialog_id, Promise &&promise) { CHECK(!td_->auth_manager_->is_bot()); diff --git a/td/telegram/MessageQueryManager.h b/td/telegram/MessageQueryManager.h index da5b6ed54..941f381fd 100644 --- a/td/telegram/MessageQueryManager.h +++ b/td/telegram/MessageQueryManager.h @@ -199,6 +199,11 @@ class MessageQueryManager final : public Actor { bool need_delete_all_messages, bool report_spam, uint64 log_event_id, Promise &&promise); + void edit_ephemeral_message(DialogId dialog_id, UserId receiver_user_id, EphemeralMessageId ephemeral_message_id, + td_api::object_ptr &&reply_markup, + td_api::object_ptr &&input_message_content, + 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, diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 7cc2c1a7a..13d08374a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -4316,7 +4316,7 @@ MessageFullId MessagesManager::on_edited_ephemeral_message( message_info.message_id = get_message_id_of_ephemeral_message_id(dialog_id, message_info.ephemeral_message_id); if (message_info.message_id == MessageId()) { - if (!force) { + if (!force && !td_->auth_manager_->is_bot()) { return MessageFullId(); } force_create_dialog(dialog_id, "on_edited_ephemeral_message", true); diff --git a/td/telegram/Requests.cpp b/td/telegram/Requests.cpp index 2d154d271..0554c17ee 100644 --- a/td/telegram/Requests.cpp +++ b/td/telegram/Requests.cpp @@ -4355,6 +4355,14 @@ void Requests::on_request(uint64 id, td_api::editInlineMessageReplyMarkup &reque std::move(request.reply_markup_), std::move(promise)); } +void Requests::on_request(uint64 id, td_api::editEphemeralMessage &request) { + CHECK_IS_BOT(); + CREATE_OK_REQUEST_PROMISE(); + td_->message_query_manager_->edit_ephemeral_message( + DialogId(request.chat_id_), UserId(request.receiver_user_id_), EphemeralMessageId(request.ephemeral_message_id_), + std::move(request.reply_markup_), std::move(request.input_message_content_), std::move(promise)); +} + void Requests::on_request(uint64 id, td_api::editMessageSchedulingState &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Requests.h b/td/telegram/Requests.h index f0055044b..5c3948264 100644 --- a/td/telegram/Requests.h +++ b/td/telegram/Requests.h @@ -704,6 +704,8 @@ class Requests { void on_request(uint64 id, td_api::editInlineMessageReplyMarkup &request); + void on_request(uint64 id, td_api::editEphemeralMessage &request); + void on_request(uint64 id, td_api::editMessageSchedulingState &request); void on_request(uint64 id, td_api::setMessageFactCheck &request); -- cgit v1.2.3