From eeaa4923a46770621e230345a9eb6c28aedd4203 Mon Sep 17 00:00:00 2001 From: RadRussianRus Date: Fri, 11 Sep 2020 09:23:30 +0300 Subject: [PATCH] Reuse sending APIs and try to fix media references --- Telegram/SourceFiles/api/api_sending.cpp | 92 ++++- Telegram/SourceFiles/api/api_sending.h | 19 +- Telegram/SourceFiles/apiwrap.cpp | 313 +++++++++--------- Telegram/SourceFiles/apiwrap.h | 5 +- .../SourceFiles/window/window_peer_menu.cpp | 267 ++++++++------- 5 files changed, 404 insertions(+), 292 deletions(-) diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index 6d569ad4f..32da40ea5 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "data/data_document.h" #include "data/data_photo.h" +#include "data/data_location.h" #include "data/data_channel.h" // ChannelData::addsSignature. #include "data/data_user.h" // UserData::name #include "data/data_session.h" @@ -62,7 +63,9 @@ void SendExistingMedia( Api::MessageToSend &&message, not_null media, Fn inputMedia, - Data::FileOrigin origin) { + Data::FileOrigin origin, + Fn doneCallback = nullptr, + bool forwarding = false) { const auto history = message.action.history; const auto peer = history->peer; const auto session = &history->session(); @@ -135,7 +138,6 @@ void SendExistingMedia( auto &histories = history->owner().histories(); const auto requestType = Data::Histories::RequestType::Send; histories.sendRequest(history, requestType, [=](Fn finish) { - const auto usedFileReference = media->fileReference(); history->sendRequestId = api->request(MTPmessages_SendMedia( MTP_flags(sendFlags), peer->input, @@ -146,12 +148,16 @@ void SendExistingMedia( MTPReplyMarkup(), sentEntities, MTP_int(message.action.options.scheduled) - )).done([=](const MTPUpdates &result) { + )).done([=](const MTPUpdates &result, mtpRequestId requestId) { api->applyUpdates(result, randomId); + if (doneCallback) { + doneCallback(); + } finish(); }).fail([=](const RPCError &error) { if (error.code() == 400 && error.type().startsWith(qstr("FILE_REFERENCE_"))) { + const auto usedFileReference = media->fileReference(); api->refreshFileReference(origin, [=](const auto &result) { if (media->fileReference() != usedFileReference) { repeatRequest(repeatRequest); @@ -170,14 +176,18 @@ void SendExistingMedia( }; performRequest(performRequest); - api->finishForwarding(message.action); + if (!forwarding) { + api->finishForwarding(message.action); + } } } // namespace void SendExistingDocument( Api::MessageToSend &&message, - not_null document) { + not_null document, + Fn doneCallback, + bool forwarding) { const auto inputMedia = [=] { return MTP_inputMediaDocument( MTP_flags(0), @@ -188,7 +198,9 @@ void SendExistingDocument( std::move(message), document, inputMedia, - document->stickerOrGifOrigin()); + document->stickerOrGifOrigin(), + (doneCallback ? std::move(doneCallback) : nullptr), + forwarding); if (document->sticker()) { document->owner().stickers().incrementSticker(document); @@ -197,7 +209,9 @@ void SendExistingDocument( void SendExistingPhoto( Api::MessageToSend &&message, - not_null photo) { + not_null photo, + Fn doneCallback, + bool forwarding) { const auto inputMedia = [=] { return MTP_inputMediaPhoto( MTP_flags(0), @@ -208,7 +222,9 @@ void SendExistingPhoto( std::move(message), photo, inputMedia, - Data::FileOrigin()); + Data::FileOrigin(), + (doneCallback ? std::move(doneCallback) : nullptr), + forwarding); } bool SendDice(Api::MessageToSend &message) { @@ -550,4 +566,64 @@ void SendConfirmedFile( } } +void SendLocationPoint( + const Data::LocationPoint &data, + const SendAction &action, + Fn done, + Fn fail) { + const auto history = action.history; + const auto session = &history->session(); + const auto api = &session->api(); + const auto peer = history->peer; + api->sendAction(action); + + auto sendFlags = MTPmessages_SendMedia::Flags(0); + if (action.replyTo) { + sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id; + } + if (action.clearDraft) { + sendFlags |= MTPmessages_SendMedia::Flag::f_clear_draft; + history->clearLocalDraft(); + history->clearCloudDraft(); + } + const auto silentPost = action.options.silent + || (peer->isBroadcast() && session->data().notifySilentPosts(peer)); + if (silentPost) { + sendFlags |= MTPmessages_SendMedia::Flag::f_silent; + } + if (action.options.scheduled) { + sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date; + } + auto &histories = history->owner().histories(); + const auto requestType = Data::Histories::RequestType::Send; + histories.sendRequest(history, requestType, [=](Fn finish) { + const auto replyTo = action.replyTo; + history->sendRequestId = api->request(MTPmessages_SendMedia( + MTP_flags(sendFlags), + peer->input, + MTP_int(replyTo), + MTP_inputMediaGeoPoint( + MTP_inputGeoPoint( + MTP_double(data.lat()), + MTP_double(data.lon()))), + MTP_string(), + MTP_long(rand_value()), + MTPReplyMarkup(), + MTPVector(), + MTP_int(action.options.scheduled) + )).done([=](const MTPUpdates &result) mutable { + api->applyUpdates(result); + done(); + finish(); + }).fail([=](const RPCError &error) mutable { + if (fail) { + fail(error); + } + finish(); + }).afterRequest(history->sendRequestId + ).send(); + return history->sendRequestId; + }); +} + } // namespace Api diff --git a/Telegram/SourceFiles/api/api_sending.h b/Telegram/SourceFiles/api/api_sending.h index 29184faea..fed71373b 100644 --- a/Telegram/SourceFiles/api/api_sending.h +++ b/Telegram/SourceFiles/api/api_sending.h @@ -11,6 +11,11 @@ class History; class PhotoData; class DocumentData; struct FileLoadResult; +class RPCError; + +namespace Data { +class LocationPoint; +} // namespace Data namespace Api { @@ -19,11 +24,15 @@ struct SendAction; void SendExistingDocument( Api::MessageToSend &&message, - not_null document); + not_null document, + Fn doneCallback = nullptr, + bool forwarding = false); void SendExistingPhoto( Api::MessageToSend &&message, - not_null photo); + not_null photo, + Fn doneCallback = nullptr, + bool forwarding = false); bool SendDice(Api::MessageToSend &message); @@ -37,4 +46,10 @@ void SendConfirmedFile( const std::shared_ptr &file, const std::optional &oldId); +void SendLocationPoint( + const Data::LocationPoint &data, + const SendAction &action, + Fn done, + Fn fail); + } // namespace Api diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 2b4a3ad4c..4caec867a 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -4086,7 +4086,9 @@ void ApiWrap::forwardMessages( ++shared->requestsLeft; } auto medias = QVector(); + auto mediaRefs = QVector(); medias.reserve(ids.size()); + mediaRefs.reserve(ids.size()); for (auto i = fromIter, e = toIter; i != e; i++) { const auto item = *i; @@ -4125,33 +4127,74 @@ void ApiWrap::forwardMessages( : MTPmessages_SendMultiMedia::Flag(0)); const auto requestType = Data::Histories::RequestType::Send; - histories.sendRequest(history, requestType, [=](Fn finish) { - history->sendRequestId = request(MTPmessages_SendMultiMedia( - MTP_flags(finalFlags), - peer->input, - MTPint(), - MTP_vector(medias), - MTP_int(action.options.scheduled) - )).done([=](const MTPUpdates &result) { - applyUpdates(result); - if (shared && !--shared->requestsLeft) { - shared->callback(); - } - finish(); - }).fail([=, ids = localIds](const RPCError &error) { - if (ids) { - for (const auto &[randomId, itemId] : *ids) { - sendMessageFail(error, peer, randomId, itemId); + auto performRequest = [=, &mediaRefs, &histories](const auto &repeatRequest) -> void { + mediaRefs.clear(); + for (auto i = fromIter, e = toIter; i != e; i++) { + const auto item = *i; + const auto media = item->media(); + mediaRefs.push_back(media->photo() + ? media->photo()->fileReference() + : media->document()->fileReference()); + } + histories.sendRequest(history, requestType, [=](Fn finish) { + history->sendRequestId = request(MTPmessages_SendMultiMedia( + MTP_flags(finalFlags), + peer->input, + MTPint(), + MTP_vector(medias), + MTP_int(action.options.scheduled) + )).done([=](const MTPUpdates &result) { + applyUpdates(result); + if (shared && !--shared->requestsLeft) { + shared->callback(); } - } else { - sendMessageFail(error, peer); - } - finish(); - }).afterRequest( - history->sendRequestId - ).send(); - return history->sendRequestId; - }); + finish(); + }).fail([=, ids = localIds](const RPCError &error) { + if (error.code() == 400 + && error.type().startsWith(qstr("FILE_REFERENCE_"))) { + auto refreshRequests = mediaRefs.size(); + auto index = 0; + for (auto i = fromIter, e = toIter; i != e; i++) { + const auto item = *i; + const auto media = item->media(); + const auto origin = media->document() + ? media->document()->stickerOrGifOrigin() + : Data::FileOrigin(); + const auto usedFileReference = mediaRefs.value(index); + + refreshFileReference(origin, [=, &refreshRequests](const auto &result) { + if (refreshRequests > 0) { + refreshRequests--; + return; + } + + const auto currentMediaReference = media->photo() + ? media->photo()->fileReference() + : media->document()->fileReference(); + + if (currentMediaReference != usedFileReference) { + repeatRequest(repeatRequest); + } else { + sendMessageFail(error, peer); + } + }); + index++; + } + } else if (ids) { + for (const auto &[randomId, itemId] : *ids) { + sendMessageFail(error, peer, randomId, itemId); + } + } else { + sendMessageFail(error, peer); + } + finish(); + }).afterRequest( + history->sendRequestId + ).send(); + return history->sendRequestId; + }); + }; + performRequest(performRequest); }; const auto forwardMediaUnquoted = [&] (not_null item) { @@ -4160,86 +4203,62 @@ void ApiWrap::forwardMessages( } const auto media = item->media(); - auto newSendFlags = MTPmessages_SendMedia::Flags(0) - | (action.options.silent - ? MTPmessages_SendMedia::Flag::f_silent - : MTPmessages_SendMedia::Flag(0)) - | (action.options.scheduled - ? MTPmessages_SendMedia::Flag::f_schedule_date - : MTPmessages_SendMedia::Flag(0)); + auto message = ApiWrap::MessageToSend(history); + const auto caption = (cForwardCaptioned() + && !media->geoPoint() + && !media->sharedContact()) + ? item->originalText() + : TextWithEntities(); - auto caption = (cForwardCaptioned() - && !media->geoPoint() - && !media->sharedContact()) - ? item->originalText() - : TextWithEntities(); + message.textWithTags = TextWithTags{ + caption.text, + TextUtilities::ConvertEntitiesToTextTags(caption.entities) + }; + message.action.options = action.options; + message.action.clearDraft = false; - auto sentEntities = Api::EntitiesToMTP( - _session, - caption.entities, - Api::ConvertOption::SkipLocal); - if (!sentEntities.v.isEmpty()) { - newSendFlags |= MTPmessages_SendMedia::Flag::f_entities; + auto doneCallback = [=] () { + if (shared && !--shared->requestsLeft) { + shared->callback(); + } + }; + + if (media->poll()) { + const auto poll = *(media->poll()); + createPoll( + poll, + message.action, + std::move(doneCallback), + nullptr); + } else if (media->geoPoint()) { + const auto location = *(media->geoPoint()); + Api::SendLocationPoint( + location, + message.action, + std::move(doneCallback), + nullptr); + } else if (media->sharedContact()) { + const auto contact = media->sharedContact(); + shareContact( + contact->phoneNumber, + contact->firstName, + contact->lastName, + message.action); + } else if (media->photo()) { + Api::SendExistingPhoto( + std::move(message), + media->photo(), + std::move(doneCallback), + true); // forwarding + } else if (media->document()) { + Api::SendExistingDocument( + std::move(message), + media->document(), + std::move(doneCallback), + true); // forwarding + } else { + Unexpected("Media type in ApiWrap::forwardMessages."); } - - auto inputMedia = media->poll() - ? PollDataToInputMedia(media->poll()) - : media->geoPoint() - ? MTP_inputMediaGeoPoint( - MTP_inputGeoPoint( - MTP_double(media->geoPoint()->lat()), - MTP_double(media->geoPoint()->lon()))) - : media->sharedContact() - ? MTP_inputMediaContact( - MTP_string(media->sharedContact()->phoneNumber), - MTP_string(media->sharedContact()->firstName), - MTP_string(media->sharedContact()->lastName), - MTPstring()) - : media->photo() - ? MTP_inputMediaPhoto(MTP_flags(0), media->photo()->mtpInput(), MTPint()) - : MTP_inputMediaDocument(MTP_flags(0), media->document()->mtpInput(), MTPint()); - - const auto requestType = Data::Histories::RequestType::Send; - const auto currentRandomId = randomIds.takeFirst(); - histories.sendRequest(history, requestType, [=](Fn finish) { - history->sendRequestId = request(MTPmessages_SendMedia( - MTP_flags(newSendFlags), - peer->input, - MTPint(), - inputMedia, - MTP_string(caption.text), - currentRandomId, - MTPReplyMarkup(), - sentEntities, - MTP_int(action.options.scheduled) - )).done([=](const MTPUpdates &result) { - applyUpdates(result); - if (shared && !--shared->requestsLeft) { - shared->callback(); - } - finish(); - }).fail([=, ids = localIds](const RPCError &error) { - if (ids) { - auto found = false; - for (const auto &[randomId, itemId] : *ids) { - if (currentRandomId == MTP_long(randomId)) { - sendMessageFail(error, peer, randomId, itemId); - found = true; - break; - } - } - if (!found) { - sendMessageFail(error, peer); - } - } else { - sendMessageFail(error, peer); - } - finish(); - }).afterRequest( - history->sendRequestId - ).send(); - return history->sendRequestId; - }); }; const auto forwardMessageUnquoted = [&] (not_null item) { @@ -4248,65 +4267,27 @@ void ApiWrap::forwardMessages( } const auto media = item->media(); - auto newSendFlags = MTPmessages_SendMessage::Flag(0) - | (!media || !media->webpage() - ? MTPmessages_SendMessage::Flag::f_no_webpage - : MTPmessages_SendMessage::Flag(0)) - | (action.options.silent - ? MTPmessages_SendMessage::Flag::f_silent - : MTPmessages_SendMessage::Flag(0)) - | (action.options.scheduled - ? MTPmessages_SendMessage::Flag::f_schedule_date - : MTPmessages_SendMessage::Flag(0)); + const auto webPageId = (!media || !media->webpage()) + ? CancelledWebPageId + : media->webpage()->id; - auto sentEntities = Api::EntitiesToMTP( - _session, - item->originalText().entities, - Api::ConvertOption::SkipLocal); - if (!sentEntities.v.isEmpty()) { - newSendFlags |= MTPmessages_SendMessage::Flag::f_entities; - } + auto message = ApiWrap::MessageToSend(history); + message.textWithTags = TextWithTags{ + item->originalText().text, + TextUtilities::ConvertEntitiesToTextTags(item->originalText().entities) + }; + message.action.options = action.options; + message.action.clearDraft = false; + message.webPageId = webPageId; - const auto requestType = Data::Histories::RequestType::Send; - const auto currentRandomId = randomIds.takeFirst(); - histories.sendRequest(history, requestType, [=](Fn finish) { - history->sendRequestId = request(MTPmessages_SendMessage( - MTP_flags(newSendFlags), - peer->input, - MTPint(), - MTP_string(item->originalText().text), - currentRandomId, - MTPReplyMarkup(), - sentEntities, - MTP_int(action.options.scheduled) - )).done([=](const MTPUpdates &result) { - applyUpdates(result); + session().api().sendMessage( + std::move(message), + [=] (const MTPUpdates &result, mtpRequestId requestId) { if (shared && !--shared->requestsLeft) { shared->callback(); } - finish(); - }).fail([=, ids = localIds](const RPCError &error) { - if (ids) { - auto found = false; - for (const auto &[randomId, itemId] : *ids) { - if (currentRandomId == MTP_long(randomId)) { - sendMessageFail(error, peer, randomId, itemId); - found = true; - break; - } - } - if (!found) { - sendMessageFail(error, peer); - } - } else { - sendMessageFail(error, peer); - } - finish(); - }).afterRequest( - history->sendRequestId - ).send(); - return history->sendRequestId; - }); + }, + true); // forwarding }; const auto sendAccumulated = [&] { @@ -4650,7 +4631,10 @@ void ApiWrap::cancelLocalItem(not_null item) { } } -void ApiWrap::sendMessage(MessageToSend &&message) { +void ApiWrap::sendMessage( + MessageToSend &&message, + Fn doneCallback, + bool forwarding) { const auto history = message.action.history; const auto peer = history->peer; auto &textWithTags = message.textWithTags; @@ -4779,9 +4763,12 @@ void ApiWrap::sendMessage(MessageToSend &&message) { MTPReplyMarkup(), sentEntities, MTP_int(action.options.scheduled) - )).done([=](const MTPUpdates &result) { + )).done([=](const MTPUpdates &result, mtpRequestId requestId) { applyUpdates(result, randomId); history->clearSentDraftText(QString()); + if (doneCallback) { + doneCallback(result, requestId); + } finish(); }).fail([=](const RPCError &error) { if (error.type() == qstr("MESSAGE_EMPTY")) { @@ -4797,7 +4784,9 @@ void ApiWrap::sendMessage(MessageToSend &&message) { }); } - finishForwarding(action); + if (!forwarding) { + finishForwarding(action); + } } void ApiWrap::sendBotStart(not_null bot, PeerData *chat) { @@ -5621,7 +5610,9 @@ void ApiWrap::createPoll( done(); finish(); }).fail([=](const RPCError &error) mutable { - fail(error); + if (fail) { + fail(error); + } finish(); }).afterRequest(history->sendRequestId ).send(); diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 3284a10cf..79c12acc9 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -421,7 +421,10 @@ public: void cancelLocalItem(not_null item); - void sendMessage(MessageToSend &&message); + void sendMessage( + MessageToSend &&message, + Fn doneCallback = nullptr, + bool forwarding = false); void sendBotStart(not_null bot, PeerData *chat = nullptr); void sendInlineResult( not_null bot, diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 420374c94..6631be98d 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_peer_menu.h" #include "lang/lang_keys.h" +#include "api/api_sending.h" #include "boxes/confirm_box.h" #include "boxes/mute_settings_box.h" #include "boxes/add_contact_box.h" @@ -54,9 +55,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_drafts.h" #include "data/data_user.h" #include "data/data_game.h" +#include "data/data_web_page.h" #include "data/data_scheduled_messages.h" #include "data/data_histories.h" #include "data/data_chat_filters.h" +#include "data/data_file_origin.h" #include "dialogs/dialogs_key.h" #include "core/application.h" #include "export/export_manager.h" @@ -1116,7 +1119,7 @@ QPointer ShowForwardMessagesBox( } not_null peer; MessageIdsList msgIds; - base::flat_set requests; + int requestsLeft = 0; FnMut submitCallback; }; struct MsgIdsGroup { @@ -1188,7 +1191,7 @@ QPointer ShowForwardMessagesBox( std::vector> &&result, TextWithTags &&comment, Api::SendOptions options) { - if (!data->requests.empty()) { + if (data->requestsLeft > 0) { return; // Share clicked already. } auto items = history->owner().idsToItems(data->msgIds); @@ -1278,9 +1281,9 @@ QPointer ShowForwardMessagesBox( } return result; }; - const auto checkAndClose = [=] (mtpRequestId requestId) { - data->requests.remove(requestId); - if (data->requests.empty()) { + const auto checkAndClose = [=] { + data->requestsLeft--; + if (!data->requestsLeft) { Ui::Toast::Show(tr::lng_share_done(tr::now)); Ui::hideLayer(); } @@ -1304,19 +1307,21 @@ QPointer ShowForwardMessagesBox( MTP_int(options.scheduled) )).done([=](const MTPUpdates &updates, mtpRequestId requestId) { history->session().api().applyUpdates(updates); - checkAndClose(requestId); + checkAndClose(); finish(); }).fail([=](const RPCError &error) { finish(); }).afterRequest(history->sendRequestId).send(); return history->sendRequestId; }); - data->requests.insert(history->sendRequestId); + data->requestsLeft++; }; const auto forwardAlbumUnquoted = [&] (MsgIdsGroup &&group, not_null history) { auto medias = QVector(); + auto mediaRefs = QVector(); medias.reserve(group.items.size()); + mediaRefs.reserve(group.items.size()); auto randomIds = generateRandom(group.items.size()); @@ -1345,6 +1350,9 @@ QPointer ShowForwardMessagesBox( randomId, MTP_string(caption.text), sentEntities)); + mediaRefs.push_back(media->photo() + ? media->photo()->fileReference() + : media->document()->fileReference()); } const auto flags = MTPmessages_SendMultiMedia::Flags(0) @@ -1355,135 +1363,154 @@ QPointer ShowForwardMessagesBox( ? MTPmessages_SendMultiMedia::Flag::f_schedule_date : MTPmessages_SendMultiMedia::Flag(0)); - histories.sendRequest(history, requestType, [=](Fn finish) { - auto &api = history->session().api(); - history->sendRequestId = api.request(MTPmessages_SendMultiMedia( - MTP_flags(flags), - history->peer->input, - MTPint(), - MTP_vector(medias), - MTP_int(options.scheduled) - )).done([=](const MTPUpdates &updates, mtpRequestId requestId) { - history->session().api().applyUpdates(updates); - checkAndClose(requestId); - finish(); - }).fail([=](const RPCError &error) { - finish(); - }).afterRequest(history->sendRequestId).send(); - return history->sendRequestId; - }); - data->requests.insert(history->sendRequestId); + auto performRequest = [=, &mediaRefs, &histories](const auto &repeatRequest) -> void { + mediaRefs.clear(); + for (const auto item : group.items) { + const auto media = item->media(); + mediaRefs.push_back(media->photo() + ? media->photo()->fileReference() + : media->document()->fileReference()); + } + histories.sendRequest(history, requestType, [=](Fn finish) { + auto &api = history->session().api(); + history->sendRequestId = api.request(MTPmessages_SendMultiMedia( + MTP_flags(flags), + history->peer->input, + MTPint(), + MTP_vector(medias), + MTP_int(options.scheduled) + )).done([=](const MTPUpdates &updates, mtpRequestId requestId) { + history->session().api().applyUpdates(updates); + checkAndClose(); + finish(); + }).fail([=](const RPCError &error) { + if (error.code() == 400 + && error.type().startsWith(qstr("FILE_REFERENCE_"))) { + auto refreshRequests = mediaRefs.size(); + auto index = 0; + for (const auto item : group.items) { + const auto media = item->media(); + const auto origin = media->document() + ? media->document()->stickerOrGifOrigin() + : Data::FileOrigin(); + const auto usedFileReference = mediaRefs.value(index); + + history->session().api().refreshFileReference(origin, [=, &refreshRequests](const auto &result) { + if (refreshRequests > 0) { + refreshRequests--; + return; + } + + const auto currentMediaReference = media->photo() + ? media->photo()->fileReference() + : media->document()->fileReference(); + + if (currentMediaReference != usedFileReference) { + repeatRequest(repeatRequest); + } else { + history->session().api().sendMessageFail(error, history->peer); + } + }); + index++; + } + } else { + finish(); + } + }).afterRequest(history->sendRequestId).send(); + return history->sendRequestId; + }); + }; + performRequest(performRequest); + data->requestsLeft++; }; const auto forwardMediaUnquoted = [&] (not_null item, not_null history) { const auto media = item->media(); - auto newSendFlags = MTPmessages_SendMedia::Flags(0) - | (options.silent - ? MTPmessages_SendMedia::Flag::f_silent - : MTPmessages_SendMedia::Flag(0)) - | (options.scheduled - ? MTPmessages_SendMedia::Flag::f_schedule_date - : MTPmessages_SendMedia::Flag(0)); - + auto message = ApiWrap::MessageToSend(history); const auto caption = (cForwardCaptioned() - && !media->geoPoint() - && !media->sharedContact()) - ? item->originalText() - : TextWithEntities(); + && !media->geoPoint() + && !media->sharedContact()) + ? item->originalText() + : TextWithEntities(); - const auto sentEntities = Api::EntitiesToMTP( - session, - caption.entities, - Api::ConvertOption::SkipLocal); - if (!sentEntities.v.isEmpty()) { - newSendFlags |= MTPmessages_SendMedia::Flag::f_entities; + message.textWithTags = TextWithTags{ + caption.text, + TextUtilities::ConvertEntitiesToTextTags(caption.entities) + }; + message.action.options = options; + message.action.clearDraft = false; + + auto doneCallback = [=] () { + checkAndClose(); + }; + + auto &api = history->session().api(); + + if (media->poll()) { + const auto poll = *(media->poll()); + api.createPoll( + poll, + message.action, + std::move(doneCallback), + nullptr); + } else if (media->geoPoint()) { + const auto location = *(media->geoPoint()); + Api::SendLocationPoint( + location, + message.action, + std::move(doneCallback), + nullptr); + } else if (media->sharedContact()) { + const auto contact = media->sharedContact(); + api.shareContact( + contact->phoneNumber, + contact->firstName, + contact->lastName, + message.action); + } else if (media->photo()) { + Api::SendExistingPhoto( + std::move(message), + media->photo(), + std::move(doneCallback), + true); // forwarding + } else if (media->document()) { + Api::SendExistingDocument( + std::move(message), + media->document(), + std::move(doneCallback), + true); // forwarding + } else { + Unexpected("Media type in Window::ShowForwardMessagesBox."); } - const auto inputMedia = media->poll() - ? PollDataToInputMedia(media->poll()) - : media->geoPoint() - ? MTP_inputMediaGeoPoint( - MTP_inputGeoPoint( - MTP_double(media->geoPoint()->lat()), - MTP_double(media->geoPoint()->lon()))) - : media->sharedContact() - ? MTP_inputMediaContact( - MTP_string(media->sharedContact()->phoneNumber), - MTP_string(media->sharedContact()->firstName), - MTP_string(media->sharedContact()->lastName), - MTPstring()) - : media->photo() - ? MTP_inputMediaPhoto(MTP_flags(0), media->photo()->mtpInput(), MTPint()) - : MTP_inputMediaDocument(MTP_flags(0), media->document()->mtpInput(), MTPint()); - - histories.sendRequest(history, requestType, [=](Fn finish) { - auto &api = history->session().api(); - history->sendRequestId = api.request(MTPmessages_SendMedia( - MTP_flags(newSendFlags), - history->peer->input, - MTPint(), - inputMedia, - MTP_string(caption.text), - rand_value(), - MTPReplyMarkup(), - sentEntities, - MTP_int(options.scheduled) - )).done([=](const MTPUpdates &updates, mtpRequestId requestId) { - history->session().api().applyUpdates(updates); - checkAndClose(requestId); - finish(); - }).fail([=](const RPCError &error) { - finish(); - }).afterRequest(history->sendRequestId).send(); - return history->sendRequestId; - }); - data->requests.insert(history->sendRequestId); + data->requestsLeft++; }; const auto forwardMessageUnquoted = [&] (not_null item, not_null history) { const auto media = item->media(); - auto newSendFlags = MTPmessages_SendMessage::Flag(0) - | (!media || !media->webpage() - ? MTPmessages_SendMessage::Flag::f_no_webpage - : MTPmessages_SendMessage::Flag(0)) - | (options.silent - ? MTPmessages_SendMessage::Flag::f_silent - : MTPmessages_SendMessage::Flag(0)) - | (options.scheduled - ? MTPmessages_SendMessage::Flag::f_schedule_date - : MTPmessages_SendMessage::Flag(0)); + const auto webPageId = (!media || !media->webpage()) + ? CancelledWebPageId + : media->webpage()->id; - const auto sentEntities = Api::EntitiesToMTP( - session, - item->originalText().entities, - Api::ConvertOption::SkipLocal); - if (!sentEntities.v.isEmpty()) { - newSendFlags |= MTPmessages_SendMessage::Flag::f_entities; - } + auto message = ApiWrap::MessageToSend(history); + message.textWithTags = TextWithTags{ + item->originalText().text, + TextUtilities::ConvertEntitiesToTextTags(item->originalText().entities) + }; + message.action.options = options; + message.action.clearDraft = false; + message.webPageId = webPageId; - histories.sendRequest(history, requestType, [=](Fn finish) { - auto &api = history->session().api(); - history->sendRequestId = api.request(MTPmessages_SendMessage( - MTP_flags(newSendFlags), - history->peer->input, - MTPint(), - MTP_string(item->originalText().text), - rand_value(), - MTPReplyMarkup(), - sentEntities, - MTP_int(options.scheduled) - )).done([=](const MTPUpdates &updates, mtpRequestId requestId) { - history->session().api().applyUpdates(updates); - checkAndClose(requestId); - finish(); - }).fail([=](const RPCError &error) { - finish(); - }).afterRequest(history->sendRequestId).send(); - return history->sendRequestId; - }); - data->requests.insert(history->sendRequestId); + history->session().api().sendMessage( + std::move(message), + [=] (const MTPUpdates &result, mtpRequestId requestId) { + checkAndClose(); + }, + true); // forwarding + + data->requestsLeft++; }; for (const auto peer : result) {