From 7b8ce74ec2522e12531c1e6e08dc153fa8c45757 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 15 Dec 2022 17:44:26 +0300 Subject: [PATCH] Allow to set fallback profile photo. --- td/generate/scheme/td_api.tl | 4 +- td/telegram/ContactsManager.cpp | 94 +++++++++++++++++++-------------- td/telegram/ContactsManager.h | 23 ++++---- td/telegram/Td.cpp | 2 +- td/telegram/cli.cpp | 16 +++--- 5 files changed, 80 insertions(+), 59 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 8dbb62d43..03d9d80f8 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -7153,8 +7153,8 @@ 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 -setProfilePhoto photo:InputChatPhoto = Ok; +//@description Changes a profile photo for the current user @photo Profile photo to set @is_fallback Pass true to set a fallback photo, which will be visible even the main photo is hidden by privacy settings +setProfilePhoto photo:InputChatPhoto is_fallback:Bool = Ok; //@description Deletes a profile photo @profile_photo_id Identifier of the profile photo to delete deleteProfilePhoto profile_photo_id:int64 = Ok; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 8548281aa..8aa733cd2 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -439,18 +439,20 @@ class UploadProfilePhotoQuery final : public Td::ResultHandler { Promise promise_; UserId user_id_; FileId file_id_; + bool is_fallback_; public: explicit UploadProfilePhotoQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(UserId user_id, FileId file_id, tl_object_ptr &&input_file, bool is_animation, - double main_frame_timestamp) { + void send(UserId user_id, FileId file_id, tl_object_ptr &&input_file, bool is_fallback, + bool is_animation, double main_frame_timestamp) { CHECK(input_file != nullptr); CHECK(file_id.is_valid()); user_id_ = user_id; file_id_ = file_id; + is_fallback_ = is_fallback; static_assert(telegram_api::photos_uploadProfilePhoto::VIDEO_MASK == telegram_api::photos_uploadContactProfilePhoto::VIDEO_MASK, @@ -477,6 +479,9 @@ class UploadProfilePhotoQuery final : public Td::ResultHandler { photo_input_file = std::move(input_file); } if (user_id == td_->contacts_manager_->get_my_id()) { + if (is_fallback) { + flags |= telegram_api::photos_uploadProfilePhoto::FALLBACK_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), @@ -504,7 +509,7 @@ class UploadProfilePhotoQuery final : public Td::ResultHandler { return on_error(result_ptr.move_as_error()); } - td_->contacts_manager_->on_set_profile_photo(user_id_, result_ptr.move_as_ok(), 0); + td_->contacts_manager_->on_set_profile_photo(user_id_, result_ptr.move_as_ok(), is_fallback_, 0); td_->file_manager_->delete_partial_remote_location(file_id_); @@ -521,18 +526,24 @@ class UpdateProfilePhotoQuery final : public Td::ResultHandler { Promise promise_; FileId file_id_; int64 old_photo_id_; + bool is_fallback_; string file_reference_; public: explicit UpdateProfilePhotoQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(FileId file_id, int64 old_photo_id, tl_object_ptr &&input_photo) { + void send(FileId file_id, int64 old_photo_id, bool is_fallback, + tl_object_ptr &&input_photo) { CHECK(input_photo != nullptr); file_id_ = file_id; old_photo_id_ = old_photo_id; + is_fallback_ = is_fallback; file_reference_ = FileManager::extract_file_reference(input_photo); int32 flags = 0; + if (is_fallback) { + flags |= telegram_api::photos_updateProfilePhoto::FALLBACK_MASK; + } send_query(G()->net_query_creator().create( telegram_api::photos_updateProfilePhoto(flags, false /*ignored*/, std::move(input_photo)), {{"me"}})); } @@ -544,7 +555,7 @@ class UpdateProfilePhotoQuery final : public Td::ResultHandler { } td_->contacts_manager_->on_set_profile_photo(td_->contacts_manager_->get_my_id(), result_ptr.move_as_ok(), - old_photo_id_); + is_fallback_, old_photo_id_); promise_.set_value(Unit()); } @@ -555,14 +566,15 @@ class UpdateProfilePhotoQuery final : public Td::ResultHandler { VLOG(file_references) << "Receive " << status << " for " << file_id_; td_->file_manager_->delete_file_reference(file_id_, file_reference_); td_->file_reference_manager_->repair_file_reference( - file_id_, PromiseCreator::lambda([file_id = file_id_, old_photo_id = old_photo_id_, - promise = std::move(promise_)](Result result) mutable { + file_id_, + PromiseCreator::lambda([file_id = file_id_, is_fallback = is_fallback_, old_photo_id = old_photo_id_, + promise = std::move(promise_)](Result result) mutable { if (result.is_error()) { return promise.set_error(Status::Error(400, "Can't find the photo")); } send_closure(G()->contacts_manager(), &ContactsManager::send_update_profile_photo_query, file_id, - old_photo_id, std::move(promise)); + old_photo_id, is_fallback, std::move(promise)); })); return; } else { @@ -6910,14 +6922,14 @@ FileId ContactsManager::get_profile_photo_file_id(int64 photo_id) const { return it->second; } -void ContactsManager::set_profile_photo(const td_api::object_ptr &input_photo, +void ContactsManager::set_profile_photo(const td_api::object_ptr &input_photo, bool is_fallback, Promise &&promise) { - set_profile_photo_impl(get_my_id(), input_photo, std::move(promise)); + set_profile_photo_impl(get_my_id(), input_photo, is_fallback, std::move(promise)); } void ContactsManager::set_profile_photo_impl(UserId user_id, const td_api::object_ptr &input_photo, - Promise &&promise) { + bool is_fallback, Promise &&promise) { if (input_photo == nullptr) { return promise.set_error(Status::Error(400, "New profile photo must be non-empty")); } @@ -6942,7 +6954,7 @@ void ContactsManager::set_profile_photo_impl(UserId user_id, return promise.set_error(Status::Error(400, "Unknown profile photo ID specified")); } return send_update_profile_photo_query(td_->file_manager_->dup_file_id(file_id, "set_profile_photo_impl"), - photo_id, std::move(promise)); + photo_id, is_fallback, std::move(promise)); } case td_api::inputChatPhotoStatic::ID: { auto photo = static_cast(input_photo.get()); @@ -6975,8 +6987,8 @@ 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_animation, - main_frame_timestamp, std::move(promise)); + upload_profile_photo(user_id, td_->file_manager_->dup_file_id(file_id, "set_profile_photo_impl"), is_fallback, + is_animation, main_frame_timestamp, std::move(promise)); } void ContactsManager::set_user_profile_photo(UserId user_id, @@ -6993,22 +7005,23 @@ void ContactsManager::set_user_profile_photo(UserId user_id, return promise.set_error(Status::Error(400, "Can't set personal photo to self")); } - set_profile_photo_impl(user_id, input_photo, std::move(promise)); + set_profile_photo_impl(user_id, input_photo, false, std::move(promise)); } -void ContactsManager::send_update_profile_photo_query(FileId file_id, int64 old_photo_id, Promise &&promise) { +void ContactsManager::send_update_profile_photo_query(FileId file_id, int64 old_photo_id, bool is_fallback, + Promise &&promise) { FileView file_view = td_->file_manager_->get_file_view(file_id); td_->create_handler(std::move(promise)) - ->send(file_id, old_photo_id, file_view.main_remote_location().as_input_photo()); + ->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_animation, +void ContactsManager::upload_profile_photo(UserId user_id, FileId file_id, bool is_fallback, bool is_animation, double main_frame_timestamp, Promise &&promise, int reupload_count, vector bad_parts) { CHECK(file_id.is_valid()); bool is_inserted = uploaded_profile_photos_ - .emplace(file_id, UploadedProfilePhoto{user_id, main_frame_timestamp, is_animation, - reupload_count, std::move(promise)}) + .emplace(file_id, UploadedProfilePhoto{user_id, is_fallback, 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 @@ -7021,7 +7034,7 @@ void ContactsManager::delete_profile_photo(int64 profile_photo_id, Promise const User *u = get_user(get_my_id()); if (u != nullptr && u->photo.id == profile_photo_id) { td_->create_handler(std::move(promise)) - ->send(FileId(), profile_photo_id, make_tl_object()); + ->send(FileId(), profile_photo_id, false, make_tl_object()); return; } @@ -12866,15 +12879,15 @@ void ContactsManager::on_ignored_restriction_reasons_changed() { } void ContactsManager::on_set_profile_photo(UserId user_id, tl_object_ptr &&photo, - int64 old_photo_id) { + bool is_fallback, int64 old_photo_id) { LOG(INFO) << "Changed profile photo to " << to_string(photo); bool is_my = (user_id == get_my_id()); if (is_my) { delete_profile_photo_from_cache(user_id, old_photo_id, false); } - add_set_profile_photo_to_cache(user_id, - get_photo(td_->file_manager_.get(), std::move(photo->photo_), DialogId(user_id))); + add_set_profile_photo_to_cache( + user_id, get_photo(td_->file_manager_.get(), std::move(photo->photo_), DialogId(user_id)), is_fallback); User *u = get_user(user_id); if (u != nullptr) { @@ -12910,7 +12923,7 @@ int64 ContactsManager::get_user_full_profile_photo_id(const UserFull *user_full) return user_full->fallback_photo.id.get(); } -void ContactsManager::add_set_profile_photo_to_cache(UserId user_id, Photo &&photo) { +void ContactsManager::add_set_profile_photo_to_cache(UserId user_id, Photo &&photo, bool is_fallback) { if (photo.is_empty()) { return; } @@ -12929,7 +12942,7 @@ void ContactsManager::add_set_profile_photo_to_cache(UserId user_id, Photo &&pho // update photo list auto user_photos = user_photos_.get_pointer(user_id); - if (is_me && user_photos != nullptr && user_photos->count != -1) { + if (is_me && !is_fallback && user_photos != nullptr && user_photos->count != -1) { if (user_photos->offset == 0) { if (user_photos->photos.empty() || user_photos->photos[0].id.get() != photo.id.get()) { user_photos->photos.insert(user_photos->photos.begin(), photo); @@ -12950,18 +12963,18 @@ void ContactsManager::add_set_profile_photo_to_cache(UserId user_id, Photo &&pho // update Photo in UserFull auto user_full = get_user_full_force(user_id); if (user_full != nullptr) { - if (is_me) { - if (user_full->photo != photo) { - user_full->photo = photo; - user_full->is_changed = true; - register_user_photo(u, user_id, photo); - } + Photo *current_photo = nullptr; + if (!is_me) { + current_photo = &user_full->personal_photo; + } else if (!is_fallback) { + current_photo = &user_full->photo; } else { - if (user_full->personal_photo != photo) { - user_full->personal_photo = photo; - user_full->is_changed = true; - register_user_photo(u, user_id, photo); - } + current_photo = &user_full->fallback_photo; + } + if (*current_photo != photo) { + *current_photo = photo; + user_full->is_changed = true; + register_user_photo(u, user_id, photo); } update_user_full(user_full, user_id, "add_set_profile_photo_to_cache"); } @@ -17665,6 +17678,7 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptrsecond.user_id; + bool is_fallback = it->second.is_fallback; double main_frame_timestamp = it->second.main_frame_timestamp; bool is_animation = it->second.is_animation; int32 reupload_count = it->second.reupload_count; @@ -17695,14 +17709,14 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptrfile_manager_->delete_file_reference(file_id, file_reference); - upload_profile_photo(user_id, file_id, is_animation, main_frame_timestamp, std::move(promise), reupload_count + 1, - {-1}); + upload_profile_photo(user_id, file_id, is_fallback, is_animation, main_frame_timestamp, std::move(promise), + reupload_count + 1, {-1}); return; } CHECK(input_file != nullptr); td_->create_handler(std::move(promise)) - ->send(user_id, file_id, std::move(input_file), is_animation, main_frame_timestamp); + ->send(user_id, file_id, std::move(input_file), is_fallback, is_animation, main_frame_timestamp); } void ContactsManager::on_upload_profile_photo_error(FileId file_id, Status status) { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 714eed9b9..1b00a3974 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -188,7 +188,8 @@ class ContactsManager final : public Actor { void on_update_user_common_chat_count(UserId user_id, int32 common_chat_count); void on_update_user_need_phone_number_privacy_exception(UserId user_id, bool need_phone_number_privacy_exception); - void on_set_profile_photo(UserId user_id, tl_object_ptr &&photo, int64 old_photo_id); + void on_set_profile_photo(UserId user_id, tl_object_ptr &&photo, bool is_fallback, + int64 old_photo_id); void on_delete_profile_photo(int64 profile_photo_id, Promise promise); @@ -362,12 +363,13 @@ class ContactsManager final : public Actor { FileId get_profile_photo_file_id(int64 photo_id) const; - void set_profile_photo(const td_api::object_ptr &input_photo, Promise &&promise); + void set_profile_photo(const td_api::object_ptr &input_photo, bool is_fallback, + Promise &&promise); void set_user_profile_photo(UserId user_id, const td_api::object_ptr &input_photo, Promise &&promise); - void send_update_profile_photo_query(FileId file_id, int64 old_photo_id, Promise &&promise); + void send_update_profile_photo_query(FileId file_id, int64 old_photo_id, bool is_fallback, Promise &&promise); void delete_profile_photo(int64 profile_photo_id, Promise &&promise); @@ -1343,10 +1345,11 @@ 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 &input_photo, - Promise &&promise); + bool is_fallback, Promise &&promise); - void upload_profile_photo(UserId user_id, FileId file_id, bool is_animation, double main_frame_timestamp, - Promise &&promise, int reupload_count = 0, vector bad_parts = {}); + void upload_profile_photo(UserId user_id, FileId file_id, bool is_fallback, bool is_animation, + double main_frame_timestamp, Promise &&promise, int reupload_count = 0, + vector bad_parts = {}); void on_upload_profile_photo(FileId file_id, tl_object_ptr input_file); void on_upload_profile_photo_error(FileId file_id, Status status); @@ -1364,7 +1367,7 @@ class ContactsManager final : public Actor { UserPhotos *add_user_photos(UserId user_id); int64 get_user_full_profile_photo_id(const UserFull *user_full); - void add_set_profile_photo_to_cache(UserId user_id, Photo &&photo); + void add_set_profile_photo_to_cache(UserId user_id, Photo &&photo, bool is_fallback); bool delete_profile_photo_from_cache(UserId user_id, int64 profile_photo_id, bool send_updates); void drop_user_photos(UserId user_id, bool is_empty, bool drop_user_full_photo, const char *source); void drop_user_full(UserId user_id); @@ -1873,14 +1876,16 @@ class ContactsManager final : public Actor { struct UploadedProfilePhoto { UserId user_id; + bool is_fallback; double main_frame_timestamp; bool is_animation; int reupload_count; Promise promise; - UploadedProfilePhoto(UserId user_id, double main_frame_timestamp, bool is_animation, int32 reupload_count, - Promise promise) + UploadedProfilePhoto(UserId user_id, bool is_fallback, double main_frame_timestamp, bool is_animation, + int32 reupload_count, Promise promise) : user_id(user_id) + , is_fallback(is_fallback) , main_frame_timestamp(main_frame_timestamp) , is_animation(is_animation) , reupload_count(reupload_count) diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 63f3a0484..6ff37ca55 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6970,7 +6970,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_, std::move(promise)); + contacts_manager_->set_profile_photo(request.photo_, request.is_fallback_, std::move(promise)); } void Td::on_request(uint64 id, const td_api::deleteProfilePhoto &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 93f114410..daa24e290 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4799,20 +4799,22 @@ class CliClient final : public Actor { bool force_full; get_args(args, url, force_full); send_request(td_api::make_object(url, force_full)); - } else if (op == "sppp") { + } else if (op == "sppp" || op == "spppf") { int64 profile_photo_id; get_args(args, profile_photo_id); send_request(td_api::make_object( - td_api::make_object(profile_photo_id))); - } else if (op == "spp") { + td_api::make_object(profile_photo_id), op == "spppf")); + } else if (op == "spp" || op == "sppf") { send_request(td_api::make_object( - td_api::make_object(as_input_file(args)))); - } else if (op == "sppa" || op == "sppv") { + td_api::make_object(as_input_file(args)), op == "sppf")); + } else if (op == "sppa" || op == "sppaf") { string animation; string main_frame_timestamp; get_args(args, animation, main_frame_timestamp); - send_request(td_api::make_object(td_api::make_object( - as_input_file(animation), to_double(main_frame_timestamp)))); + send_request( + td_api::make_object(td_api::make_object( + as_input_file(animation), to_double(main_frame_timestamp)), + op == "sppaf")); } else if (op == "sh") { const string &prefix = args; send_request(td_api::make_object(prefix, 10));