Send and delete messages through Histories.

This commit is contained in:
John Preston 2020-02-21 14:29:48 +04:00
parent 147e8cc467
commit 818f5cd004
8 changed files with 363 additions and 258 deletions

View File

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h" // UserData::name
#include "data/data_session.h"
#include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "history/history.h"
#include "history/history_message.h" // NewMessageFlags.
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
@ -110,23 +111,30 @@ void SendExistingMedia(
auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
auto performRequest = [=] {
const auto usedFileReference = media->fileReference();
history->sendRequestId = api->request(MTPmessages_SendMedia(
MTP_flags(sendFlags),
peer->input,
MTP_int(replyTo),
inputMedia(),
MTP_string(captionText),
MTP_long(randomId),
MTPReplyMarkup(),
sentEntities,
MTP_int(message.action.options.scheduled)
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result, randomId);
}).fail([=](const RPCError &error) {
(*failHandler)(error, usedFileReference);
}).afterRequest(history->sendRequestId
).send();
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,
MTP_int(replyTo),
inputMedia(),
MTP_string(captionText),
MTP_long(randomId),
MTPReplyMarkup(),
sentEntities,
MTP_int(message.action.options.scheduled)
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result, randomId);
finish();
}).fail([=](const RPCError &error) {
(*failHandler)(error, usedFileReference);
finish();
}).afterRequest(history->sendRequestId
).send();
return history->sendRequestId;
});
};
*failHandler = [=](const RPCError &error, QByteArray usedFileReference) {
if (error.code() == 400

View File

@ -2319,8 +2319,8 @@ void ApiWrap::deleteHistory(
bool justClear,
bool revoke) {
auto deleteTillId = MsgId(0);
const auto history = _session->data().historyLoaded(peer);
if (history && justClear) {
const auto history = _session->data().history(peer);
if (justClear) {
// In case of clear history we need to know the last server message.
while (history->lastMessageKnown()) {
const auto last = history->lastMessage();
@ -2350,30 +2350,22 @@ void ApiWrap::deleteHistory(
leaveChannel(channel);
} else {
if (const auto migrated = peer->migrateFrom()) {
clearHistory(migrated, revoke);
deleteHistory(migrated, justClear, revoke);
}
if (IsServerMsgId(deleteTillId)) {
request(MTPchannels_DeleteHistory(
channel->inputChannel,
MTP_int(deleteTillId)
)).send();
history->owner().histories().deleteAllMessages(
history,
deleteTillId,
justClear,
revoke);
}
}
} else {
using Flag = MTPmessages_DeleteHistory::Flag;
const auto flags = Flag(0)
| (justClear ? Flag::f_just_clear : Flag(0))
| ((peer->isUser() && revoke) ? Flag::f_revoke : Flag(0));
request(MTPmessages_DeleteHistory(
MTP_flags(flags),
peer->input,
MTP_int(0)
)).done([=](const MTPmessages_AffectedHistory &result) {
const auto offset = applyAffectedHistory(peer, result);
if (offset > 0) {
deleteHistory(peer, justClear, revoke);
}
}).send();
history->owner().histories().deleteAllMessages(
history,
deleteTillId,
justClear,
revoke);
}
if (!justClear) {
_session->data().deleteConversationLocally(peer);
@ -2411,30 +2403,6 @@ void ApiWrap::applyAffectedMessages(
App::main()->ptsUpdateAndApply(data.vpts().v, data.vpts_count().v);
}
void ApiWrap::deleteMessages(
not_null<PeerData*> peer,
const QVector<MTPint> &ids,
bool revoke) {
const auto done = [=](const MTPmessages_AffectedMessages & result) {
applyAffectedMessages(peer, result);
if (const auto history = peer->owner().historyLoaded(peer)) {
history->requestChatListMessage();
}
};
if (const auto channel = peer->asChannel()) {
request(MTPchannels_DeleteMessages(
channel->inputChannel,
MTP_vector<MTPint>(ids)
)).done(done).send();
} else {
using Flag = MTPmessages_DeleteMessages::Flag;
request(MTPmessages_DeleteMessages(
MTP_flags(revoke ? Flag::f_revoke : Flag(0)),
MTP_vector<MTPint>(ids)
)).done(done).send();
}
}
void ApiWrap::saveDraftsToCloud() {
for (auto i = _draftsSaveRequestIds.begin(), e = _draftsSaveRequestIds.end(); i != e; ++i) {
if (i->second) continue; // sent already
@ -4326,6 +4294,8 @@ void ApiWrap::forwardMessages(
FnMut<void()> &&successCallback) {
Expects(!items.empty());
auto &histories = session().data().histories();
struct SharedCallback {
int requestsLeft = 0;
FnMut<void()> callback;
@ -4342,7 +4312,7 @@ void ApiWrap::forwardMessages(
const auto history = action.history;
const auto peer = history->peer;
session().data().histories().readInbox(history);
histories.readInbox(history);
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = action.options.silent
@ -4374,7 +4344,7 @@ void ApiWrap::forwardMessages(
auto currentGroupId = items.front()->groupId();
auto ids = QVector<MTPint>();
auto randomIds = QVector<MTPlong>();
auto localIds = std::unique_ptr<base::flat_map<uint64, FullMsgId>>();
auto localIds = std::shared_ptr<base::flat_map<uint64, FullMsgId>>();
const auto sendAccumulated = [&] {
if (shared) {
@ -4384,30 +4354,36 @@ void ApiWrap::forwardMessages(
| (currentGroupId == MessageGroupId()
? MTPmessages_ForwardMessages::Flag(0)
: MTPmessages_ForwardMessages::Flag::f_grouped);
history->sendRequestId = request(MTPmessages_ForwardMessages(
MTP_flags(finalFlags),
forwardFrom->input,
MTP_vector<MTPint>(ids),
MTP_vector<MTPlong>(randomIds),
peer->input,
MTP_int(action.options.scheduled)
)).done([=, callback = std::move(successCallback)](
const MTPUpdates &updates) {
applyUpdates(updates);
if (shared && !--shared->requestsLeft) {
shared->callback();
}
}).fail([=, ids = std::move(localIds)](const RPCError &error) {
if (ids) {
for (const auto &[randomId, itemId] : *ids) {
sendMessageFail(error, peer, randomId, itemId);
const auto requestType = Data::Histories::RequestType::Send;
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
history->sendRequestId = request(MTPmessages_ForwardMessages(
MTP_flags(finalFlags),
forwardFrom->input,
MTP_vector<MTPint>(ids),
MTP_vector<MTPlong>(randomIds),
peer->input,
MTP_int(action.options.scheduled)
)).done([=](
const MTPUpdates &updates) {
applyUpdates(updates);
if (shared && !--shared->requestsLeft) {
shared->callback();
}
} else {
sendMessageFail(error, peer);
}
}).afterRequest(
history->sendRequestId
).send();
finish();
}).fail([=, ids = localIds](const RPCError &error) {
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;
});
ids.resize(0);
randomIds.resize(0);
@ -4440,7 +4416,7 @@ void ApiWrap::forwardMessages(
message);
_session->data().registerMessageRandomId(randomId, newId);
if (!localIds) {
localIds = std::make_unique<base::flat_map<uint64, FullMsgId>>();
localIds = std::make_shared<base::flat_map<uint64, FullMsgId>>();
}
localIds->emplace(randomId, newId);
}
@ -4855,6 +4831,9 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
HistoryItem *lastMessage = nullptr;
auto &histories = history->owner().histories();
const auto requestType = Data::Histories::RequestType::Send;
while (TextUtilities::CutPart(sending, left, MaxMessageSize)) {
auto newId = FullMsgId(
peerToChannel(peer->id),
@ -4945,27 +4924,32 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
MTPVector<MTPRestrictionReason>()),
clientFlags,
NewMessageType::Unread);
history->sendRequestId = request(MTPmessages_SendMessage(
MTP_flags(sendFlags),
peer->input,
MTP_int(action.replyTo),
msgText,
MTP_long(randomId),
MTPReplyMarkup(),
sentEntities,
MTP_int(action.options.scheduled)
)).done([=](const MTPUpdates &result) {
applyUpdates(result, randomId);
history->clearSentDraftText(QString());
}).fail([=](const RPCError &error) {
if (error.type() == qstr("MESSAGE_EMPTY")) {
lastMessage->destroy();
} else {
sendMessageFail(error, peer, randomId, newId);
}
history->clearSentDraftText(QString());
}).afterRequest(history->sendRequestId
).send();
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
history->sendRequestId = request(MTPmessages_SendMessage(
MTP_flags(sendFlags),
peer->input,
MTP_int(action.replyTo),
msgText,
MTP_long(randomId),
MTPReplyMarkup(),
sentEntities,
MTP_int(action.options.scheduled)
)).done([=](const MTPUpdates &result) {
applyUpdates(result, randomId);
history->clearSentDraftText(QString());
finish();
}).fail([=](const RPCError &error) {
if (error.type() == qstr("MESSAGE_EMPTY")) {
lastMessage->destroy();
} else {
sendMessageFail(error, peer, randomId, newId);
}
history->clearSentDraftText(QString());
finish();
}).afterRequest(history->sendRequestId
).send();
return history->sendRequestId;
});
}
if (const auto main = App::main()) {
@ -5071,23 +5055,29 @@ void ApiWrap::sendInlineResult(
history->clearCloudDraft();
history->setSentDraftText(QString());
history->sendRequestId = request(MTPmessages_SendInlineBotResult(
MTP_flags(sendFlags),
peer->input,
MTP_int(action.replyTo),
MTP_long(randomId),
MTP_long(data->getQueryId()),
MTP_string(data->getId()),
MTP_int(action.options.scheduled)
)).done([=](const MTPUpdates &result) {
applyUpdates(result, randomId);
history->clearSentDraftText(QString());
}).fail([=](const RPCError &error) {
sendMessageFail(error, peer, randomId, newId);
history->clearSentDraftText(QString());
}).afterRequest(history->sendRequestId
).send();
auto &histories = history->owner().histories();
const auto requestType = Data::Histories::RequestType::Send;
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
history->sendRequestId = request(MTPmessages_SendInlineBotResult(
MTP_flags(sendFlags),
peer->input,
MTP_int(action.replyTo),
MTP_long(randomId),
MTP_long(data->getQueryId()),
MTP_string(data->getId()),
MTP_int(action.options.scheduled)
)).done([=](const MTPUpdates &result) {
applyUpdates(result, randomId);
history->clearSentDraftText(QString());
finish();
}).fail([=](const RPCError &error) {
sendMessageFail(error, peer, randomId, newId);
history->clearSentDraftText(QString());
finish();
}).afterRequest(history->sendRequestId
).send();
return history->sendRequestId;
});
if (const auto main = App::main()) {
main->finishForwarding(action);
}
@ -5206,25 +5196,32 @@ void ApiWrap::sendMediaWithRandomId(
? MTPmessages_SendMedia::Flag::f_schedule_date
: MTPmessages_SendMedia::Flag(0));
const auto peer = history->peer;
const auto itemId = item->fullId();
history->sendRequestId = request(MTPmessages_SendMedia(
MTP_flags(flags),
peer->input,
MTP_int(replyTo),
media,
MTP_string(caption.text),
MTP_long(randomId),
MTPReplyMarkup(),
sentEntities,
MTP_int(options.scheduled)
)).done([=](const MTPUpdates &result) {
applyUpdates(result);
}).fail([=](const RPCError &error) {
sendMessageFail(error, peer, randomId, itemId);
}).afterRequest(
history->sendRequestId
).send();
auto &histories = history->owner().histories();
const auto requestType = Data::Histories::RequestType::Send;
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
const auto peer = history->peer;
const auto itemId = item->fullId();
history->sendRequestId = request(MTPmessages_SendMedia(
MTP_flags(flags),
peer->input,
MTP_int(replyTo),
media,
MTP_string(caption.text),
MTP_long(randomId),
MTPReplyMarkup(),
sentEntities,
MTP_int(options.scheduled)
)).done([=](const MTPUpdates &result) {
applyUpdates(result);
finish();
}).fail([=](const RPCError &error) {
sendMessageFail(error, peer, randomId, itemId);
finish();
}).afterRequest(
history->sendRequestId
).send();
return history->sendRequestId;
});
}
void ApiWrap::sendAlbumWithUploaded(
@ -5302,27 +5299,34 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
| (album->options.scheduled
? MTPmessages_SendMultiMedia::Flag::f_schedule_date
: MTPmessages_SendMultiMedia::Flag(0));
const auto peer = history->peer;
history->sendRequestId = request(MTPmessages_SendMultiMedia(
MTP_flags(flags),
peer->input,
MTP_int(replyTo),
MTP_vector<MTPInputSingleMedia>(medias),
MTP_int(album->options.scheduled)
)).done([=](const MTPUpdates &result) {
_sendingAlbums.remove(groupId);
applyUpdates(result);
}).fail([=](const RPCError &error) {
if (const auto album = _sendingAlbums.take(groupId)) {
for (const auto &item : (*album)->items) {
sendMessageFail(error, peer, item.randomId, item.msgId);
auto &histories = history->owner().histories();
const auto requestType = Data::Histories::RequestType::Send;
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
const auto peer = history->peer;
history->sendRequestId = request(MTPmessages_SendMultiMedia(
MTP_flags(flags),
peer->input,
MTP_int(replyTo),
MTP_vector<MTPInputSingleMedia>(medias),
MTP_int(album->options.scheduled)
)).done([=](const MTPUpdates &result) {
_sendingAlbums.remove(groupId);
applyUpdates(result);
finish();
}).fail([=](const RPCError &error) {
if (const auto album = _sendingAlbums.take(groupId)) {
for (const auto &item : (*album)->items) {
sendMessageFail(error, peer, item.randomId, item.msgId);
}
} else {
sendMessageFail(error, peer);
}
} else {
sendMessageFail(error, peer);
}
}).afterRequest(
history->sendRequestId
).send();
finish();
}).afterRequest(
history->sendRequestId
).send();
return history->sendRequestId;
});
}
FileLoadTo ApiWrap::fileLoadTaskOptions(const SendAction &action) const {
@ -5719,8 +5723,8 @@ Api::SensitiveContent &ApiWrap::sensitiveContent() {
void ApiWrap::createPoll(
const PollData &data,
const SendAction &action,
FnMut<void()> done,
FnMut<void(const RPCError &error)> fail) {
Fn<void()> done,
Fn<void(const RPCError &error)> fail) {
sendAction(action);
const auto history = action.history;
@ -5753,27 +5757,34 @@ void ApiWrap::createPoll(
correct.push_back(MTP_bytes(answer.option));
}
}
const auto replyTo = action.replyTo;
history->sendRequestId = request(MTPmessages_SendMedia(
MTP_flags(sendFlags),
peer->input,
MTP_int(replyTo),
MTP_inputMediaPoll(
MTP_flags(inputFlags),
PollDataToMTP(&data),
MTP_vector<MTPbytes>(correct)),
MTP_string(),
MTP_long(rand_value<uint64>()),
MTPReplyMarkup(),
MTPVector<MTPMessageEntity>(),
MTP_int(action.options.scheduled)
)).done([=, done = std::move(done)](const MTPUpdates &result) mutable {
applyUpdates(result);
done();
}).fail([=, fail = std::move(fail)](const RPCError &error) mutable {
fail(error);
}).afterRequest(history->sendRequestId
).send();
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 = request(MTPmessages_SendMedia(
MTP_flags(sendFlags),
peer->input,
MTP_int(replyTo),
MTP_inputMediaPoll(
MTP_flags(inputFlags),
PollDataToMTP(&data),
MTP_vector<MTPbytes>(correct)),
MTP_string(),
MTP_long(rand_value<uint64>()),
MTPReplyMarkup(),
MTPVector<MTPMessageEntity>(),
MTP_int(action.options.scheduled)
)).done([=](const MTPUpdates &result) mutable {
applyUpdates(result);
done();
finish();
}).fail([=](const RPCError &error) mutable {
fail(error);
finish();
}).afterRequest(history->sendRequestId
).send();
return history->sendRequestId;
});
}
void ApiWrap::sendPollVotes(

View File

@ -141,6 +141,9 @@ public:
void applyUpdates(
const MTPUpdates &updates,
uint64 sentMessageRandomId = 0);
int applyAffectedHistory(
not_null<PeerData*> peer,
const MTPmessages_AffectedHistory &result);
void registerModifyRequest(const QString &key, mtpRequestId requestId);
void clearModifyRequest(const QString &key);
@ -298,10 +301,6 @@ public:
void clearHistory(not_null<PeerData*> peer, bool revoke);
void deleteConversation(not_null<PeerData*> peer, bool revoke);
void deleteMessages(
not_null<PeerData*> peer,
const QVector<MTPint> &ids,
bool revoke);
base::Observable<PeerData*> &fullPeerUpdated() {
return _fullPeerUpdated;
@ -469,8 +468,8 @@ public:
void createPoll(
const PollData &data,
const SendAction &action,
FnMut<void()> done,
FnMut<void(const RPCError &error)> fail);
Fn<void()> done,
Fn<void(const RPCError &error)> fail);
void sendPollVotes(
FullMsgId itemId,
const std::vector<QByteArray> &options);
@ -616,9 +615,6 @@ private:
not_null<PeerData*> peer,
bool justClear,
bool revoke);
int applyAffectedHistory(
not_null<PeerData*> peer,
const MTPmessages_AffectedHistory &result);
void applyAffectedMessages(const MTPmessages_AffectedMessages &result);
void deleteAllFromUserSend(

View File

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_chat.h"
#include "data/data_user.h"
#include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "base/unixtime.h"
#include "main/main_session.h"
#include "observer_peer.h"
@ -787,7 +788,7 @@ void DeleteMessagesBox::deleteAndClear() {
auto remove = std::vector<not_null<HistoryItem*>>();
remove.reserve(_ids.size());
base::flat_map<not_null<PeerData*>, QVector<MTPint>> idsByPeer;
base::flat_map<not_null<History*>, QVector<MTPint>> idsByPeer;
base::flat_map<not_null<PeerData*>, QVector<MTPint>> scheduledIdsByPeer;
for (const auto itemId : _ids) {
if (const auto item = _session->data().message(itemId)) {
@ -805,13 +806,13 @@ void DeleteMessagesBox::deleteAndClear() {
}
remove.push_back(item);
if (IsServerMsgId(item->id)) {
idsByPeer[history->peer].push_back(MTP_int(itemId.msg));
idsByPeer[history].push_back(MTP_int(itemId.msg));
}
}
}
for (const auto &[peer, ids] : idsByPeer) {
peer->session().api().deleteMessages(peer, ids, revoke);
for (const auto &[history, ids] : idsByPeer) {
history->owner().histories().deleteMessages(history, ids, revoke);
}
for (const auto &[peer, ids] : scheduledIdsByPeer) {
peer->session().api().request(MTPmessages_DeleteScheduledMessages(

View File

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_chat.h"
#include "data/data_user.h"
#include "data/data_folder.h"
#include "data/data_histories.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "lang/lang_keys.h"
@ -30,33 +31,36 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace {
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = chat->owner().historyLoaded(chat);
const auto randomId = rand_value<uint64>();
const auto api = &chat->session().api();
const auto requestId = api->request(MTPmessages_SendMedia(
MTP_flags(0),
chat->input,
MTP_int(0),
MTP_inputMediaGame(
MTP_inputGameShortName(
bot->inputUser,
MTP_string(bot->botInfo->shareGameShortName))),
MTP_string(),
MTP_long(randomId),
MTPReplyMarkup(),
MTPVector<MTPMessageEntity>(),
MTP_int(0) // schedule_date
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result, randomId);
}).fail([=](const RPCError &error) {
api->sendMessageFail(error, chat);
}).afterRequest(
history ? history->sendRequestId : 0
).send();
if (history) {
history->sendRequestId = requestId;
}
const auto history = chat->owner().history(chat);
auto &histories = history->owner().histories();
const auto requestType = Data::Histories::RequestType::Send;
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
const auto randomId = rand_value<uint64>();
const auto api = &chat->session().api();
history->sendRequestId = api->request(MTPmessages_SendMedia(
MTP_flags(0),
chat->input,
MTP_int(0),
MTP_inputMediaGame(
MTP_inputGameShortName(
bot->inputUser,
MTP_string(bot->botInfo->shareGameShortName))),
MTP_string(),
MTP_long(randomId),
MTPReplyMarkup(),
MTPVector<MTPMessageEntity>(),
MTP_int(0) // schedule_date
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result, randomId);
finish();
}).fail([=](const RPCError &error) {
api->sendMessageFail(error, chat);
finish();
}).afterRequest(
history->sendRequestId
).send();
return history->sendRequestId;
});
Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
}

View File

@ -369,7 +369,7 @@ void Histories::sendReadRequests() {
void Histories::sendReadRequest(not_null<History*> history, State &state) {
const auto tillId = state.readTill;
state.readWhen = kReadRequestSent;
sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> done) {
sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> finish) {
const auto finished = [=] {
const auto state = lookup(history);
Assert(state != nullptr);
@ -386,7 +386,7 @@ void Histories::sendReadRequest(not_null<History*> history, State &state) {
sendReadRequests();
}
}
done();
finish();
};
if (const auto channel = history->peer->asChannel()) {
return session().api().request(MTPchannels_ReadHistory(
@ -439,10 +439,81 @@ bool Histories::postponeEntryRequest(const State &state) const {
return (i != end(state.sent));
}
void Histories::deleteMessages(
not_null<History*> history,
const QVector<MTPint> &ids,
bool revoke) {
sendRequest(history, RequestType::Delete, [=](Fn<void()> finish) {
const auto done = [=](const MTPmessages_AffectedMessages &result) {
session().api().applyAffectedMessages(history->peer, result);
finish();
history->requestChatListMessage();
};
const auto fail = [=](const RPCError &error) {
finish();
};
if (const auto channel = history->peer->asChannel()) {
return session().api().request(MTPchannels_DeleteMessages(
channel->inputChannel,
MTP_vector<MTPint>(ids)
)).done(done).fail(fail).send();
} else {
using Flag = MTPmessages_DeleteMessages::Flag;
return session().api().request(MTPmessages_DeleteMessages(
MTP_flags(revoke ? Flag::f_revoke : Flag(0)),
MTP_vector<MTPint>(ids)
)).done(done).fail(fail).send();
}
});
}
void Histories::deleteAllMessages(
not_null<History*> history,
MsgId deleteTillId,
bool justClear,
bool revoke) {
sendRequest(history, RequestType::Delete, [=](Fn<void()> finish) {
const auto peer = history->peer;
const auto fail = [=](const RPCError &error) {
finish();
};
if (const auto channel = peer->asChannel()) {
return session().api().request(MTPchannels_DeleteHistory(
channel->inputChannel,
MTP_int(deleteTillId)
)).done([=](const MTPBool &result) {
finish();
}).fail(fail).send();
} else {
using Flag = MTPmessages_DeleteHistory::Flag;
const auto flags = Flag(0)
| (justClear ? Flag::f_just_clear : Flag(0))
| ((peer->isUser() && revoke) ? Flag::f_revoke : Flag(0));
return session().api().request(MTPmessages_DeleteHistory(
MTP_flags(flags),
peer->input,
MTP_int(0)
)).done([=](const MTPmessages_AffectedHistory &result) {
const auto offset = session().api().applyAffectedHistory(
peer,
result);
if (offset > 0) {
deleteAllMessages(
history,
deleteTillId,
justClear,
revoke);
}
finish();
}).fail(fail).send();
}
});
}
int Histories::sendRequest(
not_null<History*> history,
RequestType type,
Fn<mtpRequestId(Fn<void()> done)> generator) {
Fn<mtpRequestId(Fn<void()> finish)> generator) {
Expects(type != RequestType::None);
auto &state = _states[history];

View File

@ -57,18 +57,28 @@ public:
void changeDialogUnreadMark(not_null<History*> history, bool unread);
//void changeDialogUnreadMark(not_null<Data::Feed*> feed, bool unread); // #feed
void deleteMessages(
not_null<History*> history,
const QVector<MTPint> &ids,
bool revoke);
void deleteAllMessages(
not_null<History*> history,
MsgId deleteTillId,
bool justClear,
bool revoke);
int sendRequest(
not_null<History*> history,
RequestType type,
Fn<mtpRequestId(Fn<void()> done)> generator);
Fn<mtpRequestId(Fn<void()> finish)> generator);
void cancelRequest(not_null<History*> history, int id);
private:
struct PostponedHistoryRequest {
Fn<mtpRequestId(Fn<void()> done)> generator;
Fn<mtpRequestId(Fn<void()> finish)> generator;
};
struct SentRequest {
Fn<mtpRequestId(Fn<void()> done)> generator;
Fn<mtpRequestId(Fn<void()> finish)> generator;
mtpRequestId id = 0;
RequestType type = RequestType::None;
};

View File

@ -38,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_media_types.h"
#include "data/data_channel.h"
#include "data/data_user.h"
#include "data/data_histories.h"
#include "facades.h"
#include "app.h"
#include "styles/style_dialogs.h"
@ -265,15 +266,6 @@ void FastShareMessage(not_null<HistoryItem*> item) {
return;
}
auto doneCallback = [=](const MTPUpdates &updates, mtpRequestId requestId) {
history->session().api().applyUpdates(updates);
data->requests.remove(requestId);
if (data->requests.empty()) {
Ui::Toast::Show(tr::lng_share_done(tr::now));
Ui::hideLayer();
}
};
const auto sendFlags = MTPmessages_ForwardMessages::Flag(0)
| MTPmessages_ForwardMessages::Flag::f_with_my_score
| (isGroup
@ -297,28 +289,40 @@ void FastShareMessage(not_null<HistoryItem*> item) {
}
return result;
};
auto &api = owner->session().api();
auto &histories = owner->histories();
const auto requestType = Data::Histories::RequestType::Send;
for (const auto peer : result) {
const auto history = peer->owner().history(peer);
const auto history = owner->history(peer);
if (!comment.text.isEmpty()) {
auto message = ApiWrap::MessageToSend(history);
message.textWithTags = comment;
message.action.options = options;
message.action.clearDraft = false;
history->session().api().sendMessage(std::move(message));
api.sendMessage(std::move(message));
}
history->sendRequestId = MTP::send(
MTPmessages_ForwardMessages(
MTP_flags(sendFlags),
data->peer->input,
MTP_vector<MTPint>(msgIds),
MTP_vector<MTPlong>(generateRandom()),
peer->input,
MTP_int(options.scheduled)),
rpcDone(base::duplicate(doneCallback)),
nullptr,
0,
0,
history->sendRequestId);
histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
auto &api = history->session().api();
history->sendRequestId = api.request(MTPmessages_ForwardMessages(
MTP_flags(sendFlags),
data->peer->input,
MTP_vector<MTPint>(msgIds),
MTP_vector<MTPlong>(generateRandom()),
peer->input,
MTP_int(options.scheduled)
)).done([=](const MTPUpdates &updates, mtpRequestId requestId) {
history->session().api().applyUpdates(updates);
data->requests.remove(requestId);
if (data->requests.empty()) {
Ui::Toast::Show(tr::lng_share_done(tr::now));
Ui::hideLayer();
}
finish();
}).fail([=](const RPCError &error) {
finish();
}).afterRequest(history->sendRequestId).send();
return history->sendRequestId;
});
data->requests.insert(history->sendRequestId);
}
};