Allow to upload custom emoji photos.

This commit is contained in:
levlam 2023-01-19 14:06:27 +03:00
parent 68e939985f
commit a14d749893
7 changed files with 129 additions and 33 deletions

View File

@ -7273,8 +7273,11 @@ getWebPagePreview text:formattedText = WebPage;
getWebPageInstantView url:string force_full:Bool = WebPageInstantView;
//@description Changes a profile photo for the current user @photo Profile photo to 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 is_public:Bool = Ok;
//@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
//@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;
//@description Deletes a profile photo @profile_photo_id Identifier of the profile photo to delete
deleteProfilePhoto profile_photo_id:int64 = Ok;

View File

@ -447,8 +447,9 @@ class UploadProfilePhotoQuery final : public Td::ResultHandler {
explicit UploadProfilePhotoQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(UserId user_id, FileId file_id, tl_object_ptr<telegram_api::InputFile> &&input_file, bool is_fallback,
bool only_suggest, bool is_animation, double main_frame_timestamp) {
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,
double main_frame_timestamp) {
CHECK(input_file != nullptr);
CHECK(file_id.is_valid());
@ -485,9 +486,13 @@ 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()) {
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, nullptr),
std::move(video_input_file), main_frame_timestamp,
get_input_video_size_object(custom_emoji_size)),
{{"me"}}));
} else {
if (only_suggest) {
@ -7048,13 +7053,15 @@ FileId ContactsManager::get_profile_photo_file_id(int64 photo_id) const {
return it->second;
}
void ContactsManager::set_profile_photo(const td_api::object_ptr<td_api::InputChatPhoto> &input_photo, bool is_fallback,
Promise<Unit> &&promise) {
set_profile_photo_impl(get_my_id(), input_photo, is_fallback, false, std::move(promise));
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,
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,
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"));
@ -7068,6 +7075,9 @@ void ContactsManager::set_profile_photo_impl(UserId user_id,
if (user_id != get_my_id()) {
return promise.set_error(Status::Error(400, "Can't use inputChatPhotoPrevious"));
}
if (custom_emoji != nullptr) {
return promise.set_error(Status::Error(400, "Can't use custom emoji with a previous photo"));
}
auto photo = static_cast<const td_api::inputChatPhotoPrevious *>(input_photo.get());
auto photo_id = photo->chat_photo_id_;
auto *u = get_user(user_id);
@ -7114,8 +7124,10 @@ void ContactsManager::set_profile_photo_impl(UserId user_id,
FileId file_id = r_file_id.ok();
CHECK(file_id.is_valid());
upload_profile_photo(user_id, td_->file_manager_->dup_file_id(file_id, "set_profile_photo_impl"), is_fallback,
only_suggest, is_animation, main_frame_timestamp, std::move(promise));
auto custom_emoji_size = get_custom_emoji_size(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(promise));
}
void ContactsManager::set_user_profile_photo(UserId user_id,
@ -7139,7 +7151,7 @@ void ContactsManager::set_user_profile_photo(UserId user_id,
return;
}
set_profile_photo_impl(user_id, input_photo, false, only_suggest, std::move(promise));
set_profile_photo_impl(user_id, input_photo, nullptr, false, only_suggest, std::move(promise));
}
void ContactsManager::send_update_profile_photo_query(FileId file_id, int64 old_photo_id, bool is_fallback,
@ -7149,15 +7161,16 @@ 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, bool is_fallback, bool only_suggest,
bool is_animation, double main_frame_timestamp, Promise<Unit> &&promise,
int reupload_count, vector<int> bad_parts) {
void ContactsManager::upload_profile_photo(UserId user_id, FileId file_id, CustomEmojiSize custom_emoji_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, is_fallback, only_suggest, main_frame_timestamp, is_animation,
reupload_count, std::move(promise)})
.second;
bool is_inserted = uploaded_profile_photos_
.emplace(file_id, UploadedProfilePhoto{user_id, std::move(custom_emoji_size), is_fallback,
only_suggest, main_frame_timestamp, is_animation,
reupload_count, std::move(promise)})
.second;
CHECK(is_inserted);
LOG(INFO) << "Ask to upload " << (is_animation ? "animated" : "static") << " profile photo " << file_id
<< " for user " << user_id << " with bad parts " << bad_parts;
@ -17889,6 +17902,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);
bool is_fallback = it->second.is_fallback;
bool only_suggest = it->second.only_suggest;
double main_frame_timestamp = it->second.main_frame_timestamp;
@ -17921,14 +17935,15 @@ 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, is_fallback, only_suggest, is_animation, main_frame_timestamp,
std::move(promise), reupload_count + 1, {-1});
upload_profile_photo(user_id, file_id, std::move(custom_emoji_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), is_fallback, only_suggest, is_animation, main_frame_timestamp);
->send(user_id, file_id, std::move(input_file), custom_emoji_size, is_fallback, only_suggest, is_animation,
main_frame_timestamp);
}
void ContactsManager::on_upload_profile_photo_error(FileId file_id, Status status) {

View File

@ -365,7 +365,8 @@ 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, bool is_fallback,
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,
Promise<Unit> &&promise);
void set_user_profile_photo(UserId user_id, const td_api::object_ptr<td_api::InputChatPhoto> &input_photo,
@ -1351,11 +1352,12 @@ 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,
bool is_fallback, bool only_suggest, Promise<Unit> &&promise);
const td_api::object_ptr<td_api::chatPhotoCustomEmoji> &custom_emoji, bool is_fallback,
bool only_suggest, Promise<Unit> &&promise);
void upload_profile_photo(UserId user_id, FileId file_id, bool is_fallback, bool only_suggest, bool is_animation,
double main_frame_timestamp, Promise<Unit> &&promise, int reupload_count = 0,
vector<int> bad_parts = {});
void upload_profile_photo(UserId user_id, FileId file_id, CustomEmojiSize custom_emoji_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 = {});
void on_upload_profile_photo(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file);
void on_upload_profile_photo_error(FileId file_id, Status status);
@ -1894,6 +1896,7 @@ class ContactsManager final : public Actor {
struct UploadedProfilePhoto {
UserId user_id;
CustomEmojiSize custom_emoji_size;
bool is_fallback;
bool only_suggest;
double main_frame_timestamp;
@ -1901,9 +1904,10 @@ class ContactsManager final : public Actor {
int reupload_count;
Promise<Unit> promise;
UploadedProfilePhoto(UserId user_id, bool is_fallback, bool only_suggest, double main_frame_timestamp,
bool is_animation, int32 reupload_count, Promise<Unit> promise)
UploadedProfilePhoto(UserId user_id, CustomEmojiSize custom_emoji_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)
, is_fallback(is_fallback)
, only_suggest(only_suggest)
, main_frame_timestamp(main_frame_timestamp)

View File

@ -303,6 +303,9 @@ Variant<AnimationSize, CustomEmojiSize> get_animation_size(FileManager *file_man
LOG(ERROR) << "Receive invalid " << result;
return {};
}
for (auto &color : result.background_colors) {
color &= 0xFFFFFF;
}
return std::move(result);
}
case telegram_api::videoSizeStickerMarkup::ID:
@ -312,6 +315,53 @@ Variant<AnimationSize, CustomEmojiSize> get_animation_size(FileManager *file_man
}
}
CustomEmojiSize get_custom_emoji_size(const td_api::object_ptr<td_api::chatPhotoCustomEmoji> &custom_emoji) {
if (custom_emoji == nullptr || custom_emoji->background_fill_ == nullptr) {
return {};
}
CustomEmojiSize result;
result.custom_emoji_id = CustomEmojiId(custom_emoji->custom_emoji_id_);
auto fill = custom_emoji->background_fill_.get();
switch (fill->get_id()) {
case td_api::backgroundFillSolid::ID: {
auto solid = static_cast<const td_api::backgroundFillSolid *>(fill);
result.background_colors.push_back(solid->color_);
break;
}
case td_api::backgroundFillGradient::ID: {
auto gradient = static_cast<const td_api::backgroundFillGradient *>(fill);
result.background_colors.push_back(gradient->top_color_);
result.background_colors.push_back(gradient->bottom_color_);
break;
}
case td_api::backgroundFillFreeformGradient::ID: {
auto freeform = static_cast<const td_api::backgroundFillFreeformGradient *>(fill);
if (freeform->colors_.size() != 3 && freeform->colors_.size() != 4) {
return {};
}
result.background_colors = freeform->colors_;
break;
}
default:
UNREACHABLE();
break;
}
for (auto &color : result.background_colors) {
color &= 0xFFFFFF;
}
return result;
}
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;
}
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,
tl_object_ptr<telegram_api::WebDocument> web_document_ptr) {
if (web_document_ptr == nullptr) {

View File

@ -64,6 +64,10 @@ Variant<AnimationSize, CustomEmojiSize> get_animation_size(FileManager *file_man
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);
telegram_api::object_ptr<telegram_api::VideoSize> get_input_video_size_object(const CustomEmojiSize &custom_emoji_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);

View File

@ -6980,7 +6980,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.is_public_, std::move(promise));
contacts_manager_->set_profile_photo(request.photo_, request.custom_emoji_, request.is_public_, std::move(promise));
}
void Td::on_request(uint64 id, const td_api::deleteProfilePhoto &request) {

View File

@ -4859,10 +4859,10 @@ class CliClient final : public Actor {
int64 profile_photo_id;
get_args(args, profile_photo_id);
send_request(td_api::make_object<td_api::setProfilePhoto>(
td_api::make_object<td_api::inputChatPhotoPrevious>(profile_photo_id), op == "spppf"));
td_api::make_object<td_api::inputChatPhotoPrevious>(profile_photo_id), nullptr, op == "spppf"));
} else if (op == "spp" || op == "sppf") {
send_request(td_api::make_object<td_api::setProfilePhoto>(
td_api::make_object<td_api::inputChatPhotoStatic>(as_input_file(args)), op == "sppf"));
td_api::make_object<td_api::inputChatPhotoStatic>(as_input_file(args)), nullptr, op == "sppf"));
} else if (op == "sppa" || op == "sppaf") {
string animation;
string main_frame_timestamp;
@ -4870,7 +4870,27 @@ class CliClient final : public Actor {
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)),
op == "sppaf"));
nullptr, op == "sppaf"));
} else if (op == "spppce" || op == "spppcef") {
string photo;
int64 custom_emoji_id;
get_args(args, photo, custom_emoji_id);
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)),
op == "spppcef"));
} else if (op == "sppace" || op == "sppacef") {
string animation;
string main_frame_timestamp;
int64 custom_emoji_id;
get_args(args, animation, main_frame_timestamp, custom_emoji_id);
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)),
op == "sppacef"));
} else if (op == "suppp") {
UserId user_id;
string photo;