Support sticker chat photos.

This commit is contained in:
levlam 2023-01-20 17:31:33 +03:00
parent 8137572794
commit 425bd0e364
19 changed files with 274 additions and 132 deletions

View File

@ -538,10 +538,22 @@ botMenuButton text:string url:string = BotMenuButton;
chatLocation location:location address:string = ChatLocation;
//@class ChatPhotoStickerType @description Describes type of a sticker, which was used to create a chat photo
//@description Information about the sticker, which was used to create the chat photo
//@sticker_set_id Sticker set identifier
//@sticker_id Identifier of the sticker in the set
chatPhotoStickerTypeRegularOrMask sticker_set_id:int64 sticker_id:int64 = ChatPhotoStickerType;
//@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;
chatPhotoStickerTypeCustomEmoji custom_emoji_id:int64 = ChatPhotoStickerType;
//@description Information about the sticker, which was used to create the chat photo
//@type Type of the sticker
//@background_fill Describes a fill of the background under the sticker; rotation angle in backgroundFillGradient isn't supported
chatPhotoSticker type:ChatPhotoStickerType background_fill:BackgroundFill = ChatPhotoSticker;
//@description Animated variant of a chat photo in MPEG4 format
//@length Animation width and height
@ -557,8 +569,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
//@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;
//@sticker Sticker-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 sticker:chatPhotoSticker = 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;
@ -7314,9 +7326,9 @@ getWebPageInstantView url:string force_full:Bool = WebPageInstantView;
//@description Changes a profile photo for the current user
//@photo Profile photo to set
//@custom_emoji Custom-emoji-based version of the profile photo; pass null if none or an existing photo is set
//@sticker Sticker-based version of the profile photo; pass null if none or an existing photo is set
//@is_public Pass true to set a public photo, which will be visible even the main photo is hidden by privacy settings
setProfilePhoto photo:InputChatPhoto custom_emoji:chatPhotoCustomEmoji is_public:Bool = Ok;
setProfilePhoto photo:InputChatPhoto sticker:chatPhotoSticker is_public:Bool = Ok;
//@description Deletes a profile photo @profile_photo_id Identifier of the profile photo to delete
deleteProfilePhoto profile_photo_id:int64 = Ok;

View File

