mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Use split ranges to export all messages.
This commit is contained in:
parent
36fb6dac89
commit
d056c00c67
8 changed files with 231 additions and 97 deletions
|
@ -1089,6 +1089,8 @@ void FinalizeDialogsInfo(DialogsInfo &info, const Settings &settings) {
|
||||||
Unexpected("Type in ApiWrap::onlyMyMessages.");
|
Unexpected("Type in ApiWrap::onlyMyMessages.");
|
||||||
}();
|
}();
|
||||||
dialog.onlyMyMessages = ((settings.fullChats & setting) != setting);
|
dialog.onlyMyMessages = ((settings.fullChats & setting) != setting);
|
||||||
|
|
||||||
|
ranges::reverse(dialog.splits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -446,13 +446,15 @@ struct DialogInfo {
|
||||||
TimeId topMessageDate = 0;
|
TimeId topMessageDate = 0;
|
||||||
PeerId peerId = 0;
|
PeerId peerId = 0;
|
||||||
|
|
||||||
|
// User messages splits which contained that dialog.
|
||||||
|
std::vector<int> splits;
|
||||||
|
|
||||||
// Filled after the whole dialogs list is accumulated.
|
// Filled after the whole dialogs list is accumulated.
|
||||||
bool onlyMyMessages = false;
|
bool onlyMyMessages = false;
|
||||||
QString relativePath;
|
QString relativePath;
|
||||||
|
|
||||||
// Filled when requesting dialog messages.
|
// Filled when requesting dialog messages.
|
||||||
int messagesCount = 0;
|
std::vector<int> messagesCountPerSplit;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DialogsInfo {
|
struct DialogsInfo {
|
||||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/value_ordering.h"
|
#include "base/value_ordering.h"
|
||||||
#include "base/bytes.h"
|
#include "base/bytes.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
namespace Export {
|
namespace Export {
|
||||||
|
@ -107,10 +108,12 @@ struct ApiWrap::StartProcess {
|
||||||
|
|
||||||
enum class Step {
|
enum class Step {
|
||||||
UserpicsCount,
|
UserpicsCount,
|
||||||
|
SplitRanges,
|
||||||
DialogsCount,
|
DialogsCount,
|
||||||
LeftChannelsCount,
|
LeftChannelsCount,
|
||||||
};
|
};
|
||||||
std::deque<Step> steps;
|
std::deque<Step> steps;
|
||||||
|
int splitIndex = 0;
|
||||||
StartInfo info;
|
StartInfo info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -160,23 +163,23 @@ struct ApiWrap::FileProgress {
|
||||||
int total = 0;
|
int total = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ApiWrap::LeftChannelsProcess {
|
struct ApiWrap::ChatsProcess {
|
||||||
Fn<bool(int count)> progress;
|
Fn<bool(int count)> progress;
|
||||||
FnMut<void(Data::DialogsInfo&&)> done;
|
FnMut<void(Data::DialogsInfo&&)> done;
|
||||||
|
|
||||||
Data::DialogsInfo info;
|
Data::DialogsInfo info;
|
||||||
|
int processedCount = 0;
|
||||||
|
std::map<Data::PeerId, int> indexByPeer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ApiWrap::LeftChannelsProcess : ChatsProcess {
|
||||||
int fullCount = 0;
|
int fullCount = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ApiWrap::DialogsProcess {
|
struct ApiWrap::DialogsProcess : ChatsProcess {
|
||||||
Fn<bool(int count)> progress;
|
int splitIndexPlusOne = 0;
|
||||||
FnMut<void(Data::DialogsInfo&&)> done;
|
|
||||||
|
|
||||||
Data::DialogsInfo info;
|
|
||||||
|
|
||||||
Data::TimeId offsetDate = 0;
|
Data::TimeId offsetDate = 0;
|
||||||
int32 offsetId = 0;
|
int32 offsetId = 0;
|
||||||
MTPInputPeer offsetPeer = MTP_inputPeerEmpty();
|
MTPInputPeer offsetPeer = MTP_inputPeerEmpty();
|
||||||
|
@ -190,7 +193,8 @@ struct ApiWrap::ChatProcess {
|
||||||
Fn<bool(Data::MessagesSlice&&)> handleSlice;
|
Fn<bool(Data::MessagesSlice&&)> handleSlice;
|
||||||
FnMut<void()> done;
|
FnMut<void()> done;
|
||||||
|
|
||||||
int32 offsetId = 1;
|
int localSplitIndex = 0;
|
||||||
|
int32 largestIdPlusOne = 1;
|
||||||
|
|
||||||
Data::ParseMediaContext context;
|
Data::ParseMediaContext context;
|
||||||
base::optional<Data::MessagesSlice> slice;
|
base::optional<Data::MessagesSlice> slice;
|
||||||
|
@ -234,12 +238,24 @@ auto ApiWrap::mainRequest(Request &&request) {
|
||||||
|
|
||||||
return std::move(_mtp.request(MTPInvokeWithTakeout<Request>(
|
return std::move(_mtp.request(MTPInvokeWithTakeout<Request>(
|
||||||
MTP_long(*_takeoutId),
|
MTP_long(*_takeoutId),
|
||||||
request
|
std::forward<Request>(request)
|
||||||
)).fail([=](RPCError &&result) {
|
)).fail([=](RPCError &&result) {
|
||||||
error(std::move(result));
|
error(std::move(result));
|
||||||
}).toDC(MTP::ShiftDcId(0, MTP::kExportDcShift)));
|
}).toDC(MTP::ShiftDcId(0, MTP::kExportDcShift)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Request>
|
||||||
|
auto ApiWrap::splitRequest(int index, Request &&request) {
|
||||||
|
Expects(index < _splits.size());
|
||||||
|
|
||||||
|
//if (index == _splits.size() - 1) {
|
||||||
|
// return mainRequest(std::forward<Request>(request));
|
||||||
|
//}
|
||||||
|
return mainRequest(MTPInvokeWithMessagesRange<Request>(
|
||||||
|
_splits[index],
|
||||||
|
std::forward<Request>(request)));
|
||||||
|
}
|
||||||
|
|
||||||
auto ApiWrap::fileRequest(const Data::FileLocation &location, int offset) {
|
auto ApiWrap::fileRequest(const Data::FileLocation &location, int offset) {
|
||||||
Expects(location.dcId != 0);
|
Expects(location.dcId != 0);
|
||||||
Expects(_takeoutId.has_value());
|
Expects(_takeoutId.has_value());
|
||||||
|
@ -284,6 +300,9 @@ void ApiWrap::startExport(
|
||||||
if (_settings->types & Settings::Type::Userpics) {
|
if (_settings->types & Settings::Type::Userpics) {
|
||||||
_startProcess->steps.push_back(Step::UserpicsCount);
|
_startProcess->steps.push_back(Step::UserpicsCount);
|
||||||
}
|
}
|
||||||
|
if (_settings->types & Settings::Type::NonChannelChatsMask) {
|
||||||
|
_startProcess->steps.push_back(Step::SplitRanges);
|
||||||
|
}
|
||||||
if (_settings->types & Settings::Type::AnyChatsMask) {
|
if (_settings->types & Settings::Type::AnyChatsMask) {
|
||||||
_startProcess->steps.push_back(Step::DialogsCount);
|
_startProcess->steps.push_back(Step::DialogsCount);
|
||||||
}
|
}
|
||||||
|
@ -303,14 +322,17 @@ void ApiWrap::sendNextStartRequest() {
|
||||||
finishStartProcess();
|
finishStartProcess();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
using Step = StartProcess::Step;
|
||||||
const auto step = steps.front();
|
const auto step = steps.front();
|
||||||
steps.pop_front();
|
steps.pop_front();
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case StartProcess::Step::UserpicsCount:
|
case Step::UserpicsCount:
|
||||||
return requestUserpicsCount();
|
return requestUserpicsCount();
|
||||||
case StartProcess::Step::DialogsCount:
|
case Step::SplitRanges:
|
||||||
|
return requestSplitRanges();
|
||||||
|
case Step::DialogsCount:
|
||||||
return requestDialogsCount();
|
return requestDialogsCount();
|
||||||
case StartProcess::Step::LeftChannelsCount:
|
case Step::LeftChannelsCount:
|
||||||
return requestLeftChannelsCount();
|
return requestLeftChannelsCount();
|
||||||
}
|
}
|
||||||
Unexpected("Step in ApiWrap::sendNextStartRequest.");
|
Unexpected("Step in ApiWrap::sendNextStartRequest.");
|
||||||
|
@ -339,10 +361,20 @@ void ApiWrap::requestUserpicsCount() {
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiWrap::requestSplitRanges() {
|
||||||
|
Expects(_startProcess != nullptr);
|
||||||
|
|
||||||
|
mainRequest(MTPmessages_GetSplitRanges(
|
||||||
|
)).done([=](const MTPVector<MTPMessageRange> &result) {
|
||||||
|
_splits = result.v;
|
||||||
|
sendNextStartRequest();
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
void ApiWrap::requestDialogsCount() {
|
void ApiWrap::requestDialogsCount() {
|
||||||
Expects(_startProcess != nullptr);
|
Expects(_startProcess != nullptr);
|
||||||
|
|
||||||
mainRequest(MTPmessages_GetDialogs(
|
splitRequest(_startProcess->splitIndex, MTPmessages_GetDialogs(
|
||||||
MTP_flags(0),
|
MTP_flags(0),
|
||||||
MTP_int(0), // offset_date
|
MTP_int(0), // offset_date
|
||||||
MTP_int(0), // offset_id
|
MTP_int(0), // offset_id
|
||||||
|
@ -352,14 +384,18 @@ void ApiWrap::requestDialogsCount() {
|
||||||
Expects(_settings != nullptr);
|
Expects(_settings != nullptr);
|
||||||
Expects(_startProcess != nullptr);
|
Expects(_startProcess != nullptr);
|
||||||
|
|
||||||
_startProcess->info.dialogsCount = result.match(
|
_startProcess->info.dialogsCount += result.match(
|
||||||
[](const MTPDmessages_dialogs &data) {
|
[](const MTPDmessages_dialogs &data) {
|
||||||
return int(data.vdialogs.v.size());
|
return int(data.vdialogs.v.size());
|
||||||
}, [](const MTPDmessages_dialogsSlice &data) {
|
}, [](const MTPDmessages_dialogsSlice &data) {
|
||||||
return data.vcount.v;
|
return data.vcount.v;
|
||||||
});
|
});
|
||||||
|
|
||||||
sendNextStartRequest();
|
if (++_startProcess->splitIndex >= _splits.size()) {
|
||||||
|
sendNextStartRequest();
|
||||||
|
} else {
|
||||||
|
requestDialogsCount();
|
||||||
|
}
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,6 +426,8 @@ void ApiWrap::requestLeftChannelsList(
|
||||||
FnMut<void(Data::DialogsInfo&&)> done) {
|
FnMut<void(Data::DialogsInfo&&)> done) {
|
||||||
Expects(_leftChannelsProcess != nullptr);
|
Expects(_leftChannelsProcess != nullptr);
|
||||||
|
|
||||||
|
validateSplits();
|
||||||
|
|
||||||
_leftChannelsProcess->progress = std::move(progress);
|
_leftChannelsProcess->progress = std::move(progress);
|
||||||
_leftChannelsProcess->done = std::move(done);
|
_leftChannelsProcess->done = std::move(done);
|
||||||
requestLeftChannelsSlice();
|
requestLeftChannelsSlice();
|
||||||
|
@ -414,13 +452,24 @@ void ApiWrap::requestDialogsList(
|
||||||
FnMut<void(Data::DialogsInfo&&)> done) {
|
FnMut<void(Data::DialogsInfo&&)> done) {
|
||||||
Expects(_dialogsProcess == nullptr);
|
Expects(_dialogsProcess == nullptr);
|
||||||
|
|
||||||
|
validateSplits();
|
||||||
|
|
||||||
_dialogsProcess = std::make_unique<DialogsProcess>();
|
_dialogsProcess = std::make_unique<DialogsProcess>();
|
||||||
|
_dialogsProcess->splitIndexPlusOne = _splits.size();
|
||||||
_dialogsProcess->progress = std::move(progress);
|
_dialogsProcess->progress = std::move(progress);
|
||||||
_dialogsProcess->done = std::move(done);
|
_dialogsProcess->done = std::move(done);
|
||||||
|
|
||||||
requestDialogsSlice();
|
requestDialogsSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiWrap::validateSplits() {
|
||||||
|
if (_splits.empty()) {
|
||||||
|
_splits.push_back(MTP_messageRange(
|
||||||
|
MTP_int(0),
|
||||||
|
MTP_int(std::numeric_limits<int>::max())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ApiWrap::startMainSession(FnMut<void()> done) {
|
void ApiWrap::startMainSession(FnMut<void()> done) {
|
||||||
const auto sizeLimit = _settings->media.sizeLimit;
|
const auto sizeLimit = _settings->media.sizeLimit;
|
||||||
const auto hasFiles = (_settings->media.types != 0) && (sizeLimit > 0);
|
const auto hasFiles = (_settings->media.types != 0) && (sizeLimit > 0);
|
||||||
|
@ -699,11 +748,41 @@ void ApiWrap::requestMessages(
|
||||||
_chatProcess->handleSlice = std::move(slice);
|
_chatProcess->handleSlice = std::move(slice);
|
||||||
_chatProcess->done = std::move(done);
|
_chatProcess->done = std::move(done);
|
||||||
|
|
||||||
requestMessagesSlice([=](int count) {
|
requestMessagesCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiWrap::requestMessagesCount(int localSplitIndex) {
|
||||||
|
Expects(_chatProcess != nullptr);
|
||||||
|
Expects(localSplitIndex < _chatProcess->info.splits.size());
|
||||||
|
|
||||||
|
requestChatMessages(
|
||||||
|
_chatProcess->info.splits[localSplitIndex],
|
||||||
|
0, // offset_id
|
||||||
|
0, // add_offset
|
||||||
|
1, // limit
|
||||||
|
[=](const MTPmessages_Messages &result) {
|
||||||
Expects(_chatProcess != nullptr);
|
Expects(_chatProcess != nullptr);
|
||||||
|
|
||||||
_chatProcess->info.messagesCount = count;
|
const auto count = result.match(
|
||||||
return _chatProcess->start(_chatProcess->info);
|
[](const MTPDmessages_messages &data) {
|
||||||
|
return data.vmessages.v.size();
|
||||||
|
}, [](const MTPDmessages_messagesSlice &data) {
|
||||||
|
return data.vcount.v;
|
||||||
|
}, [](const MTPDmessages_channelMessages &data) {
|
||||||
|
return data.vcount.v;
|
||||||
|
}, [](const MTPDmessages_messagesNotModified &data) {
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
if (count < 0) {
|
||||||
|
error("Unexpected messagesNotModified received.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_chatProcess->info.messagesCountPerSplit[localSplitIndex] = count;
|
||||||
|
if (localSplitIndex + 1 < _chatProcess->info.splits.size()) {
|
||||||
|
requestMessagesCount(localSplitIndex + 1);
|
||||||
|
} else if (_chatProcess->start(_chatProcess->info)) {
|
||||||
|
requestMessagesSlice();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,14 +806,15 @@ void ApiWrap::cancelExportFast() {
|
||||||
void ApiWrap::requestDialogsSlice() {
|
void ApiWrap::requestDialogsSlice() {
|
||||||
Expects(_dialogsProcess != nullptr);
|
Expects(_dialogsProcess != nullptr);
|
||||||
|
|
||||||
mainRequest(MTPmessages_GetDialogs(
|
const auto splitIndex = _dialogsProcess->splitIndexPlusOne - 1;
|
||||||
|
splitRequest(splitIndex, MTPmessages_GetDialogs(
|
||||||
MTP_flags(0),
|
MTP_flags(0),
|
||||||
MTP_int(_dialogsProcess->offsetDate),
|
MTP_int(_dialogsProcess->offsetDate),
|
||||||
MTP_int(_dialogsProcess->offsetId),
|
MTP_int(_dialogsProcess->offsetId),
|
||||||
_dialogsProcess->offsetPeer,
|
_dialogsProcess->offsetPeer,
|
||||||
MTP_int(kChatsSliceLimit)
|
MTP_int(kChatsSliceLimit)
|
||||||
)).done([=](const MTPmessages_Dialogs &result) {
|
)).done([=](const MTPmessages_Dialogs &result) {
|
||||||
const auto finished = result.match(
|
auto finished = result.match(
|
||||||
[](const MTPDmessages_dialogs &data) {
|
[](const MTPDmessages_dialogs &data) {
|
||||||
return true;
|
return true;
|
||||||
}, [](const MTPDmessages_dialogsSlice &data) {
|
}, [](const MTPDmessages_dialogsSlice &data) {
|
||||||
|
@ -742,30 +822,40 @@ void ApiWrap::requestDialogsSlice() {
|
||||||
});
|
});
|
||||||
|
|
||||||
auto info = Data::ParseDialogsInfo(result);
|
auto info = Data::ParseDialogsInfo(result);
|
||||||
if (finished || info.list.empty()) {
|
_dialogsProcess->processedCount += info.list.size();
|
||||||
finishDialogsList();
|
const auto last = info.list.empty()
|
||||||
} else {
|
? Data::DialogInfo()
|
||||||
const auto &last = info.list.back();
|
: info.list.back();
|
||||||
|
appendDialogsSlice(std::move(info));
|
||||||
|
|
||||||
|
if (!_dialogsProcess->progress(_dialogsProcess->processedCount)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!finished && last.topMessageDate > 0) {
|
||||||
_dialogsProcess->offsetId = last.topMessageId;
|
_dialogsProcess->offsetId = last.topMessageId;
|
||||||
_dialogsProcess->offsetDate = last.topMessageDate;
|
_dialogsProcess->offsetDate = last.topMessageDate;
|
||||||
_dialogsProcess->offsetPeer = last.input;
|
_dialogsProcess->offsetPeer = last.input;
|
||||||
|
} else if (--_dialogsProcess->splitIndexPlusOne > 0) {
|
||||||
appendDialogsSlice(std::move(info));
|
_dialogsProcess->offsetId = 0;
|
||||||
|
_dialogsProcess->offsetDate = 0;
|
||||||
const auto count = _dialogsProcess->info.list.size();
|
_dialogsProcess->offsetPeer = MTP_inputPeerEmpty();
|
||||||
if (!_dialogsProcess->progress(count)) {
|
} else {
|
||||||
return;
|
finishDialogsList();
|
||||||
}
|
return;
|
||||||
|
|
||||||
requestDialogsSlice();
|
|
||||||
}
|
}
|
||||||
|
requestDialogsSlice();
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::appendDialogsSlice(Data::DialogsInfo &&info) {
|
void ApiWrap::appendDialogsSlice(Data::DialogsInfo &&info) {
|
||||||
Expects(_dialogsProcess != nullptr);
|
Expects(_dialogsProcess != nullptr);
|
||||||
|
Expects(_dialogsProcess->splitIndexPlusOne <= _splits.size());
|
||||||
|
|
||||||
appendChatsSlice(_dialogsProcess->info, std::move(info));
|
appendChatsSlice(
|
||||||
|
*_dialogsProcess,
|
||||||
|
std::move(info),
|
||||||
|
_dialogsProcess->splitIndexPlusOne - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::finishDialogsList() {
|
void ApiWrap::finishDialogsList() {
|
||||||
|
@ -822,13 +912,18 @@ void ApiWrap::requestLeftChannelsSliceGeneric(FnMut<void()> done) {
|
||||||
|
|
||||||
void ApiWrap::appendLeftChannelsSlice(Data::DialogsInfo &&info) {
|
void ApiWrap::appendLeftChannelsSlice(Data::DialogsInfo &&info) {
|
||||||
Expects(_leftChannelsProcess != nullptr);
|
Expects(_leftChannelsProcess != nullptr);
|
||||||
|
Expects(!_splits.empty());
|
||||||
|
|
||||||
appendChatsSlice(_leftChannelsProcess->info, std::move(info));
|
appendChatsSlice(
|
||||||
|
*_leftChannelsProcess,
|
||||||
|
std::move(info),
|
||||||
|
_splits.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::appendChatsSlice(
|
void ApiWrap::appendChatsSlice(
|
||||||
Data::DialogsInfo &to,
|
ChatsProcess &to,
|
||||||
Data::DialogsInfo &&info) {
|
Data::DialogsInfo &&info,
|
||||||
|
int splitIndex) {
|
||||||
Expects(_settings != nullptr);
|
Expects(_settings != nullptr);
|
||||||
|
|
||||||
const auto types = _settings->types;
|
const auto types = _settings->types;
|
||||||
|
@ -837,41 +932,33 @@ void ApiWrap::appendChatsSlice(
|
||||||
) | ranges::view::filter([&](const Data::DialogInfo &info) {
|
) | ranges::view::filter([&](const Data::DialogInfo &info) {
|
||||||
return (types & SettingsFromDialogsType(info.type)) != 0;
|
return (types & SettingsFromDialogsType(info.type)) != 0;
|
||||||
});
|
});
|
||||||
auto &list = to.list;
|
auto &list = to.info.list;
|
||||||
if (list.empty()) {
|
list.reserve(list.size() + info.list.size());
|
||||||
list = filtered | ranges::to_vector;
|
for (auto &info : filtered) {
|
||||||
} else {
|
const auto nextIndex = list.size();
|
||||||
list.reserve(list.size() + info.list.size());
|
const auto [i, ok] = to.indexByPeer.emplace(info.peerId, nextIndex);
|
||||||
for (auto &info : filtered) {
|
if (ok) {
|
||||||
list.push_back(std::move(info));
|
list.push_back(std::move(info));
|
||||||
}
|
}
|
||||||
|
list[i->second].splits.push_back(splitIndex);
|
||||||
|
list[i->second].messagesCountPerSplit.push_back(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::requestMessagesSlice(FnMut<bool(int count)> start) {
|
void ApiWrap::requestMessagesSlice() {
|
||||||
Expects(_chatProcess != nullptr);
|
Expects(_chatProcess != nullptr);
|
||||||
|
|
||||||
auto handleResult = [=, start = std::move(start)](
|
requestChatMessages(
|
||||||
const MTPmessages_Messages &result) mutable {
|
_chatProcess->info.splits[_chatProcess->localSplitIndex],
|
||||||
|
_chatProcess->largestIdPlusOne,
|
||||||
|
-kMessagesSliceLimit,
|
||||||
|
kMessagesSliceLimit,
|
||||||
|
[=](const MTPmessages_Messages &result) {
|
||||||
Expects(_chatProcess != nullptr);
|
Expects(_chatProcess != nullptr);
|
||||||
|
|
||||||
const auto count = result.match(
|
|
||||||
[](const MTPDmessages_messages &data) {
|
|
||||||
return data.vmessages.v.size();
|
|
||||||
}, [](const MTPDmessages_messagesSlice &data) {
|
|
||||||
return data.vcount.v;
|
|
||||||
}, [](const MTPDmessages_channelMessages &data) {
|
|
||||||
return data.vcount.v;
|
|
||||||
}, [](const MTPDmessages_messagesNotModified &data) {
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
result.match([&](const MTPDmessages_messagesNotModified &data) {
|
result.match([&](const MTPDmessages_messagesNotModified &data) {
|
||||||
error("Unexpected messagesNotModified received.");
|
error("Unexpected messagesNotModified received.");
|
||||||
}, [&](const auto &data) {
|
}, [&](const auto &data) {
|
||||||
if (start && !start(count)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if constexpr (MTPDmessages_messages::Is<decltype(data)>()) {
|
if constexpr (MTPDmessages_messages::Is<decltype(data)>()) {
|
||||||
_chatProcess->lastSlice = true;
|
_chatProcess->lastSlice = true;
|
||||||
}
|
}
|
||||||
|
@ -882,9 +969,17 @@ void ApiWrap::requestMessagesSlice(FnMut<bool(int count)> start) {
|
||||||
data.vchats,
|
data.vchats,
|
||||||
_chatProcess->info.relativePath));
|
_chatProcess->info.relativePath));
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiWrap::requestChatMessages(
|
||||||
|
int splitIndex,
|
||||||
|
int offsetId,
|
||||||
|
int addOffset,
|
||||||
|
int limit,
|
||||||
|
FnMut<void(MTPmessages_Messages&&)> done) {
|
||||||
if (_chatProcess->info.onlyMyMessages) {
|
if (_chatProcess->info.onlyMyMessages) {
|
||||||
mainRequest(MTPmessages_Search(
|
splitRequest(splitIndex, MTPmessages_Search(
|
||||||
MTP_flags(MTPmessages_Search::Flag::f_from_id),
|
MTP_flags(MTPmessages_Search::Flag::f_from_id),
|
||||||
_chatProcess->info.input,
|
_chatProcess->info.input,
|
||||||
MTP_string(""), // query
|
MTP_string(""), // query
|
||||||
|
@ -892,24 +987,24 @@ void ApiWrap::requestMessagesSlice(FnMut<bool(int count)> start) {
|
||||||
MTP_inputMessagesFilterEmpty(),
|
MTP_inputMessagesFilterEmpty(),
|
||||||
MTP_int(0), // min_date
|
MTP_int(0), // min_date
|
||||||
MTP_int(0), // max_date
|
MTP_int(0), // max_date
|
||||||
MTP_int(_chatProcess->offsetId),
|
MTP_int(offsetId),
|
||||||
MTP_int(-kMessagesSliceLimit),
|
MTP_int(addOffset),
|
||||||
MTP_int(kMessagesSliceLimit),
|
MTP_int(limit),
|
||||||
MTP_int(0), // max_id
|
MTP_int(0), // max_id
|
||||||
MTP_int(0), // min_id
|
MTP_int(0), // min_id
|
||||||
MTP_int(0) // hash
|
MTP_int(0) // hash
|
||||||
)).done(std::move(handleResult)).send();
|
)).done(std::move(done)).send();
|
||||||
} else {
|
} else {
|
||||||
mainRequest(MTPmessages_GetHistory(
|
splitRequest(splitIndex, MTPmessages_GetHistory(
|
||||||
_chatProcess->info.input,
|
_chatProcess->info.input,
|
||||||
MTP_int(_chatProcess->offsetId),
|
MTP_int(offsetId),
|
||||||
MTP_int(0), // offset_date
|
MTP_int(0), // offset_date
|
||||||
MTP_int(-kMessagesSliceLimit),
|
MTP_int(addOffset),
|
||||||
MTP_int(kMessagesSliceLimit),
|
MTP_int(limit),
|
||||||
MTP_int(0), // max_id
|
MTP_int(0), // max_id
|
||||||
MTP_int(0), // min_id
|
MTP_int(0), // min_id
|
||||||
MTP_int(0) // hash
|
MTP_int(0) // hash
|
||||||
)).done(std::move(handleResult)).send();
|
)).done(std::move(done)).send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,15 +1052,21 @@ void ApiWrap::finishMessagesSlice() {
|
||||||
|
|
||||||
auto slice = *base::take(_chatProcess->slice);
|
auto slice = *base::take(_chatProcess->slice);
|
||||||
if (!slice.list.empty()) {
|
if (!slice.list.empty()) {
|
||||||
_chatProcess->offsetId = slice.list.back().id + 1;
|
_chatProcess->largestIdPlusOne = slice.list.back().id + 1;
|
||||||
if (!_chatProcess->handleSlice(std::move(slice))) {
|
if (!_chatProcess->handleSlice(std::move(slice))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_chatProcess->lastSlice) {
|
if (_chatProcess->lastSlice
|
||||||
finishMessages();
|
&& (++_chatProcess->localSplitIndex
|
||||||
} else {
|
< _chatProcess->info.splits.size())) {
|
||||||
|
_chatProcess->lastSlice = false;
|
||||||
|
_chatProcess->largestIdPlusOne = 1;
|
||||||
|
}
|
||||||
|
if (!_chatProcess->lastSlice) {
|
||||||
requestMessagesSlice();
|
requestMessagesSlice();
|
||||||
|
} else {
|
||||||
|
finishMessages();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,7 @@ private:
|
||||||
struct UserpicsProcess;
|
struct UserpicsProcess;
|
||||||
struct FileProcess;
|
struct FileProcess;
|
||||||
struct FileProgress;
|
struct FileProgress;
|
||||||
|
struct ChatsProcess;
|
||||||
struct LeftChannelsProcess;
|
struct LeftChannelsProcess;
|
||||||
struct DialogsProcess;
|
struct DialogsProcess;
|
||||||
struct ChatProcess;
|
struct ChatProcess;
|
||||||
|
@ -100,6 +101,7 @@ private:
|
||||||
void startMainSession(FnMut<void()> done);
|
void startMainSession(FnMut<void()> done);
|
||||||
void sendNextStartRequest();
|
void sendNextStartRequest();
|
||||||
void requestUserpicsCount();
|
void requestUserpicsCount();
|
||||||
|
void requestSplitRanges();
|
||||||
void requestDialogsCount();
|
void requestDialogsCount();
|
||||||
void requestLeftChannelsCount();
|
void requestLeftChannelsCount();
|
||||||
void finishStartProcess();
|
void finishStartProcess();
|
||||||
|
@ -114,6 +116,8 @@ private:
|
||||||
void finishUserpicsSlice();
|
void finishUserpicsSlice();
|
||||||
void finishUserpics();
|
void finishUserpics();
|
||||||
|
|
||||||
|
void validateSplits();
|
||||||
|
|
||||||
void requestDialogsSlice();
|
void requestDialogsSlice();
|
||||||
void appendDialogsSlice(Data::DialogsInfo &&info);
|
void appendDialogsSlice(Data::DialogsInfo &&info);
|
||||||
void finishDialogsList();
|
void finishDialogsList();
|
||||||
|
@ -122,9 +126,19 @@ private:
|
||||||
void requestLeftChannelsSlice();
|
void requestLeftChannelsSlice();
|
||||||
void appendLeftChannelsSlice(Data::DialogsInfo &&info);
|
void appendLeftChannelsSlice(Data::DialogsInfo &&info);
|
||||||
|
|
||||||
void appendChatsSlice(Data::DialogsInfo &to, Data::DialogsInfo &&info);
|
void appendChatsSlice(
|
||||||
|
ChatsProcess &to,
|
||||||
|
Data::DialogsInfo &&info,
|
||||||
|
int splitIndex);
|
||||||
|
|
||||||
void requestMessagesSlice(FnMut<bool(int count)> start = nullptr);
|
void requestMessagesCount(int localSplitIndex);
|
||||||
|
void requestMessagesSlice();
|
||||||
|
void requestChatMessages(
|
||||||
|
int splitIndex,
|
||||||
|
int offsetId,
|
||||||
|
int addOffset,
|
||||||
|
int limit,
|
||||||
|
FnMut<void(MTPmessages_Messages&&)> done);
|
||||||
void loadMessagesFiles(Data::MessagesSlice &&slice);
|
void loadMessagesFiles(Data::MessagesSlice &&slice);
|
||||||
void loadNextMessageFile();
|
void loadNextMessageFile();
|
||||||
bool loadMessageFileProgress(FileProgress value);
|
bool loadMessageFileProgress(FileProgress value);
|
||||||
|
@ -150,6 +164,9 @@ private:
|
||||||
template <typename Request>
|
template <typename Request>
|
||||||
[[nodiscard]] auto mainRequest(Request &&request);
|
[[nodiscard]] auto mainRequest(Request &&request);
|
||||||
|
|
||||||
|
template <typename Request>
|
||||||
|
[[nodiscard]] auto splitRequest(int index, Request &&request);
|
||||||
|
|
||||||
[[nodiscard]] auto fileRequest(
|
[[nodiscard]] auto fileRequest(
|
||||||
const Data::FileLocation &location,
|
const Data::FileLocation &location,
|
||||||
int offset);
|
int offset);
|
||||||
|
@ -173,6 +190,7 @@ private:
|
||||||
std::unique_ptr<LeftChannelsProcess> _leftChannelsProcess;
|
std::unique_ptr<LeftChannelsProcess> _leftChannelsProcess;
|
||||||
std::unique_ptr<DialogsProcess> _dialogsProcess;
|
std::unique_ptr<DialogsProcess> _dialogsProcess;
|
||||||
std::unique_ptr<ChatProcess> _chatProcess;
|
std::unique_ptr<ChatProcess> _chatProcess;
|
||||||
|
QVector<MTPMessageRange> _splits;
|
||||||
|
|
||||||
rpl::event_stream<RPCError> _errors;
|
rpl::event_stream<RPCError> _errors;
|
||||||
rpl::event_stream<Output::Result> _ioErrors;
|
rpl::event_stream<Output::Result> _ioErrors;
|
||||||
|
|
|
@ -465,7 +465,9 @@ void Controller::exportNextDialog() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_messagesWritten = 0;
|
_messagesWritten = 0;
|
||||||
_messagesCount = info.messagesCount;
|
_messagesCount = ranges::accumulate(
|
||||||
|
info.messagesCountPerSplit,
|
||||||
|
0);
|
||||||
setState(stateDialogs(DownloadProgress()));
|
setState(stateDialogs(DownloadProgress()));
|
||||||
return true;
|
return true;
|
||||||
}, [=](DownloadProgress progress) {
|
}, [=](DownloadProgress progress) {
|
||||||
|
@ -509,7 +511,9 @@ void Controller::exportNextLeftChannel() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_messagesWritten = 0;
|
_messagesWritten = 0;
|
||||||
_messagesCount = info.messagesCount;
|
_messagesCount = ranges::accumulate(
|
||||||
|
info.messagesCountPerSplit,
|
||||||
|
0);
|
||||||
setState(stateLeftChannels(DownloadProgress()));
|
setState(stateLeftChannels(DownloadProgress()));
|
||||||
return true;
|
return true;
|
||||||
}, [=](DownloadProgress progress) {
|
}, [=](DownloadProgress progress) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
|
|
@ -39,21 +39,22 @@ struct MediaSettings {
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
enum class Type {
|
enum class Type {
|
||||||
PersonalInfo = 0x001,
|
PersonalInfo = 0x001,
|
||||||
Userpics = 0x002,
|
Userpics = 0x002,
|
||||||
Contacts = 0x004,
|
Contacts = 0x004,
|
||||||
Sessions = 0x008,
|
Sessions = 0x008,
|
||||||
PersonalChats = 0x010,
|
PersonalChats = 0x010,
|
||||||
BotChats = 0x020,
|
BotChats = 0x020,
|
||||||
PrivateGroups = 0x040,
|
PrivateGroups = 0x040,
|
||||||
PublicGroups = 0x080,
|
PublicGroups = 0x080,
|
||||||
PrivateChannels = 0x100,
|
PrivateChannels = 0x100,
|
||||||
PublicChannels = 0x200,
|
PublicChannels = 0x200,
|
||||||
|
|
||||||
GroupsMask = PrivateGroups | PublicGroups,
|
GroupsMask = PrivateGroups | PublicGroups,
|
||||||
ChannelsMask = PrivateChannels | PublicChannels,
|
ChannelsMask = PrivateChannels | PublicChannels,
|
||||||
GroupsChannelsMask = GroupsMask | ChannelsMask,
|
GroupsChannelsMask = GroupsMask | ChannelsMask,
|
||||||
AnyChatsMask = PersonalChats | BotChats | GroupsChannelsMask,
|
NonChannelChatsMask = PersonalChats | BotChats | PrivateGroups,
|
||||||
|
AnyChatsMask = PersonalChats | BotChats | GroupsChannelsMask,
|
||||||
};
|
};
|
||||||
using Types = base::flags<Type>;
|
using Types = base::flags<Type>;
|
||||||
friend inline constexpr auto is_flag_type(Type) { return true; };
|
friend inline constexpr auto is_flag_type(Type) { return true; };
|
||||||
|
|
|
@ -490,7 +490,7 @@ Result TextWriter::writeUserpicsSlice(const Data::UserpicsSlice &data) {
|
||||||
"Photo",
|
"Photo",
|
||||||
(userpic.image.file.relativePath.isEmpty()
|
(userpic.image.file.relativePath.isEmpty()
|
||||||
? QByteArray("(file unavailable)")
|
? QByteArray("(file unavailable)")
|
||||||
: userpic.image.file.relativePath.toUtf8())
|
: FormatFilePath(userpic.image.file))
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -792,7 +792,12 @@ Result TextWriter::writeChatEnd() {
|
||||||
return _chats->writeBlock(SerializeKeyValue({
|
return _chats->writeBlock(SerializeKeyValue({
|
||||||
{ "Name", NameString(_dialog.name, _dialog.type) },
|
{ "Name", NameString(_dialog.name, _dialog.type) },
|
||||||
{ "Type", TypeString(_dialog.type) },
|
{ "Type", TypeString(_dialog.type) },
|
||||||
{ "Messages count", Data::NumberToString(_messagesCount) },
|
{
|
||||||
|
(_dialog.onlyMyMessages
|
||||||
|
? "Outgoing messages count"
|
||||||
|
: "Messages count"),
|
||||||
|
Data::NumberToString(_messagesCount)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Content",
|
"Content",
|
||||||
(_messagesCount > 0
|
(_messagesCount > 0
|
||||||
|
|
Loading…
Add table
Reference in a new issue