Support CustomEmojiSize.

This commit is contained in:
levlam 2023-01-18 22:25:25 +03:00
parent 3f7148407c
commit 68e939985f
8 changed files with 155 additions and 40 deletions

View File

@ -527,6 +527,11 @@ botMenuButton text:string url:string = BotMenuButton;
chatLocation location:location address:string = ChatLocation;
//@description Information about the custom emoji, which was used to create the chat photo
//@custom_emoji_id Identifier of the custom emoji
//@background_fill Describes a fill of the background under the custom emoji; rotation angle in backgroundFillGradient isn't supported
chatPhotoCustomEmoji custom_emoji_id:int64 background_fill:BackgroundFill = ChatPhotoCustomEmoji;
//@description Animated variant of a chat photo in MPEG4 format
//@length Animation width and height
//@file Information about the animation file
@ -541,7 +546,8 @@ animatedChatPhoto length:int32 file:file main_frame_timestamp:double = AnimatedC
//@sizes Available variants of the photo in JPEG format, in different size
//@animation A big (640x640) animated variant of the photo in MPEG4 format; may be null
//@small_animation A small (160x160) animated variant of the photo in MPEG4 format; may be null even the big animation is available
chatPhoto id:int64 added_date:int32 minithumbnail:minithumbnail sizes:vector<photoSize> animation:animatedChatPhoto small_animation:animatedChatPhoto = ChatPhoto;
//@custom_emoji Custom-emoji-based version of the chat photo; may be null
chatPhoto id:int64 added_date:int32 minithumbnail:minithumbnail sizes:vector<photoSize> animation:animatedChatPhoto small_animation:animatedChatPhoto custom_emoji:chatPhotoCustomEmoji = 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;

View File

