diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 5a4abc1e7..1f4646ffd 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2579,7 +2579,8 @@ inputMessageDocument document:InputFile thumbnail:inputThumbnail disable_content //@height Photo height //@caption Photo caption; pass null to use an empty caption; 0-getOption("message_caption_length_max") characters //@ttl Photo TTL (Time To Live), in seconds (0-60). A non-zero TTL can be specified only in private chats -inputMessagePhoto photo:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector width:int32 height:int32 caption:formattedText ttl:int32 = InputMessageContent; +//@has_spoiler True, if the photo preview should be covered by spoiler animation +inputMessagePhoto photo:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector width:int32 height:int32 caption:formattedText ttl:int32 has_spoiler:Bool = InputMessageContent; //@description A sticker message //@sticker Sticker to be sent @@ -2599,7 +2600,8 @@ inputMessageSticker sticker:InputFile thumbnail:inputThumbnail width:int32 heigh //@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 //@ttl Video TTL (Time To Live), in seconds (0-60). A non-zero TTL can be specified only in private chats -inputMessageVideo video:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector duration:int32 width:int32 height:int32 supports_streaming:Bool caption:formattedText ttl:int32 = InputMessageContent; +//@has_spoiler True, if the video preview should be covered by spoiler animation +inputMessageVideo video:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector duration:int32 width:int32 height:int32 supports_streaming:Bool caption:formattedText ttl:int32 has_spoiler:Bool = InputMessageContent; //@description A video note message //@video_note Video note to be sent diff --git a/td/telegram/DocumentsManager.cpp b/td/telegram/DocumentsManager.cpp index 9da2fc010..1bedf80c7 100644 --- a/td/telegram/DocumentsManager.cpp +++ b/td/telegram/DocumentsManager.cpp @@ -673,7 +673,8 @@ tl_object_ptr DocumentsManager::get_input_media( if (input_thumbnail != nullptr) { flags |= telegram_api::inputMediaUploadedDocument::THUMB_MASK; } - if (file_view.get_type() == FileType::DocumentAsFile) { + auto file_type = file_view.get_type(); + if (file_type == FileType::DocumentAsFile) { flags |= telegram_api::inputMediaUploadedDocument::FORCE_FILE_MASK; } return make_tl_object( diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 2d6e9c12e..7bc719aea 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2193,8 +2193,8 @@ Result get_input_message_content( } case td_api::inputMessagePhoto::ID: { auto input_message = static_cast(input_message_content.get()); - r_file_id = - td->file_manager_->get_input_file_id(FileType::Photo, input_message->photo_, dialog_id, false, is_secret); + auto file_type = input_message->has_spoiler_ ? FileType::PhotoWithSpoiler : FileType::Photo; + r_file_id = td->file_manager_->get_input_file_id(file_type, input_message->photo_, dialog_id, false, is_secret); input_thumbnail = std::move(input_message->thumbnail_); if (!input_message->added_sticker_file_ids_.empty()) { sticker_file_ids = td->stickers_manager_->get_attached_sticker_file_ids(input_message->added_sticker_file_ids_); @@ -2210,8 +2210,8 @@ Result get_input_message_content( } case td_api::inputMessageVideo::ID: { auto input_message = static_cast(input_message_content.get()); - r_file_id = - td->file_manager_->get_input_file_id(FileType::Video, input_message->video_, dialog_id, false, is_secret); + auto file_type = input_message->has_spoiler_ ? FileType::VideoWithSpoiler : FileType::Video; + r_file_id = td->file_manager_->get_input_file_id(file_type, input_message->video_, dialog_id, false, is_secret); input_thumbnail = std::move(input_message->thumbnail_); if (!input_message->added_sticker_file_ids_.empty()) { sticker_file_ids = td->stickers_manager_->get_attached_sticker_file_ids(input_message->added_sticker_file_ids_); @@ -2638,9 +2638,12 @@ tl_object_ptr get_fake_input_media(Td *td, tl_object_p } string mime_type = MimeType::from_extension(path_view.extension()); int32 flags = 0; - if (file_type == FileType::Video) { + if (file_type == FileType::Video || file_type == FileType::VideoWithSpoiler) { flags |= telegram_api::inputMediaUploadedDocument::NOSOUND_VIDEO_MASK; } + if (file_type == FileType::VideoWithSpoiler) { + flags |= telegram_api::inputMediaUploadedDocument::SPOILER_MASK; + } if (file_type == FileType::DocumentAsFile) { flags |= telegram_api::inputMediaUploadedDocument::FORCE_FILE_MASK; } @@ -2648,9 +2651,13 @@ tl_object_ptr get_fake_input_media(Td *td, tl_object_p flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, std::move(input_file), nullptr, mime_type, std::move(attributes), vector>(), 0); } else { - CHECK(file_type == FileType::Photo); + CHECK(file_type == FileType::Photo || file_type == FileType::PhotoWithSpoiler); + int32 flags = 0; + if (file_type == FileType::PhotoWithSpoiler) { + flags |= telegram_api::inputMediaUploadedPhoto::SPOILER_MASK; + } return make_tl_object( - 0, false /*ignored*/, std::move(input_file), vector>(), 0); + flags, false /*ignored*/, std::move(input_file), vector>(), 0); } } @@ -3468,7 +3475,7 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo old_file_view.main_remote_location().get_access_hash() != new_file_view.remote_location().get_access_hash()) { FileId file_id = td->file_manager_->register_remote( - FullRemoteFileLocation(PhotoSizeSource::thumbnail(FileType::Photo, 'i'), + FullRemoteFileLocation(PhotoSizeSource::thumbnail(new_file_view.get_type(), 'i'), new_file_view.remote_location().get_id(), new_file_view.remote_location().get_access_hash(), DcId::invalid(), new_file_view.remote_location().get_file_reference().str()), diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 149ef10be..108ee5f61 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -9023,7 +9023,7 @@ void MessagesManager::report_dialog_photo(DialogId dialog_id, FileId file_id, Re if (file_view.empty()) { return promise.set_error(Status::Error(400, "Unknown file ID")); } - if (file_view.get_type() != FileType::Photo || !file_view.has_remote_location() || + if (get_main_file_type(file_view.get_type()) != FileType::Photo || !file_view.has_remote_location() || !file_view.remote_location().is_photo()) { return promise.set_error(Status::Error(400, "Only full chat photos can be reported")); } @@ -26512,7 +26512,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect if (content_type == MessageContentType::Game || content_type == MessageContentType::Poll) { return; } - if (file_view.get_type() == FileType::Photo) { + if (get_main_file_type(file_view.get_type()) == FileType::Photo) { thumbnail_file_id = FileId(); } diff --git a/td/telegram/Photo.cpp b/td/telegram/Photo.cpp index d562308c5..467429e0c 100644 --- a/td/telegram/Photo.cpp +++ b/td/telegram/Photo.cpp @@ -454,8 +454,13 @@ tl_object_ptr photo_get_input_media(FileManager *file_ if (ttl != 0) { flags |= telegram_api::inputMediaUploadedPhoto::TTL_SECONDS_MASK; } - if (ttl != 0) { - flags |= telegram_api::inputMediaUploadedPhoto::TTL_SECONDS_MASK; + + CHECK(!photo.photos.empty()); + auto file_id = photo.photos.back().file_id; + auto file_view = file_manager->get_file_view(file_id); + auto file_type = file_view.get_type(); + if (file_type == FileType::PhotoWithSpoiler) { + flags |= telegram_api::inputMediaUploadedPhoto::SPOILER_MASK; } return make_tl_object(flags, false /*ignored*/, std::move(input_file), diff --git a/td/telegram/VideosManager.cpp b/td/telegram/VideosManager.cpp index f3adbd7a8..529162499 100644 --- a/td/telegram/VideosManager.cpp +++ b/td/telegram/VideosManager.cpp @@ -8,6 +8,7 @@ #include "td/telegram/AuthManager.h" #include "td/telegram/files/FileManager.h" +#include "td/telegram/files/FileType.h" #include "td/telegram/Global.h" #include "td/telegram/PhotoFormat.h" #include "td/telegram/secret_api.h" @@ -279,6 +280,10 @@ tl_object_ptr VideosManager::get_input_media( if (input_thumbnail != nullptr) { flags |= telegram_api::inputMediaUploadedDocument::THUMB_MASK; } + auto file_type = file_view.get_type(); + if (file_type == FileType::VideoWithSpoiler) { + flags |= telegram_api::inputMediaUploadedDocument::SPOILER_MASK; + } return make_tl_object( flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, std::move(input_file), std::move(input_thumbnail), mime_type, std::move(attributes), std::move(added_stickers), ttl); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index e706416f8..978574ed1 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3684,8 +3684,8 @@ class CliClient final : public Actor { message = string(4097, 'a'); } if (op[3] == 'p') { - send_message(chat_id, td_api::make_object(as_local_file("rgb.jpg"), nullptr, - Auto(), 0, 0, as_caption(message), 0)); + send_message(chat_id, td_api::make_object( + as_local_file("rgb.jpg"), nullptr, Auto(), 0, 0, as_caption(message), 0, false)); } else { send_message(chat_id, td_api::make_object(as_formatted_text(message), false, true)); } @@ -3758,7 +3758,7 @@ class CliClient final : public Actor { } auto input_message_contents = transform(full_split(args), [](const string &photo) { td_api::object_ptr content = td_api::make_object( - as_input_file(photo), nullptr, Auto(), 0, 0, as_caption(""), 0); + as_input_file(photo), nullptr, Auto(), 0, 0, as_caption(""), 0, false); return content; }); send_request(td_api::make_object( @@ -3837,7 +3837,7 @@ 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(""), op == "empttl" ? 10 : 0))); + as_caption(""), op == "empttl" ? 10 : 0, false))); } else if (op == "emvt") { ChatId chat_id; MessageId message_id; @@ -3847,7 +3847,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(""), 0))); + 2, 3, true, as_caption(""), 0, false))); } else if (op == "emll") { ChatId chat_id; MessageId message_id; @@ -4161,7 +4161,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), op == "spttl" ? 10 : 0)); + as_caption(caption), op == "spttl" ? 10 : 0, false)); } else if (op == "spg" || op == "spgttl") { ChatId chat_id; string photo_path; @@ -4170,15 +4170,15 @@ 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(""), op == "spgttl" ? 10 : 0)); + 0, as_caption(""), op == "spgttl" ? 10 : 0, false)); } else if (op == "spt") { ChatId chat_id; string photo_path; string thumbnail_path; 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(""), 0)); + 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(""), 0, false)); } else if (op == "sptg") { ChatId chat_id; string photo_path; @@ -4188,7 +4188,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(""), 0)); + vector(), 0, 0, as_caption(""), 0, false)); } else if (op == "spgtg") { ChatId chat_id; string photo_path; @@ -4199,13 +4199,13 @@ 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(""), 0)); + as_caption(""), 0, false)); } 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(""), 0)); + send_message(chat_id, td_api::make_object( + as_input_file_id(file_id), nullptr, vector(), 0, 0, as_caption(""), 0, false)); } else if (op == "ss") { ChatId chat_id; string sticker_path; @@ -4237,9 +4237,9 @@ class CliClient final : public Actor { } else { sticker_file_ids = to_integers(sticker_file_ids_str); } - 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(""), op == "svttl" ? 10 : 0)); + 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(""), op == "svttl" ? 10 : 0, false)); } else if (op == "svt" || op == "svtttl") { ChatId chat_id; string video; @@ -4247,7 +4247,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(""), op == "svtttl" ? 10 : 0)); + as_caption(""), op == "svtttl" ? 10 : 0, false)); } else if (op == "svn") { ChatId chat_id; string video_path; diff --git a/td/telegram/files/FileDownloader.cpp b/td/telegram/files/FileDownloader.cpp index 433c5717b..5dc735617 100644 --- a/td/telegram/files/FileDownloader.cpp +++ b/td/telegram/files/FileDownloader.cpp @@ -109,12 +109,11 @@ Result FileDownloader::init() { res.ready_parts = bitmask.as_vector(); res.use_part_count_limit = false; res.only_check = only_check_; - auto file_type = remote_.file_type_; + auto file_type = get_main_file_type(remote_.file_type_); res.need_delay = - !is_small_ && - (file_type == FileType::VideoNote || file_type == FileType::Document || file_type == FileType::DocumentAsFile || - file_type == FileType::VoiceNote || file_type == FileType::Audio || file_type == FileType::Video || - file_type == FileType::Animation || (file_type == FileType::Encrypted && size_ > (1 << 20))); + !is_small_ && (file_type == FileType::VideoNote || file_type == FileType::Document || + file_type == FileType::VoiceNote || file_type == FileType::Audio || file_type == FileType::Video || + file_type == FileType::Animation || (file_type == FileType::Encrypted && size_ > (1 << 20))); res.offset = offset_; res.limit = limit_; return res; diff --git a/td/telegram/files/FileLoaderUtils.cpp b/td/telegram/files/FileLoaderUtils.cpp index 5e2e12d4c..dbb3f7970 100644 --- a/td/telegram/files/FileLoaderUtils.cpp +++ b/td/telegram/files/FileLoaderUtils.cpp @@ -332,7 +332,7 @@ Result check_full_local_location(FullLocalLocationInfo lo if (size > MAX_FILE_SIZE) { return get_file_size_error(""); } - if (location.file_type_ == FileType::Photo && size > MAX_PHOTO_SIZE) { + if (get_file_type_class(location.file_type_) == FileTypeClass::Photo && size > MAX_PHOTO_SIZE) { return get_file_size_error(" for a photo"); } if (location.file_type_ == FileType::VideoNote && diff --git a/td/telegram/files/FileLocation.h b/td/telegram/files/FileLocation.h index b553c54bc..fd3d48840 100644 --- a/td/telegram/files/FileLocation.h +++ b/td/telegram/files/FileLocation.h @@ -393,6 +393,7 @@ class FullRemoteFileLocation { auto &thumbnail = source.thumbnail(); switch (thumbnail.file_type) { case FileType::Photo: + case FileType::PhotoWithSpoiler: return make_tl_object( id, access_hash, BufferSlice(file_reference_), std::string(1, static_cast(static_cast(thumbnail.thumbnail_type)))); diff --git a/td/telegram/files/FileLocation.hpp b/td/telegram/files/FileLocation.hpp index 19e16976d..8709c1127 100644 --- a/td/telegram/files/FileLocation.hpp +++ b/td/telegram/files/FileLocation.hpp @@ -237,8 +237,8 @@ void FullRemoteFileLocation::parse(ParserT &parser) { break; case PhotoSizeSource::Type::Thumbnail: if (photo().source_.get_file_type("FullRemoteFileLocation::parse") != file_type_ || - (file_type_ != FileType::Photo && file_type_ != FileType::Thumbnail && - file_type_ != FileType::EncryptedThumbnail)) { + (file_type_ != FileType::Photo && file_type_ != FileType::PhotoWithSpoiler && + file_type_ != FileType::Thumbnail && file_type_ != FileType::EncryptedThumbnail)) { parser.set_error("Invalid FileType in PhotoRemoteFileLocation Thumbnail"); } break; diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index c28874437..eac8a4f85 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -861,6 +861,7 @@ string FileManager::get_file_name(FileType file_type, Slice path) { break; case FileType::ProfilePhoto: case FileType::Photo: + case FileType::PhotoWithSpoiler: if (extension != "jpg" && extension != "jpeg" && extension != "gif" && extension != "png" && extension != "tif" && extension != "bmp") { return fix_file_extension(file_name, "photo", "jpg"); @@ -873,6 +874,7 @@ string FileManager::get_file_name(FileType file_type, Slice path) { } break; case FileType::Video: + case FileType::VideoWithSpoiler: case FileType::VideoNote: if (extension != "mov" && extension != "3gp" && extension != "mpeg4" && extension != "mp4" && extension != "mkv") { @@ -902,13 +904,13 @@ string FileManager::get_file_name(FileType file_type, Slice path) { } break; case FileType::Document: + case FileType::DocumentAsFile: case FileType::Animation: case FileType::Encrypted: case FileType::Temp: case FileType::EncryptedThumbnail: case FileType::SecureEncrypted: case FileType::SecureDecrypted: - case FileType::DocumentAsFile: case FileType::CallLog: break; default: @@ -3278,7 +3280,8 @@ Result FileManager::get_input_file_id(FileType type, const tl_object_ptr return FileId(); } string hash; - if (G()->get_option_boolean("reuse_uploaded_photos_by_hash") && new_type == FileType::Photo) { + if (G()->get_option_boolean("reuse_uploaded_photos_by_hash") && + get_main_file_type(new_type) == FileType::Photo) { auto r_stat = stat(path); if (r_stat.is_ok() && r_stat.ok().size_ > 0 && r_stat.ok().size_ < 11000000) { auto r_file_content = read_file_str(path, r_stat.ok().size_); diff --git a/td/telegram/files/FileType.cpp b/td/telegram/files/FileType.cpp index a02224df7..f6ad3f1cc 100644 --- a/td/telegram/files/FileType.cpp +++ b/td/telegram/files/FileType.cpp @@ -93,6 +93,10 @@ tl_object_ptr get_file_type_object(FileType file_type) { return make_tl_object(); case FileType::CallLog: return make_tl_object(); + case FileType::PhotoWithSpoiler: + return make_tl_object(); + case FileType::VideoWithSpoiler: + return make_tl_object(); case FileType::None: return make_tl_object(); default: @@ -111,13 +115,17 @@ FileType get_main_file_type(FileType file_type) { return FileType::Document; case FileType::CallLog: return FileType::Document; + case FileType::PhotoWithSpoiler: + return FileType::Photo; + case FileType::VideoWithSpoiler: + return FileType::Video; default: return file_type; } } CSlice get_file_type_name(FileType file_type) { - switch (file_type) { + switch (get_main_file_type(file_type)) { case FileType::Thumbnail: return CSlice("thumbnails"); case FileType::ProfilePhoto: @@ -142,24 +150,14 @@ CSlice get_file_type_name(FileType file_type) { return CSlice("animations"); case FileType::EncryptedThumbnail: return CSlice("secret_thumbnails"); - case FileType::Wallpaper: - return CSlice("wallpapers"); case FileType::VideoNote: return CSlice("video_notes"); - case FileType::SecureDecrypted: - return CSlice("passport"); case FileType::SecureEncrypted: return CSlice("passport"); case FileType::Background: return CSlice("wallpapers"); - case FileType::DocumentAsFile: - return CSlice("documents"); case FileType::Ringtone: return CSlice("notification_sounds"); - case FileType::CallLog: - return CSlice("documents"); - case FileType::Size: - case FileType::None: default: UNREACHABLE(); return CSlice("none"); @@ -173,6 +171,7 @@ FileTypeClass get_file_type_class(FileType file_type) { case FileType::Thumbnail: case FileType::EncryptedThumbnail: case FileType::Wallpaper: + case FileType::PhotoWithSpoiler: return FileTypeClass::Photo; case FileType::Video: case FileType::VoiceNote: @@ -185,6 +184,7 @@ FileTypeClass get_file_type_class(FileType file_type) { case FileType::DocumentAsFile: case FileType::Ringtone: case FileType::CallLog: + case FileType::VideoWithSpoiler: return FileTypeClass::Document; case FileType::SecureDecrypted: case FileType::SecureEncrypted: @@ -247,6 +247,10 @@ StringBuilder &operator<<(StringBuilder &string_builder, FileType file_type) { return string_builder << "NotificationSound"; case FileType::CallLog: return string_builder << "CallLog"; + case FileType::PhotoWithSpoiler: + return string_builder << "PhotoWithSpoiler"; + case FileType::VideoWithSpoiler: + return string_builder << "VideoWithSpoiler"; case FileType::Size: case FileType::None: default: @@ -274,11 +278,10 @@ FileDirType get_file_dir_type(FileType file_type) { } bool is_file_big(FileType file_type, int64 expected_size) { + if (get_file_type_class(file_type) == FileTypeClass::Photo) { + return false; + } switch (file_type) { - case FileType::Thumbnail: - case FileType::ProfilePhoto: - case FileType::Photo: - case FileType::EncryptedThumbnail: case FileType::VideoNote: case FileType::Ringtone: case FileType::CallLog: diff --git a/td/telegram/files/FileType.h b/td/telegram/files/FileType.h index 5281c7901..8606e6507 100644 --- a/td/telegram/files/FileType.h +++ b/td/telegram/files/FileType.h @@ -35,6 +35,8 @@ enum class FileType : int32 { DocumentAsFile, Ringtone, CallLog, + PhotoWithSpoiler, + VideoWithSpoiler, Size, None };