Support sending of photos and videos with spoiler animation.

This commit is contained in:
levlam 2022-12-15 22:41:55 +03:00
parent ab349e1562
commit 02db4f2fac
14 changed files with 86 additions and 58 deletions

View File

@ -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<int32> 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<int32> 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<int32> 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<int32> 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

View File

@ -673,7 +673,8 @@ tl_object_ptr<telegram_api::InputMedia> 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<telegram_api::inputMediaUploadedDocument>(

View File

@ -2193,8 +2193,8 @@ Result<InputMessageContent> get_input_message_content(
}
case td_api::inputMessagePhoto::ID: {
auto input_message = static_cast<td_api::inputMessagePhoto *>(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<InputMessageContent> get_input_message_content(
}
case td_api::inputMessageVideo::ID: {
auto input_message = static_cast<td_api::inputMessageVideo *>(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<telegram_api::InputMedia> 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<telegram_api::InputMedia> 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<tl_object_ptr<telegram_api::InputDocument>>(), 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<telegram_api::inputMediaUploadedPhoto>(
0, false /*ignored*/, std::move(input_file), vector<tl_object_ptr<telegram_api::InputDocument>>(), 0);
flags, false /*ignored*/, std::move(input_file), vector<tl_object_ptr<telegram_api::InputDocument>>(), 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()),

View File

@ -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();
}

View File

@ -454,8 +454,13 @@ tl_object_ptr<telegram_api::InputMedia> 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<telegram_api::inputMediaUploadedPhoto>(flags, false /*ignored*/, std::move(input_file),

View File

@ -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<telegram_api::InputMedia> 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<telegram_api::inputMediaUploadedDocument>(
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);

View File

@ -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<td_api::inputMessagePhoto>(as_local_file("rgb.jpg"), nullptr,
Auto(), 0, 0, as_caption(message), 0));
send_message(chat_id, td_api::make_object<td_api::inputMessagePhoto>(
as_local_file("rgb.jpg"), nullptr, Auto(), 0, 0, as_caption(message), 0, false));
} else {
send_message(chat_id, td_api::make_object<td_api::inputMessageText>(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<td_api::InputMessageContent> content = td_api::make_object<td_api::inputMessagePhoto>(
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<td_api::sendMessageAlbum>(
@ -3837,7 +3837,7 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::editMessageMedia>(
chat_id, message_id, nullptr,
td_api::make_object<td_api::inputMessagePhoto>(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<td_api::editMessageMedia>(
chat_id, message_id, nullptr,
td_api::make_object<td_api::inputMessageVideo>(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<td_api::inputMessagePhoto>(
as_input_file(photo), nullptr, to_integers<int32>(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<td_api::inputMessagePhoto>(
as_generated_file(photo_path, conversion, expected_size), nullptr, vector<int32>(), 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<td_api::inputMessagePhoto>(as_input_file(photo_path),
as_input_thumbnail(thumbnail_path, 90, 89),
vector<int32>(), 0, 0, as_caption(""), 0));
send_message(chat_id, td_api::make_object<td_api::inputMessagePhoto>(
as_input_file(photo_path), as_input_thumbnail(thumbnail_path, 90, 89), vector<int32>(),
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<td_api::inputMessagePhoto>(
as_input_file(photo_path), as_input_thumbnail(thumbnail_path, thumbnail_conversion, 90, 89),
vector<int32>(), 0, 0, as_caption(""), 0));
vector<int32>(), 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<td_api::inputMessagePhoto>(
as_generated_file(photo_path, conversion),
as_input_thumbnail(thumbnail_path, thumbnail_conversion, 90, 89), vector<int32>(), 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<td_api::inputMessagePhoto>(as_input_file_id(file_id), nullptr,
vector<int32>(), 0, 0, as_caption(""), 0));
send_message(chat_id, td_api::make_object<td_api::inputMessagePhoto>(
as_input_file_id(file_id), nullptr, vector<int32>(), 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<int32>(sticker_file_ids_str);
}
send_message(chat_id, td_api::make_object<td_api::inputMessageVideo>(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<td_api::inputMessageVideo>(
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<td_api::inputMessageVideo>(
as_input_file(video), as_input_thumbnail(thumbnail), vector<int32>(), 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;

View File

@ -109,12 +109,11 @@ Result<FileLoader::FileInfo> 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;

View File

@ -332,7 +332,7 @@ Result<FullLocalLocationInfo> 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 &&

View File

@ -393,6 +393,7 @@ class FullRemoteFileLocation {
auto &thumbnail = source.thumbnail();
switch (thumbnail.file_type) {
case FileType::Photo:
case FileType::PhotoWithSpoiler:
return make_tl_object<telegram_api::inputPhotoFileLocation>(
id, access_hash, BufferSlice(file_reference_),
std::string(1, static_cast<char>(static_cast<uint8>(thumbnail.thumbnail_type))));

View File

@ -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;

View File

@ -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<FileId> 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_);

View File

@ -93,6 +93,10 @@ tl_object_ptr<td_api::FileType> get_file_type_object(FileType file_type) {
return make_tl_object<td_api::fileTypeNotificationSound>();
case FileType::CallLog:
return make_tl_object<td_api::fileTypeDocument>();
case FileType::PhotoWithSpoiler:
return make_tl_object<td_api::fileTypePhoto>();
case FileType::VideoWithSpoiler:
return make_tl_object<td_api::fileTypeVideo>();
case FileType::None:
return make_tl_object<td_api::fileTypeNone>();
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:

View File

@ -35,6 +35,8 @@ enum class FileType : int32 {
DocumentAsFile,
Ringtone,
CallLog,
PhotoWithSpoiler,
VideoWithSpoiler,
Size,
None
};