@ -339,9 +339,14 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
auto thumb = move_tl_object_as<telegram_api::videoSize>(thumb_ptr);
if (thumb->type_ == "v") {
if (!animated_thumbnail.file_id.is_valid()) {
animated_thumbnail =
auto animation_size =
get_animation_size(td_->file_manager_.get(), PhotoSizeSource::thumbnail(FileType::Thumbnail, 0), id,
access_hash, file_reference, DcId::create(dc_id), owner_dialog_id, std::move(thumb));
if (animation_size.get_offset() == 0) {
animated_thumbnail = std::move(animation_size.get<0>());
} else {
CHECK(animation_size.get_offset() == -1);
}
}
} else if (thumb->type_ == "f") {
if (!premium_animation_file_id.is_valid()) {

View File

@ -19,6 +19,7 @@
#include "td/utils/common.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/overloaded.h"
#include "td/utils/SliceBuilder.h"
#include <algorithm>
@ -264,6 +265,31 @@ static tl_object_ptr<td_api::animatedChatPhoto> get_animated_chat_photo_object(F
animation_size->main_frame_timestamp);
}
static tl_object_ptr<td_api::chatPhotoCustomEmoji> get_chat_photo_custom_emoji_object(
const CustomEmojiSize &custom_emoji_size) {
if (!custom_emoji_size.custom_emoji_id.is_valid()) {
return nullptr;
}
auto background_fill = [&](vector<int32> colors) -> td_api::object_ptr<td_api::BackgroundFill> {
switch (colors.size()) {
case 1:
return td_api::make_object<td_api::backgroundFillSolid>(colors[0]);
case 2:
return td_api::make_object<td_api::backgroundFillGradient>(colors[0], colors[1], 0);
case 3:
case 4:
return td_api::make_object<td_api::backgroundFillFreeformGradient>(std::move(colors));
default:
UNREACHABLE();
return nullptr;
}
}(custom_emoji_size.background_colors);
return td_api::make_object<td_api::chatPhotoCustomEmoji>(custom_emoji_size.custom_emoji_id.get(),
std::move(background_fill));
}
Photo get_encrypted_file_photo(FileManager *file_manager, unique_ptr<EncryptedFile> &&file,
tl_object_ptr<secret_api::decryptedMessageMediaPhoto> &&photo,
DialogId owner_dialog_id) {
@ -335,9 +361,16 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
auto animation = get_animation_size(file_manager, PhotoSizeSource::thumbnail(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));
if (animation.empty()) {
continue;
}
animation.visit(overloaded(
[&](const AnimationSize &animation_size) {
if (animation_size.type != 0 && animation_size.dimensions.width == animation_size.dimensions.height) {
res.animations.push_back(std::move(animation_size));
}
},
[&](const CustomEmojiSize &custom_emoji_size) { res.custom_emoji_size = std::move(custom_emoji_size); }));
}
return res;
@ -384,7 +417,8 @@ tl_object_ptr<td_api::chatPhoto> get_chat_photo_object(FileManager *file_manager
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_animated_chat_photo_object(file_manager, big_animation),
get_animated_chat_photo_object(file_manager, small_animation));
get_animated_chat_photo_object(file_manager, small_animation),
get_chat_photo_custom_emoji_object(photo.custom_emoji_size));
}
void photo_delete_thumbnail(Photo &photo) {
@ -572,7 +606,8 @@ FileId get_photo_thumbnail_file_id(const Photo &photo) {
}
bool operator==(const Photo &lhs, const Photo &rhs) {
return lhs.id.get() == rhs.id.get() && lhs.photos == rhs.photos && lhs.animations == rhs.animations;
return lhs.id.get() == rhs.id.get() && lhs.photos == rhs.photos && lhs.animations == rhs.animations &&
lhs.custom_emoji_size == rhs.custom_emoji_size;
}
bool operator!=(const Photo &lhs, const Photo &rhs) {
@ -584,6 +619,9 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Photo &photo) {
if (!photo.animations.empty()) {
string_builder << ", animations = " << format::as_array(photo.animations);
}
if (photo.custom_emoji_size.custom_emoji_id.is_valid()) {
string_builder << ", custom emoji size = " << photo.custom_emoji_size;
}
return string_builder << ']';
}

View File

@ -45,6 +45,8 @@ struct Photo {
vector<AnimationSize> animations;
CustomEmojiSize custom_emoji_size;
bool has_stickers = false;
vector<FileId> sticker_file_ids;

View File

@ -71,10 +71,12 @@ template <class StorerT>
void store(const Photo &photo, StorerT &storer) {
bool has_minithumbnail = !photo.minithumbnail.empty();
bool has_animations = !photo.animations.empty();
bool has_custom_emoji_size = photo.custom_emoji_size.custom_emoji_id.is_valid();
BEGIN_STORE_FLAGS();
STORE_FLAG(photo.has_stickers);
STORE_FLAG(has_minithumbnail);
STORE_FLAG(has_animations);
STORE_FLAG(has_custom_emoji_size);
END_STORE_FLAGS();
store(photo.id.get(), storer);
store(photo.date, storer);
@ -88,16 +90,21 @@ void store(const Photo &photo, StorerT &storer) {
if (has_animations) {
store(photo.animations, storer);
}
if (has_custom_emoji_size) {
store(photo.custom_emoji_size, storer);
}
}
template <class ParserT>
void parse(Photo &photo, ParserT &parser) {
bool has_minithumbnail;
bool has_animations;
bool has_custom_emoji_size;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(photo.has_stickers);
PARSE_FLAG(has_minithumbnail);
PARSE_FLAG(has_animations);
PARSE_FLAG(has_custom_emoji_size);
END_PARSE_FLAGS();
int64 id;
parse(id, parser);
@ -113,6 +120,9 @@ void parse(Photo &photo, ParserT &parser) {
if (has_animations) {
parse(photo.animations, parser);
}
if (has_custom_emoji_size) {
parse(photo.custom_emoji_size, parser);
}
}
} // namespace td

View File

@ -258,40 +258,58 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
return std::move(res);
}
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_ptr) {
Variant<AnimationSize, CustomEmojiSize> 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_ptr) {
CHECK(size_ptr != nullptr);
if (size_ptr->get_id() != telegram_api::videoSize::ID) {
return {};
}
auto size = move_tl_object_as<telegram_api::videoSize>(size_ptr);
AnimationSize res;
if (size->type_ != "p" && size->type_ != "u" && size->type_ != "v") {
LOG(ERROR) << "Unsupported videoSize \"" << size->type_ << "\" in " << to_string(size);
}
res.type = static_cast<uint8>(size->type_[0]);
if (res.type >= 128) {
LOG(ERROR) << "Wrong videoSize \"" << res.type << "\" " << res;
res.type = 0;
}
res.dimensions = get_dimensions(size->w_, size->h_, "get_animation_size");
res.size = size->size_;
if ((size->flags_ & telegram_api::videoSize::VIDEO_START_TS_MASK) != 0) {
res.main_frame_timestamp = size->video_start_ts_;
}
switch (size_ptr->get_id()) {
case telegram_api::videoSize::ID: {
auto size = move_tl_object_as<telegram_api::videoSize>(size_ptr);
AnimationSize result;
if (size->type_ != "p" && size->type_ != "u" && size->type_ != "v") {
LOG(ERROR) << "Unsupported videoSize \"" << size->type_ << "\" in " << to_string(size);
}
result.type = static_cast<uint8>(size->type_[0]);
if (result.type >= 128) {
LOG(ERROR) << "Wrong videoSize \"" << result.type << "\" " << result;
result.type = 0;
}
result.dimensions = get_dimensions(size->w_, size->h_, "get_animation_size");
result.size = size->size_;
if ((size->flags_ & telegram_api::videoSize::VIDEO_START_TS_MASK) != 0) {
result.main_frame_timestamp = size->video_start_ts_;
}
if (source.get_type("get_animation_size") == PhotoSizeSource::Type::Thumbnail) {
source.thumbnail().thumbnail_type = res.type;
}
if (res.size < 0 || res.size > 1000000000) {
LOG(ERROR) << "Receive animation of size " << res.size;
res.size = 0;
}
if (source.get_type("get_animation_size") == PhotoSizeSource::Type::Thumbnail) {
source.thumbnail().thumbnail_type = result.type;
}
if (result.size < 0 || result.size > 1000000000) {
LOG(ERROR) << "Receive animation of size " << result.size;
result.size = 0;
}
res.file_id = register_photo_size(file_manager, source, id, access_hash, std::move(file_reference), owner_dialog_id,
res.size, dc_id, PhotoFormat::Mpeg4);
return res;
result.file_id = register_photo_size(file_manager, source, id, access_hash, std::move(file_reference),
owner_dialog_id, result.size, dc_id, PhotoFormat::Mpeg4);
return std::move(result);
}
case telegram_api::videoSizeEmojiMarkup::ID: {
auto size = move_tl_object_as<telegram_api::videoSizeEmojiMarkup>(size_ptr);
CustomEmojiSize result;
result.custom_emoji_id = CustomEmojiId(size->emoji_id_);
result.background_colors = std::move(size->background_colors_);
if (!result.custom_emoji_id.is_valid() || result.background_colors.empty() ||
result.background_colors.size() > 4) {
LOG(ERROR) << "Receive invalid " << result;
return {};
}
return std::move(result);
}
case telegram_api::videoSizeStickerMarkup::ID:
return {};
default:
UNREACHABLE();
}
}
PhotoSize get_web_document_photo_size(FileManager *file_manager, FileType file_type, DialogId owner_dialog_id,
@ -448,4 +466,16 @@ StringBuilder &operator<<(StringBuilder &string_builder, const AnimationSize &an
<< animation_size.main_frame_timestamp;
}
bool operator==(const CustomEmojiSize &lhs, const CustomEmojiSize &rhs) {
return lhs.custom_emoji_id == rhs.custom_emoji_id && lhs.background_colors == rhs.background_colors;
}
bool operator!=(const CustomEmojiSize &lhs, const CustomEmojiSize &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const CustomEmojiSize &custom_emoji_size) {
return string_builder << custom_emoji_size.custom_emoji_id << " on " << custom_emoji_size.background_colors;
}
} // namespace td

View File

@ -6,6 +6,7 @@
//
#pragma once
#include "td/telegram/CustomEmojiId.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/Dimensions.h"
#include "td/telegram/files/FileId.h"
@ -37,6 +38,11 @@ struct AnimationSize final : public PhotoSize {
double main_frame_timestamp = 0.0;
};
struct CustomEmojiSize {
CustomEmojiId custom_emoji_id;
vector<int32> background_colors;
};
bool need_update_dialog_photo_minithumbnail(const string &from, const string &to);
td_api::object_ptr<td_api::minithumbnail> get_minithumbnail_object(const string &packed);
@ -53,9 +59,10 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
DialogId owner_dialog_id, tl_object_ptr<telegram_api::PhotoSize> &&size_ptr,
PhotoFormat format);
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_ptr);
Variant<AnimationSize, CustomEmojiSize> 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_ptr);
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);
@ -75,4 +82,9 @@ bool operator!=(const AnimationSize &lhs, const AnimationSize &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const AnimationSize &animation_size);
bool operator==(const CustomEmojiSize &lhs, const CustomEmojiSize &rhs);
bool operator!=(const CustomEmojiSize &lhs, const CustomEmojiSize &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const CustomEmojiSize &custom_emoji_size);
} // namespace td

View File

@ -57,4 +57,16 @@ void parse(AnimationSize &animation_size, ParserT &parser) {
}
}
template <class StorerT>
void store(const CustomEmojiSize &custom_emoji_size, StorerT &storer) {
store(custom_emoji_size.custom_emoji_id, storer);
store(custom_emoji_size.background_colors, storer);
}
template <class ParserT>
void parse(CustomEmojiSize &custom_emoji_size, ParserT &parser) {
parse(custom_emoji_size.custom_emoji_id, parser);
parse(custom_emoji_size.background_colors, parser);
}
} // namespace td