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

View File

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

View File

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

View File

@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "observer_peer.h" #include "observer_peer.h"
@ -787,7 +788,7 @@ void DeleteMessagesBox::deleteAndClear() {
auto remove = std::vector<not_null<HistoryItem*>>(); auto remove = std::vector<not_null<HistoryItem*>>();
remove.reserve(_ids.size()); 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; base::flat_map<not_null<PeerData*>, QVector<MTPint>> scheduledIdsByPeer;
for (const auto itemId : _ids) { for (const auto itemId : _ids) {
if (const auto item = _session->data().message(itemId)) { if (const auto item = _session->data().message(itemId)) {
@ -805,13 +806,13 @@ void DeleteMessagesBox::deleteAndClear() {
} }
remove.push_back(item); remove.push_back(item);
if (IsServerMsgId(item->id)) { 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) { for (const auto &[history, ids] : idsByPeer) {
peer->session().api().deleteMessages(peer, ids, revoke); history->owner().histories().deleteMessages(history, ids, revoke);
} }
for (const auto &[peer, ids] : scheduledIdsByPeer) { for (const auto &[peer, ids] : scheduledIdsByPeer) {
peer->session().api().request(MTPmessages_DeleteScheduledMessages( 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_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_histories.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -30,33 +31,36 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace { namespace {
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) { void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = chat->owner().historyLoaded(chat); const auto history = chat->owner().history(chat);
const auto randomId = rand_value<uint64>(); auto &histories = history->owner().histories();
const auto api = &chat->session().api(); const auto requestType = Data::Histories::RequestType::Send;
const auto requestId = api->request(MTPmessages_SendMedia( histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
MTP_flags(0), const auto randomId = rand_value<uint64>();
chat->input, const auto api = &chat->session().api();
MTP_int(0), history->sendRequestId = api->request(MTPmessages_SendMedia(
MTP_inputMediaGame( MTP_flags(0),
MTP_inputGameShortName( chat->input,
bot->inputUser, MTP_int(0),
MTP_string(bot->botInfo->shareGameShortName))), MTP_inputMediaGame(
MTP_string(), MTP_inputGameShortName(
MTP_long(randomId), bot->inputUser,
MTPReplyMarkup(), MTP_string(bot->botInfo->shareGameShortName))),
MTPVector<MTPMessageEntity>(), MTP_string(),
MTP_int(0) // schedule_date MTP_long(randomId),
)).done([=](const MTPUpdates &result) { MTPReplyMarkup(),
api->applyUpdates(result, randomId); MTPVector<MTPMessageEntity>(),
}).fail([=](const RPCError &error) { MTP_int(0) // schedule_date
api->sendMessageFail(error, chat); )).done([=](const MTPUpdates &result) {
}).afterRequest( api->applyUpdates(result, randomId);
history ? history->sendRequestId : 0 finish();
).send(); }).fail([=](const RPCError &error) {
api->sendMessageFail(error, chat);
if (history) { finish();
history->sendRequestId = requestId; }).afterRequest(
} history->sendRequestId
).send();
return history->sendRequestId;
});
Ui::hideLayer(); Ui::hideLayer();
Ui::showPeerHistory(chat, ShowAtUnreadMsgId); Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
} }

View File

@ -369,7 +369,7 @@ void Histories::sendReadRequests() {
void Histories::sendReadRequest(not_null<History*> history, State &state) { void Histories::sendReadRequest(not_null<History*> history, State &state) {
const auto tillId = state.readTill; const auto tillId = state.readTill;
state.readWhen = kReadRequestSent; state.readWhen = kReadRequestSent;
sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> done) { sendRequest(history, RequestType::ReadInbox, [=](Fn<void()> finish) {
const auto finished = [=] { const auto finished = [=] {
const auto state = lookup(history); const auto state = lookup(history);
Assert(state != nullptr); Assert(state != nullptr);
@ -386,7 +386,7 @@ void Histories::sendReadRequest(not_null<History*> history, State &state) {
sendReadRequests(); sendReadRequests();
} }
} }
done(); finish();
}; };
if (const auto channel = history->peer->asChannel()) { if (const auto channel = history->peer->asChannel()) {
return session().api().request(MTPchannels_ReadHistory( return session().api().request(MTPchannels_ReadHistory(
@ -439,10 +439,81 @@ bool Histories::postponeEntryRequest(const State &state) const {
return (i != end(state.sent)); 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( int Histories::sendRequest(
not_null<History*> history, not_null<History*> history,
RequestType type, RequestType type,
Fn<mtpRequestId(Fn<void()> done)> generator) { Fn<mtpRequestId(Fn<void()> finish)> generator) {
Expects(type != RequestType::None); Expects(type != RequestType::None);
auto &state = _states[history]; auto &state = _states[history];

View File

@ -57,18 +57,28 @@ public:
void changeDialogUnreadMark(not_null<History*> history, bool unread); void changeDialogUnreadMark(not_null<History*> history, bool unread);
//void changeDialogUnreadMark(not_null<Data::Feed*> feed, bool unread); // #feed //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( int sendRequest(
not_null<History*> history, not_null<History*> history,
RequestType type, RequestType type,
Fn<mtpRequestId(Fn<void()> done)> generator); Fn<mtpRequestId(Fn<void()> finish)> generator);
void cancelRequest(not_null<History*> history, int id); void cancelRequest(not_null<History*> history, int id);
private: private:
struct PostponedHistoryRequest { struct PostponedHistoryRequest {
Fn<mtpRequestId(Fn<void()> done)> generator; Fn<mtpRequestId(Fn<void()> finish)> generator;
}; };
struct SentRequest { struct SentRequest {
Fn<mtpRequestId(Fn<void()> done)> generator; Fn<mtpRequestId(Fn<void()> finish)> generator;
mtpRequestId id = 0; mtpRequestId id = 0;
RequestType type = RequestType::None; 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_media_types.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_histories.h"
#include "facades.h" #include "facades.h"
#include "app.h" #include "app.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
@ -265,15 +266,6 @@ void FastShareMessage(not_null<HistoryItem*> item) {
return; 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) const auto sendFlags = MTPmessages_ForwardMessages::Flag(0)
| MTPmessages_ForwardMessages::Flag::f_with_my_score | MTPmessages_ForwardMessages::Flag::f_with_my_score
| (isGroup | (isGroup
@ -297,28 +289,40 @@ void FastShareMessage(not_null<HistoryItem*> item) {
} }
return result; return result;
}; };
auto &api = owner->session().api();
auto &histories = owner->histories();
const auto requestType = Data::Histories::RequestType::Send;
for (const auto peer : result) { for (const auto peer : result) {
const auto history = peer->owner().history(peer); const auto history = owner->history(peer);
if (!comment.text.isEmpty()) { if (!comment.text.isEmpty()) {
auto message = ApiWrap::MessageToSend(history); auto message = ApiWrap::MessageToSend(history);
message.textWithTags = comment; message.textWithTags = comment;
message.action.options = options; message.action.options = options;
message.action.clearDraft = false; message.action.clearDraft = false;
history->session().api().sendMessage(std::move(message)); api.sendMessage(std::move(message));
} }
history->sendRequestId = MTP::send( histories.sendRequest(history, requestType, [=](Fn<void()> finish) {
MTPmessages_ForwardMessages( auto &api = history->session().api();
MTP_flags(sendFlags), history->sendRequestId = api.request(MTPmessages_ForwardMessages(
data->peer->input, MTP_flags(sendFlags),
MTP_vector<MTPint>(msgIds), data->peer->input,
MTP_vector<MTPlong>(generateRandom()), MTP_vector<MTPint>(msgIds),
peer->input, MTP_vector<MTPlong>(generateRandom()),
MTP_int(options.scheduled)), peer->input,
rpcDone(base::duplicate(doneCallback)), MTP_int(options.scheduled)
nullptr, )).done([=](const MTPUpdates &updates, mtpRequestId requestId) {
0, history->session().api().applyUpdates(updates);
0, data->requests.remove(requestId);
history->sendRequestId); 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); data->requests.insert(history->sendRequestId);
} }
}; };