@ -448,7 +448,7 @@ class UploadProfilePhotoQuery final : public Td::ResultHandler {
}
void send(UserId user_id, FileId file_id, tl_object_ptr<telegram_api::InputFile> &&input_file,
const CustomEmojiSize &custom_emoji_size, bool is_fallback, bool only_suggest, bool is_animation,
const StickerPhotoSize &sticker_photo_size, bool is_fallback, bool only_suggest, bool is_animation,
double main_frame_timestamp) {
CHECK(input_file != nullptr);
CHECK(file_id.is_valid());
@ -486,13 +486,14 @@ class UploadProfilePhotoQuery final : public Td::ResultHandler {
if (is_fallback) {
flags |= telegram_api::photos_uploadProfilePhoto::FALLBACK_MASK;
}
if (custom_emoji_size.custom_emoji_id.is_valid()) {
auto video_emoji_markup = get_input_video_size_object(td_, sticker_photo_size);
if (video_emoji_markup != nullptr) {
flags |= telegram_api::photos_uploadProfilePhoto::VIDEO_EMOJI_MARKUP_MASK;
}
send_query(G()->net_query_creator().create(
telegram_api::photos_uploadProfilePhoto(flags, false /*ignored*/, std::move(photo_input_file),
std::move(video_input_file), main_frame_timestamp,
get_input_video_size_object(custom_emoji_size)),
std::move(video_emoji_markup)),
{{"me"}}));
} else {
if (only_suggest) {
@ -7054,14 +7055,14 @@ FileId ContactsManager::get_profile_photo_file_id(int64 photo_id) const {
}
void ContactsManager::set_profile_photo(const td_api::object_ptr<td_api::InputChatPhoto> &input_photo,
const td_api::object_ptr<td_api::chatPhotoCustomEmoji> &custom_emoji,
const td_api::object_ptr<td_api::chatPhotoSticker> &custom_emoji,
bool is_fallback, Promise<Unit> &&promise) {
set_profile_photo_impl(get_my_id(), input_photo, custom_emoji, is_fallback, false, std::move(promise));
}
void ContactsManager::set_profile_photo_impl(UserId user_id,
const td_api::object_ptr<td_api::InputChatPhoto> &input_photo,
const td_api::object_ptr<td_api::chatPhotoCustomEmoji> &custom_emoji,
const td_api::object_ptr<td_api::chatPhotoSticker> &custom_emoji,
bool is_fallback, bool only_suggest, Promise<Unit> &&promise) {
if (input_photo == nullptr) {
return promise.set_error(Status::Error(400, "New profile photo must be non-empty"));
@ -7124,9 +7125,9 @@ void ContactsManager::set_profile_photo_impl(UserId user_id,
FileId file_id = r_file_id.ok();
CHECK(file_id.is_valid());
auto custom_emoji_size = get_custom_emoji_size(custom_emoji);
auto sticker_photo_size = get_sticker_photo_size(td_, custom_emoji);
upload_profile_photo(user_id, td_->file_manager_->dup_file_id(file_id, "set_profile_photo_impl"),
std::move(custom_emoji_size), is_fallback, only_suggest, is_animation, main_frame_timestamp,
std::move(sticker_photo_size), is_fallback, only_suggest, is_animation, main_frame_timestamp,
std::move(promise));
}
@ -7161,13 +7162,13 @@ void ContactsManager::send_update_profile_photo_query(FileId file_id, int64 old_
->send(file_id, old_photo_id, is_fallback, file_view.main_remote_location().as_input_photo());
}
void ContactsManager::upload_profile_photo(UserId user_id, FileId file_id, CustomEmojiSize custom_emoji_size,
void ContactsManager::upload_profile_photo(UserId user_id, FileId file_id, StickerPhotoSize sticker_photo_size,
bool is_fallback, bool only_suggest, bool is_animation,
double main_frame_timestamp, Promise<Unit> &&promise, int reupload_count,
vector<int> bad_parts) {
CHECK(file_id.is_valid());
bool is_inserted = uploaded_profile_photos_
.emplace(file_id, UploadedProfilePhoto{user_id, std::move(custom_emoji_size), is_fallback,
.emplace(file_id, UploadedProfilePhoto{user_id, std::move(sticker_photo_size), is_fallback,
only_suggest, main_frame_timestamp, is_animation,
reupload_count, std::move(promise)})
.second;
@ -11983,8 +11984,7 @@ void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&u
FileId description_animation_file_id;
if (user->bot_info_ != nullptr && !td_->auth_manager_->is_bot()) {
description = std::move(user->bot_info_->description_);
description_photo =
get_photo(td_->file_manager_.get(), std::move(user->bot_info_->description_photo_), DialogId(user_id));
description_photo = get_photo(td_, std::move(user->bot_info_->description_photo_), DialogId(user_id));
auto document = std::move(user->bot_info_->description_document_);
if (document != nullptr) {
int32 document_id = document->get_id();
@ -12013,9 +12013,9 @@ void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&u
user_full->is_changed = true;
}
auto photo = get_photo(td_->file_manager_.get(), std::move(user->profile_photo_), DialogId(user_id));
auto personal_photo = get_photo(td_->file_manager_.get(), std::move(user->personal_photo_), DialogId(user_id));
auto fallback_photo = get_photo(td_->file_manager_.get(), std::move(user->fallback_photo_), DialogId(user_id));
auto photo = get_photo(td_, std::move(user->profile_photo_), DialogId(user_id));
auto personal_photo = get_photo(td_, std::move(user->personal_photo_), DialogId(user_id));
auto fallback_photo = get_photo(td_, std::move(user->fallback_photo_), DialogId(user_id));
// do_update_user_photo should be a no-op if server sent consistent data
const Photo *photo_ptr = nullptr;
bool is_personal = false;
@ -12109,7 +12109,7 @@ void ContactsManager::on_get_user_photos(UserId user_id, int32 offset, int32 lim
}
}
auto photo = get_photo(td_->file_manager_.get(), std::move(server_photo), DialogId(user_id));
auto photo = get_photo(td_, std::move(server_photo), DialogId(user_id));
register_user_photo(u, user_id, photo);
}
}
@ -12136,7 +12136,7 @@ void ContactsManager::on_get_user_photos(UserId user_id, int32 offset, int32 lim
}
for (auto &photo : photos) {
auto user_photo = get_photo(td_->file_manager_.get(), std::move(photo), DialogId(user_id));
auto user_photo = get_photo(td_, std::move(photo), DialogId(user_id));
if (user_photo.is_empty()) {
LOG(ERROR) << "Receive empty profile photo in getUserPhotos request for " << user_id << " with offset " << offset
<< " and limit " << limit << ". Receive " << photo_count << " photos out of " << total_count
@ -12278,7 +12278,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
ChatFull *chat_full = add_chat_full(chat_id);
on_update_chat_full_invite_link(chat_full, std::move(chat->exported_invite_));
auto photo = get_photo(td_->file_manager_.get(), std::move(chat->chat_photo_), DialogId(chat_id));
auto photo = get_photo(td_, std::move(chat->chat_photo_), DialogId(chat_id));
// on_update_chat_photo should be a no-op if server sent consistent data
on_update_chat_photo(c, chat_id, as_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), 0, photo, false),
false);
@ -12454,7 +12454,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
channel_full->need_save_to_database = true;
}
auto photo = get_photo(td_->file_manager_.get(), std::move(channel->chat_photo_), DialogId(channel_id));
auto photo = get_photo(td_, std::move(channel->chat_photo_), DialogId(channel_id));
// on_update_channel_photo should be a no-op if server sent consistent data
on_update_channel_photo(
c, channel_id, as_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), c->access_hash, photo, false),
@ -13121,8 +13121,7 @@ void ContactsManager::on_set_profile_photo(UserId user_id, tl_object_ptr<telegra
delete_my_profile_photo_from_cache(old_photo_id);
}
on_get_users(std::move(photo->users_), "on_set_profile_photo");
add_set_profile_photo_to_cache(
user_id, get_photo(td_->file_manager_.get(), std::move(photo->photo_), DialogId(user_id)), is_fallback);
add_set_profile_photo_to_cache(user_id, get_photo(td_, std::move(photo->photo_), DialogId(user_id)), is_fallback);
}
void ContactsManager::on_delete_profile_photo(int64 profile_photo_id, Promise<Unit> promise) {
@ -14541,7 +14540,7 @@ void ContactsManager::on_get_dialog_invite_link_info(const string &invite_link,
}
invite_link_info->dialog_id = DialogId();
invite_link_info->title = chat_invite->title_;
invite_link_info->photo = get_photo(td_->file_manager_.get(), std::move(chat_invite->photo_), DialogId());
invite_link_info->photo = get_photo(td_, std::move(chat_invite->photo_), DialogId());
invite_link_info->description = std::move(chat_invite->about_);
invite_link_info->participant_count = chat_invite->participants_count_;
invite_link_info->participant_user_ids = std::move(participant_user_ids);
@ -17909,7 +17908,7 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<tele
CHECK(it != uploaded_profile_photos_.end());
UserId user_id = it->second.user_id;
auto custom_emoji_size = std::move(it->second.custom_emoji_size);
auto sticker_photo_size = std::move(it->second.sticker_photo_size);
bool is_fallback = it->second.is_fallback;
bool only_suggest = it->second.only_suggest;
double main_frame_timestamp = it->second.main_frame_timestamp;
@ -17942,14 +17941,14 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<tele
is_animation ? FileManager::extract_file_reference(file_view.main_remote_location().as_input_document())
: FileManager::extract_file_reference(file_view.main_remote_location().as_input_photo());
td_->file_manager_->delete_file_reference(file_id, file_reference);
upload_profile_photo(user_id, file_id, std::move(custom_emoji_size), is_fallback, only_suggest, is_animation,
upload_profile_photo(user_id, file_id, std::move(sticker_photo_size), is_fallback, only_suggest, is_animation,
main_frame_timestamp, std::move(promise), reupload_count + 1, {-1});
return;
}
CHECK(input_file != nullptr);
td_->create_handler<UploadProfilePhotoQuery>(std::move(promise))
->send(user_id, file_id, std::move(input_file), custom_emoji_size, is_fallback, only_suggest, is_animation,
->send(user_id, file_id, std::move(input_file), sticker_photo_size, is_fallback, only_suggest, is_animation,
main_frame_timestamp);
}

View File

@ -366,7 +366,7 @@ class ContactsManager final : public Actor {
FileId get_profile_photo_file_id(int64 photo_id) const;
void set_profile_photo(const td_api::object_ptr<td_api::InputChatPhoto> &input_photo,
const td_api::object_ptr<td_api::chatPhotoCustomEmoji> &custom_emoji, bool is_fallback,
const td_api::object_ptr<td_api::chatPhotoSticker> &custom_emoji, bool is_fallback,
Promise<Unit> &&promise);
void set_user_profile_photo(UserId user_id, const td_api::object_ptr<td_api::InputChatPhoto> &input_photo,
@ -1352,10 +1352,10 @@ class ContactsManager final : public Actor {
void apply_pending_user_photo(User *u, UserId user_id);
void set_profile_photo_impl(UserId user_id, const td_api::object_ptr<td_api::InputChatPhoto> &input_photo,
const td_api::object_ptr<td_api::chatPhotoCustomEmoji> &custom_emoji, bool is_fallback,
const td_api::object_ptr<td_api::chatPhotoSticker> &custom_emoji, bool is_fallback,
bool only_suggest, Promise<Unit> &&promise);
void upload_profile_photo(UserId user_id, FileId file_id, CustomEmojiSize custom_emoji_size, bool is_fallback,
void upload_profile_photo(UserId user_id, FileId file_id, StickerPhotoSize sticker_photo_size, bool is_fallback,
bool only_suggest, bool is_animation, double main_frame_timestamp, Promise<Unit> &&promise,
int reupload_count = 0, vector<int> bad_parts = {});
@ -1896,7 +1896,7 @@ class ContactsManager final : public Actor {
struct UploadedProfilePhoto {
UserId user_id;
CustomEmojiSize custom_emoji_size;
StickerPhotoSize sticker_photo_size;
bool is_fallback;
bool only_suggest;
double main_frame_timestamp;
@ -1904,10 +1904,10 @@ class ContactsManager final : public Actor {
int reupload_count;
Promise<Unit> promise;
UploadedProfilePhoto(UserId user_id, CustomEmojiSize custom_emoji_size, bool is_fallback, bool only_suggest,
UploadedProfilePhoto(UserId user_id, StickerPhotoSize sticker_photo_size, bool is_fallback, bool only_suggest,
double main_frame_timestamp, bool is_animation, int32 reupload_count, Promise<Unit> promise)
: user_id(user_id)
, custom_emoji_size(custom_emoji_size)
, sticker_photo_size(sticker_photo_size)
, is_fallback(is_fallback)
, only_suggest(only_suggest)
, main_frame_timestamp(main_frame_timestamp)

View File

@ -135,9 +135,9 @@ static td_api::object_ptr<td_api::ChatEventAction> get_chat_event_action_object(
}
case telegram_api::channelAdminLogEventActionChangePhoto::ID: {
auto action = move_tl_object_as<telegram_api::channelAdminLogEventActionChangePhoto>(action_ptr);
auto old_photo = get_photo(td, std::move(action->prev_photo_), DialogId(channel_id));
auto new_photo = get_photo(td, std::move(action->new_photo_), DialogId(channel_id));
auto file_manager = td->file_manager_.get();
auto old_photo = get_photo(file_manager, std::move(action->prev_photo_), DialogId(channel_id));
auto new_photo = get_photo(file_manager, std::move(action->new_photo_), DialogId(channel_id));
return td_api::make_object<td_api::chatEventPhotoChanged>(get_chat_photo_object(file_manager, old_photo),
get_chat_photo_object(file_manager, new_photo));
}

View File

@ -340,8 +340,8 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
if (thumb->type_ == "v") {
if (!animated_thumbnail.file_id.is_valid()) {
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));
get_animation_size(td_, 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 {

View File

@ -35,7 +35,7 @@ Game::Game(Td *td, string title, string description, tl_object_ptr<telegram_api:
: title_(std::move(title)), description_(std::move(description)) {
CHECK(td != nullptr);
CHECK(photo != nullptr);
photo_ = get_photo(td->file_manager_.get(), std::move(photo), owner_dialog_id);
photo_ = get_photo(td, std::move(photo), owner_dialog_id);
if (photo_.is_empty()) {
LOG(ERROR) << "Receive empty photo for game " << title_;
photo_.id = 0; // to prevent null photo in td_api

View File

@ -1651,7 +1651,7 @@ void InlineQueriesManager::on_get_inline_query_results(DialogId dialog_id, UserI
LOG_IF(ERROR, !is_photo) << "Wrong result type " << result->type_;
auto photo = make_tl_object<td_api::inlineQueryResultPhoto>();
photo->id_ = std::move(result->id_);
Photo p = get_photo(td_->file_manager_.get(), std::move(result->photo_), DialogId());
Photo p = get_photo(td_, std::move(result->photo_), DialogId());
if (p.is_empty()) {
LOG(ERROR) << "Receive empty cached photo in the result of inline query";
break;

View File

@ -4654,7 +4654,7 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
return make_unique<MessageExpiredPhoto>();
}
auto photo = get_photo(td->file_manager_.get(), std::move(media->photo_), owner_dialog_id);
auto photo = get_photo(td, std::move(media->photo_), owner_dialog_id);
if (photo.is_empty()) {
return make_unique<MessageExpiredPhoto>();
}
@ -5085,7 +5085,7 @@ unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<tele
}
case telegram_api::messageActionChatEditPhoto::ID: {
auto action = move_tl_object_as<telegram_api::messageActionChatEditPhoto>(action_ptr);
auto photo = get_photo(td->file_manager_.get(), std::move(action->photo_), owner_dialog_id);
auto photo = get_photo(td, std::move(action->photo_), owner_dialog_id);
if (photo.is_empty()) {
break;
}
@ -5359,7 +5359,7 @@ unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<tele
}
case telegram_api::messageActionSuggestProfilePhoto::ID: {
auto action = move_tl_object_as<telegram_api::messageActionSuggestProfilePhoto>(action_ptr);
auto photo = get_photo(td->file_manager_.get(), std::move(action->photo_), owner_dialog_id);
auto photo = get_photo(td, std::move(action->photo_), owner_dialog_id);
if (photo.is_empty()) {
break;
}

View File

@ -53,7 +53,7 @@ MessageExtendedMedia::MessageExtendedMedia(
break;
}
photo_ = get_photo(td->file_manager_.get(), std::move(photo->photo_), owner_dialog_id);
photo_ = get_photo(td, std::move(photo->photo_), owner_dialog_id);
if (photo_.is_empty()) {
break;
}

View File

@ -3377,8 +3377,7 @@ Status NotificationManager::process_push_notification_payload(string payload, bo
VLOG(notifications) << "Have attached photo";
loc_key.resize(loc_key.rfind('_') + 1);
loc_key += "PHOTO";
attached_photo = get_photo(td_->file_manager_.get(),
telegram_api::move_object_as<telegram_api::photo>(result), dialog_id);
attached_photo = get_photo(td_, telegram_api::move_object_as<telegram_api::photo>(result), dialog_id);
} else {
LOG(ERROR) << "Receive attached photo for " << loc_key;
}

View File

@ -14,6 +14,7 @@
#include "td/telegram/net/DcId.h"
#include "td/telegram/PhotoFormat.h"
#include "td/telegram/PhotoSizeSource.h"
#include "td/telegram/Td.h"
#include "td/utils/algorithm.h"
#include "td/utils/common.h"
@ -265,11 +266,28 @@ 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;
static tl_object_ptr<td_api::chatPhotoSticker> get_chat_photo_sticker_object(
const StickerPhotoSize &sticker_photo_size) {
td_api::object_ptr<td_api::ChatPhotoStickerType> type;
switch (sticker_photo_size.type) {
case StickerPhotoSize::Type::Sticker:
if (!sticker_photo_size.sticker_set_id.is_valid()) {
return nullptr;
}
type = td_api::make_object<td_api::chatPhotoStickerTypeRegularOrMask>(sticker_photo_size.sticker_set_id.get(),
sticker_photo_size.sticker_id);
break;
case StickerPhotoSize::Type::CustomEmoji:
if (!sticker_photo_size.custom_emoji_id.is_valid()) {
return nullptr;
}
type = td_api::make_object<td_api::chatPhotoStickerTypeCustomEmoji>(sticker_photo_size.custom_emoji_id.get());
break;
default:
UNREACHABLE();
return nullptr;
}
CHECK(type != nullptr);
auto background_fill = [&](vector<int32> colors) -> td_api::object_ptr<td_api::BackgroundFill> {
switch (colors.size()) {
@ -284,10 +302,9 @@ static tl_object_ptr<td_api::chatPhotoCustomEmoji> get_chat_photo_custom_emoji_o
UNREACHABLE();
return nullptr;
}
}(custom_emoji_size.background_colors);
}(sticker_photo_size.background_colors);
return td_api::make_object<td_api::chatPhotoCustomEmoji>(custom_emoji_size.custom_emoji_id.get(),
std::move(background_fill));
return td_api::make_object<td_api::chatPhotoSticker>(std::move(type), std::move(background_fill));
}
Photo get_encrypted_file_photo(FileManager *file_manager, unique_ptr<EncryptedFile> &&file,
@ -318,15 +335,15 @@ Photo get_encrypted_file_photo(FileManager *file_manager, unique_ptr<EncryptedFi
return res;
}
Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::Photo> &&photo, DialogId owner_dialog_id) {
Photo get_photo(Td *td, tl_object_ptr<telegram_api::Photo> &&photo, DialogId owner_dialog_id) {
if (photo == nullptr || photo->get_id() == telegram_api::photoEmpty::ID) {
return Photo();
}
CHECK(photo->get_id() == telegram_api::photo::ID);
return get_photo(file_manager, move_tl_object_as<telegram_api::photo>(photo), owner_dialog_id);
return get_photo(td, move_tl_object_as<telegram_api::photo>(photo), owner_dialog_id);
}
Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&photo, DialogId owner_dialog_id) {
Photo get_photo(Td *td, tl_object_ptr<telegram_api::photo> &&photo, DialogId owner_dialog_id) {
CHECK(photo != nullptr);
Photo res;
@ -341,8 +358,8 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
DcId dc_id = DcId::create(photo->dc_id_);
for (auto &size_ptr : photo->sizes_) {
auto photo_size = get_photo_size(file_manager, PhotoSizeSource::thumbnail(FileType::Photo, 0), photo->id_,
photo->access_hash_, photo->file_reference_.as_slice().str(), dc_id,
auto photo_size = get_photo_size(td->file_manager_.get(), 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), PhotoFormat::Jpeg);
if (photo_size.get_offset() == 0) {
PhotoSize &size = photo_size.get<0>();
@ -358,9 +375,9 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
}
for (auto &size_ptr : photo->video_sizes_) {
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));
auto animation =
get_animation_size(td, 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.empty()) {
continue;
}
@ -370,7 +387,7 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
res.animations.push_back(std::move(animation_size));
}
},
[&](const CustomEmojiSize &custom_emoji_size) { res.custom_emoji_size = std::move(custom_emoji_size); }));
[&](const StickerPhotoSize &sticker_photo_size) { res.sticker_photo_size = std::move(sticker_photo_size); }));
}
return res;
@ -418,7 +435,7 @@ tl_object_ptr<td_api::chatPhoto> get_chat_photo_object(FileManager *file_manager
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_chat_photo_custom_emoji_object(photo.custom_emoji_size));
get_chat_photo_sticker_object(photo.sticker_photo_size));
}
void photo_delete_thumbnail(Photo &photo) {
@ -607,7 +624,7 @@ 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 &&
lhs.custom_emoji_size == rhs.custom_emoji_size;
lhs.sticker_photo_size == rhs.sticker_photo_size;
}
bool operator!=(const Photo &lhs, const Photo &rhs) {
@ -619,8 +636,8 @@ 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;
if (photo.sticker_photo_size.custom_emoji_id.is_valid()) {
string_builder << ", custom emoji size = " << photo.sticker_photo_size;
}
return string_builder << ']';
}

View File

@ -24,6 +24,7 @@
namespace td {
class FileManager;
class Td;
struct DialogPhoto {
FileId small_file_id;
@ -45,7 +46,7 @@ struct Photo {
vector<AnimationSize> animations;
CustomEmojiSize custom_emoji_size;
StickerPhotoSize sticker_photo_size;
bool has_stickers = false;
vector<FileId> sticker_file_ids;
@ -100,8 +101,8 @@ bool need_update_dialog_photo(const DialogPhoto &from, const DialogPhoto &to);
StringBuilder &operator<<(StringBuilder &string_builder, const DialogPhoto &dialog_photo);
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_photo(Td *td, tl_object_ptr<telegram_api::Photo> &&photo, DialogId owner_dialog_id);
Photo get_photo(Td *td, tl_object_ptr<telegram_api::photo> &&photo, DialogId owner_dialog_id);
Photo get_encrypted_file_photo(FileManager *file_manager, unique_ptr<EncryptedFile> &&file,
tl_object_ptr<secret_api::decryptedMessageMediaPhoto> &&photo, DialogId owner_dialog_id);
Photo get_web_document_photo(FileManager *file_manager, tl_object_ptr<telegram_api::WebDocument> web_document,

View File

@ -71,12 +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();
bool has_sticker_photo_size = photo.sticker_photo_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);
STORE_FLAG(has_sticker_photo_size);
END_STORE_FLAGS();
store(photo.id.get(), storer);
store(photo.date, storer);
@ -90,8 +90,8 @@ 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);
if (has_sticker_photo_size) {
store(photo.sticker_photo_size, storer);
}
}
@ -99,12 +99,12 @@ template <class ParserT>
void parse(Photo &photo, ParserT &parser) {
bool has_minithumbnail;
bool has_animations;
bool has_custom_emoji_size;
bool has_sticker_photo_size;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(photo.has_stickers);
PARSE_FLAG(has_minithumbnail);
PARSE_FLAG(has_animations);
PARSE_FLAG(has_custom_emoji_size);
PARSE_FLAG(has_sticker_photo_size);
END_PARSE_FLAGS();
int64 id;
parse(id, parser);
@ -120,8 +120,8 @@ void parse(Photo &photo, ParserT &parser) {
if (has_animations) {
parse(photo.animations, parser);
}
if (has_custom_emoji_size) {
parse(photo.custom_emoji_size, parser);
if (has_sticker_photo_size) {
parse(photo.sticker_photo_size, parser);
}
}

View File

@ -8,6 +8,8 @@
#include "td/telegram/files/FileLocation.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/StickersManager.h"
#include "td/telegram/Td.h"
#include "td/utils/base64.h"
#include "td/utils/HttpUrl.h"
@ -258,10 +260,10 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
return std::move(res);
}
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) {
Variant<AnimationSize, StickerPhotoSize> get_animation_size(Td *td, 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);
switch (size_ptr->get_id()) {
case telegram_api::videoSize::ID: {
@ -289,13 +291,14 @@ Variant<AnimationSize, CustomEmojiSize> get_animation_size(FileManager *file_man
result.size = 0;
}
result.file_id = register_photo_size(file_manager, source, id, access_hash, std::move(file_reference),
result.file_id = register_photo_size(td->file_manager_.get(), 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;
StickerPhotoSize result;
result.type = StickerPhotoSize::Type::CustomEmoji;
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() ||
@ -308,20 +311,55 @@ Variant<AnimationSize, CustomEmojiSize> get_animation_size(FileManager *file_man
}
return std::move(result);
}
case telegram_api::videoSizeStickerMarkup::ID:
return {};
case telegram_api::videoSizeStickerMarkup::ID: {
auto size = move_tl_object_as<telegram_api::videoSizeStickerMarkup>(size_ptr);
StickerPhotoSize result;
result.type = StickerPhotoSize::Type::Sticker;
result.sticker_set_id = td->stickers_manager_->add_sticker_set(std::move(size->stickerset_));
result.sticker_id = size->sticker_id_;
result.background_colors = std::move(size->background_colors_);
if (!result.sticker_set_id.is_valid() || result.sticker_id == 0 || !result.custom_emoji_id.is_valid() ||
result.background_colors.empty() || result.background_colors.size() > 4) {
LOG(ERROR) << "Receive invalid " << result;
return {};
}
for (auto &color : result.background_colors) {
color &= 0xFFFFFF;
}
return std::move(result);
}
default:
UNREACHABLE();
}
}
CustomEmojiSize get_custom_emoji_size(const td_api::object_ptr<td_api::chatPhotoCustomEmoji> &custom_emoji) {
if (custom_emoji == nullptr || custom_emoji->background_fill_ == nullptr) {
StickerPhotoSize get_sticker_photo_size(Td *td, const td_api::object_ptr<td_api::chatPhotoSticker> &sticker) {
if (sticker == nullptr || sticker->type_ == nullptr || sticker->background_fill_ == nullptr) {
return {};
}
CustomEmojiSize result;
result.custom_emoji_id = CustomEmojiId(custom_emoji->custom_emoji_id_);
auto fill = custom_emoji->background_fill_.get();
StickerPhotoSize result;
switch (sticker->type_->get_id()) {
case td_api::chatPhotoStickerTypeRegularOrMask::ID: {
auto type = static_cast<const td_api::chatPhotoStickerTypeRegularOrMask *>(sticker->type_.get());
result.type = StickerPhotoSize::Type::Sticker;
result.sticker_set_id = StickerSetId(type->sticker_set_id_);
result.sticker_id = type->sticker_id_;
//if (!td->stickers_manager_->have_sticker(result.sticker_set_id, result.sticker_id)) {
// return {};
//}
break;
}
case td_api::chatPhotoStickerTypeCustomEmoji::ID: {
auto type = static_cast<const td_api::chatPhotoStickerTypeCustomEmoji *>(sticker->type_.get());
result.type = StickerPhotoSize::Type::CustomEmoji;
result.custom_emoji_id = CustomEmojiId(type->custom_emoji_id_);
//if (!td->stickers_manager_->have_custom_emoji_id(result.custom_emoji_id)) {
// return {};
//}
break;
}
}
auto fill = sticker->background_fill_.get();
switch (fill->get_id()) {
case td_api::backgroundFillSolid::ID: {
auto solid = static_cast<const td_api::backgroundFillSolid *>(fill);
@ -353,13 +391,25 @@ CustomEmojiSize get_custom_emoji_size(const td_api::object_ptr<td_api::chatPhoto
}
telegram_api::object_ptr<telegram_api::VideoSize> get_input_video_size_object(
const CustomEmojiSize &custom_emoji_size) {
if (!custom_emoji_size.custom_emoji_id.is_valid()) {
return nullptr;
Td *td, const StickerPhotoSize &sticker_photo_size) {
switch (sticker_photo_size.type) {
case StickerPhotoSize::Type::Sticker:
if (!sticker_photo_size.sticker_set_id.is_valid()) {
return nullptr;
}
return telegram_api::make_object<telegram_api::videoSizeStickerMarkup>(
td->stickers_manager_->get_input_sticker_set(sticker_photo_size.sticker_set_id),
sticker_photo_size.sticker_id, vector<int32>(sticker_photo_size.background_colors));
case StickerPhotoSize::Type::CustomEmoji:
if (!sticker_photo_size.custom_emoji_id.is_valid()) {
return nullptr;
}
return telegram_api::make_object<telegram_api::videoSizeEmojiMarkup>(
sticker_photo_size.custom_emoji_id.get(), vector<int32>(sticker_photo_size.background_colors));
default:
UNREACHABLE();
return nullptr;
}
return telegram_api::make_object<telegram_api::videoSizeEmojiMarkup>(
custom_emoji_size.custom_emoji_id.get(), vector<int32>(custom_emoji_size.background_colors));
}
PhotoSize get_web_document_photo_size(FileManager *file_manager, FileType file_type, DialogId owner_dialog_id,
@ -516,16 +566,26 @@ 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 StickerPhotoSize &lhs, const StickerPhotoSize &rhs) {
return lhs.type == rhs.type && lhs.sticker_set_id == rhs.sticker_set_id && lhs.sticker_id == rhs.sticker_id &&
lhs.custom_emoji_id == rhs.custom_emoji_id && lhs.background_colors == rhs.background_colors;
}
bool operator!=(const CustomEmojiSize &lhs, const CustomEmojiSize &rhs) {
bool operator!=(const StickerPhotoSize &lhs, const StickerPhotoSize &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;
StringBuilder &operator<<(StringBuilder &string_builder, const StickerPhotoSize &sticker_photo_size) {
switch (sticker_photo_size.type) {
case StickerPhotoSize::Type::Sticker:
return string_builder << sticker_photo_size.sticker_id << " from " << sticker_photo_size.sticker_set_id << " on "
<< sticker_photo_size.background_colors;
case StickerPhotoSize::Type::CustomEmoji:
return string_builder << sticker_photo_size.custom_emoji_id << " on " << sticker_photo_size.background_colors;
default:
UNREACHABLE();
return string_builder;
}
}
} // namespace td

View File

@ -14,6 +14,7 @@
#include "td/telegram/net/DcId.h"
#include "td/telegram/PhotoFormat.h"
#include "td/telegram/PhotoSizeSource.h"
#include "td/telegram/StickerSetId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
@ -25,6 +26,7 @@
namespace td {
class FileManager;
class Td;
struct PhotoSize {
int32 type = 0;
@ -38,8 +40,12 @@ struct AnimationSize final : public PhotoSize {
double main_frame_timestamp = 0.0;
};
struct CustomEmojiSize {
struct StickerPhotoSize {
enum class Type : int32 { Sticker, CustomEmoji };
Type type = Type::CustomEmoji;
CustomEmojiId custom_emoji_id;
StickerSetId sticker_set_id;
int64 sticker_id = 0;
vector<int32> background_colors;
};
@ -59,14 +65,14 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
DialogId owner_dialog_id, tl_object_ptr<telegram_api::PhotoSize> &&size_ptr,
PhotoFormat format);
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);
Variant<AnimationSize, StickerPhotoSize> get_animation_size(Td *td, 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);
CustomEmojiSize get_custom_emoji_size(const td_api::object_ptr<td_api::chatPhotoCustomEmoji> &custom_emoji);
StickerPhotoSize get_sticker_photo_size(Td *td, const td_api::object_ptr<td_api::chatPhotoSticker> &chat_photo_sticker);
telegram_api::object_ptr<telegram_api::VideoSize> get_input_video_size_object(const CustomEmojiSize &custom_emoji_size);
telegram_api::object_ptr<telegram_api::VideoSize> get_input_video_size_object(
Td *td, const StickerPhotoSize &sticker_photo_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);
@ -86,9 +92,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);
bool operator==(const StickerPhotoSize &lhs, const StickerPhotoSize &rhs);
bool operator!=(const StickerPhotoSize &lhs, const StickerPhotoSize &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const CustomEmojiSize &custom_emoji_size);
StringBuilder &operator<<(StringBuilder &string_builder, const StickerPhotoSize &sticker_photo_size);
} // namespace td

View File

@ -9,6 +9,7 @@
#include "td/telegram/Dimensions.hpp"
#include "td/telegram/files/FileId.hpp"
#include "td/telegram/PhotoSize.h"
#include "td/telegram/StickerSetId.hpp"
#include "td/telegram/Version.h"
#include "td/utils/tl_helpers.h"
@ -58,15 +59,41 @@ 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);
void store(const StickerPhotoSize &sticker_photo_size, StorerT &storer) {
bool is_custom_emoji = sticker_photo_size.type == StickerPhotoSize::Type::CustomEmoji;
bool is_sticker = sticker_photo_size.type == StickerPhotoSize::Type::Sticker;
BEGIN_STORE_FLAGS();
STORE_FLAG(is_custom_emoji);
STORE_FLAG(is_sticker);
END_STORE_FLAGS();
if (is_custom_emoji) {
store(sticker_photo_size.custom_emoji_id, storer);
} else if (is_sticker) {
store(sticker_photo_size.sticker_set_id, storer);
store(sticker_photo_size.sticker_id, storer);
}
store(sticker_photo_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);
void parse(StickerPhotoSize &sticker_photo_size, ParserT &parser) {
bool is_custom_emoji;
bool is_sticker;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_custom_emoji);
PARSE_FLAG(is_sticker);
END_PARSE_FLAGS();
if (is_custom_emoji) {
sticker_photo_size.type = StickerPhotoSize::Type::CustomEmoji;
parse(sticker_photo_size.custom_emoji_id, parser);
} else if (is_sticker) {
sticker_photo_size.type = StickerPhotoSize::Type::Sticker;
parse(sticker_photo_size.sticker_set_id, parser);
parse(sticker_photo_size.sticker_id, parser);
} else {
UNREACHABLE();
}
parse(sticker_photo_size.background_colors, parser);
}
} // namespace td

View File

@ -6992,7 +6992,7 @@ void Td::on_request(uint64 id, const td_api::setLocation &request) {
void Td::on_request(uint64 id, td_api::setProfilePhoto &request) {
CHECK_IS_USER();
CREATE_OK_REQUEST_PROMISE();
contacts_manager_->set_profile_photo(request.photo_, request.custom_emoji_, request.is_public_, std::move(promise));
contacts_manager_->set_profile_photo(request.photo_, request.sticker_, request.is_public_, std::move(promise));
}
void Td::on_request(uint64 id, const td_api::deleteProfilePhoto &request) {

View File

@ -492,7 +492,7 @@ WebPageId WebPagesManager::on_get_web_page(tl_object_ptr<telegram_api::WebPage>
page->site_name = std::move(web_page->site_name_);
page->title = std::move(web_page->title_);
page->description = std::move(web_page->description_);
page->photo = get_photo(td_->file_manager_.get(), std::move(web_page->photo_), owner_dialog_id);
page->photo = get_photo(td_, std::move(web_page->photo_), owner_dialog_id);
page->embed_url = std::move(web_page->embed_url_);
page->embed_type = std::move(web_page->embed_type_);
page->embed_dimensions = get_dimensions(web_page->embed_width_, web_page->embed_height_, "webPage");
@ -1415,7 +1415,7 @@ void WebPagesManager::on_get_web_page_instant_view(WebPage *web_page, tl_object_
CHECK(page != nullptr);
FlatHashMap<int64, unique_ptr<Photo>> photos;
for (auto &photo_ptr : page->photos_) {
Photo photo = get_photo(td_->file_manager_.get(), std::move(photo_ptr), owner_dialog_id);
Photo photo = get_photo(td_, std::move(photo_ptr), owner_dialog_id);
if (photo.is_empty() || photo.id.get() == 0) {
LOG(ERROR) << "Receive empty photo in web page instant view for " << web_page->url;
} else {

View File

@ -872,6 +872,27 @@ class CliClient final : public Actor {
}
}
struct ChatPhotoStickerType {
int64 sticker_set_id = 0;
int64 sticker_id = 0;
operator td_api::object_ptr<td_api::ChatPhotoStickerType>() const {
if (sticker_set_id != 0) {
return td_api::make_object<td_api::chatPhotoStickerTypeRegularOrMask>(sticker_set_id, sticker_id);
} else {
return td_api::make_object<td_api::chatPhotoStickerTypeCustomEmoji>(sticker_id);
}
}
};
void get_args(string &args, ChatPhotoStickerType &arg) const {
string sticker_set_id;
string sticker_id;
std::tie(sticker_set_id, sticker_id) = split(args, get_delimiter(args));
arg.sticker_set_id = to_integer<int64>(sticker_set_id);
arg.sticker_id = to_integer<int64>(sticker_id);
}
template <class FirstType, class SecondType, class... Types>
void get_args(string &args, FirstType &first_arg, SecondType &second_arg, Types &...other_args) const {
string arg;
@ -4876,25 +4897,25 @@ class CliClient final : public Actor {
td_api::make_object<td_api::setProfilePhoto>(td_api::make_object<td_api::inputChatPhotoAnimation>(
as_input_file(animation), to_double(main_frame_timestamp)),
nullptr, op == "sppaf"));
} else if (op == "spppce" || op == "spppcef") {
} else if (op == "sppps" || op == "spppsf") {
string photo;
int64 custom_emoji_id;
get_args(args, photo, custom_emoji_id);
ChatPhotoStickerType type;
get_args(args, photo, type);
send_request(td_api::make_object<td_api::setProfilePhoto>(
td_api::make_object<td_api::inputChatPhotoStatic>(as_input_file(photo)),
td_api::make_object<td_api::chatPhotoCustomEmoji>(
custom_emoji_id, td_api::make_object<td_api::backgroundFillSolid>(0x7FFFFFFF)),
td_api::make_object<td_api::chatPhotoSticker>(type,
td_api::make_object<td_api::backgroundFillSolid>(0x7FFFFFFF)),
op == "spppcef"));
} else if (op == "sppace" || op == "sppacef") {
} else if (op == "sppas" || op == "sppasf") {
string animation;
string main_frame_timestamp;
int64 custom_emoji_id;
get_args(args, animation, main_frame_timestamp, custom_emoji_id);
ChatPhotoStickerType type;
get_args(args, animation, main_frame_timestamp, type);
send_request(td_api::make_object<td_api::setProfilePhoto>(
td_api::make_object<td_api::inputChatPhotoAnimation>(as_input_file(animation),
to_double(main_frame_timestamp)),
td_api::make_object<td_api::chatPhotoCustomEmoji>(
custom_emoji_id, td_api::make_object<td_api::backgroundFillSolid>(0x7FFFFFFF)),
td_api::make_object<td_api::chatPhotoSticker>(type,
td_api::make_object<td_api::backgroundFillSolid>(0x7FFFFFFF)),
op == "sppacef"));
} else if (op == "suppp") {
UserId user_id;