From 44ed807417c309f432a903d2ad8f01044327d55c Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Jan 2019 04:38:11 +0300 Subject: [PATCH] Do not throw away file ids of reused media. GitOrigin-RevId: dcc460775768ae87ffc3be01ef8da8985b394463 --- td/telegram/DocumentsManager.cpp | 6 +- td/telegram/MessageContent.cpp | 36 +++++++- td/telegram/MessageContent.h | 4 +- td/telegram/MessagesManager.cpp | 146 +++++++++++++++++------------- td/telegram/MessagesManager.h | 3 +- td/telegram/StickersManager.cpp | 19 ++++ td/telegram/files/FileManager.cpp | 22 ++++- td/telegram/files/FileManager.h | 10 +- 8 files changed, 169 insertions(+), 77 deletions(-) diff --git a/td/telegram/DocumentsManager.cpp b/td/telegram/DocumentsManager.cpp index 1cbb3a31..4eee8e60 100644 --- a/td/telegram/DocumentsManager.cpp +++ b/td/telegram/DocumentsManager.cpp @@ -488,10 +488,10 @@ tl_object_ptr DocumentsManager::get_input_media( } CHECK(!file_view.has_remote_location()); - const Document *document = get_document(file_id); - CHECK(document != nullptr); - if (input_file != nullptr) { + const Document *document = get_document(file_id); + CHECK(document != nullptr); + vector> attributes; if (document->file_name.size()) { attributes.push_back(make_tl_object(document->file_name)); diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 92e81214..b692c1c1 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -2004,10 +2004,10 @@ static tl_object_ptr get_input_media_invoice(co message_invoice->start_parameter); } -tl_object_ptr get_input_media(const MessageContent *content, Td *td, - tl_object_ptr input_file, - tl_object_ptr input_thumbnail, - int32 ttl) { +static tl_object_ptr get_input_media(const MessageContent *content, Td *td, + tl_object_ptr input_file, + tl_object_ptr input_thumbnail, + int32 ttl) { switch (content->get_type()) { case MessageContentType::Animation: { auto m = static_cast(content); @@ -2098,6 +2098,34 @@ tl_object_ptr get_input_media(const MessageContent *co return nullptr; } +tl_object_ptr get_input_media(const MessageContent *content, Td *td, + tl_object_ptr input_file, + tl_object_ptr input_thumbnail, + FileId file_id, FileId thumbnail_file_id, int32 ttl) { + bool had_input_file = input_file != nullptr; + bool had_input_thumbnail = input_thumbnail != nullptr; + auto input_media = get_input_media(content, td, std::move(input_file), std::move(input_thumbnail), ttl); + if (had_input_file) { + if (!FileManager::extract_was_uploaded(input_media)) { + // if we had InputFile, but has failed to use it, then we need to immediately cancel file upload + // so the next upload with the same file can succeed + CHECK(file_id.is_valid()); + td->file_manager_->upload(file_id, nullptr, 0, 0); + if (had_input_thumbnail) { + CHECK(thumbnail_file_id.is_valid()); + td->file_manager_->upload(thumbnail_file_id, nullptr, 0, 0); + } + } + } else { + CHECK(!had_input_thumbnail); + } + return input_media; +} + +tl_object_ptr get_input_media(const MessageContent *content, Td *td, int32 ttl) { + return get_input_media(content, td, nullptr, nullptr, ttl); +} + void delete_message_content_thumbnail(MessageContent *content, Td *td) { switch (content->get_type()) { case MessageContentType::Animation: { diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index 5eac3de7..8ce2e4b7 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -144,7 +144,9 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td, tl_object_ptr get_input_media(const MessageContent *content, Td *td, tl_object_ptr input_file, tl_object_ptr input_thumbnail, - int32 ttl); + FileId file_id, FileId thumbnail_file_id, int32 ttl); + +tl_object_ptr get_input_media(const MessageContent *content, Td *td, int32 ttl); void delete_message_content_thumbnail(MessageContent *content, Td *td); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index c8e3c516..a1663405 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -702,11 +702,12 @@ class SaveDraftMessageQuery : public Td::ResultHandler { void send(DialogId dialog_id, const unique_ptr &draft_message) { LOG(INFO) << "Save draft in " << dialog_id; + dialog_id_ = dialog_id; + auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Write); if (input_peer == nullptr) { LOG(INFO) << "Can't update draft message because have no write access to " << dialog_id; - on_error(0, Status::Error(500, "Can't save draft message")); - return; + return on_error(0, Status::Error(500, "Can't save draft message")); } int32 flags = 0; @@ -724,7 +725,6 @@ class SaveDraftMessageQuery : public Td::ResultHandler { } } - dialog_id_ = dialog_id; send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_saveDraft( flags, false /*ignored*/, reply_to_message_id.get(), std::move(input_peer), draft_message == nullptr ? "" : draft_message->input_message_text.text.text, @@ -801,10 +801,10 @@ class ToggleDialogPinQuery : public Td::ResultHandler { void send(DialogId dialog_id, bool is_pinned) { dialog_id_ = dialog_id; is_pinned_ = is_pinned; + auto input_peer = td->messages_manager_->get_input_dialog_peer(dialog_id, AccessRights::Read); if (input_peer == nullptr) { - on_error(0, Status::Error(500, "Can't update dialog is_pinned")); - return; + return on_error(0, Status::Error(500, "Can't update dialog is_pinned")); } int32 flags = 0; @@ -885,10 +885,10 @@ class ToggleDialogUnreadMarkQuery : public Td::ResultHandler { void send(DialogId dialog_id, bool is_marked_as_unread) { dialog_id_ = dialog_id; is_marked_as_unread_ = is_marked_as_unread; + auto input_peer = td->messages_manager_->get_input_dialog_peer(dialog_id, AccessRights::Read); if (input_peer == nullptr) { - on_error(0, Status::Error(500, "Can't update dialog is_marked_as_unread")); - return; + return on_error(0, Status::Error(500, "Can't update dialog is_marked_as_unread")); } int32 flags = 0; @@ -928,17 +928,17 @@ class GetMessagesViewsQuery : public Td::ResultHandler { public: void send(DialogId dialog_id, vector &&message_ids, bool increment_view_counter) { + dialog_id_ = dialog_id; + message_ids_ = std::move(message_ids); + auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read); if (input_peer == nullptr) { LOG(ERROR) << "Can't update message views because doesn't have info about the " << dialog_id; - on_error(0, Status::Error(500, "Can't update message views")); - return; + return on_error(0, Status::Error(500, "Can't update message views")); } - LOG(INFO) << "View " << message_ids.size() << " messages in " << dialog_id + LOG(INFO) << "View " << message_ids_.size() << " messages in " << dialog_id << ", increment = " << increment_view_counter; - dialog_id_ = dialog_id; - message_ids_ = std::move(message_ids); send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_getMessagesViews( std::move(input_peer), MessagesManager::get_server_message_ids(message_ids_), increment_view_counter)))); } @@ -1019,8 +1019,7 @@ class ReadChannelMessagesContentsQuery : public Td::ResultHandler { auto input_channel = td->contacts_manager_->get_input_channel(channel_id); if (input_channel == nullptr) { LOG(ERROR) << "Have no input channel for " << channel_id; - on_error(0, Status::Error(500, "Can't read channel message contents")); - return; + return on_error(0, Status::Error(500, "Can't read channel message contents")); } LOG(INFO) << "Receive ReadChannelMessagesContentsQuery for messages " << format::as_array(message_ids) << " in " @@ -1951,10 +1950,12 @@ class SendMultiMediaActor : public NetActorOnce { }; class SendMediaActor : public NetActorOnce { - int64 random_id_; + int64 random_id_ = 0; FileId file_id_; FileId thumbnail_file_id_; DialogId dialog_id_; + bool was_uploaded_ = false; + bool was_thumbnail_uploaded_ = false; public: void send(FileId file_id, FileId thumbnail_file_id, int32 flags, DialogId dialog_id, MessageId reply_to_message_id, @@ -1966,6 +1967,8 @@ class SendMediaActor : public NetActorOnce { file_id_ = file_id; thumbnail_file_id_ = thumbnail_file_id; dialog_id_ = dialog_id; + was_uploaded_ = FileManager::extract_was_uploaded(input_media); + was_thumbnail_uploaded_ = FileManager::extract_was_thumbnail_uploaded(input_media); auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Write); if (input_peer == nullptr) { @@ -2002,7 +2005,8 @@ class SendMediaActor : public NetActorOnce { return on_error(id, result_ptr.move_as_error()); } - if (thumbnail_file_id_.is_valid()) { + if (was_thumbnail_uploaded_) { + CHECK(thumbnail_file_id_.is_valid()); // always delete partial remote location for the thumbnail, because it can't be reused anyway // TODO delete it only in the case it can't be merged with file thumbnail td->file_manager_->delete_partial_remote_location(thumbnail_file_id_); @@ -2021,11 +2025,14 @@ class SendMediaActor : public NetActorOnce { return; } td->messages_manager_->on_get_dialog_error(dialog_id_, status, "SendMediaActor"); - if (thumbnail_file_id_.is_valid()) { - // always delete partial remote location for the thumbnail, because it can't be reused anyway - td->file_manager_->delete_partial_remote_location(thumbnail_file_id_); - } - if (file_id_.is_valid()) { + if (was_uploaded_) { + if (was_thumbnail_uploaded_) { + CHECK(thumbnail_file_id_.is_valid()); + // always delete partial remote location for the thumbnail, because it can't be reused anyway + td->file_manager_->delete_partial_remote_location(thumbnail_file_id_); + } + + CHECK(file_id_.is_valid()); if (begins_with(status.message(), "FILE_PART_") && ends_with(status.message(), "_MISSING")) { td->messages_manager_->on_send_message_file_part_missing(random_id_, to_integer(status.message().substr(10))); @@ -2036,6 +2043,7 @@ class SendMediaActor : public NetActorOnce { } } } + td->messages_manager_->on_send_message_fail(random_id_, std::move(status)); } }; @@ -2045,20 +2053,24 @@ class UploadMediaQuery : public Td::ResultHandler { MessageId message_id_; FileId file_id_; FileId thumbnail_file_id_; + bool was_uploaded_ = false; + bool was_thumbnail_uploaded_ = false; public: void send(DialogId dialog_id, MessageId message_id, FileId file_id, FileId thumbnail_file_id, tl_object_ptr &&input_media) { - auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Write); - if (input_peer == nullptr) { - return on_error(0, Status::Error(400, "Have no write access to the chat")); - } CHECK(input_media != nullptr); - dialog_id_ = dialog_id; message_id_ = message_id; file_id_ = file_id; thumbnail_file_id_ = thumbnail_file_id; + was_uploaded_ = FileManager::extract_was_uploaded(input_media); + was_thumbnail_uploaded_ = FileManager::extract_was_thumbnail_uploaded(input_media); + + auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Write); + if (input_peer == nullptr) { + return on_error(0, Status::Error(400, "Have no write access to the chat")); + } send_query(G()->net_query_creator().create( create_storer(telegram_api::messages_uploadMedia(std::move(input_peer), std::move(input_media))))); @@ -2070,7 +2082,8 @@ class UploadMediaQuery : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - if (thumbnail_file_id_.is_valid()) { + if (was_thumbnail_uploaded_) { + CHECK(thumbnail_file_id_.is_valid()); // always delete partial remote location for the thumbnail, because it can't be reused anyway td->file_manager_->delete_partial_remote_location(thumbnail_file_id_); } @@ -2087,11 +2100,14 @@ class UploadMediaQuery : public Td::ResultHandler { return; } td->messages_manager_->on_get_dialog_error(dialog_id_, status, "UploadMediaQuery"); - if (thumbnail_file_id_.is_valid()) { - // always delete partial remote location for the thumbnail, because it can't be reused anyway - td->file_manager_->delete_partial_remote_location(thumbnail_file_id_); - } - if (file_id_.is_valid()) { + if (was_uploaded_) { + if (was_thumbnail_uploaded_) { + CHECK(thumbnail_file_id_.is_valid()); + // always delete partial remote location for the thumbnail, because it can't be reused anyway + td->file_manager_->delete_partial_remote_location(thumbnail_file_id_); + } + + CHECK(file_id_.is_valid()); if (begins_with(status.message(), "FILE_PART_") && ends_with(status.message(), "_MISSING")) { td->messages_manager_->on_upload_message_media_file_part_missing( dialog_id_, message_id_, to_integer(status.message().substr(10))); @@ -2119,14 +2135,14 @@ class EditMessageActor : public NetActorOnce { tl_object_ptr &&input_media, tl_object_ptr &&input_geo_point, tl_object_ptr &&reply_markup, uint64 sequence_dispatcher_id) { + dialog_id_ = dialog_id; + if (false && input_media != nullptr) { on_error(0, Status::Error(400, "FILE_PART_1_MISSING")); stop(); return; } - dialog_id_ = dialog_id; - auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Edit); if (input_peer == nullptr) { on_error(0, Status::Error(400, "Can't access the chat")); @@ -2202,6 +2218,10 @@ class EditInlineMessageQuery : public Td::ResultHandler { tl_object_ptr &&reply_markup) { CHECK(input_bot_inline_message_id != nullptr); + // file in an inline message can't be uploaded to another datacenter, + // so only previously uploaded files or URLs can be used in the InputMedia + CHECK(!FileManager::extract_was_uploaded(input_media)); + if (reply_markup != nullptr) { flags |= MessagesManager::SEND_MESSAGE_FLAG_HAS_REPLY_MARKUP; } @@ -2805,11 +2825,13 @@ class UpdateDialogNotifySettingsQuery : public Td::ResultHandler { } void send(DialogId dialog_id, const DialogNotificationSettings &new_settings) { + dialog_id_ = dialog_id; + auto input_notify_peer = td->messages_manager_->get_input_notify_peer(dialog_id); if (input_notify_peer == nullptr) { - on_error(0, Status::Error(500, "Can't update chat notification settings")); - return; + return on_error(0, Status::Error(500, "Can't update chat notification settings")); } + int32 flags = 0; if (!new_settings.use_default_mute_until) { flags |= telegram_api::inputPeerNotifySettings::MUTE_UNTIL_MASK; @@ -2827,7 +2849,6 @@ class UpdateDialogNotifySettingsQuery : public Td::ResultHandler { std::move(input_notify_peer), make_tl_object( flags, new_settings.show_preview, new_settings.silent_send_message, new_settings.mute_until, new_settings.sound))))); - dialog_id_ = dialog_id; } void on_result(uint64 id, BufferSlice packet) override { @@ -6110,11 +6131,6 @@ void MessagesManager::on_upload_media(FileId file_id, tl_object_ptr input_file, tl_object_ptr input_thumbnail) { - if (input_file == nullptr) { - CHECK(input_thumbnail == nullptr); - file_id = FileId(); - thumbnail_file_id = FileId(); - } CHECK(m != nullptr); MessageContent *content = nullptr; @@ -6129,18 +6145,14 @@ void MessagesManager::do_send_media(DialogId dialog_id, Message *m, FileId file_ } on_message_media_uploaded(dialog_id, m, - get_input_media(content, td_, std::move(input_file), std::move(input_thumbnail), m->ttl), + get_input_media(content, td_, std::move(input_file), std::move(input_thumbnail), file_id, + thumbnail_file_id, m->ttl), file_id, thumbnail_file_id); } void MessagesManager::do_send_secret_media(DialogId dialog_id, Message *m, FileId file_id, FileId thumbnail_file_id, tl_object_ptr input_encrypted_file, BufferSlice thumbnail) { - if (input_encrypted_file == nullptr) { - file_id = FileId(); - thumbnail_file_id = FileId(); - } - CHECK(dialog_id.get_type() == DialogType::SecretChat); CHECK(m != nullptr); CHECK(m->message_id.is_yet_unsent()); @@ -15316,10 +15328,10 @@ void MessagesManager::do_send_message(DialogId dialog_id, Message *m, vectorfile_manager_->resume_upload(file_id, std::move(bad_parts), upload_media_callback_, 1, m->message_id.get()); } else { - on_secret_message_media_uploaded(dialog_id, m, std::move(secret_input_media), FileId(), FileId()); + on_secret_message_media_uploaded(dialog_id, m, std::move(secret_input_media), file_id, thumbnail_file_id); } } else { - auto input_media = get_input_media(content, td_, nullptr, nullptr, m->ttl); + auto input_media = get_input_media(content, td_, m->ttl); if (input_media == nullptr) { if (content_type == MessageContentType::Photo) { thumbnail_file_id = FileId(); @@ -15331,7 +15343,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, Message *m, vectorfile_manager_->resume_upload(file_id, std::move(bad_parts), upload_media_callback_, 1, m->message_id.get()); } else { - on_message_media_uploaded(dialog_id, m, std::move(input_media), FileId(), FileId()); + on_message_media_uploaded(dialog_id, m, std::move(input_media), file_id, thumbnail_file_id); } } } @@ -15346,12 +15358,15 @@ void MessagesManager::on_message_media_uploaded(DialogId dialog_id, Message *m, if (message_id.is_server()) { const FormattedText *caption = get_message_content_caption(m->edited_content.get()); auto input_reply_markup = get_input_reply_markup(m->edited_reply_markup); + bool was_uploaded = FileManager::extract_was_uploaded(input_media); + bool was_thumbnail_uploaded = FileManager::extract_was_thumbnail_uploaded(input_media); LOG(INFO) << "Edit media from " << message_id << " in " << dialog_id; auto promise = PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, message_id, file_id, thumbnail_file_id, - generation = m->edit_generation](Result result) { + generation = m->edit_generation, was_uploaded, + was_thumbnail_uploaded](Result result) { send_closure(actor_id, &MessagesManager::on_message_media_edited, dialog_id, message_id, file_id, - thumbnail_file_id, generation, std::move(result)); + thumbnail_file_id, was_uploaded, was_thumbnail_uploaded, generation, std::move(result)); }); send_closure(td_->create_net_actor(std::move(promise)), &EditMessageActor::send, 1 << 11, dialog_id, message_id, caption == nullptr ? "" : caption->text, @@ -15431,8 +15446,8 @@ void MessagesManager::on_secret_message_media_uploaded(DialogId dialog_id, Messa dialog_id, m->message_id, Status::Error(400, "Wrong input media")); } */ - // TODO use file_id, thumbnail_file_id, invalidate partial remote location for file_id in case of failed upload - // even message has already been deleted + // TODO use file_id, thumbnail_file_id, was_uploaded, was_thumbnail_uploaded, + // invalidate partial remote location for file_id in case of failed upload even message has already been deleted on_media_message_ready_to_send( dialog_id, m->message_id, PromiseCreator::lambda( @@ -15480,7 +15495,7 @@ void MessagesManager::on_upload_message_media_success(DialogId dialog_id, Messag update_message_content(dialog_id, m, std::move(content), true, true); - auto input_media = get_input_media(m->content.get(), td_, nullptr, nullptr, m->ttl); + auto input_media = get_input_media(m->content.get(), td_, m->ttl); Status result; if (input_media == nullptr) { result = Status::Error(400, "Failed to upload file"); @@ -15617,7 +15632,7 @@ void MessagesManager::do_send_message_group(int64 media_album_id) { random_ids.push_back(begin_send_message(dialog_id, m)); const FormattedText *caption = get_message_content_caption(m->content.get()); - auto input_media = get_input_media(m->content.get(), td_, nullptr, nullptr, m->ttl); + auto input_media = get_input_media(m->content.get(), td_, m->ttl); auto entities = get_input_message_entities(td_->contacts_manager_.get(), caption, "do_send_message_group"); int32 input_single_media_flags = 0; if (!entities.empty()) { @@ -16280,7 +16295,8 @@ void MessagesManager::cancel_edit_message_media(DialogId dialog_id, Message *m) } void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId message_id, FileId file_id, - FileId thumbnail_file_id, uint64 generation, Result &&result) { + FileId thumbnail_file_id, bool was_uploaded, bool was_thumbnail_uploaded, + uint64 generation, Result &&result) { CHECK(message_id.is_server()); auto m = get_message({dialog_id, message_id}); if (m == nullptr || m->edit_generation != generation) { @@ -16301,11 +16317,13 @@ void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId mess update_message_content(dialog_id, m, std::move(m->edited_content), need_send_update_message_content, true); } else { auto error_message = result.error().message(); - if (thumbnail_file_id.is_valid()) { - // always delete partial remote location for the thumbnail, because it can't be reused anyway - td_->file_manager_->delete_partial_remote_location(thumbnail_file_id); - } - if (file_id.is_valid()) { + if (was_uploaded) { + if (was_thumbnail_uploaded) { + CHECK(thumbnail_file_id.is_valid()); + // always delete partial remote location for the thumbnail, because it can't be reused anyway + td_->file_manager_->delete_partial_remote_location(thumbnail_file_id); + } + CHECK(file_id.is_valid()); if (begins_with(error_message, "FILE_PART_") && ends_with(error_message, "_MISSING")) { do_send_message(dialog_id, m, {to_integer(error_message.substr(10))}); return; @@ -16618,7 +16636,7 @@ void MessagesManager::edit_inline_message_media(const string &inline_message_id, return promise.set_error(Status::Error(400, "Wrong inline message identifier specified")); } - auto input_media = get_input_media(content.content.get(), td_, nullptr, nullptr, 0); + auto input_media = get_input_media(content.content.get(), td_, 0); if (input_media == nullptr) { return promise.set_error(Status::Error(400, "Wrong message content specified")); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c4b01081..da8366dc 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1269,7 +1269,8 @@ class MessagesManager : public Actor { void cancel_edit_message_media(DialogId dialog_id, Message *m); void on_message_media_edited(DialogId dialog_id, MessageId message_id, FileId file_id, FileId thumbnail_file_id, - uint64 generation, Result &&result); + bool was_uploaded, bool was_thumbnail_uploaded, uint64 generation, + Result &&result); MessageId get_persistent_message_id(const Dialog *d, MessageId message_id) const; diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index a769fbbf..9d60e572 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -583,6 +583,7 @@ class ReadFeaturedStickerSetsQuery : public Td::ResultHandler { class UploadStickerFileQuery : public Td::ResultHandler { Promise promise_; FileId file_id_; + bool was_uploaded_ = false; public: explicit UploadStickerFileQuery(Promise &&promise) : promise_(std::move(promise)) { @@ -593,6 +594,7 @@ class UploadStickerFileQuery : public Td::ResultHandler { CHECK(input_peer != nullptr); CHECK(input_media != nullptr); file_id_ = file_id; + was_uploaded_ = FileManager::extract_was_uploaded(input_media); send_query(G()->net_query_creator().create( create_storer(telegram_api::messages_uploadMedia(std::move(input_peer), std::move(input_media))))); } @@ -608,6 +610,17 @@ class UploadStickerFileQuery : public Td::ResultHandler { void on_error(uint64 id, Status status) override { CHECK(status.is_error()); + if (was_uploaded_) { + CHECK(file_id_.is_valid()); + if (begins_with(status.message(), "FILE_PART_") && ends_with(status.message(), "_MISSING")) { + // TODO td->stickers_manager_->on_upload_sticker_file_part_missing(file_id_, to_integer(status.message().substr(10))); + return; + } else { + if (status.code() != 429 && status.code() < 500 && !G()->close_flag()) { + td->file_manager_->delete_partial_remote_location(file_id_); + } + } + } promise_.set_error(std::move(status)); } }; @@ -3291,8 +3304,14 @@ void StickersManager::do_upload_sticker_file(UserId user_id, FileId file_id, return promise.set_error(Status::Error(3, "Have no access to the user")); } + bool had_input_file = input_file != nullptr; auto input_media = td_->documents_manager_->get_input_media(file_id, std::move(input_file), nullptr); CHECK(input_media != nullptr); + if (had_input_file && !FileManager::extract_was_uploaded(input_media)) { + // if we had InputFile, but has failed to use it, then we need to immediately cancel file upload + // so the next upload with the same file can succeed + td_->file_manager_->upload(file_id, nullptr, 0, 0); + } td_->create_handler(std::move(promise)) ->send(std::move(input_peer), file_id, std::move(input_media)); diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index 027ceb97..0895a794 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -163,13 +163,15 @@ void FileNode::set_remote_location(const RemoteFileLocation &remote, FileLocatio on_changed(); } -void FileNode::delete_file_reference(Slice file_reference) { +bool FileNode::delete_file_reference(Slice file_reference) { if (remote_.type() == RemoteFileLocation::Type::Full && remote_.full().delete_file_reference(file_reference)) { VLOG(file_references) << "Do delete file reference of main file " << main_file_id_; upload_was_update_file_reference_ = false; download_was_update_file_reference_ = false; on_pmc_changed(); + return true; } + return false; } void FileNode::set_generate_location(unique_ptr &&generate) { @@ -2447,6 +2449,24 @@ vector> FileManager::get_input_docume return result; } +bool FileManager::extract_was_uploaded(const tl_object_ptr &input_media) { + if (input_media == nullptr) { + return false; + } + + auto input_media_id = input_media->get_id(); + return input_media_id == telegram_api::inputMediaUploadedPhoto::ID || + input_media_id == telegram_api::inputMediaUploadedDocument::ID; +} + +bool FileManager::extract_was_thumbnail_uploaded(const tl_object_ptr &input_media) { + if (input_media == nullptr || input_media->get_id() != telegram_api::inputMediaUploadedDocument::ID) { + return false; + } + + return static_cast(input_media.get())->thumb_ != nullptr; +} + FileId FileManager::next_file_id() { if (!empty_file_ids_.empty()) { auto res = empty_file_ids_.back(); diff --git a/td/telegram/files/FileManager.h b/td/telegram/files/FileManager.h index 42c6d541..7b6f444a 100644 --- a/td/telegram/files/FileManager.h +++ b/td/telegram/files/FileManager.h @@ -69,7 +69,7 @@ class FileNode { void set_local_location(const LocalFileLocation &local, int64 ready_size, int64 prefix_offset, int64 ready_prefix_size); void set_remote_location(const RemoteFileLocation &remote, FileLocationSource source, int64 ready_size); - void delete_file_reference(Slice file_reference); + bool delete_file_reference(Slice file_reference); void set_generate_location(unique_ptr &&generate); void set_size(int64 size); void set_expected_size(int64 expected_size); @@ -374,8 +374,6 @@ class FileManager : public FileLoadManager::Callback { void external_file_generate_progress(int64 id, int32 expected_size, int32 local_prefix_size, Promise<> promise); void external_file_generate_finish(int64 id, Status status, Promise<> promise); - static constexpr char PERSISTENT_ID_VERSION = 2; - static constexpr char PERSISTENT_ID_VERSION_MAP = 3; Result from_persistent_id(CSlice persistent_id, FileType file_type) TD_WARN_UNUSED_RESULT; FileView get_file_view(FileId file_id) const; FileView get_sync_file_view(FileId file_id); @@ -393,6 +391,9 @@ class FileManager : public FileLoadManager::Callback { vector> get_input_documents(const vector &file_ids); + static bool extract_was_uploaded(const tl_object_ptr &input_media); + static bool extract_was_thumbnail_uploaded(const tl_object_ptr &input_media); + template void store_file(FileId file_id, T &storer, int32 ttl = 5) const; @@ -400,6 +401,9 @@ class FileManager : public FileLoadManager::Callback { FileId parse_file(T &parser); private: + static constexpr char PERSISTENT_ID_VERSION = 2; + static constexpr char PERSISTENT_ID_VERSION_MAP = 3; + Result check_input_file_id(FileType type, Result result, bool is_encrypted, bool allow_zero, bool is_secure) TD_WARN_UNUSED_RESULT;