diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index ebd0be1c7..bc68c7123 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" // ChannelData::addsSignature. #include "data/data_user.h" // UserData::name #include "data/data_session.h" -#include "data/data_file_origin.h" +//#include "data/data_file_origin.h" // included in header #include "data/data_histories.h" #include "data/data_changes.h" #include "data/stickers/data_stickers.h" @@ -184,6 +184,166 @@ void SendExistingMedia( } // namespace +void SendExistingAlbum( + Api::MessageToSend &&message, + std::vector &&items, + Fn doneCallback, + bool forwarding) { + const auto history = message.action.history; + const auto peer = history->peer; + const auto session = &history->session(); + const auto api = &session->api(); + + message.action.clearDraft = false; + message.action.generateLocal = true; + api->sendAction(message.action); + + auto flags = NewMessageFlags(peer) | MTPDmessage::Flag::f_media; + auto clientFlags = NewMessageClientFlags(); + auto sendFlags = MTPmessages_SendMultiMedia::Flags(0); + if (message.action.replyTo) { + flags |= MTPDmessage::Flag::f_reply_to; + sendFlags |= MTPmessages_SendMultiMedia::Flag::f_reply_to_msg_id; + } + const auto anonymousPost = peer->amAnonymous(); + const auto silentPost = ShouldSendSilent(peer, message.action.options); + InnerFillMessagePostFlags(message.action.options, peer, flags); + if (silentPost) { + sendFlags |= MTPmessages_SendMultiMedia::Flag::f_silent; + } + auto messageFromId = anonymousPost ? 0 : session->userPeerId(); + auto messagePostAuthor = peer->isBroadcast() ? session->user()->name : QString(); + + const auto replyTo = message.action.replyTo; + + if (message.action.options.scheduled) { + flags |= MTPDmessage::Flag::f_from_scheduled; + sendFlags |= MTPmessages_SendMultiMedia::Flag::f_schedule_date; + } else { + clientFlags |= MTPDmessage_ClientFlag::f_local_history_entry; + } + + const auto newGroupId = openssl::RandomValue(); + auto mediaInputs = QVector(); + mediaInputs.reserve(items.size()); + + for (auto i = items.begin(), e = items.end(); i != e; ++i) { + auto caption = i->text; + TextUtilities::Trim(caption); + auto sentEntities = EntitiesToMTP( + session, + caption.entities, + ConvertOption::SkipLocal); + + const auto singleFlags = !sentEntities.v.isEmpty() + ? MTPDinputSingleMedia::Flag::f_entities + : MTPDinputSingleMedia::Flag(0); + + const auto newId = FullMsgId( + peerToChannel(peer->id), + session->data().nextLocalMessageId()); + const auto randomId = openssl::RandomValue(); + + session->data().registerMessageRandomId(randomId, newId); + + if (i->photo) { + history->addNewLocalMessage( + newId.msg, + flags, + clientFlags, + 0, + replyTo, + HistoryItem::NewMessageDate(message.action.options.scheduled), + messageFromId, + messagePostAuthor, + i->photo, + caption, + MTPReplyMarkup(), + newGroupId); + } else if (i->document) { + history->addNewLocalMessage( + newId.msg, + flags, + clientFlags, + 0, + replyTo, + HistoryItem::NewMessageDate(message.action.options.scheduled), + messageFromId, + messagePostAuthor, + i->document, + caption, + MTPReplyMarkup(), + newGroupId); + } + + mediaInputs.push_back(MTP_inputSingleMedia( + MTP_flags(singleFlags), + i->inputMedia, + MTP_long(randomId), + MTP_string(caption.text), + sentEntities)); + } + + auto performRequest = [=](const auto &repeatRequest) -> void { + auto &histories = history->owner().histories(); + const auto requestType = Data::Histories::RequestType::Send; + histories.sendRequest(history, requestType, [=](Fn finish) { + history->sendRequestId = api->request(MTPmessages_SendMultiMedia( + MTP_flags(sendFlags), + peer->input, + MTPint(), + MTP_vector(mediaInputs), + MTP_int(message.action.options.scheduled) + )).done([=](const MTPUpdates &result, mtpRequestId requestId) { + api->applyUpdates(result); + if (doneCallback) { + doneCallback(); + } + finish(); + }).fail([=](const MTP::Error &error) { + if (error.code() == 400 + && error.type().startsWith(qstr("FILE_REFERENCE_"))) { + auto requestsLeft = items.size(); + auto refreshed = false; + for (auto i = items.begin(), e = items.end(); i != e; ++i) { + const auto iter = i; + const auto usedFileReference = iter->photo + ? iter->photo->fileReference() + : iter->document->fileReference(); + api->refreshFileReference(i->origin, [=, &requestsLeft, &refreshed](const auto &result) { + const auto newFileReference = iter->photo + ? iter->photo->fileReference() + : iter->document->fileReference(); + + if (newFileReference != usedFileReference) { + refreshed = true; + } + + if (--requestsLeft == 0) { + if (refreshed) { + repeatRequest(repeatRequest); + } else { + api->sendMessageFail(error, peer); + } + } + }); + } + } else { + api->sendMessageFail(error, peer); + } + finish(); + }).afterRequest(history->sendRequestId + ).send(); + return history->sendRequestId; + }); + }; + performRequest(performRequest); + + if (!forwarding) { + api->finishForwarding(message.action); + } +} + void SendExistingDocument( Api::MessageToSend &&message, not_null document, diff --git a/Telegram/SourceFiles/api/api_sending.h b/Telegram/SourceFiles/api/api_sending.h index 459b3063a..3ab98f77b 100644 --- a/Telegram/SourceFiles/api/api_sending.h +++ b/Telegram/SourceFiles/api/api_sending.h @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "data/data_file_origin.h" + class History; class PhotoData; class DocumentData; @@ -25,6 +27,20 @@ namespace Api { struct MessageToSend; struct SendAction; +struct ExistingAlbumItem { + PhotoData* photo; + DocumentData* document; + MTPInputMedia inputMedia; + Data::FileOrigin origin; + TextWithEntities text; +}; + +void SendExistingAlbum( + Api::MessageToSend &&message, + std::vector &&items, + Fn doneCallback = nullptr, + bool forwarding = false); + void SendExistingDocument( Api::MessageToSend &&message, not_null document, diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 285ecca62..bd278f9cb 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -3881,168 +3881,42 @@ void ApiWrap::forwardMessagesUnquoted( ++shared->requestsLeft; } - const auto medias = std::make_shared>(); - const auto mediaInputs = std::make_shared>(); - const auto mediaRefs = std::make_shared>(); - mediaInputs->reserve(ids.size()); - mediaRefs->reserve(ids.size()); - - const auto views = 1; - const auto forwards = 0; - const auto newGroupId = openssl::RandomValue(); - - auto msgFlags = NewMessageFlags(peer) | MTPDmessage::Flag::f_media; - auto clientFlags = NewMessageClientFlags(); - - FillMessagePostFlags(action, peer, msgFlags); - - if (action.options.scheduled) { - msgFlags |= MTPDmessage::Flag::f_from_scheduled; - } else { - clientFlags |= MTPDmessage_ClientFlag::f_local_history_entry; - } + std::vector items; for (auto i = fromIter, e = toIter; i != e; i++) { const auto item = *i; const auto media = item->media(); - medias->push_back(media); - - const auto inputMedia = media->photo() - ? MTP_inputMediaPhoto(MTP_flags(0), media->photo()->mtpInput(), MTPint()) - : MTP_inputMediaDocument(MTP_flags(0), media->document()->mtpInput(), MTPint(), MTPstring()); - auto caption = cForwardCaptioned() - ? item->originalText() - : TextWithEntities(); - auto sentEntities = Api::EntitiesToMTP( - _session, - caption.entities, - Api::ConvertOption::SkipLocal); - - const auto flags = !sentEntities.v.isEmpty() - ? MTPDinputSingleMedia::Flag::f_entities - : MTPDinputSingleMedia::Flag(0); - - const auto newId = FullMsgId( - peerToChannel(peer->id), - _session->data().nextLocalMessageId()); - auto randomId = randomIds.takeFirst(); - - mediaInputs->push_back(MTP_inputSingleMedia( - MTP_flags(flags), - inputMedia, - MTP_long(randomId), - MTP_string(caption.text), - sentEntities)); - - _session->data().registerMessageRandomId(randomId, newId); - + auto albumItem = Api::ExistingAlbumItem(); if (const auto photo = media->photo()) { - history->addNewLocalMessage( - newId.msg, - msgFlags, - clientFlags, - 0, // viaBotId - 0, // replyTo - HistoryItem::NewMessageDate(action.options.scheduled), - messageFromId, - messagePostAuthor, - photo, - caption, - MTPReplyMarkup(), - newGroupId); + albumItem.photo = photo; + albumItem.inputMedia = MTP_inputMediaPhoto( + MTP_flags(0), photo->mtpInput(), MTPint()); } else if (const auto document = media->document()) { - history->addNewLocalMessage( - newId.msg, - msgFlags, - clientFlags, - 0, // viaBotId - 0, // replyTo - HistoryItem::NewMessageDate(action.options.scheduled), - messageFromId, - messagePostAuthor, - document, - caption, - MTPReplyMarkup(), - newGroupId); + albumItem.document = document; + albumItem.inputMedia = MTP_inputMediaDocument( + MTP_flags(0), document->mtpInput(), MTPint(), MTPstring()); + albumItem.origin = document->stickerOrGifOrigin(); } + albumItem.text = cForwardCaptioned() + ? item->originalText() + : TextWithEntities(); + + items.push_back(albumItem); } - const auto finalFlags = MTPmessages_SendMultiMedia::Flags(0) - | (action.options.silent - ? MTPmessages_SendMultiMedia::Flag::f_silent - : MTPmessages_SendMultiMedia::Flag(0)) - | (action.options.scheduled - ? MTPmessages_SendMultiMedia::Flag::f_schedule_date - : MTPmessages_SendMultiMedia::Flag(0)); - - const auto requestType = Data::Histories::RequestType::Send; - auto performRequest = [=, &histories](const auto &repeatRequest) -> void { - mediaRefs->clear(); - for (auto i = medias->begin(), e = medias->end(); i != e; i++) { - const auto media = *i; - mediaRefs->push_back(media->photo() - ? media->photo()->fileReference() - : media->document()->fileReference()); + auto doneCallback = [=] () { + if (shared && !--shared->requestsLeft) { + shared->callback(); } - histories.sendRequest(history, requestType, [=](Fn finish) { - history->sendRequestId = request(MTPmessages_SendMultiMedia( - MTP_flags(finalFlags), - peer->input, - MTPint(), - MTP_vector(*mediaInputs), - MTP_int(action.options.scheduled) - )).done([=](const MTPUpdates &result) { - applyUpdates(result); - if (shared && !--shared->requestsLeft) { - shared->callback(); - } - finish(); - }).fail([=](const MTP::Error &error) { - if (error.code() == 400 - && error.type().startsWith(qstr("FILE_REFERENCE_"))) { - auto refreshRequests = mediaRefs->size(); - auto index = 0; - auto wasUpdated = false; - for (auto i = medias->begin(), e = medias->end(); i != e; i++) { - const auto media = *i; - const auto origin = media->document() - ? media->document()->stickerOrGifOrigin() - : Data::FileOrigin(); - const auto usedFileReference = mediaRefs->value(index); - - refreshFileReference(origin, [=, &refreshRequests, &wasUpdated](const auto &result) { - const auto currentMediaReference = media->photo() - ? media->photo()->fileReference() - : media->document()->fileReference(); - - if (currentMediaReference != usedFileReference) { - wasUpdated = true; - } - - if (refreshRequests > 0) { - refreshRequests--; - return; - } - - if (wasUpdated) { - repeatRequest(repeatRequest); - } else { - sendMessageFail(error, peer); - } - }); - index++; - } - } else { - sendMessageFail(error, peer); - } - finish(); - }).afterRequest( - history->sendRequestId - ).send(); - return history->sendRequestId; - }); }; - performRequest(performRequest); + + auto message = ApiWrap::MessageToSend(history); + + Api::SendExistingAlbum( + std::move(message), + std::move(items), + std::move(doneCallback), + true); // forwarding }; const auto forwardMediaUnquoted = [&] (not_null item) {