Use ApiWrap::forwardMessages for multi-forward
This commit is contained in:
parent
7b3f3b3f22
commit
468eb91c0e
1 changed files with 8 additions and 326 deletions
|
|
@ -1104,20 +1104,6 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
int requestsLeft = 0;
|
int requestsLeft = 0;
|
||||||
FnMut<void()> submitCallback;
|
FnMut<void()> submitCallback;
|
||||||
};
|
};
|
||||||
struct MsgIdsGroup {
|
|
||||||
MsgIdsGroup() = default;
|
|
||||||
MsgIdsGroup(not_null<HistoryItem*> item, MTPint fullId, bool isGrouped = false)
|
|
||||||
: grouped(isGrouped) {
|
|
||||||
add(item, fullId);
|
|
||||||
}
|
|
||||||
void add(not_null<HistoryItem*> item, MTPint fullId) {
|
|
||||||
items.push_back(item);
|
|
||||||
ids.push_back(fullId);
|
|
||||||
}
|
|
||||||
HistoryItemsList items;
|
|
||||||
QVector<MTPint> ids;
|
|
||||||
bool grouped = false;
|
|
||||||
};
|
|
||||||
const auto weak = std::make_shared<QPointer<ShareBox>>();
|
const auto weak = std::make_shared<QPointer<ShareBox>>();
|
||||||
const auto firstItem = navigation->session().data().message(items[0]);
|
const auto firstItem = navigation->session().data().message(items[0]);
|
||||||
const auto history = firstItem->history();
|
const auto history = firstItem->history();
|
||||||
|
|
@ -1207,62 +1193,6 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto sendFlags = MTPmessages_ForwardMessages::Flag(0)
|
|
||||||
| MTPmessages_ForwardMessages::Flag::f_with_my_score
|
|
||||||
| (options.silent
|
|
||||||
? MTPmessages_ForwardMessages::Flag::f_silent
|
|
||||||
: MTPmessages_ForwardMessages::Flag(0))
|
|
||||||
| (options.scheduled
|
|
||||||
? MTPmessages_ForwardMessages::Flag::f_schedule_date
|
|
||||||
: MTPmessages_ForwardMessages::Flag(0));
|
|
||||||
|
|
||||||
// Regroup messages if needed
|
|
||||||
auto groupedMsgIds = QVector<MsgIdsGroup>();
|
|
||||||
for (const auto fullId : data->msgIds) {
|
|
||||||
const auto item = navigation->session().data().message(fullId);
|
|
||||||
const auto group = owner->groups().find(item);
|
|
||||||
const auto canBeGrouped = hasMediaForGrouping && item->media() && item->media()->canBeGrouped();
|
|
||||||
|
|
||||||
if (groupedMsgIds.size() > 0) {
|
|
||||||
auto lastGroup = &groupedMsgIds.back();
|
|
||||||
|
|
||||||
if (cForwardAlbumsAsIs()) {
|
|
||||||
if (owner->groups().find(lastGroup->items.back()) == group) {
|
|
||||||
lastGroup->add(item, MTP_int(fullId.msg));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (lastGroup->grouped) {
|
|
||||||
if (lastGroup->items.size() < 10 && canBeGrouped) {
|
|
||||||
lastGroup->add(item, MTP_int(fullId.msg));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!canBeGrouped) {
|
|
||||||
lastGroup->add(item, MTP_int(fullId.msg));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
groupedMsgIds.push_back(MsgIdsGroup(
|
|
||||||
item,
|
|
||||||
MTP_int(fullId.msg),
|
|
||||||
cForwardAlbumsAsIs()
|
|
||||||
? (group != nullptr)
|
|
||||||
: canBeGrouped
|
|
||||||
? cForwardGrouped()
|
|
||||||
: false));
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto generateRandom = [&] (int size) {
|
|
||||||
auto result = QVector<MTPlong>(size);
|
|
||||||
for (auto &value : result) {
|
|
||||||
value = rand_value<MTPlong>();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
const auto checkAndClose = [=] {
|
const auto checkAndClose = [=] {
|
||||||
data->requestsLeft--;
|
data->requestsLeft--;
|
||||||
if (!data->requestsLeft) {
|
if (!data->requestsLeft) {
|
||||||
|
|
@ -1271,229 +1201,6 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto &api = owner->session().api();
|
auto &api = owner->session().api();
|
||||||
auto &histories = owner->histories();
|
|
||||||
const auto requestType = Data::Histories::RequestType::Send;
|
|
||||||
|
|
||||||
const auto forwardQuoted = [&] (
|
|
||||||
MsgIdsGroup &&group,
|
|
||||||
not_null<History*> history,
|
|
||||||
MTPmessages_ForwardMessages::Flags flags) {
|
|
||||||
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
|
|
||||||
auto &api = history->session().api();
|
|
||||||
history->sendRequestId = api.request(MTPmessages_ForwardMessages(
|
|
||||||
MTP_flags(flags),
|
|
||||||
data->peer->input,
|
|
||||||
MTP_vector<MTPint>(group.ids),
|
|
||||||
MTP_vector<MTPlong>(generateRandom(group.ids.size())),
|
|
||||||
history->peer->input,
|
|
||||||
MTP_int(options.scheduled)
|
|
||||||
)).done([=](const MTPUpdates &updates, mtpRequestId requestId) {
|
|
||||||
history->session().api().applyUpdates(updates);
|
|
||||||
checkAndClose();
|
|
||||||
finish();
|
|
||||||
}).fail([=](const RPCError &error) {
|
|
||||||
finish();
|
|
||||||
}).afterRequest(history->sendRequestId).send();
|
|
||||||
return 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());
|
|
||||||
|
|
||||||
for (const auto item : group.items) {
|
|
||||||
const auto media = item->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());
|
|
||||||
const auto caption = cForwardCaptioned()
|
|
||||||
? item->originalText()
|
|
||||||
: TextWithEntities();
|
|
||||||
const 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 randomId = randomIds.takeFirst();
|
|
||||||
|
|
||||||
medias.push_back(MTP_inputSingleMedia(
|
|
||||||
MTP_flags(flags),
|
|
||||||
inputMedia,
|
|
||||||
randomId,
|
|
||||||
MTP_string(caption.text),
|
|
||||||
sentEntities));
|
|
||||||
mediaRefs.push_back(media->photo()
|
|
||||||
? media->photo()->fileReference()
|
|
||||||
: media->document()->fileReference());
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto flags = MTPmessages_SendMultiMedia::Flags(0)
|
|
||||||
| (options.silent
|
|
||||||
? MTPmessages_SendMultiMedia::Flag::f_silent
|
|
||||||
: MTPmessages_SendMultiMedia::Flag(0))
|
|
||||||
| (options.scheduled
|
|
||||||
? MTPmessages_SendMultiMedia::Flag::f_schedule_date
|
|
||||||
: MTPmessages_SendMultiMedia::Flag(0));
|
|
||||||
|
|
||||||
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 message = ApiWrap::MessageToSend(history);
|
|
||||||
const auto caption = (cForwardCaptioned()
|
|
||||||
&& !media->geoPoint()
|
|
||||||
&& !media->sharedContact())
|
|
||||||
? item->originalText()
|
|
||||||
: TextWithEntities();
|
|
||||||
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
data->requestsLeft++;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto forwardMessageUnquoted = [&] (not_null<HistoryItem *> item, not_null<History*> history) {
|
|
||||||
const auto media = item->media();
|
|
||||||
|
|
||||||
const auto webPageId = (!media || !media->webpage())
|
|
||||||
? CancelledWebPageId
|
|
||||||
: media->webpage()->id;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
history->session().api().sendMessage(
|
|
||||||
std::move(message),
|
|
||||||
[=] (const MTPUpdates &result, mtpRequestId requestId) {
|
|
||||||
checkAndClose();
|
|
||||||
},
|
|
||||||
true); // forwarding
|
|
||||||
|
|
||||||
data->requestsLeft++;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto peer : result) {
|
for (const auto peer : result) {
|
||||||
const auto history = owner->history(peer);
|
const auto history = owner->history(peer);
|
||||||
|
|
@ -1504,40 +1211,15 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
||||||
message.action.clearDraft = false;
|
message.action.clearDraft = false;
|
||||||
api.sendMessage(std::move(message));
|
api.sendMessage(std::move(message));
|
||||||
}
|
}
|
||||||
for (auto &group : groupedMsgIds) {
|
|
||||||
if (cForwardQuoted()) {
|
|
||||||
// Forward regrouped messages as is
|
|
||||||
const auto flags = sendFlags;
|
|
||||||
forwardQuoted(std::move(group), history, sendFlags);
|
|
||||||
} else if (group.grouped) {
|
|
||||||
// Sending albums without author
|
|
||||||
forwardAlbumUnquoted(std::move(group), history);
|
|
||||||
} else {
|
|
||||||
for (const auto item : group.items) {
|
|
||||||
const auto media = item->media();
|
|
||||||
|
|
||||||
if (media && !media->webpage()) {
|
data->requestsLeft++;
|
||||||
if ((media->poll() && !history->peer->isUser())
|
auto action = Api::SendAction(history);
|
||||||
|| media->geoPoint()
|
action.options = options;
|
||||||
|| media->sharedContact()
|
action.clearDraft = false;
|
||||||
|| media->photo()
|
|
||||||
|| media->document()) {
|
api.forwardMessages(history->owner().idsToItems(data->msgIds), action, [=] {
|
||||||
// Send media messages without author
|
checkAndClose();
|
||||||
forwardMediaUnquoted(item, history);
|
});
|
||||||
} else {
|
|
||||||
// Forward message if type doesn't support forwarding unquoted
|
|
||||||
forwardQuoted(
|
|
||||||
MsgIdsGroup(item, MTP_int(item->fullId().msg)),
|
|
||||||
history,
|
|
||||||
sendFlags);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Send messages without author
|
|
||||||
forwardMessageUnquoted(item, history);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (data->submitCallback && !cForwardRetainSelection()) {
|
if (data->submitCallback && !cForwardRetainSelection()) {
|
||||||
data->submitCallback();
|
data->submitCallback();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue