Add td_api::animatedChatPhoto.

GitOrigin-RevId: 430f3b6bcb0bcfaffdcc6f26a4ee017518a64162
This commit is contained in:
levlam 2020-07-07 11:41:01 +03:00
parent fe01434b3d
commit 3fefdb6462
12 changed files with 106 additions and 49 deletions

View File

@ -344,13 +344,20 @@ botInfo description:string commands:vector<botCommand> = BotInfo;
chatLocation location:location address:string = ChatLocation;
//@description Animated variant of a chat photo in MPEG4 format
//@length Animation width and height
//@file Information about the animation file
//@main_frame_timestamp Timestamp of the frame, used as static chat photo
animatedChatPhoto length:int32 file:file main_frame_timestamp:double = AnimatedChatPhoto;
//@description Describes a chat or user profile photo
//@id Unique photo identifier
//@added_date Point in time (Unix timestamp) when the photo has been added
//@minithumbnail Photo minithumbnail; may be null
//@sizes Available variants of the photo in JPEG format, in different size
//@animation Animated variant of the photo in MPEG4 format; may be null
chatPhoto id:int64 added_date:int32 minithumbnail:minithumbnail sizes:vector<photoSize> animation:photoSize = ChatPhoto;
chatPhoto id:int64 added_date:int32 minithumbnail:minithumbnail sizes:vector<photoSize> animation:animatedChatPhoto = ChatPhoto;
//@description Contains a list of chat or user profile photos @total_count Total number of photos @photos List of photos
chatPhotos total_count:int32 photos:vector<chatPhoto> = ChatPhotos;

Binary file not shown.

View File

