Moving to new Api::SendExistingAlbum function

This should reduce complexity of main unquoted forward function and potentially resolve Windows CI faliure.
This commit is contained in:
Eric Kotato 2021-04-23 23:21:05 +03:00
parent 5654ab6fdf
commit 0aea7e8d75
3 changed files with 202 additions and 152 deletions

View file

@ -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<ExistingAlbumItem> &&items,
Fn<void()> 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<uint64>();
auto mediaInputs = QVector<MTPInputSingleMedia>();
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<uint64>();
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<void()> finish) {
history->sendRequestId = api->request(MTPmessages_SendMultiMedia(
MTP_flags(sendFlags),
peer->input,
MTPint(),
MTP_vector<MTPInputSingleMedia>(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<DocumentData*> document,

View file

@ -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<ExistingAlbumItem> &&items,
Fn<void()> doneCallback = nullptr,
bool forwarding = false);
void SendExistingDocument(
Api::MessageToSend &&message,
not_null<DocumentData*> document,

View file

@ -3881,168 +3881,42 @@ void ApiWrap::forwardMessagesUnquoted(
++shared->requestsLeft;
}
const auto medias = std::make_shared<QVector<Data::Media*>>();
const auto mediaInputs = std::make_shared<QVector<MTPInputSingleMedia>>();
const auto mediaRefs = std::make_shared<QVector<QByteArray>>();
mediaInputs->reserve(ids.size());
mediaRefs->reserve(ids.size());
const auto views = 1;
const auto forwards = 0;
const auto newGroupId = openssl::RandomValue<uint64>();
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<Api::ExistingAlbumItem> 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<void()> finish) {
history->sendRequestId = request(MTPmessages_SendMultiMedia(
MTP_flags(finalFlags),
peer->input,
MTPint(),
MTP_vector<MTPInputSingleMedia>(*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<HistoryItem *> item) {