From 6476e05d1e209a7de1661366172442dae6998762 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 8 Jul 2020 19:40:23 +0300 Subject: [PATCH] Change input photo type to InputChatPhoto in setChatPhoto. GitOrigin-RevId: fae612a07ffdf71f393ffea7951a76808b90f7b3 --- td/generate/scheme/td_api.tl | 8 +-- td/generate/scheme/td_api.tlo | Bin 176960 -> 176960 bytes td/telegram/ContactsManager.cpp | 33 ++++++--- td/telegram/ContactsManager.h | 2 + td/telegram/MessagesManager.cpp | 124 ++++++++++++++++++++++++-------- td/telegram/MessagesManager.h | 20 +++++- td/telegram/cli.cpp | 26 +++++-- 7 files changed, 160 insertions(+), 53 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index cab2b6b7f..892390f86 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3847,13 +3847,13 @@ getRecommendedChatFilters = RecommendedChatFilters; getChatFilterDefaultIconName filter:chatFilter = Text; -//@description Changes the chat title. Supported only for basic groups, supergroups and channels. Requires can_change_info rights. The title will not be changed until the request to the server has been completed +//@description Changes the chat title. Supported only for basic groups, supergroups and channels. Requires can_change_info rights //@chat_id Chat identifier @title New title of the chat; 1-128 characters setChatTitle chat_id:int53 title:string = Ok; -//@description Changes the photo of a chat. Supported only for basic groups, supergroups and channels. Requires can_change_info rights. The photo will not be changed before request to the server has been completed -//@chat_id Chat identifier @photo New chat photo. You can use a zero InputFileId to delete the chat photo. Files that are accessible only by HTTP URL are not acceptable -setChatPhoto chat_id:int53 photo:InputFile = Ok; +//@description Changes the photo of a chat. Supported only for basic groups, supergroups and channels. Requires can_change_info rights +//@chat_id Chat identifier @photo New chat photo. You can pass null to delete the chat photo +setChatPhoto chat_id:int53 photo:InputChatPhoto = Ok; //@description Changes the chat members permissions. Supported only for basic groups and supergroups. Requires can_restrict_members administrator right //@chat_id Chat identifier @permissions New non-administrator members permissions in the chat diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index b160031aa756a0a4d0f9f984ff99df5917e9fb46..9fd99ca75d18edc9862892780076bfc75d7749fa 100644 GIT binary patch delta 34 scmV+-0Nww<<_f^(3V?(Gv;sVm1OttG>6bu~0#KLyo&qGdw2}ghAPN=^p8x;= delta 38 wcmV+>0NMY*<_f^(3V?(Gv;sVm1o`6O2bVyS0#K8D(+rmoY62Lyw2}ghAXLK;FaQ7m diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 6944d2709..9850ee757 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -5489,6 +5489,14 @@ void ContactsManager::update_is_location_visible() { G()->shared_config().set_option_boolean("is_location_visible", expire_date != 0); } +FileId ContactsManager::get_profile_photo_file_id(int64 photo_id) const { + auto it = my_photo_file_id_.find(photo_id); + if (it == my_photo_file_id_.end()) { + return FileId(); + } + return it->second; +} + void ContactsManager::set_profile_photo(const td_api::object_ptr &input_photo, Promise &&promise) { if (input_photo == nullptr) { @@ -5502,18 +5510,16 @@ void ContactsManager::set_profile_photo(const td_api::object_ptr(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) { + if (u != nullptr && u->photo.id > 0 && 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")); + + auto file_id = get_profile_photo_file_id(photo_id); + if (!file_id.is_valid()) { + return promise.set_error(Status::Error(400, "Unknown profile photo ID specified")); } - return send_update_profile_photo_query(td_->file_manager_->dup_file_id(it->second), std::move(promise)); + return send_update_profile_photo_query(td_->file_manager_->dup_file_id(file_id), std::move(promise)); } case td_api::inputChatPhotoStatic::ID: { auto photo = static_cast(input_photo.get()); @@ -13722,11 +13728,18 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptrfile_manager_->delete_file_reference(file_id, file_reference); upload_profile_photo(file_id, is_animation, main_frame_timestamp, std::move(promise), {-1}); return; diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 957dd09e2..fae012417 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -324,6 +324,8 @@ class ContactsManager : public Actor { void set_location_visibility(); + FileId get_profile_photo_file_id(int64 photo_id) const; + void set_profile_photo(const td_api::object_ptr &input_photo, Promise &&promise); void send_update_profile_photo_query(FileId file_id, Promise &&promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index faacf4687..9ee2600da 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -894,7 +894,7 @@ class EditDialogPhotoQuery : public Td::ResultHandler { if (file_id_.is_valid() && !was_uploaded_) { VLOG(file_references) << "Receive " << status << " for " << file_id_; td->file_manager_->delete_file_reference(file_id_, file_reference_); - td->messages_manager_->upload_dialog_photo(dialog_id_, file_id_, std::move(promise_)); + td->messages_manager_->upload_dialog_photo(dialog_id_, file_id_, false, 0.0, false, std::move(promise_), {-1}); return; } else { LOG(ERROR) << "Receive file reference error, but file_id = " << file_id_ @@ -7823,27 +7823,57 @@ void MessagesManager::on_upload_dialog_photo(FileId file_id, tl_object_ptr promise = std::move(it->second.promise); DialogId dialog_id = it->second.dialog_id; + double main_frame_timestamp = it->second.main_frame_timestamp; + bool is_animation = it->second.is_animation; + bool is_reupload = it->second.is_reupload; + Promise promise = std::move(it->second.promise); being_uploaded_dialog_photos_.erase(it); - tl_object_ptr input_chat_photo; FileView file_view = td_->file_manager_->get_file_view(file_id); CHECK(!file_view.is_encrypted()); if (input_file == nullptr && file_view.has_remote_location()) { 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 reupload the file")); + } + + if (is_animation) { + CHECK(file_view.get_type() == FileType::Animation); + // delete file reference and forcely reupload the file + auto file_reference = FileManager::extract_file_reference(file_view.main_remote_location().as_input_document()); + td_->file_manager_->delete_file_reference(file_id, file_reference); + upload_dialog_photo(dialog_id, file_id, is_animation, main_frame_timestamp, true, std::move(promise), {-1}); + } else { + CHECK(file_view.get_type() == FileType::Photo); + auto input_photo = file_view.main_remote_location().as_input_photo(); + auto input_chat_photo = make_tl_object(std::move(input_photo)); + send_edit_dialog_photo_query(dialog_id, file_id, std::move(input_chat_photo), std::move(promise)); + } + return; + } + CHECK(input_file != nullptr); + + int32 flags = 0; + tl_object_ptr photo_input_file; + tl_object_ptr video_input_file; + if (is_animation) { + flags |= telegram_api::inputChatUploadedPhoto::VIDEO_MASK; + video_input_file = std::move(input_file); + + if (main_frame_timestamp != 0.0) { + flags |= telegram_api::inputChatUploadedPhoto::VIDEO_START_TS_MASK; } - auto input_photo = file_view.main_remote_location().as_input_photo(); - input_chat_photo = make_tl_object(std::move(input_photo)); } else { - int32 flags = telegram_api::inputChatUploadedPhoto::FILE_MASK; - input_chat_photo = make_tl_object(flags, std::move(input_file), nullptr, 0.0); + flags |= telegram_api::inputChatUploadedPhoto::FILE_MASK; + photo_input_file = std::move(input_file); } + auto input_chat_photo = make_tl_object( + flags, std::move(photo_input_file), std::move(video_input_file), main_frame_timestamp); send_edit_dialog_photo_query(dialog_id, file_id, std::move(input_chat_photo), std::move(promise)); } @@ -27127,7 +27157,7 @@ void MessagesManager::on_updated_dialog_folder_id(DialogId dialog_id, uint64 gen } } -void MessagesManager::set_dialog_photo(DialogId dialog_id, const tl_object_ptr &photo, +void MessagesManager::set_dialog_photo(DialogId dialog_id, const tl_object_ptr &input_photo, Promise &&promise) { LOG(INFO) << "Receive setChatPhoto request to change photo of " << dialog_id; @@ -27161,30 +27191,62 @@ void MessagesManager::set_dialog_photo(DialogId dialog_id, const tl_object_ptrfile_manager_->get_input_file_id(FileType::Photo, photo, dialog_id, true, false); + const td_api::object_ptr *input_file = nullptr; + double main_frame_timestamp = 0.0; + bool is_animation = false; + if (input_photo != nullptr) { + switch (input_photo->get_id()) { + case td_api::inputChatPhotoPrevious::ID: { + auto photo = static_cast(input_photo.get()); + auto file_id = td_->contacts_manager_->get_profile_photo_file_id(photo->chat_photo_id_); + if (!file_id.is_valid()) { + return promise.set_error(Status::Error(400, "Unknown profile photo ID specified")); + } + + auto file_view = td_->file_manager_->get_file_view(file_id); + auto input_chat_photo = + make_tl_object(file_view.main_remote_location().as_input_photo()); + send_edit_dialog_photo_query(dialog_id, file_id, std::move(input_chat_photo), std::move(promise)); + return; + } + case td_api::inputChatPhotoStatic::ID: { + auto photo = static_cast(input_photo.get()); + input_file = &photo->photo_; + break; + } + case td_api::inputChatPhotoAnimation::ID: { + auto photo = static_cast(input_photo.get()); + input_file = &photo->animation_; + main_frame_timestamp = photo->main_frame_timestamp_; + is_animation = true; + break; + } + default: + UNREACHABLE(); + break; + } + } + + const double MAX_ANIMATION_DURATION = 10.0; + if (main_frame_timestamp < 0.0 || main_frame_timestamp > MAX_ANIMATION_DURATION) { + return promise.set_error(Status::Error(400, "Wrong main frame timestamp specified")); + } + + auto file_type = is_animation ? FileType::Animation : FileType::Photo; + auto r_file_id = td_->file_manager_->get_input_file_id(file_type, *input_file, dialog_id, true, false); if (r_file_id.is_error()) { - return promise.set_error(Status::Error(7, r_file_id.error().message())); + // TODO promise.set_error(std::move(status)); + return promise.set_error(Status::Error(400, r_file_id.error().message())); } FileId file_id = r_file_id.ok(); - if (!file_id.is_valid()) { send_edit_dialog_photo_query(dialog_id, FileId(), make_tl_object(), std::move(promise)); return; } - 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()) { - // file has already been uploaded, just send change photo request - auto input_photo = file_view.main_remote_location().as_input_photo(); - send_edit_dialog_photo_query( - dialog_id, file_id, make_tl_object(std::move(input_photo)), std::move(promise)); - return; - } - - // need to upload file first - upload_dialog_photo(dialog_id, td_->file_manager_->dup_file_id(file_id), std::move(promise)); + upload_dialog_photo(dialog_id, td_->file_manager_->dup_file_id(file_id), is_animation, main_frame_timestamp, false, + std::move(promise)); } void MessagesManager::send_edit_dialog_photo_query(DialogId dialog_id, FileId file_id, @@ -27194,12 +27256,16 @@ void MessagesManager::send_edit_dialog_photo_query(DialogId dialog_id, FileId fi td_->create_handler(std::move(promise))->send(dialog_id, file_id, std::move(input_chat_photo)); } -void MessagesManager::upload_dialog_photo(DialogId dialog_id, FileId file_id, Promise &&promise) { +void MessagesManager::upload_dialog_photo(DialogId dialog_id, FileId file_id, bool is_animation, + double main_frame_timestamp, bool is_reupload, Promise &&promise, + vector bad_parts) { CHECK(file_id.is_valid()); LOG(INFO) << "Ask to upload chat photo " << file_id; CHECK(being_uploaded_dialog_photos_.find(file_id) == being_uploaded_dialog_photos_.end()); - being_uploaded_dialog_photos_[file_id] = {std::move(promise), dialog_id}; - td_->file_manager_->upload(file_id, upload_dialog_photo_callback_, 32, 0); + being_uploaded_dialog_photos_.emplace( + file_id, UploadedDialogPhotoInfo{dialog_id, main_frame_timestamp, is_animation, is_reupload, std::move(promise)}); + // TODO use force_reupload if is_reupload + td_->file_manager_->resume_upload(file_id, std::move(bad_parts), upload_dialog_photo_callback_, 32, 0); } void MessagesManager::set_dialog_title(DialogId dialog_id, const string &title, Promise &&promise) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 7917c929a..486966390 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -455,7 +455,8 @@ class MessagesManager : public Actor { void add_dialog_to_list(DialogId dialog_id, DialogListId dialog_list_id, Promise &&promise); - void set_dialog_photo(DialogId dialog_id, const tl_object_ptr &photo, Promise &&promise); + void set_dialog_photo(DialogId dialog_id, const tl_object_ptr &input_photo, + Promise &&promise); void set_dialog_title(DialogId dialog_id, const string &title, Promise &&promise); @@ -832,7 +833,8 @@ class MessagesManager : public Actor { void remove_message_notifications(DialogId dialog_id, NotificationGroupId group_id, NotificationId max_notification_id, MessageId max_message_id); - void upload_dialog_photo(DialogId dialog_id, FileId file_id, Promise &&promise); + void upload_dialog_photo(DialogId dialog_id, FileId file_id, bool is_animation, double main_frame_timestamp, + bool is_reupload, Promise &&promise, vector bad_parts = {}); void on_binlog_events(vector &&events); @@ -2817,8 +2819,20 @@ class MessagesManager : public Actor { const char *debug_add_message_to_dialog_fail_reason_ = ""; struct UploadedDialogPhotoInfo { - Promise promise; DialogId dialog_id; + double main_frame_timestamp; + bool is_animation; + bool is_reupload; + Promise promise; + + UploadedDialogPhotoInfo(DialogId dialog_id, double main_frame_timestamp, bool is_animation, bool is_reupload, + Promise promise) + : dialog_id(dialog_id) + , main_frame_timestamp(main_frame_timestamp) + , is_animation(is_animation) + , is_reupload(is_reupload) + , promise(std::move(promise)) { + } }; std::unordered_map being_uploaded_dialog_photos_; // file_id -> ... diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index bd8531488..4b9ee46c5 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3549,12 +3549,30 @@ class CliClient final : public Actor { std::tie(chat_id, title) = split(args); send_request(td_api::make_object(as_chat_id(chat_id), title)); + } else if (op == "scpp") { + string chat_id; + string photo_id; + + std::tie(chat_id, photo_id) = split(args); + send_request(td_api::make_object( + as_chat_id(chat_id), td_api::make_object(to_integer(photo_id)))); } else if (op == "scp") { string chat_id; string photo_path; std::tie(chat_id, photo_path) = split(args); - send_request(td_api::make_object(as_chat_id(chat_id), as_input_file(photo_path))); + send_request(td_api::make_object( + as_chat_id(chat_id), td_api::make_object(as_input_file(photo_path)))); + } else if (op == "scpa" || op == "scpv") { + string chat_id; + string animation; + string main_frame_timestamp; + + std::tie(chat_id, args) = split(args); + std::tie(animation, main_frame_timestamp) = split(args); + send_request(td_api::make_object( + as_chat_id(chat_id), td_api::make_object(as_input_file(animation), + to_double(main_frame_timestamp)))); } else if (op == "scperm") { string chat_id; string permissions; @@ -3569,12 +3587,6 @@ class CliClient final : public Actor { } else { LOG(ERROR) << "Wrong permissions size, expected 8"; } - } else if (op == "scpid") { - string chat_id; - string file_id; - - std::tie(chat_id, file_id) = split(args); - send_request(td_api::make_object(as_chat_id(chat_id), as_input_file_id(file_id))); } else if (op == "sccd") { string chat_id; string client_data;