@ -263,7 +263,7 @@ void AnimationsManager::delete_animation_thumbnail(FileId file_id) {
auto &animation = animations_[file_id];
CHECK(animation != nullptr);
animation->thumbnail = PhotoSize();
animation->animated_thumbnail = PhotoSize();
animation->animated_thumbnail = AnimationSize();
}
FileId AnimationsManager::dup_animation(FileId new_id, FileId old_id) {
@ -320,7 +320,7 @@ bool AnimationsManager::merge_animations(FileId new_id, FileId old_id, bool can_
}
void AnimationsManager::create_animation(FileId file_id, string minithumbnail, PhotoSize thumbnail,
PhotoSize animated_thumbnail, bool has_stickers,
AnimationSize animated_thumbnail, bool has_stickers,
vector<FileId> &&sticker_file_ids, string file_name, string mime_type,
int32 duration, Dimensions dimensions, bool replace) {
auto a = make_unique<Animation>();

View File

@ -35,7 +35,7 @@ class AnimationsManager : public Actor {
tl_object_ptr<td_api::animation> get_animation_object(FileId file_id, const char *source);
void create_animation(FileId file_id, string minithumbnail, PhotoSize thumbnail, PhotoSize animated_thumbnail,
void create_animation(FileId file_id, string minithumbnail, PhotoSize thumbnail, AnimationSize animated_thumbnail,
bool has_stickers, vector<FileId> &&sticker_file_ids, string file_name, string mime_type,
int32 duration, Dimensions dimensions, bool replace);
@ -104,7 +104,7 @@ class AnimationsManager : public Actor {
Dimensions dimensions;
string minithumbnail;
PhotoSize thumbnail;
PhotoSize animated_thumbnail;
AnimationSize animated_thumbnail;
bool has_stickers = false;
vector<FileId> sticker_file_ids;

View File

@ -214,7 +214,7 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
string file_reference;
string minithumbnail;
PhotoSize thumbnail;
PhotoSize animated_thumbnail;
AnimationSize animated_thumbnail;
FileEncryptionKey encryption_key;
bool is_animated_sticker = false;
bool is_web = false;
@ -273,9 +273,8 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
}
for (auto &thumb : document->video_thumbs_) {
if (thumb->type_ == "v") {
animated_thumbnail =
get_video_photo_size(td_->file_manager_.get(), {FileType::Thumbnail, 0}, id, access_hash, file_reference,
DcId::create(dc_id), owner_dialog_id, std::move(thumb));
animated_thumbnail = get_animation_size(td_->file_manager_.get(), {FileType::Thumbnail, 0}, id, access_hash,
file_reference, DcId::create(dc_id), owner_dialog_id, std::move(thumb));
if (animated_thumbnail.file_id.is_valid()) {
break;
}
@ -310,7 +309,7 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
dc_id = 0;
access_hash = 0;
if (remote_document.thumbnail.type == 'v') {
animated_thumbnail = std::move(remote_document.thumbnail);
static_cast<PhotoSize &>(animated_thumbnail) = std::move(remote_document.thumbnail);
} else {
thumbnail = std::move(remote_document.thumbnail);
if (remote_document.thumbnail.type == 'g') {

View File

@ -1475,8 +1475,8 @@ static Result<InputMessageContent> create_input_message_content(
bool has_stickers = !sticker_file_ids.empty();
td->animations_manager_->create_animation(
file_id, string(), thumbnail, PhotoSize(), has_stickers, std::move(sticker_file_ids), std::move(file_name),
std::move(mime_type), input_animation->duration_,
file_id, string(), thumbnail, AnimationSize(), has_stickers, std::move(sticker_file_ids),
std::move(file_name), std::move(mime_type), input_animation->duration_,
get_dimensions(input_animation->width_, input_animation->height_), false);
content = make_unique<MessageAnimation>(file_id, std::move(caption));
@ -1579,9 +1579,9 @@ static Result<InputMessageContent> create_input_message_content(
bool has_stickers = !sticker_file_ids.empty();
td->videos_manager_->create_video(
file_id, string(), thumbnail, PhotoSize(), has_stickers, std::move(sticker_file_ids), std::move(file_name),
std::move(mime_type), input_video->duration_, get_dimensions(input_video->width_, input_video->height_),
input_video->supports_streaming_, false);
file_id, string(), thumbnail, AnimationSize(), has_stickers, std::move(sticker_file_ids),
std::move(file_name), std::move(mime_type), input_video->duration_,
get_dimensions(input_video->width_, input_video->height_), input_video->supports_streaming_, false);
content = make_unique<MessageVideo>(file_id, std::move(caption));
break;
@ -4707,7 +4707,7 @@ FileId get_message_content_thumbnail_file_id(const MessageContent *content, cons
return FileId();
}
FileId get_message_content_animated_thumbnail_file_id(const MessageContent *content, const Td *td) {
static FileId get_message_content_animated_thumbnail_file_id(const MessageContent *content, const Td *td) {
switch (content->get_type()) {
case MessageContentType::Animation:
return td->animations_manager_->get_animation_animated_thumbnail_file_id(

View File

@ -199,8 +199,6 @@ void update_message_content_file_id_remote(MessageContent *content, FileId file_
FileId get_message_content_thumbnail_file_id(const MessageContent *content, const Td *td);
FileId get_message_content_animated_thumbnail_file_id(const MessageContent *content, const Td *td);
vector<FileId> get_message_content_file_ids(const MessageContent *content, const Td *td);
string get_message_content_search_text(const Td *td, const MessageContent *content);

View File

@ -23,6 +23,7 @@
#include "td/utils/Random.h"
#include <algorithm>
#include <cmath>
#include <limits>
namespace td {
@ -279,7 +280,7 @@ DialogPhoto as_dialog_photo(const Photo &photo) {
result.big_file_id = size.file_id;
}
}
result.is_animated = !photo.animated_photos.empty();
result.is_animated = !photo.animations.empty();
if (!result.small_file_id.is_valid() || !result.big_file_id.is_valid()) {
LOG(ERROR) << "Failed to convert " << photo << " to chat photo";
return DialogPhoto();
@ -393,17 +394,20 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
return std::move(res);
}
PhotoSize get_video_photo_size(FileManager *file_manager, PhotoSizeSource source, int64 id, int64 access_hash,
std::string file_reference, DcId dc_id, DialogId owner_dialog_id,
tl_object_ptr<telegram_api::videoSize> &&size) {
AnimationSize get_animation_size(FileManager *file_manager, PhotoSizeSource source, int64 id, int64 access_hash,
std::string file_reference, DcId dc_id, DialogId owner_dialog_id,
tl_object_ptr<telegram_api::videoSize> &&size) {
CHECK(size != nullptr);
PhotoSize res;
AnimationSize res;
if (size->type_ != "v" && size->type_ != "u") {
LOG(ERROR) << "Wrong videoSize \"" << size->type_ << "\" in " << to_string(size);
}
res.type = static_cast<uint8>(size->type_[0]);
res.dimensions = get_dimensions(size->w_, size->h_);
res.size = size->size_;
if ((size->flags_ & telegram_api::videoSize::VIDEO_START_TS_MASK) != 0) {
res.main_frame_timestamp = size->video_start_ts_;
}
if (source.get_type() == PhotoSizeSource::Type::Thumbnail) {
source.thumbnail().thumbnail_type = res.type;
@ -572,6 +576,31 @@ StringBuilder &operator<<(StringBuilder &string_builder, const PhotoSize &photo_
<< ", size = " << photo_size.size << ", file_id = " << photo_size.file_id << "}";
}
static tl_object_ptr<td_api::animatedChatPhoto> get_animated_chat_photo_object(FileManager *file_manager,
const AnimationSize *animation_size) {
if (animation_size == nullptr || !animation_size->file_id.is_valid()) {
return nullptr;
}
return td_api::make_object<td_api::animatedChatPhoto>(animation_size->dimensions.width,
file_manager->get_file_object(animation_size->file_id),
animation_size->main_frame_timestamp);
}
bool operator==(const AnimationSize &lhs, const AnimationSize &rhs) {
return static_cast<const PhotoSize &>(lhs) == static_cast<const PhotoSize &>(rhs) &&
fabs(lhs.main_frame_timestamp - rhs.main_frame_timestamp) < 1e-3;
}
bool operator!=(const AnimationSize &lhs, const AnimationSize &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const AnimationSize &animation_size) {
return string_builder << static_cast<const PhotoSize &>(animation_size) << " from "
<< animation_size.main_frame_timestamp;
}
Photo get_encrypted_file_photo(FileManager *file_manager, tl_object_ptr<telegram_api::encryptedFile> &&file,
tl_object_ptr<secret_api::decryptedMessageMediaPhoto> &&photo,
DialogId owner_dialog_id) {
@ -639,9 +668,12 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
}
for (auto &size_ptr : photo->video_sizes_) {
res.animated_photos.push_back(get_video_photo_size(file_manager, {FileType::Photo, 0}, photo->id_,
photo->access_hash_, photo->file_reference_.as_slice().str(),
dc_id, owner_dialog_id, std::move(size_ptr)));
auto animation =
get_animation_size(file_manager, {FileType::Photo, 0}, photo->id_, photo->access_hash_,
photo->file_reference_.as_slice().str(), dc_id, owner_dialog_id, std::move(size_ptr));
if (animation.type != 0 && animation.dimensions.width == animation.dimensions.height) {
res.animations.push_back(std::move(animation));
}
}
return res;
@ -672,10 +704,10 @@ tl_object_ptr<td_api::chatPhoto> get_chat_photo_object(FileManager *file_manager
return nullptr;
}
const PhotoSize *animation = photo.animated_photos.empty() ? nullptr : &photo.animated_photos.back();
const AnimationSize *animation = photo.animations.empty() ? nullptr : &photo.animations.back();
return td_api::make_object<td_api::chatPhoto>(
photo.id.get(), photo.date, get_minithumbnail_object(photo.minithumbnail),
get_photo_sizes_object(file_manager, photo.photos), get_photo_size_object(file_manager, animation));
get_photo_sizes_object(file_manager, photo.photos), get_animated_chat_photo_object(file_manager, animation));
}
void photo_delete_thumbnail(Photo &photo) {
@ -814,15 +846,15 @@ SecretInputMedia photo_get_secret_input_media(FileManager *file_manager, const P
vector<FileId> photo_get_file_ids(const Photo &photo) {
auto result = transform(photo.photos, [](auto &size) { return size.file_id; });
if (!photo.animated_photos.empty()) {
if (!photo.animations.empty()) {
// photo file IDs must be first
append(result, transform(photo.animated_photos, [](auto &size) { return size.file_id; }));
append(result, transform(photo.animations, [](auto &size) { return size.file_id; }));
}
return result;
}
bool operator==(const Photo &lhs, const Photo &rhs) {
return lhs.id.get() == rhs.id.get() && lhs.photos == rhs.photos && lhs.animated_photos == rhs.animated_photos;
return lhs.id.get() == rhs.id.get() && lhs.photos == rhs.photos && lhs.animations == rhs.animations;
}
bool operator!=(const Photo &lhs, const Photo &rhs) {
@ -831,8 +863,8 @@ bool operator!=(const Photo &lhs, const Photo &rhs) {
StringBuilder &operator<<(StringBuilder &string_builder, const Photo &photo) {
string_builder << "[id = " << photo.id.get() << ", photos = " << format::as_array(photo.photos);
if (!photo.animated_photos.empty()) {
string_builder << ", animated photos = " << format::as_array(photo.animated_photos);
if (!photo.animations.empty()) {
string_builder << ", animations = " << format::as_array(photo.animations);
}
return string_builder << "]";
}

View File

@ -50,13 +50,17 @@ struct PhotoSize {
FileId file_id;
};
struct AnimationSize : public PhotoSize {
double main_frame_timestamp = 0.0;
};
struct Photo {
MovableValue<int64, -2> id;
int32 date = 0;
string minithumbnail;
vector<PhotoSize> photos;
vector<PhotoSize> animated_photos;
vector<AnimationSize> animations;
bool has_stickers = false;
vector<FileId> sticker_file_ids;
@ -107,9 +111,9 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
int64 access_hash, string file_reference, DcId dc_id,
DialogId owner_dialog_id, tl_object_ptr<telegram_api::PhotoSize> &&size_ptr,
PhotoFormat format);
PhotoSize get_video_photo_size(FileManager *file_manager, PhotoSizeSource source, int64 id, int64 access_hash,
string file_reference, DcId dc_id, DialogId owner_dialog_id,
tl_object_ptr<telegram_api::videoSize> &&size);
AnimationSize get_animation_size(FileManager *file_manager, PhotoSizeSource source, int64 id, int64 access_hash,
string file_reference, DcId dc_id, DialogId owner_dialog_id,
tl_object_ptr<telegram_api::videoSize> &&size);
PhotoSize get_web_document_photo_size(FileManager *file_manager, FileType file_type, DialogId owner_dialog_id,
tl_object_ptr<telegram_api::WebDocument> web_document_ptr);
td_api::object_ptr<td_api::thumbnail> get_thumbnail_object(FileManager *file_manager, const PhotoSize &photo_size,
@ -122,6 +126,11 @@ bool operator<(const PhotoSize &lhs, const PhotoSize &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const PhotoSize &photo_size);
bool operator==(const AnimationSize &lhs, const AnimationSize &rhs);
bool operator!=(const AnimationSize &lhs, const AnimationSize &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const AnimationSize &animation_size);
Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::Photo> &&photo, DialogId owner_dialog_id);
Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&photo, DialogId owner_dialog_id);
Photo get_encrypted_file_photo(FileManager *file_manager, tl_object_ptr<telegram_api::encryptedFile> &&file,

View File

@ -70,14 +70,26 @@ void parse(PhotoSize &photo_size, ParserT &parser) {
LOG(DEBUG) << "Parsed photo size " << photo_size;
}
template <class StorerT>
void store(const AnimationSize &animation_size, StorerT &storer) {
store(static_cast<const PhotoSize &>(animation_size), storer);
store(animation_size.main_frame_timestamp, storer);
}
template <class ParserT>
void parse(AnimationSize &animation_size, ParserT &parser) {
parse(static_cast<PhotoSize &>(animation_size), parser);
parse(animation_size.main_frame_timestamp, parser);
}
template <class StorerT>
void store(const Photo &photo, StorerT &storer) {
bool has_minithumbnail = !photo.minithumbnail.empty();
bool has_animated_photos = !photo.animated_photos.empty();
bool has_animations = !photo.animations.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(photo.has_stickers);
STORE_FLAG(has_minithumbnail);
STORE_FLAG(has_animated_photos);
STORE_FLAG(has_animations);
END_STORE_FLAGS();
store(photo.id.get(), storer);
store(photo.date, storer);
@ -88,19 +100,19 @@ void store(const Photo &photo, StorerT &storer) {
if (has_minithumbnail) {
store(photo.minithumbnail, storer);
}
if (has_animated_photos) {
store(photo.animated_photos, storer);
if (has_animations) {
store(photo.animations, storer);
}
}
template <class ParserT>
void parse(Photo &photo, ParserT &parser) {
bool has_minithumbnail;
bool has_animated_photos;
bool has_animations;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(photo.has_stickers);
PARSE_FLAG(has_minithumbnail);
PARSE_FLAG(has_animated_photos);
PARSE_FLAG(has_animations);
END_PARSE_FLAGS();
int64 id;
parse(id, parser);
@ -113,8 +125,8 @@ void parse(Photo &photo, ParserT &parser) {
if (has_minithumbnail) {
parse(photo.minithumbnail, parser);
}
if (has_animated_photos) {
parse(photo.animated_photos, parser);
if (has_animations) {
parse(photo.animations, parser);
}
}

View File

@ -135,7 +135,7 @@ void VideosManager::delete_video_thumbnail(FileId file_id) {
auto &video = videos_[file_id];
CHECK(video != nullptr);
video->thumbnail = PhotoSize();
video->animated_thumbnail = PhotoSize();
video->animated_thumbnail = AnimationSize();
}
FileId VideosManager::dup_video(FileId new_id, FileId old_id) {
@ -194,7 +194,7 @@ bool VideosManager::merge_videos(FileId new_id, FileId old_id, bool can_delete_o
}
void VideosManager::create_video(FileId file_id, string minithumbnail, PhotoSize thumbnail,
PhotoSize animated_thumbnail, bool has_stickers, vector<FileId> &&sticker_file_ids,
AnimationSize animated_thumbnail, bool has_stickers, vector<FileId> &&sticker_file_ids,
string file_name, string mime_type, int32 duration, Dimensions dimensions,
bool supports_streaming, bool replace) {
auto v = make_unique<Video>();

View File

@ -30,7 +30,7 @@ class VideosManager {
tl_object_ptr<td_api::video> get_video_object(FileId file_id);
void create_video(FileId file_id, string minithumbnail, PhotoSize thumbnail, PhotoSize animated_thumbnail,
void create_video(FileId file_id, string minithumbnail, PhotoSize thumbnail, AnimationSize animated_thumbnail,
bool has_stickers, vector<FileId> &&sticker_file_ids, string file_name, string mime_type,
int32 duration, Dimensions dimensions, bool supports_streaming, bool replace);
@ -70,7 +70,7 @@ class VideosManager {
Dimensions dimensions;
string minithumbnail;
PhotoSize thumbnail;
PhotoSize animated_thumbnail;
AnimationSize animated_thumbnail;
bool supports_streaming = false;