Improve setProfilePhoto.
GitOrigin-RevId: 9a5ee470c0a38c7989cef642b2f69faa2228baaa
This commit is contained in:
parent
004e1dcc8d
commit
0ed26e5321
@ -63,7 +63,7 @@ authenticationCodeInfo phone_number:string type:AuthenticationCodeType next_type
|
||||
emailAddressAuthenticationCodeInfo email_address_pattern:string length:int32 = EmailAddressAuthenticationCodeInfo;
|
||||
|
||||
|
||||
//@description Represents a part of the text that needs to be formatted in some unusual way @offset Offset of the entity in UTF-16 code units @length Length of the entity, in UTF-16 code units @type Type of the entity
|
||||
//@description Represents a part of the text that needs to be formatted in some unusual way @offset Offset of the entity, in UTF-16 code units @length Length of the entity, in UTF-16 code units @type Type of the entity
|
||||
textEntity offset:int32 length:int32 type:TextEntityType = TextEntity;
|
||||
|
||||
//@description Contains a list of text entities @entities List of text entities
|
||||
@ -355,6 +355,18 @@ chatPhoto id:int64 added_date:int32 sizes:vector<photoSize> animation:photoSize
|
||||
chatPhotos total_count:int32 photos:vector<chatPhoto> = ChatPhotos;
|
||||
|
||||
|
||||
//@class InputChatPhoto @description Describes a photo to be set as a user profile or chat photo
|
||||
|
||||
//@description A previously used profile photo of the current user @chat_photo_id Identifier of the profile photo to reuse
|
||||
inputChatPhotoPrevious chat_photo_id:int64 = InputChatPhoto;
|
||||
|
||||
//@description A static photo in JPEG format @photo Photo to be set as profile photo. Only inputFileLocal and inputFileGenerated are allowed
|
||||
inputChatPhotoStatic photo:InputFile = InputChatPhoto;
|
||||
|
||||
//@description An animation in MPEG4 format; must be square, shorter than 10 seconds, have width between 160 and 800 and be at most 2MB in size @animation Animation to be set as profile photo. Only inputFileLocal and inputFileGenerated are allowed
|
||||
inputChatPhotoAnimation animation:InputFile = InputChatPhoto;
|
||||
|
||||
|
||||
//@description Represents a user @id User identifier @first_name First name of the user @last_name Last name of the user @username Username of the user
|
||||
//@phone_number Phone number of the user @status Current online status of the user @profile_photo Profile photo of the user; may be null
|
||||
//@is_contact The user is a contact of the current user
|
||||
@ -1623,7 +1635,7 @@ textEntityTypeTextUrl url:string = TextEntityType;
|
||||
textEntityTypeMentionName user_id:int32 = TextEntityType;
|
||||
|
||||
|
||||
//@description A thumbnail to be sent along with a file; should be in JPEG or WEBP format for stickers, and less than 200 KB in size @thumbnail Thumbnail file to send. Sending thumbnails by file_id is currently not supported
|
||||
//@description A thumbnail to be sent along with a file; must be in JPEG or WEBP format for stickers, and less than 200 KB in size @thumbnail Thumbnail file to send. Sending thumbnails by file_id is currently not supported
|
||||
//@width Thumbnail width, usually shouldn't exceed 320. Use 0 if unknown @height Thumbnail height, usually shouldn't exceed 320. Use 0 if unknown
|
||||
inputThumbnail thumbnail:InputFile width:int32 height:int32 = InputThumbnail;
|
||||
|
||||
@ -4117,19 +4129,19 @@ getWebPagePreview text:formattedText = WebPage;
|
||||
getWebPageInstantView url:string force_full:Bool = WebPageInstantView;
|
||||
|
||||
|
||||
//@description Uploads a new profile photo for the current user. If something changes, updateUser will be sent @photo Profile photo to set. inputFileId and inputFileRemote may still be unsupported
|
||||
setProfilePhoto photo:InputFile = Ok;
|
||||
//@description Changes a profile photo for the current user @photo Profile photo to set
|
||||
setProfilePhoto photo:InputChatPhoto = Ok;
|
||||
|
||||
//@description Deletes a profile photo. If something changes, updateUser will be sent @profile_photo_id Identifier of the profile photo to delete
|
||||
//@description Deletes a profile photo @profile_photo_id Identifier of the profile photo to delete
|
||||
deleteProfilePhoto profile_photo_id:int64 = Ok;
|
||||
|
||||
//@description Changes the first and last name of the current user. If something changes, updateUser will be sent @first_name The new value of the first name for the user; 1-64 characters @last_name The new value of the optional last name for the user; 0-64 characters
|
||||
//@description Changes the first and last name of the current user @first_name The new value of the first name for the user; 1-64 characters @last_name The new value of the optional last name for the user; 0-64 characters
|
||||
setName first_name:string last_name:string = Ok;
|
||||
|
||||
//@description Changes the bio of the current user @bio The new value of the user bio; 0-70 characters without line feeds
|
||||
setBio bio:string = Ok;
|
||||
|
||||
//@description Changes the username of the current user. If something changes, updateUser will be sent @username The new value of the username. Use an empty string to remove the username
|
||||
//@description Changes the username of the current user @username The new value of the username. Use an empty string to remove the username
|
||||
setUsername username:string = Ok;
|
||||
|
||||
//@description Changes the location of the current user. Needs to be called if GetOption("is_location_visible") is true and location changes for more than 1 kilometer @location The new location of the user
|
||||
|
Binary file not shown.
@ -809,15 +809,24 @@ class UploadProfilePhotoQuery : public Td::ResultHandler {
|
||||
explicit UploadProfilePhotoQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(FileId file_id, tl_object_ptr<telegram_api::InputFile> &&input_file) {
|
||||
void send(FileId file_id, tl_object_ptr<telegram_api::InputFile> &&input_file, bool is_animation) {
|
||||
CHECK(input_file != nullptr);
|
||||
CHECK(file_id.is_valid());
|
||||
|
||||
file_id_ = file_id;
|
||||
|
||||
int32 flags = telegram_api::photos_uploadProfilePhoto::FILE_MASK;
|
||||
int32 flags = 0;
|
||||
tl_object_ptr<telegram_api::InputFile> photo_input_file;
|
||||
tl_object_ptr<telegram_api::InputFile> video_input_file;
|
||||
if (is_animation) {
|
||||
flags |= telegram_api::photos_uploadProfilePhoto::VIDEO_MASK;
|
||||
video_input_file = std::move(input_file);
|
||||
} else {
|
||||
flags |= telegram_api::photos_uploadProfilePhoto::FILE_MASK;
|
||||
photo_input_file = std::move(input_file);
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::photos_uploadProfilePhoto(flags, std::move(input_file), nullptr, 0)));
|
||||
telegram_api::photos_uploadProfilePhoto(flags, std::move(photo_input_file), std::move(video_input_file), 0)));
|
||||
}
|
||||
|
||||
void on_result(uint64 id, BufferSlice packet) override {
|
||||
@ -876,7 +885,16 @@ class UpdateProfilePhotoQuery : public Td::ResultHandler {
|
||||
if (file_id_.is_valid()) {
|
||||
VLOG(file_references) << "Receive " << status << " for " << file_id_;
|
||||
td->file_manager_->delete_file_reference(file_id_, file_reference_);
|
||||
td->contacts_manager_->upload_profile_photo(file_id_, std::move(promise_));
|
||||
td->file_reference_manager_->repair_file_reference(
|
||||
file_id_,
|
||||
PromiseCreator::lambda([file_id = file_id_, promise = std::move(promise_)](Result<Unit> 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,
|
||||
std::move(promise));
|
||||
}));
|
||||
return;
|
||||
} else {
|
||||
LOG(ERROR) << "Receive file reference error, but file_id = " << file_id_;
|
||||
@ -5362,33 +5380,73 @@ void ContactsManager::update_is_location_visible() {
|
||||
G()->shared_config().set_option_boolean("is_location_visible", expire_date != 0);
|
||||
}
|
||||
|
||||
void ContactsManager::set_profile_photo(const tl_object_ptr<td_api::InputFile> &input_photo, Promise<Unit> &&promise) {
|
||||
auto r_file_id =
|
||||
td_->file_manager_->get_input_file_id(FileType::Photo, input_photo, DialogId(get_my_id()), false, false);
|
||||
void ContactsManager::set_profile_photo(const td_api::object_ptr<td_api::InputChatPhoto> &input_photo,
|
||||
Promise<Unit> &&promise) {
|
||||
if (input_photo == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "New profile photo must be non-empty"));
|
||||
}
|
||||
|
||||
const td_api::object_ptr<td_api::InputFile> *input_file = nullptr;
|
||||
bool is_animation = false;
|
||||
switch (input_photo->get_id()) {
|
||||
case td_api::inputChatPhotoPrevious::ID: {
|
||||
auto photo = static_cast<const td_api::inputChatPhotoPrevious *>(input_photo.get());
|
||||
auto photo_id = photo->chat_photo_id_;
|
||||
if (photo_id <= 0) {
|
||||
return promise.set_error(Status::Error(400, "Wrong profile photo ID specified"));
|
||||
}
|
||||
auto *u = get_user(get_my_id());
|
||||
if (u != nullptr && photo_id == u->photo.id) {
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
auto it = my_photo_file_id_.find(photo_id);
|
||||
if (it == my_photo_file_id_.end()) {
|
||||
return promise.set_error(Status::Error(400, "Profile photo ID not found"));
|
||||
}
|
||||
return send_update_profile_photo_query(td_->file_manager_->dup_file_id(it->second), std::move(promise));
|
||||
}
|
||||
case td_api::inputChatPhotoStatic::ID: {
|
||||
auto photo = static_cast<const td_api::inputChatPhotoStatic *>(input_photo.get());
|
||||
input_file = &photo->photo_;
|
||||
break;
|
||||
}
|
||||
case td_api::inputChatPhotoAnimation::ID: {
|
||||
auto photo = static_cast<const td_api::inputChatPhotoAnimation *>(input_photo.get());
|
||||
input_file = &photo->animation_;
|
||||
is_animation = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
auto file_type = is_animation ? FileType::Animation : FileType::Photo;
|
||||
auto r_file_id = td_->file_manager_->get_input_file_id(file_type, *input_file, DialogId(get_my_id()), false, false);
|
||||
if (r_file_id.is_error()) {
|
||||
// TODO promise.set_error(std::move(status));
|
||||
return promise.set_error(Status::Error(7, r_file_id.error().message()));
|
||||
return promise.set_error(Status::Error(400, r_file_id.error().message()));
|
||||
}
|
||||
FileId file_id = r_file_id.ok();
|
||||
CHECK(file_id.is_valid());
|
||||
|
||||
FileView file_view = td_->file_manager_->get_file_view(file_id);
|
||||
CHECK(!file_view.is_encrypted());
|
||||
if (file_view.has_remote_location() && !file_view.main_remote_location().is_web()) {
|
||||
td_->create_handler<UpdateProfilePhotoQuery>(std::move(promise))
|
||||
->send(td_->file_manager_->dup_file_id(file_id), file_view.main_remote_location().as_input_photo());
|
||||
return;
|
||||
}
|
||||
|
||||
upload_profile_photo(td_->file_manager_->dup_file_id(file_id), std::move(promise));
|
||||
upload_profile_photo(td_->file_manager_->dup_file_id(file_id), is_animation, std::move(promise));
|
||||
}
|
||||
|
||||
void ContactsManager::upload_profile_photo(FileId file_id, Promise<Unit> &&promise) {
|
||||
void ContactsManager::send_update_profile_photo_query(FileId file_id, Promise<Unit> &&promise) {
|
||||
FileView file_view = td_->file_manager_->get_file_view(file_id);
|
||||
td_->create_handler<UpdateProfilePhotoQuery>(std::move(promise))
|
||||
->send(file_id, file_view.main_remote_location().as_input_photo());
|
||||
}
|
||||
|
||||
void ContactsManager::upload_profile_photo(FileId file_id, bool is_animation, Promise<Unit> &&promise,
|
||||
vector<int> bad_parts) {
|
||||
CHECK(file_id.is_valid());
|
||||
CHECK(uploaded_profile_photos_.find(file_id) == uploaded_profile_photos_.end());
|
||||
uploaded_profile_photos_.emplace(file_id, std::move(promise));
|
||||
uploaded_profile_photos_.emplace(file_id, UploadedProfilePhoto{is_animation, !bad_parts.empty(), std::move(promise)});
|
||||
LOG(INFO) << "Ask to upload profile photo " << file_id;
|
||||
td_->file_manager_->upload(file_id, upload_profile_photo_callback_, 32, 0);
|
||||
// TODO use force_reupload
|
||||
td_->file_manager_->resume_upload(file_id, std::move(bad_parts), upload_profile_photo_callback_, 32, 0);
|
||||
}
|
||||
|
||||
void ContactsManager::delete_profile_photo(int64 profile_photo_id, Promise<Unit> &&promise) {
|
||||
@ -9541,8 +9599,10 @@ void ContactsManager::register_user_photo(User *u, UserId user_id, const Photo &
|
||||
return;
|
||||
}
|
||||
CHECK(file_type == FileType::Photo);
|
||||
CHECK(u != nullptr);
|
||||
auto photo_id = photo.id.get();
|
||||
if (u->photo_ids.emplace(photo_id).second) {
|
||||
VLOG(file_references) << "Register photo " << photo_id << " of " << user_id;
|
||||
if (user_id == get_my_id()) {
|
||||
my_photo_file_id_[photo_id] = first_file_id;
|
||||
}
|
||||
@ -13525,25 +13585,30 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<tele
|
||||
auto it = uploaded_profile_photos_.find(file_id);
|
||||
CHECK(it != uploaded_profile_photos_.end());
|
||||
|
||||
auto promise = std::move(it->second);
|
||||
bool is_animation = it->second.is_animation;
|
||||
bool is_reupload = it->second.is_reupload;
|
||||
auto promise = std::move(it->second.promise);
|
||||
|
||||
uploaded_profile_photos_.erase(it);
|
||||
|
||||
FileView file_view = td_->file_manager_->get_file_view(file_id);
|
||||
if (file_view.has_remote_location() && input_file == nullptr) {
|
||||
if (file_view.main_remote_location().is_web()) {
|
||||
// TODO reupload
|
||||
promise.set_error(Status::Error(400, "Can't use web photo as profile photo"));
|
||||
return;
|
||||
return promise.set_error(Status::Error(400, "Can't use web photo as profile photo"));
|
||||
}
|
||||
if (is_reupload) {
|
||||
return promise.set_error(Status::Error(400, "Failed to reuplaod the file"));
|
||||
}
|
||||
|
||||
td_->create_handler<UpdateProfilePhotoQuery>(std::move(promise))
|
||||
->send(file_id, file_view.main_remote_location().as_input_photo());
|
||||
// delete file reference and forcely reupload the file
|
||||
auto file_reference = 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(file_id, is_animation, std::move(promise), {-1});
|
||||
return;
|
||||
}
|
||||
CHECK(input_file != nullptr);
|
||||
|
||||
td_->create_handler<UploadProfilePhotoQuery>(std::move(promise))->send(file_id, std::move(input_file));
|
||||
td_->create_handler<UploadProfilePhotoQuery>(std::move(promise))->send(file_id, std::move(input_file), is_animation);
|
||||
}
|
||||
|
||||
void ContactsManager::on_upload_profile_photo_error(FileId file_id, Status status) {
|
||||
@ -13553,7 +13618,7 @@ void ContactsManager::on_upload_profile_photo_error(FileId file_id, Status statu
|
||||
auto it = uploaded_profile_photos_.find(file_id);
|
||||
CHECK(it != uploaded_profile_photos_.end());
|
||||
|
||||
auto promise = std::move(it->second);
|
||||
auto promise = std::move(it->second.promise);
|
||||
|
||||
uploaded_profile_photos_.erase(it);
|
||||
|
||||
|
@ -322,12 +322,12 @@ class ContactsManager : public Actor {
|
||||
|
||||
void set_location_visibility();
|
||||
|
||||
void set_profile_photo(const tl_object_ptr<td_api::InputFile> &input_photo, Promise<Unit> &&promise);
|
||||
void set_profile_photo(const td_api::object_ptr<td_api::InputChatPhoto> &input_photo, Promise<Unit> &&promise);
|
||||
|
||||
void send_update_profile_photo_query(FileId file_id, Promise<Unit> &&promise);
|
||||
|
||||
void delete_profile_photo(int64 profile_photo_id, Promise<Unit> &&promise);
|
||||
|
||||
void upload_profile_photo(FileId file_id, Promise<Unit> &&promise);
|
||||
|
||||
void set_name(const string &first_name, const string &last_name, Promise<Unit> &&promise);
|
||||
|
||||
void set_bio(const string &bio, Promise<Unit> &&promise);
|
||||
@ -531,9 +531,6 @@ class ContactsManager : public Actor {
|
||||
void on_update_secret_chat(SecretChatId secret_chat_id, int64 access_hash, UserId user_id, SecretChatState state,
|
||||
bool is_outbound, int32 ttl, int32 date, string key_hash, int32 layer);
|
||||
|
||||
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);
|
||||
|
||||
tl_object_ptr<td_api::chatMember> get_chat_member_object(const DialogParticipant &dialog_participant) const;
|
||||
|
||||
tl_object_ptr<td_api::chatInviteLinkInfo> get_chat_invite_link_info_object(const string &invite_link) const;
|
||||
@ -1113,6 +1110,11 @@ class ContactsManager : public Actor {
|
||||
void do_update_user_photo(User *u, UserId user_id, tl_object_ptr<telegram_api::UserProfilePhoto> &&photo,
|
||||
const char *source);
|
||||
|
||||
void upload_profile_photo(FileId file_id, bool is_animation, Promise<Unit> &&promise, 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);
|
||||
|
||||
void register_user_photo(User *u, UserId user_id, const Photo &photo);
|
||||
|
||||
void on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked);
|
||||
@ -1495,7 +1497,16 @@ class ContactsManager : public Actor {
|
||||
class UploadProfilePhotoCallback;
|
||||
std::shared_ptr<UploadProfilePhotoCallback> upload_profile_photo_callback_;
|
||||
|
||||
std::unordered_map<FileId, Promise<Unit>, FileIdHash> uploaded_profile_photos_; // file_id -> promise
|
||||
struct UploadedProfilePhoto {
|
||||
bool is_animation;
|
||||
bool is_reupload;
|
||||
Promise<Unit> promise;
|
||||
|
||||
UploadedProfilePhoto(bool is_animation, bool is_reupload, Promise<Unit> promise)
|
||||
: is_animation(is_animation), is_reupload(is_reupload), promise(std::move(promise)) {
|
||||
}
|
||||
};
|
||||
std::unordered_map<FileId, UploadedProfilePhoto, FileIdHash> uploaded_profile_photos_; // file_id -> promise
|
||||
|
||||
std::unordered_map<int64, std::pair<vector<UserId>, vector<int32>>> imported_contacts_;
|
||||
|
||||
|
@ -815,6 +815,7 @@ SecretInputMedia photo_get_secret_input_media(FileManager *file_manager, const P
|
||||
vector<FileId> photo_get_file_ids(const Photo &photo) {
|
||||
auto result = transform(photo.photos, [](auto &size) { return size.file_id; });
|
||||
if (!photo.animated_photos.empty()) {
|
||||
// photo file IDs must be first
|
||||
append(result, transform(photo.animated_photos, [](auto &size) { return size.file_id; }));
|
||||
}
|
||||
return result;
|
||||
|
@ -2027,7 +2027,7 @@ class CliClient final : public Actor {
|
||||
|
||||
send_request(td_api::make_object<td_api::getChatMessageCount>(
|
||||
as_chat_id(chat_id), get_search_messages_filter(filter), as_bool(return_local)));
|
||||
} else if (op == "gup" || op == "gupf") {
|
||||
} else if (op == "gup" || op == "gupp") {
|
||||
string user_id;
|
||||
string offset;
|
||||
string limit;
|
||||
@ -3840,13 +3840,15 @@ class CliClient final : public Actor {
|
||||
std::tie(url, force_full) = split(args);
|
||||
|
||||
send_request(td_api::make_object<td_api::getWebPageInstantView>(url, as_bool(force_full)));
|
||||
} else if (op == "sppp") {
|
||||
send_request(td_api::make_object<td_api::setProfilePhoto>(
|
||||
td_api::make_object<td_api::inputChatPhotoPrevious>(to_integer<int64>(args))));
|
||||
} else if (op == "spp") {
|
||||
send_request(td_api::make_object<td_api::setProfilePhoto>(as_input_file(args)));
|
||||
} else if (op == "sppg") {
|
||||
string path;
|
||||
string conversion;
|
||||
std::tie(path, conversion) = split(args);
|
||||
send_request(td_api::make_object<td_api::setProfilePhoto>(as_generated_file(path, conversion)));
|
||||
send_request(td_api::make_object<td_api::setProfilePhoto>(
|
||||
td_api::make_object<td_api::inputChatPhotoStatic>(as_input_file(args))));
|
||||
} else if (op == "sppa" || op == "sppv") {
|
||||
send_request(td_api::make_object<td_api::setProfilePhoto>(
|
||||
td_api::make_object<td_api::inputChatPhotoAnimation>(as_input_file(args))));
|
||||
} else if (op == "sh") {
|
||||
auto prefix = std::move(args);
|
||||
send_request(td_api::make_object<td_api::searchHashtags>(prefix, 10));
|
||||
|
Loading…
Reference in New Issue
Block a user