From 5ebbda1c26e122c9e4c9a14d00927fd16e3698b5 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 6 Sep 2023 21:27:45 +0300 Subject: [PATCH] Add td_api::MessageSelfDestructType. --- td/generate/scheme/td_api.tl | 26 ++++++++++++++------- td/telegram/MessageContent.cpp | 31 ++++++++++++++++++------- td/telegram/MessagesManager.cpp | 19 +++++++++++---- td/telegram/cli.cpp | 41 +++++++++++++++++++++------------ 4 files changed, 81 insertions(+), 36 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index ffaaa7c29..e59e582ba 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1176,16 +1176,16 @@ messageReplyToStory story_sender_chat_id:int53 story_id:int32 = MessageReplyTo; //@unread_reactions Information about unread reactions added to the message //@reply_to Information about the message or the story this message is replying to; may be null if none //@message_thread_id If non-zero, the identifier of the message thread the message belongs to; unique within the chat to which the message belongs -//@self_destruct_time The message's self-destruct time, in seconds; 0 if none. TDLib will send updateDeleteMessages or updateMessageContent once the time expires -//@self_destruct_in Time left before the message self-destruct timer expires, in seconds. If the self-destruct timer isn't started yet, equals to the value of the self_destruct_time field -//@auto_delete_in Time left before the message will be automatically deleted by message_auto_delete_time setting of the chat, in seconds; 0 if never. TDLib will send updateDeleteMessages or updateMessageContent once the time expires +//@self_destruct_type The message's self-destruct type; may be null if none +//@self_destruct_in Time left before the message self-destruct timer expires, in seconds; 0 if self-desctruction isn't scheduled yet +//@auto_delete_in Time left before the message will be automatically deleted by message_auto_delete_time setting of the chat, in seconds; 0 if never //@via_bot_user_id If non-zero, the user identifier of the bot through which this message was sent //@author_signature For channel posts and anonymous group messages, optional author signature //@media_album_id Unique identifier of an album this message belongs to. Only audios, documents, photos and videos can be grouped together in albums //@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted //@content Content of the message //@reply_markup Reply markup for the message; may be null if none -message id:int53 sender_id:MessageSender chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool is_pinned:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_saved:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_added_reactions:Bool can_get_statistics:Bool can_get_message_thread:Bool can_get_viewers:Bool can_get_media_timestamp_links:Bool can_report_reactions:Bool has_timestamped_media:Bool is_channel_post:Bool is_topic_message:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo unread_reactions:vector reply_to:MessageReplyTo message_thread_id:int53 self_destruct_time:int32 self_destruct_in:double auto_delete_in:double via_bot_user_id:int53 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; +message id:int53 sender_id:MessageSender chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool is_pinned:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_saved:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_added_reactions:Bool can_get_statistics:Bool can_get_message_thread:Bool can_get_viewers:Bool can_get_media_timestamp_links:Bool can_report_reactions:Bool has_timestamped_media:Bool is_channel_post:Bool is_topic_message:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo unread_reactions:vector reply_to:MessageReplyTo message_thread_id:int53 self_destruct_type:MessageSelfDestructType self_destruct_in:double auto_delete_in:double via_bot_user_id:int53 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message; //@description Contains a list of messages @total_count Approximate total number of messages found @messages List of messages; messages may be null messages total_count:int32 messages:vector = Messages; @@ -2807,6 +2807,15 @@ messageSchedulingStateSendAtDate send_date:int32 = MessageSchedulingState; messageSchedulingStateSendWhenOnline = MessageSchedulingState; +//@class MessageSelfDestructType @description Describes when a message will be self-destructed + +//@description The message will be self-destructed in the specified time after its content was opened @self_destruct_time The message's self-destruct time, in seconds; must be between 0 and 60 in private chats +messageSelfDestructTypeTimer self_destruct_time:int32 = MessageSelfDestructType; + +//@description The message can be opened only once and will be self-destructed once closed +messageSelfDestructTypeImmediately = MessageSelfDestructType; + + //@description Options to be used when a message is sent //@disable_notification Pass true to disable notification for the message //@from_background Pass true if the message is sent from the background @@ -2865,9 +2874,10 @@ inputMessageDocument document:InputFile thumbnail:inputThumbnail disable_content //@width Photo width //@height Photo height //@caption Photo caption; pass null to use an empty caption; 0-getOption("message_caption_length_max") characters -//@self_destruct_time Photo self-destruct time, in seconds (0-60). A non-zero self-destruct time can be specified only in private chats +//@self_destruct_type Photo self-destruct type; pass null if none; private chats only //@has_spoiler True, if the photo preview must be covered by a spoiler animation; not supported in secret chats -inputMessagePhoto photo:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector width:int32 height:int32 caption:formattedText self_destruct_time:int32 has_spoiler:Bool = InputMessageContent; +inputMessagePhoto photo:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector width:int32 height:int32 caption:formattedText self_destruct_type:MessageSelfDestructType has_spoiler:Bool = InputMessageContent; + //@description A sticker message //@sticker Sticker to be sent @@ -2886,9 +2896,9 @@ inputMessageSticker sticker:InputFile thumbnail:inputThumbnail width:int32 heigh //@height Video height //@supports_streaming True, if the video is supposed to be streamed //@caption Video caption; pass null to use an empty caption; 0-getOption("message_caption_length_max") characters -//@self_destruct_time Video self-destruct time, in seconds (0-60). A non-zero self-destruct time can be specified only in private chats +//@self_destruct_type Video self-destruct type; pass null if none; private chats only //@has_spoiler True, if the video preview must be covered by a spoiler animation; not supported in secret chats -inputMessageVideo video:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector duration:int32 width:int32 height:int32 supports_streaming:Bool caption:formattedText self_destruct_time:int32 has_spoiler:Bool = InputMessageContent; +inputMessageVideo video:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector duration:int32 width:int32 height:int32 supports_streaming:Bool caption:formattedText self_destruct_type:MessageSelfDestructType has_spoiler:Bool = InputMessageContent; //@description A video note message //@video_note Video note to be sent diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 91345101f..26613a4a8 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2049,7 +2049,7 @@ static Result create_input_message_content( bool clear_draft = false; unique_ptr content; UserId via_bot_user_id; - int32 ttl = 0; + td_api::object_ptr self_destruct_type; string emoji; bool is_bot = td->auth_manager_->is_bot(); bool is_secret = dialog_id.get_type() == DialogType::SecretChat; @@ -2122,7 +2122,7 @@ static Result create_input_message_content( case td_api::inputMessagePhoto::ID: { auto input_photo = static_cast(input_message_content.get()); - ttl = input_photo->self_destruct_time_; + self_destruct_type = std::move(input_photo->self_destruct_type_); TRY_RESULT(photo, create_photo(td->file_manager_.get(), file_id, std::move(thumbnail), input_photo->width_, input_photo->height_, std::move(sticker_file_ids))); @@ -2146,7 +2146,7 @@ static Result create_input_message_content( case td_api::inputMessageVideo::ID: { auto input_video = static_cast(input_message_content.get()); - ttl = input_video->self_destruct_time_; + self_destruct_type = std::move(input_video->self_destruct_type_); bool has_stickers = !sticker_file_ids.empty(); td->videos_manager_->create_video(file_id, string(), thumbnail, AnimationSize(), has_stickers, @@ -2319,12 +2319,27 @@ static Result create_input_message_content( UNREACHABLE(); } - static constexpr int32 MAX_PRIVATE_MESSAGE_TTL = 60; // server side limit - if (ttl < 0 || (ttl > MAX_PRIVATE_MESSAGE_TTL && ttl != 0x7FFFFFFF)) { - return Status::Error(400, "Invalid message content self-destruct time specified"); + if (self_destruct_type != nullptr && dialog_id.get_type() != DialogType::User) { + return Status::Error(400, "Messages can self-destruct only in can be specified only in private chats"); } - if (ttl > 0 && dialog_id.get_type() != DialogType::User) { - return Status::Error(400, "Message content self-destruct time can be specified only in private chats"); + int32 ttl = 0; + if (self_destruct_type != nullptr) { + switch (self_destruct_type->get_id()) { + case td_api::messageSelfDestructTypeTimer::ID: { + ttl = static_cast(self_destruct_type.get())->self_destruct_time_; + + static constexpr int32 MAX_PRIVATE_MESSAGE_TTL = 60; // server side limit + if (ttl <= 0 || ttl > MAX_PRIVATE_MESSAGE_TTL) { + return Status::Error(400, "Invalid message content self-destruct time specified"); + } + break; + } + case td_api::messageSelfDestructTypeImmediately::ID: + ttl = 0x7FFFFFFF; + break; + default: + UNREACHABLE(); + } } return InputMessageContent{std::move(content), disable_web_page_preview, clear_draft, ttl, diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 1848350d4..baafe2211 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -24144,7 +24144,7 @@ td_api::object_ptr MessagesManager::get_dialog_event_log_messag m->message_id.get(), std::move(sender), get_chat_id_object(dialog_id, "get_dialog_event_log_message_object"), nullptr, nullptr, m->is_outgoing, false, false, false, can_be_saved, false, false, false, false, false, false, false, false, true, m->is_channel_post, m->is_topic_message, false, m->date, edit_date, std::move(forward_info), - std::move(interaction_info), Auto(), nullptr, 0, 0, 0.0, 0.0, via_bot_user_id, m->author_signature, 0, + std::move(interaction_info), Auto(), nullptr, 0, nullptr, 0.0, 0.0, via_bot_user_id, m->author_signature, 0, get_restriction_reason_description(m->restriction_reasons), std::move(content), std::move(reply_markup)); } @@ -24199,7 +24199,7 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial (!forward_info->from_dialog_id.is_valid() && !is_forward_info_sender_hidden(forward_info)); } - double ttl_expires_in = m->ttl_expires_at != 0 ? clamp(m->ttl_expires_at - Time::now(), 1e-3, m->ttl - 1e-3) : m->ttl; + double ttl_expires_in = m->ttl_expires_at != 0 ? clamp(m->ttl_expires_at - Time::now(), 1e-3, m->ttl - 1e-3) : 0.0; double auto_delete_in = m->ttl_period == 0 ? 0.0 : clamp(m->date + m->ttl_period - G()->server_time(), 1e-3, m->ttl_period - 1e-3); auto sender = get_message_sender_object_const(td_, m->sender_user_id, m->sender_dialog_id, source); @@ -24245,6 +24245,15 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial auto max_media_timestamp = get_message_max_media_timestamp(m); auto content = get_message_content_object(m->content.get(), td_, dialog_id, live_location_date, m->is_content_secret, skip_bot_commands, max_media_timestamp); + auto self_destruct_type = [&]() -> td_api::object_ptr { + if (m->ttl == 0x7FFFFFFF) { + return td_api::make_object(); + } + if (m->ttl > 0) { + return td_api::make_object(m->ttl); + } + return nullptr; + }(); return td_api::make_object( m->message_id.get(), std::move(sender), get_chat_id_object(dialog_id, "get_message_object"), @@ -24253,9 +24262,9 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial can_get_message_thread, can_get_viewers, can_get_media_timestamp_links, can_report_reactions, has_timestamped_media, m->is_channel_post, m->is_topic_message, m->contains_unread_mention, date, edit_date, std::move(forward_info), std::move(interaction_info), std::move(unread_reactions), std::move(reply_to), - top_thread_message_id, m->ttl, ttl_expires_in, auto_delete_in, via_bot_user_id, m->author_signature, - m->media_album_id, get_restriction_reason_description(m->restriction_reasons), std::move(content), - std::move(reply_markup)); + top_thread_message_id, std::move(self_destruct_type), ttl_expires_in, auto_delete_in, via_bot_user_id, + m->author_signature, m->media_album_id, get_restriction_reason_description(m->restriction_reasons), + std::move(content), std::move(reply_markup)); } tl_object_ptr MessagesManager::get_messages_object(int32 total_count, DialogId dialog_id, diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index d63eecb31..ab6f9729a 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2093,6 +2093,16 @@ class CliClient final : public Actor { true, true, -1, 5, 3, "abacaba"); } + td_api::object_ptr get_message_self_destruct_type() const { + if (message_self_destruct_time_ == -1) { + return td_api::make_object(); + } + if (message_self_destruct_time_ > 0) { + return td_api::make_object(message_self_destruct_time_); + } + return nullptr; + } + static td_api::object_ptr as_message_scheduling_state(Slice date) { date = trim(date); if (date.empty()) { @@ -4297,7 +4307,7 @@ class CliClient final : public Actor { if (op[3] == 'p') { send_message(chat_id, td_api::make_object( as_local_file("rgb.jpg"), nullptr, Auto(), 0, 0, as_caption(message), - message_self_destruct_time_, has_spoiler_)); + get_message_self_destruct_type(), has_spoiler_)); } else { send_message(chat_id, td_api::make_object(as_formatted_text(message), false, true)); } @@ -4373,8 +4383,8 @@ class CliClient final : public Actor { } auto input_message_contents = transform(full_split(args), [this](const string &photo) { td_api::object_ptr content = td_api::make_object( - as_input_file(photo), nullptr, Auto(), 0, 0, as_caption(""), rand_bool() ? message_self_destruct_time_ : 0, - has_spoiler_ && rand_bool()); + as_input_file(photo), nullptr, Auto(), 0, 0, as_caption(""), + rand_bool() ? get_message_self_destruct_type() : nullptr, has_spoiler_ && rand_bool()); return content; }); send_request(td_api::make_object( @@ -4453,7 +4463,8 @@ class CliClient final : public Actor { send_request(td_api::make_object( chat_id, message_id, nullptr, td_api::make_object(as_input_file(photo), as_input_thumbnail(photo), Auto(), 0, 0, - as_caption(""), message_self_destruct_time_, has_spoiler_))); + as_caption(""), get_message_self_destruct_type(), + has_spoiler_))); } else if (op == "emvt") { ChatId chat_id; MessageId message_id; @@ -4463,7 +4474,7 @@ class CliClient final : public Actor { send_request(td_api::make_object( chat_id, message_id, nullptr, td_api::make_object(as_input_file(video), as_input_thumbnail(thumbnail), Auto(), 1, - 2, 3, true, as_caption(""), message_self_destruct_time_, + 2, 3, true, as_caption(""), get_message_self_destruct_type(), has_spoiler_))); } else if (op == "emll") { ChatId chat_id; @@ -4792,7 +4803,7 @@ class CliClient final : public Actor { get_args(args, chat_id, photo, caption, sticker_file_ids); send_message(chat_id, td_api::make_object( as_input_file(photo), nullptr, to_integers(sticker_file_ids), 0, 0, - as_caption(caption), message_self_destruct_time_, has_spoiler_)); + as_caption(caption), get_message_self_destruct_type(), has_spoiler_)); } else if (op == "spg") { ChatId chat_id; string photo_path; @@ -4801,7 +4812,7 @@ class CliClient final : public Actor { get_args(args, chat_id, photo_path, conversion, expected_size); send_message(chat_id, td_api::make_object( as_generated_file(photo_path, conversion, expected_size), nullptr, vector(), 0, - 0, as_caption(""), message_self_destruct_time_, has_spoiler_)); + 0, as_caption(""), get_message_self_destruct_type(), has_spoiler_)); } else if (op == "spt") { ChatId chat_id; string photo_path; @@ -4809,7 +4820,7 @@ class CliClient final : public Actor { get_args(args, chat_id, photo_path, thumbnail_path); send_message(chat_id, td_api::make_object( as_input_file(photo_path), as_input_thumbnail(thumbnail_path, 90, 89), vector(), - 0, 0, as_caption(""), message_self_destruct_time_, has_spoiler_)); + 0, 0, as_caption(""), get_message_self_destruct_type(), has_spoiler_)); } else if (op == "sptg") { ChatId chat_id; string photo_path; @@ -4819,7 +4830,7 @@ class CliClient final : public Actor { send_message(chat_id, td_api::make_object( as_input_file(photo_path), as_input_thumbnail(thumbnail_path, thumbnail_conversion, 90, 89), - vector(), 0, 0, as_caption(""), message_self_destruct_time_, has_spoiler_)); + vector(), 0, 0, as_caption(""), get_message_self_destruct_type(), has_spoiler_)); } else if (op == "spgtg") { ChatId chat_id; string photo_path; @@ -4830,14 +4841,14 @@ class CliClient final : public Actor { send_message(chat_id, td_api::make_object( as_generated_file(photo_path, conversion), as_input_thumbnail(thumbnail_path, thumbnail_conversion, 90, 89), vector(), 0, 0, - as_caption(""), message_self_destruct_time_, has_spoiler_)); + as_caption(""), get_message_self_destruct_type(), has_spoiler_)); } else if (op == "spid") { ChatId chat_id; string file_id; get_args(args, chat_id, file_id); - send_message(chat_id, td_api::make_object(as_input_file_id(file_id), nullptr, - vector(), 0, 0, as_caption(""), - message_self_destruct_time_, has_spoiler_)); + send_message(chat_id, td_api::make_object( + as_input_file_id(file_id), nullptr, vector(), 0, 0, as_caption(""), + get_message_self_destruct_type(), has_spoiler_)); } else if (op == "ss") { ChatId chat_id; string sticker_path; @@ -4877,7 +4888,7 @@ class CliClient final : public Actor { } send_message(chat_id, td_api::make_object( as_input_file(video_path), nullptr, std::move(sticker_file_ids), 1, 2, 3, true, - as_caption(""), message_self_destruct_time_, has_spoiler_)); + as_caption(""), get_message_self_destruct_type(), has_spoiler_)); } else if (op == "svt") { ChatId chat_id; string video; @@ -4885,7 +4896,7 @@ class CliClient final : public Actor { get_args(args, chat_id, video, thumbnail); send_message(chat_id, td_api::make_object( as_input_file(video), as_input_thumbnail(thumbnail), vector(), 0, 0, 0, true, - as_caption(""), message_self_destruct_time_, has_spoiler_)); + as_caption(""), get_message_self_destruct_type(), has_spoiler_)); } else if (op == "svn") { ChatId chat_id; string video_path;