Reuse sending APIs and try to fix media references
This commit is contained in:
parent
23c8792935
commit
eeaa4923a4
5 changed files with 404 additions and 292 deletions
|
|
@ -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<MediaData*> media,
|
||||
Fn<MTPInputMedia()> inputMedia,
|
||||
Data::FileOrigin origin) {
|
||||
Data::FileOrigin origin,
|
||||
Fn<void()> 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<void()> 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<DocumentData*> document) {
|
||||
not_null<DocumentData*> document,
|
||||
Fn<void()> 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<PhotoData*> photo) {
|
||||
not_null<PhotoData*> photo,
|
||||
Fn<void()> 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<void()> done,
|
||||
Fn<void(const RPCError &error)> 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<void()> 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<uint64>()),
|
||||
MTPReplyMarkup(),
|
||||
MTPVector<MTPMessageEntity>(),
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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<DocumentData*> document);
|
||||
not_null<DocumentData*> document,
|
||||
Fn<void()> doneCallback = nullptr,
|
||||
bool forwarding = false);
|
||||
|
||||
void SendExistingPhoto(
|
||||
Api::MessageToSend &&message,
|
||||
not_null<PhotoData*> photo);
|
||||
not_null<PhotoData*> photo,
|
||||
Fn<void()> doneCallback = nullptr,
|
||||
bool forwarding = false);
|
||||
|
||||
bool SendDice(Api::MessageToSend &message);
|
||||
|
||||
|
|
@ -37,4 +46,10 @@ void SendConfirmedFile(
|
|||
const std::shared_ptr<FileLoadResult> &file,
|
||||
const std::optional<FullMsgId> &oldId);
|
||||
|
||||
void SendLocationPoint(
|
||||
const Data::LocationPoint &data,
|
||||
const SendAction &action,
|
||||
Fn<void()> done,
|
||||
Fn<void(const RPCError &error)> fail);
|
||||
|
||||
} // namespace Api
|
||||
|
|
|
|||
|
|
@ -4086,7 +4086,9 @@ void ApiWrap::forwardMessages(
|
|||
++shared->requestsLeft;
|
||||
}
|
||||
auto medias = QVector<MTPInputSingleMedia>();
|
||||
auto mediaRefs = QVector<QByteArray>();
|
||||
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<void()> finish) {
|
||||
history->sendRequestId = request(MTPmessages_SendMultiMedia(
|
||||
MTP_flags(finalFlags),
|
||||
peer->input,
|
||||
MTPint(),
|
||||
MTP_vector<MTPInputSingleMedia>(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<void()> finish) {
|
||||
history->sendRequestId = request(MTPmessages_SendMultiMedia(
|
||||
MTP_flags(finalFlags),
|
||||
peer->input,
|
||||
MTPint(),
|
||||
MTP_vector<MTPInputSingleMedia>(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<HistoryItem *> 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<void()> 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<HistoryItem *> 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<void()> 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<HistoryItem*> item) {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
void ApiWrap::sendMessage(
|
||||
MessageToSend &&message,
|
||||
Fn<void(const MTPUpdates &, mtpRequestId)> 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<UserData*> 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();
|
||||
|
|
|
|||
|
|
@ -421,7 +421,10 @@ public:
|
|||
|
||||
void cancelLocalItem(not_null<HistoryItem*> item);
|
||||
|
||||
void sendMessage(MessageToSend &&message);
|
||||
void sendMessage(
|
||||
MessageToSend &&message,
|
||||
Fn<void(const MTPUpdates &, mtpRequestId)> doneCallback = nullptr,
|
||||
bool forwarding = false);
|
||||
void sendBotStart(not_null<UserData*> bot, PeerData *chat = nullptr);
|
||||
void sendInlineResult(
|
||||
not_null<UserData*> bot,
|
||||
|
|
|
|||
|
|
@ -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<Ui::RpWidget> ShowForwardMessagesBox(
|
|||
}
|
||||
not_null<PeerData*> peer;
|
||||
MessageIdsList msgIds;
|
||||
base::flat_set<mtpRequestId> requests;
|
||||
int requestsLeft = 0;
|
||||
FnMut<void()> submitCallback;
|
||||
};
|
||||
struct MsgIdsGroup {
|
||||
|
|
@ -1188,7 +1191,7 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
|||
std::vector<not_null<PeerData*>> &&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<Ui::RpWidget> 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<Ui::RpWidget> 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*> history) {
|
||||
auto medias = QVector<MTPInputSingleMedia>();
|
||||
auto mediaRefs = QVector<QByteArray>();
|
||||
medias.reserve(group.items.size());
|
||||
mediaRefs.reserve(group.items.size());
|
||||
|
||||
auto randomIds = generateRandom(group.items.size());
|
||||
|
||||
|
|
@ -1345,6 +1350,9 @@ QPointer<Ui::RpWidget> 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<Ui::RpWidget> ShowForwardMessagesBox(
|
|||
? MTPmessages_SendMultiMedia::Flag::f_schedule_date
|
||||
: MTPmessages_SendMultiMedia::Flag(0));
|
||||
|
||||
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
||||
auto &api = history->session().api();
|
||||
history->sendRequestId = api.request(MTPmessages_SendMultiMedia(
|
||||
MTP_flags(flags),
|
||||
history->peer->input,
|
||||
MTPint(),
|
||||
MTP_vector<MTPInputSingleMedia>(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<void()> finish) {
|
||||
auto &api = history->session().api();
|
||||
history->sendRequestId = api.request(MTPmessages_SendMultiMedia(
|
||||
MTP_flags(flags),
|
||||
history->peer->input,
|
||||
MTPint(),
|
||||
MTP_vector<MTPInputSingleMedia>(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<HistoryItem *> item, not_null<History*> 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<void()> 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<MTPlong>(),
|
||||
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<HistoryItem *> item, not_null<History*> 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<void()> 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<MTPlong>(),
|
||||
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) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue