Support paid media message contents with multiple files in MessagesManager.

This commit is contained in:
levlam 2024-06-24 19:51:12 +03:00
parent 719c03b0a2
commit 9061e9f2b1
5 changed files with 144 additions and 34 deletions

View File

@ -3537,7 +3537,9 @@ tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *co
auto file_references = FileManager::extract_file_references(input_media);
for (size_t i = 0; i < file_references.size(); i++) {
if (file_references[i] == FileReferenceView::invalid_file_reference()) {
auto file_id = get_message_content_any_file_id(content);
auto file_ids = get_message_content_any_file_ids(content);
CHECK(file_ids.size() == file_references.size());
auto file_id = file_ids[i];
if (!force) {
LOG(INFO) << "File " << file_id << " has invalid file reference";
return nullptr;
@ -7799,12 +7801,27 @@ FileId get_message_content_upload_file_id(const MessageContent *content) {
return static_cast<const MessageVideoNote *>(content)->file_id;
case MessageContentType::VoiceNote:
return static_cast<const MessageVoiceNote *>(content)->file_id;
case MessageContentType::PaidMedia:
UNREACHABLE();
break;
default:
break;
}
return FileId();
}
vector<FileId> get_message_content_upload_file_ids(const MessageContent *content) {
if (content->get_type() == MessageContentType::PaidMedia) {
return transform(static_cast<const MessagePaidMedia *>(content)->media,
[](const MessageExtendedMedia &media) { return media.get_upload_file_id(); });
}
auto file_id = get_message_content_upload_file_id(content);
if (file_id.is_valid()) {
return {file_id};
}
return {};
}
FileId get_message_content_any_file_id(const MessageContent *content) {
FileId result = get_message_content_upload_file_id(content);
if (!result.is_valid()) {
@ -7817,6 +7834,18 @@ FileId get_message_content_any_file_id(const MessageContent *content) {
return result;
}
vector<FileId> get_message_content_any_file_ids(const MessageContent *content) {
if (content->get_type() == MessageContentType::PaidMedia) {
return transform(static_cast<const MessagePaidMedia *>(content)->media,
[](const MessageExtendedMedia &media) { return media.get_any_file_id(); });
}
auto file_id = get_message_content_any_file_id(content);
if (file_id.is_valid()) {
return {file_id};
}
return {};
}
void update_message_content_file_id_remote(MessageContent *content, FileId file_id) {
if (file_id.get_remote() == 0) {
return;
@ -7837,6 +7866,9 @@ void update_message_content_file_id_remote(MessageContent *content, FileId file_
return &static_cast<MessageVideoNote *>(content)->file_id;
case MessageContentType::VoiceNote:
return &static_cast<MessageVoiceNote *>(content)->file_id;
case MessageContentType::PaidMedia:
UNREACHABLE();
return static_cast<FileId *>(nullptr);
default:
return static_cast<FileId *>(nullptr);
}
@ -7846,6 +7878,23 @@ void update_message_content_file_id_remote(MessageContent *content, FileId file_
}
}
void update_message_content_file_id_remotes(MessageContent *content, const vector<FileId> &file_ids) {
if (content->get_type() == MessageContentType::PaidMedia) {
auto &media = static_cast<MessagePaidMedia *>(content)->media;
if (file_ids.size() != media.size()) {
return;
}
for (size_t i = 0; i < file_ids.size(); i++) {
media[i].update_file_id_remote(file_ids[i]);
}
return;
}
if (file_ids.size() != 1) {
return;
}
update_message_content_file_id_remote(content, file_ids[0]);
}
FileId get_message_content_thumbnail_file_id(const MessageContent *content, const Td *td) {
switch (content->get_type()) {
case MessageContentType::Animation:
@ -7870,12 +7919,27 @@ FileId get_message_content_thumbnail_file_id(const MessageContent *content, cons
static_cast<const MessageVideoNote *>(content)->file_id);
case MessageContentType::VoiceNote:
return FileId();
case MessageContentType::PaidMedia:
UNREACHABLE();
return FileId();
default:
break;
}
return FileId();
}
vector<FileId> get_message_content_thumbnail_file_ids(const MessageContent *content, const Td *td) {
if (content->get_type() == MessageContentType::PaidMedia) {
return transform(static_cast<const MessagePaidMedia *>(content)->media,
[td](const MessageExtendedMedia &media) { return media.get_thumbnail_file_id(td); });
}
auto file_id = get_message_content_thumbnail_file_id(content, td);
if (file_id.is_valid()) {
return {file_id};
}
return {};
}
vector<FileId> get_message_content_file_ids(const MessageContent *content, const Td *td) {
CHECK(content != nullptr);
switch (content->get_type()) {

View File

@ -276,12 +276,20 @@ const Photo *get_message_content_photo(const MessageContent *content);
FileId get_message_content_upload_file_id(const MessageContent *content);
vector<FileId> get_message_content_upload_file_ids(const MessageContent *content);
FileId get_message_content_any_file_id(const MessageContent *content);
vector<FileId> get_message_content_any_file_ids(const MessageContent *content);
void update_message_content_file_id_remote(MessageContent *content, FileId file_id);
void update_message_content_file_id_remotes(MessageContent *content, const vector<FileId> &file_ids);
FileId get_message_content_thumbnail_file_id(const MessageContent *content, const Td *td);
vector<FileId> get_message_content_thumbnail_file_ids(const MessageContent *content, const Td *td);
vector<FileId> get_message_content_file_ids(const MessageContent *content, const Td *td);
StoryFullId get_message_content_story_full_id(const Td *td, const MessageContent *content);

View File

@ -316,6 +316,15 @@ FileId MessageExtendedMedia::get_thumbnail_file_id(const Td *td) const {
return FileId();
}
void MessageExtendedMedia::update_file_id_remote(FileId file_id) {
if (file_id.get_remote() == 0 || type_ != Type::Video) {
return;
}
if (video_file_id_ == file_id && video_file_id_.get_remote() == 0) {
video_file_id_ = file_id;
}
}
telegram_api::object_ptr<telegram_api::InputMedia> MessageExtendedMedia::get_input_media(
Td *td, tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail) const {

View File

@ -96,6 +96,8 @@ class MessageExtendedMedia {
FileId get_thumbnail_file_id(const Td *td) const;
void update_file_id_remote(FileId file_id);
telegram_api::object_ptr<telegram_api::InputMedia> get_input_media(
Td *td, tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail) const;

View File

@ -23298,14 +23298,18 @@ vector<FileId> MessagesManager::get_message_file_ids(const Message *m) const {
}
void MessagesManager::cancel_upload_message_content_files(const MessageContent *content) {
auto file_id = get_message_content_upload_file_id(content);
auto file_ids = get_message_content_upload_file_ids(content);
// always cancel file upload, it should be a no-op in the worst case
if (being_uploaded_files_.erase(file_id) || file_id.is_valid()) {
cancel_upload_file(file_id, "cancel_upload_message_content_files");
for (auto file_id : file_ids) {
if (being_uploaded_files_.erase(file_id) || file_id.is_valid()) {
cancel_upload_file(file_id, "cancel_upload_message_content_files");
}
}
file_id = get_message_content_thumbnail_file_id(content, td_);
if (being_uploaded_thumbnails_.erase(file_id) || file_id.is_valid()) {
cancel_upload_file(file_id, "cancel_upload_message_content_files");
file_ids = get_message_content_thumbnail_file_ids(content, td_);
for (auto file_id : file_ids) {
if (being_uploaded_thumbnails_.erase(file_id) || file_id.is_valid()) {
cancel_upload_file(file_id, "cancel_upload_message_content_files");
}
}
}
@ -23963,10 +23967,18 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect
return;
}
FileId file_id = get_message_content_any_file_id(content); // any_file_id, because it could be a photo sent by ID
FileId thumbnail_file_id = get_message_content_thumbnail_file_id(content, td_);
LOG(DEBUG) << "Need to send file " << file_id << " with thumbnail " << thumbnail_file_id;
auto file_ids = get_message_content_any_file_ids(content); // any_file_ids, because it could be a photo sent by ID
auto thumbnail_file_ids = get_message_content_thumbnail_file_ids(content, td_);
LOG(DEBUG) << "Need to send files " << file_ids << " with thumbnails " << thumbnail_file_ids;
if (file_ids.size() != thumbnail_file_ids.size()) {
CHECK(file_ids.size() == 1u);
CHECK(thumbnail_file_ids.empty());
}
if (is_secret) {
CHECK(file_ids.size() <= 1);
auto file_id = file_ids.empty() ? FileId() : file_ids[0];
auto thumbnail_file_id = thumbnail_file_ids.empty() ? FileId() : thumbnail_file_ids[0];
CHECK(!is_edit);
auto layer = td_->user_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id());
auto secret_input_media = get_secret_input_media(content, td_, nullptr, BufferSlice(), layer);
@ -23993,23 +24005,32 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect
content_type == MessageContentType::Story) {
return;
}
CHECK(file_id.is_valid());
FileView file_view = td_->file_manager_->get_file_view(file_id);
if (get_main_file_type(file_view.get_type()) == FileType::Photo) {
thumbnail_file_id = FileId();
}
CHECK(!file_ids.empty());
for (size_t i = 0; i < file_ids.size(); i++) {
auto file_id = file_ids[i];
CHECK(file_id.is_valid());
LOG(INFO) << "Ask to upload file " << file_id << " with bad parts " << bad_parts;
CHECK(file_id.is_valid());
bool is_inserted =
being_uploaded_files_
.emplace(file_id, std::make_pair(MessageFullId(dialog_id, m->message_id), thumbnail_file_id))
.second;
CHECK(is_inserted);
// need to call resume_upload synchronously to make upload process consistent with being_uploaded_files_
// and to send is_uploading_active == true in the updates
td_->file_manager_->resume_upload(file_id, std::move(bad_parts), upload_media_callback_, 1, m->message_id.get());
auto thumbnail_file_id = i < thumbnail_file_ids.size() ? thumbnail_file_ids[i] : FileId();
FileView file_view = td_->file_manager_->get_file_view(file_id);
if (get_main_file_type(file_view.get_type()) == FileType::Photo) {
thumbnail_file_id = FileId();
}
LOG(INFO) << "Ask to upload file " << file_id << " with bad parts " << bad_parts;
bool is_inserted =
being_uploaded_files_
.emplace(file_id, std::make_pair(MessageFullId(dialog_id, m->message_id), thumbnail_file_id))
.second;
CHECK(is_inserted);
// need to call resume_upload synchronously to make upload process consistent with being_uploaded_files_
// and to send is_uploading_active == true in the updates
td_->file_manager_->resume_upload(file_id, std::move(bad_parts), upload_media_callback_, 1,
m->message_id.get());
}
} else {
CHECK(file_ids.size() <= 1); // TODO PaidMedia
auto file_id = file_ids.empty() ? FileId() : file_ids[0];
auto thumbnail_file_id = thumbnail_file_ids.empty() ? FileId() : thumbnail_file_ids[0];
on_message_media_uploaded(dialog_id, m, std::move(input_media), file_id, thumbnail_file_id);
}
}
@ -31106,7 +31127,7 @@ void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) {
}
CHECK(m->message_id.is_yet_unsent());
if (m->forward_info != nullptr || m->had_forward_info || m->is_copy || m->message_id.is_scheduled() ||
m->sender_dialog_id.is_valid()) {
m->sender_dialog_id.is_valid() || m->content->get_type() == MessageContentType::PaidMedia) {
return;
}
@ -33927,8 +33948,7 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me
MessageContentType old_content_type = old_content->get_type();
MessageContentType new_content_type = new_content->get_type();
auto old_file_id = get_message_content_any_file_id(old_content.get());
bool need_finish_upload = old_file_id.is_valid() && need_merge_files;
auto old_file_ids = get_message_content_any_file_ids(old_content.get());
if (old_content_type != new_content_type) {
if (old_message->ttl.is_valid() && old_message->ttl_expires_at > 0 &&
is_expired_message_content(new_content_type) &&
@ -33941,18 +33961,25 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me
old_message->is_content_secret = old_message->ttl.is_secret_message_content(new_content->get_type());
}
if (need_merge_files && old_file_id.is_valid()) {
td_->file_manager_->try_merge_documents(old_file_id, get_message_content_any_file_id(new_content.get()));
if (need_merge_files) {
auto new_file_ids = get_message_content_any_file_ids(new_content.get());
if (new_file_ids.size() == old_file_ids.size()) {
for (size_t i = 0; i < old_file_ids.size(); i++) {
td_->file_manager_->try_merge_documents(old_file_ids[i], new_file_ids[i]);
}
}
}
} else {
merge_message_contents(td_, old_content.get(), new_content.get(), need_message_changed_warning(old_message),
dialog_id, need_merge_files, is_content_changed, need_update);
compare_message_contents(td_, old_content.get(), new_content.get(), is_content_changed, need_update);
}
if (need_finish_upload) {
if (need_merge_files) {
// the file is likely to be already merged with a server file, but if not we need to
// cancel file upload of the main file to allow next upload with the same file to succeed
cancel_upload_file(old_file_id, "update_message_content");
for (auto old_file_id : old_file_ids) {
cancel_upload_file(old_file_id, "update_message_content");
}
}
if (is_content_changed || need_update) {
@ -33962,9 +33989,9 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me
}
old_content = std::move(new_content);
old_message->last_edit_pts = 0;
update_message_content_file_id_remote(old_content.get(), old_file_id);
update_message_content_file_id_remotes(old_content.get(), old_file_ids);
} else {
update_message_content_file_id_remote(old_content.get(), get_message_content_any_file_id(new_content.get()));
update_message_content_file_id_remotes(old_content.get(), get_message_content_any_file_ids(new_content.get()));
}
if (is_content_changed && !need_update) {
LOG(INFO) << "Content of " << old_message->message_id << " in " << dialog_id << " has changed";