diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 17ba6b439..fb376f306 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -364,19 +364,22 @@ game id:int64 short_name:string title:string text:formattedText description:stri poll id:int64 question:string options:vector total_voter_count:int32 recent_voter_user_ids:vector is_anonymous:Bool type:PollType open_period:int32 close_date:int32 is_closed:Bool = Poll; -//@description Describes a user profile photo @id Photo identifier; 0 for an empty photo. Can be used to find a photo in a list of user profile photos +//@description Describes a user profile photo +//@id Photo identifier; 0 for an empty photo. Can be used to find a photo in a list of user profile photos //@small A small (160x160) user profile photo. The file can be downloaded only before the photo is changed //@big A big (640x640) user profile photo. The file can be downloaded only before the photo is changed //@minithumbnail User profile photo minithumbnail; may be null //@has_animation True, if the photo has animated variant -profilePhoto id:int64 small:file big:file minithumbnail:minithumbnail has_animation:Bool = ProfilePhoto; +//@is_personal True, if the photo is visible only for the current user +profilePhoto id:int64 small:file big:file minithumbnail:minithumbnail has_animation:Bool is_personal:Bool = ProfilePhoto; //@description Contains basic information about the photo of a chat //@small A small (160x160) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed //@big A big (640x640) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed //@minithumbnail Chat photo minithumbnail; may be null //@has_animation True, if the photo has animated variant -chatPhotoInfo small:file big:file minithumbnail:minithumbnail has_animation:Bool = ChatPhotoInfo; +//@is_personal True, if the photo is visible only for the current user +chatPhotoInfo small:file big:file minithumbnail:minithumbnail has_animation:Bool is_personal:Bool = ChatPhotoInfo; //@class UserType @description Represents the type of a user. The following types are possible: regular users, deleted users and bots diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index c6e80fc36..980b94856 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -10789,7 +10789,7 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val } } - if (!is_same_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), chat_full->photo, c->photo)) { + if (!is_same_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), chat_full->photo, c->photo, false)) { chat_full->photo = Photo(); if (c->photo.small_file_id.is_valid()) { reload_chat_full(chat_id, Auto()); @@ -10900,7 +10900,7 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s } } - if (!is_same_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), channel_full->photo, c->photo)) { + if (!is_same_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), channel_full->photo, c->photo, false)) { channel_full->photo = Photo(); if (c->photo.small_file_id.is_valid()) { channel_full->expires_at = 0.0; @@ -11134,7 +11134,7 @@ void ContactsManager::update_chat(Chat *c, ChatId chat_id, bool from_binlog, boo auto chat_full = get_chat_full(chat_id); // must not load ChatFull if (chat_full != nullptr && - !is_same_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), chat_full->photo, c->photo)) { + !is_same_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), chat_full->photo, c->photo, false)) { on_update_chat_full_photo(chat_full, chat_id, Photo()); if (chat_full->is_update_chat_full_sent) { need_update_chat_full = true; @@ -11211,7 +11211,7 @@ void ContactsManager::update_channel(Channel *c, ChannelId channel_id, bool from auto channel_full = get_channel_full(channel_id, true, "update_channel"); if (channel_full != nullptr && - !is_same_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), channel_full->photo, c->photo)) { + !is_same_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), channel_full->photo, c->photo, false)) { on_update_channel_full_photo(channel_full, channel_id, Photo()); if (channel_full->is_update_channel_full_sent) { need_update_channel_full = true; @@ -11677,8 +11677,8 @@ void ContactsManager::on_get_user_full(tl_object_ptr &&u auto photo = get_photo(td_->file_manager_.get(), std::move(user->profile_photo_), DialogId(user_id)); // do_update_user_photo should be a no-op if server sent consistent data - do_update_user_photo(u, user_id, as_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, photo), false, - "on_get_user_full"); + do_update_user_photo(u, user_id, as_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, photo, false), + false, "on_get_user_full"); if (photo != user_full->photo) { user_full->photo = std::move(photo); user_full->is_changed = true; @@ -11735,7 +11735,7 @@ void ContactsManager::on_get_user_photos(UserId user_id, int32 offset, int32 lim if (photo_ptr->get_id() == telegram_api::photo::ID) { auto server_photo = telegram_api::move_object_as(photo_ptr); if (server_photo->id_ == u->photo.id) { - auto profile_photo = convert_photo_to_profile_photo(server_photo); + auto profile_photo = convert_photo_to_profile_photo(server_photo, u->photo.is_personal); if (profile_photo) { LOG_IF(ERROR, u->access_hash == -1) << "Receive profile photo of " << user_id << " without access hash"; get_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, std::move(profile_photo)); @@ -11913,7 +11913,8 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c 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)); // 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); + on_update_chat_photo(c, chat_id, as_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), 0, photo, false), + false); on_update_chat_full_photo(chat_full, chat_id, std::move(photo)); if (chat_full->description != chat->about_) { chat_full->description = std::move(chat->about_); @@ -12084,7 +12085,8 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c auto photo = get_photo(td_->file_manager_.get(), 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); + c, channel_id, as_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), c->access_hash, photo, false), + false); on_update_channel_full_photo(channel_full, channel_id, std::move(photo)); td_->messages_manager_->on_read_channel_outbox(channel_id, @@ -12803,8 +12805,8 @@ void ContactsManager::add_profile_photo_to_cache(UserId user_id, Photo &&photo) } // update ProfilePhoto in User - do_update_user_photo(u, user_id, as_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, photo), false, - "add_profile_photo_to_cache"); + do_update_user_photo(u, user_id, as_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, photo, false), + false, "add_profile_photo_to_cache"); update_user(u, user_id); // update Photo in UserFull @@ -12865,9 +12867,10 @@ bool ContactsManager::delete_profile_photo_from_cache(UserId user_id, int64 prof bool need_reget_user = false; if (is_main_photo_deleted) { if (have_new_photo) { - do_update_user_photo(u, user_id, - as_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, user_photos->photos[0]), - false, "delete_profile_photo_from_cache"); + do_update_user_photo( + u, user_id, + as_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, user_photos->photos[0], false), false, + "delete_profile_photo_from_cache"); } else { do_update_user_photo(u, user_id, ProfilePhoto(), false, "delete_profile_photo_from_cache 2"); need_reget_user = user_photos == nullptr || user_photos->count != 0; @@ -15772,7 +15775,7 @@ bool ContactsManager::is_chat_full_outdated(const ChatFull *chat_full, const Cha } if (!only_participants && - !is_same_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), chat_full->photo, c->photo)) { + !is_same_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), chat_full->photo, c->photo, false)) { LOG(INFO) << "Have outdated chat photo in " << chat_id; return true; } @@ -17916,7 +17919,7 @@ tl_object_ptr ContactsManager::get_chat_invite_link_ description = get_dialog_about(dialog_id); } else { title = invite_link_info->title; - invite_link_photo = as_fake_dialog_photo(invite_link_info->photo, dialog_id); + invite_link_photo = as_fake_dialog_photo(invite_link_info->photo, dialog_id, false); photo = &invite_link_photo; description = invite_link_info->description; participant_count = invite_link_info->participant_count; diff --git a/td/telegram/Photo.cpp b/td/telegram/Photo.cpp index 2a9f10a85..d562308c5 100644 --- a/td/telegram/Photo.cpp +++ b/td/telegram/Photo.cpp @@ -38,6 +38,7 @@ ProfilePhoto get_profile_photo(FileManager *file_manager, UserId user_id, int64 auto dc_id = DcId::create(profile_photo->dc_id_); result.has_animation = profile_photo->has_video_; + result.is_personal = profile_photo->personal_; result.id = profile_photo->photo_id_; result.minithumbnail = profile_photo->stripped_thumb_.as_slice().str(); result.small_file_id = register_photo_size( @@ -64,7 +65,7 @@ tl_object_ptr get_profile_photo_object(FileManager *file_m return td_api::make_object( profile_photo.id, file_manager->get_file_object(profile_photo.small_file_id), file_manager->get_file_object(profile_photo.big_file_id), get_minithumbnail_object(profile_photo.minithumbnail), - profile_photo.has_animation); + profile_photo.has_animation, profile_photo.is_personal); } bool need_update_profile_photo(const ProfilePhoto &from, const ProfilePhoto &to) { @@ -74,7 +75,8 @@ bool need_update_profile_photo(const ProfilePhoto &from, const ProfilePhoto &to) StringBuilder &operator<<(StringBuilder &string_builder, const ProfilePhoto &profile_photo) { return string_builder << ""; + << ", has_animation = " << profile_photo.has_animation + << ", is_personal = " << profile_photo.is_personal << '>'; } DialogPhoto get_dialog_photo(FileManager *file_manager, DialogId dialog_id, int64 dialog_access_hash, @@ -90,6 +92,7 @@ DialogPhoto get_dialog_photo(FileManager *file_manager, DialogId dialog_id, int6 auto dc_id = DcId::create(chat_photo->dc_id_); result.has_animation = chat_photo->has_video_; + result.is_personal = false; result.minithumbnail = chat_photo->stripped_thumb_.as_slice().str(); result.small_file_id = register_photo_size(file_manager, PhotoSizeSource::dialog_photo(dialog_id, dialog_access_hash, false), @@ -116,7 +119,7 @@ tl_object_ptr get_chat_photo_info_object(FileManager *fil return td_api::make_object(file_manager->get_file_object(dialog_photo->small_file_id), file_manager->get_file_object(dialog_photo->big_file_id), get_minithumbnail_object(dialog_photo->minithumbnail), - dialog_photo->has_animation); + dialog_photo->has_animation, dialog_photo->is_personal); } vector dialog_photo_get_file_ids(const DialogPhoto &dialog_photo) { @@ -130,7 +133,7 @@ vector dialog_photo_get_file_ids(const DialogPhoto &dialog_photo) { return result; } -DialogPhoto as_fake_dialog_photo(const Photo &photo, DialogId dialog_id) { +DialogPhoto as_fake_dialog_photo(const Photo &photo, DialogId dialog_id, bool is_personal) { DialogPhoto result; if (!photo.is_empty()) { for (auto &size : photo.photos) { @@ -142,6 +145,7 @@ DialogPhoto as_fake_dialog_photo(const Photo &photo, DialogId dialog_id) { } result.minithumbnail = photo.minithumbnail; result.has_animation = !photo.animations.empty(); + result.is_personal = is_personal; if (!result.small_file_id.is_valid() || !result.big_file_id.is_valid()) { LOG(ERROR) << "Failed to convert " << photo << " to chat photo of " << dialog_id; return DialogPhoto(); @@ -150,10 +154,10 @@ DialogPhoto as_fake_dialog_photo(const Photo &photo, DialogId dialog_id) { return result; } -DialogPhoto as_dialog_photo(FileManager *file_manager, DialogId dialog_id, int64 dialog_access_hash, - const Photo &photo) { +DialogPhoto as_dialog_photo(FileManager *file_manager, DialogId dialog_id, int64 dialog_access_hash, const Photo &photo, + bool is_personal) { DialogPhoto result; - static_cast(result) = as_fake_dialog_photo(photo, dialog_id); + static_cast(result) = as_fake_dialog_photo(photo, dialog_id, is_personal); if (!result.small_file_id.is_valid()) { return result; } @@ -175,9 +179,11 @@ DialogPhoto as_dialog_photo(FileManager *file_manager, DialogId dialog_id, int64 return result; } -ProfilePhoto as_profile_photo(FileManager *file_manager, UserId user_id, int64 user_access_hash, const Photo &photo) { +ProfilePhoto as_profile_photo(FileManager *file_manager, UserId user_id, int64 user_access_hash, const Photo &photo, + bool is_personal) { ProfilePhoto result; - static_cast(result) = as_dialog_photo(file_manager, DialogId(user_id), user_access_hash, photo); + static_cast(result) = + as_dialog_photo(file_manager, DialogId(user_id), user_access_hash, photo, is_personal); if (result.small_file_id.is_valid()) { result.id = photo.id.get(); } @@ -185,24 +191,25 @@ ProfilePhoto as_profile_photo(FileManager *file_manager, UserId user_id, int64 u } bool is_same_dialog_photo(FileManager *file_manager, DialogId dialog_id, const Photo &photo, - const DialogPhoto &dialog_photo) { + const DialogPhoto &dialog_photo, bool is_personal) { auto get_unique_file_id = [file_manager](FileId file_id) { return file_manager->get_file_view(file_id).get_unique_file_id(); }; - auto fake_photo = as_fake_dialog_photo(photo, dialog_id); + auto fake_photo = as_fake_dialog_photo(photo, dialog_id, is_personal); return get_unique_file_id(fake_photo.small_file_id) == get_unique_file_id(dialog_photo.small_file_id) && get_unique_file_id(fake_photo.big_file_id) == get_unique_file_id(dialog_photo.big_file_id); } bool need_update_dialog_photo(const DialogPhoto &from, const DialogPhoto &to) { return from.small_file_id != to.small_file_id || from.big_file_id != to.big_file_id || - from.has_animation != to.has_animation; + from.has_animation != to.has_animation || from.is_personal != to.is_personal; } StringBuilder &operator<<(StringBuilder &string_builder, const DialogPhoto &dialog_photo) { return string_builder << ""; + << ", has_animation = " << dialog_photo.has_animation + << ", is_personal = " << dialog_photo.is_personal << '>'; } static tl_object_ptr get_photo_size_object(FileManager *file_manager, const PhotoSize *photo_size) { @@ -562,7 +569,7 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Photo &photo) { } tl_object_ptr convert_photo_to_profile_photo( - const tl_object_ptr &photo) { + const tl_object_ptr &photo, bool is_personal) { if (photo == nullptr) { return nullptr; } @@ -611,7 +618,8 @@ tl_object_ptr convert_photo_to_profile_photo( return nullptr; } bool has_video = !photo->video_sizes_.empty(); - return make_tl_object(0, has_video, false, photo->id_, BufferSlice(), photo->dc_id_); + return make_tl_object(0, has_video, is_personal, photo->id_, BufferSlice(), + photo->dc_id_); } } // namespace td diff --git a/td/telegram/Photo.h b/td/telegram/Photo.h index 43a22ff5c..054a52350 100644 --- a/td/telegram/Photo.h +++ b/td/telegram/Photo.h @@ -30,6 +30,7 @@ struct DialogPhoto { FileId big_file_id; string minithumbnail; bool has_animation = false; + bool is_personal = false; }; struct ProfilePhoto final : public DialogPhoto { @@ -78,15 +79,16 @@ DialogPhoto get_dialog_photo(FileManager *file_manager, DialogId dialog_id, int6 tl_object_ptr get_chat_photo_info_object(FileManager *file_manager, const DialogPhoto *dialog_photo); -DialogPhoto as_fake_dialog_photo(const Photo &photo, DialogId dialog_id); +DialogPhoto as_fake_dialog_photo(const Photo &photo, DialogId dialog_id, bool is_personal); -DialogPhoto as_dialog_photo(FileManager *file_manager, DialogId dialog_id, int64 dialog_access_hash, - const Photo &photo); +DialogPhoto as_dialog_photo(FileManager *file_manager, DialogId dialog_id, int64 dialog_access_hash, const Photo &photo, + bool is_personal); -ProfilePhoto as_profile_photo(FileManager *file_manager, UserId user_id, int64 user_access_hash, const Photo &photo); +ProfilePhoto as_profile_photo(FileManager *file_manager, UserId user_id, int64 user_access_hash, const Photo &photo, + bool is_personal); bool is_same_dialog_photo(FileManager *file_manager, DialogId dialog_id, const Photo &photo, - const DialogPhoto &dialog_photo); + const DialogPhoto &dialog_photo, bool is_personal); vector dialog_photo_get_file_ids(const DialogPhoto &dialog_photo); @@ -129,6 +131,6 @@ bool operator!=(const Photo &lhs, const Photo &rhs); StringBuilder &operator<<(StringBuilder &string_builder, const Photo &photo); tl_object_ptr convert_photo_to_profile_photo( - const tl_object_ptr &photo); + const tl_object_ptr &photo, bool is_personal); } // namespace td diff --git a/td/telegram/Photo.hpp b/td/telegram/Photo.hpp index 1003e9529..5c90586d5 100644 --- a/td/telegram/Photo.hpp +++ b/td/telegram/Photo.hpp @@ -23,6 +23,7 @@ void store(const DialogPhoto &dialog_photo, StorerT &storer) { STORE_FLAG(has_file_ids); STORE_FLAG(dialog_photo.has_animation); STORE_FLAG(has_minithumbnail); + STORE_FLAG(dialog_photo.is_personal); END_STORE_FLAGS(); if (has_file_ids) { store(dialog_photo.small_file_id, storer); @@ -42,6 +43,7 @@ void parse(DialogPhoto &dialog_photo, ParserT &parser) { PARSE_FLAG(has_file_ids); PARSE_FLAG(dialog_photo.has_animation); PARSE_FLAG(has_minithumbnail); + PARSE_FLAG(dialog_photo.is_personal); END_PARSE_FLAGS(); } if (has_file_ids) {