Limit single chat export by dates.

This commit is contained in:
John Preston 2018-10-06 15:17:29 +03:00
parent f362702856
commit 841abc2e87
8 changed files with 128 additions and 11 deletions

View File

@ -1569,6 +1569,44 @@ MessagesSlice ParseMessagesSlice(
return result; return result;
} }
TimeId SingleMessageDate(const MTPmessages_Messages &data) {
return data.match([&](const MTPDmessages_messagesNotModified &data) {
return 0;
}, [&](const auto &data) {
const auto &list = data.vmessages.v;
if (list.isEmpty()) {
return 0;
}
return list[0].match([](const MTPDmessageEmpty &data) {
return 0;
}, [](const auto &data) {
return data.vdate.v;
});
});
}
bool SingleMessageBefore(
const MTPmessages_Messages &data,
TimeId date) {
const auto single = SingleMessageDate(data);
return (single > 0 && single < date);
}
bool SingleMessageAfter(
const MTPmessages_Messages &data,
TimeId date) {
const auto single = SingleMessageDate(data);
return (single > 0 && single > date);
}
bool SkipMessageByDate(const Message &message, const Settings &settings) {
const auto goodFrom = (settings.singlePeerFrom <= 0)
|| (settings.singlePeerFrom <= message.date);
const auto goodTill = (settings.singlePeerTill <= 0)
|| (message.date < settings.singlePeerTill);
return !goodFrom || !goodTill;
}
Utf8String FormatPhoneNumber(const Utf8String &phoneNumber) { Utf8String FormatPhoneNumber(const Utf8String &phoneNumber) {
return phoneNumber.isEmpty() return phoneNumber.isEmpty()
? Utf8String() ? Utf8String()

View File

@ -66,6 +66,7 @@ struct File {
Unavailable, Unavailable,
FileType, FileType,
FileSize, FileSize,
DateLimits,
}; };
FileLocation location; FileLocation location;
int size = 0; int size = 0;
@ -568,6 +569,14 @@ MessagesSlice ParseMessagesSlice(
const MTPVector<MTPChat> &chats, const MTPVector<MTPChat> &chats,
const QString &mediaFolder); const QString &mediaFolder);
bool SingleMessageBefore(
const MTPmessages_Messages &data,
TimeId date);
bool SingleMessageAfter(
const MTPmessages_Messages &data,
TimeId date);
bool SkipMessageByDate(const Message &message, const Settings &settings);
Utf8String FormatPhoneNumber(const Utf8String &phoneNumber); Utf8String FormatPhoneNumber(const Utf8String &phoneNumber);
Utf8String FormatDateTime( Utf8String FormatDateTime(
TimeId date, TimeId date,

View File

@ -931,7 +931,7 @@ void ApiWrap::requestMessagesCount(int localSplitIndex) {
Expects(_chatProcess != nullptr); Expects(_chatProcess != nullptr);
const auto count = result.match( const auto count = result.match(
[](const MTPDmessages_messages &data) { [](const MTPDmessages_messages &data) {
return data.vmessages.v.size(); return data.vmessages.v.size();
}, [](const MTPDmessages_messagesSlice &data) { }, [](const MTPDmessages_messagesSlice &data) {
return data.vcount.v; return data.vcount.v;
@ -944,15 +944,55 @@ void ApiWrap::requestMessagesCount(int localSplitIndex) {
error("Unexpected messagesNotModified received."); error("Unexpected messagesNotModified received.");
return; return;
} }
_chatProcess->info.messagesCountPerSplit[localSplitIndex] = count; const auto skipSplit = !Data::SingleMessageAfter(
if (localSplitIndex + 1 < _chatProcess->info.splits.size()) { result,
requestMessagesCount(localSplitIndex + 1); _settings->singlePeerFrom);
} else if (_chatProcess->start(_chatProcess->info)) { if (skipSplit) {
requestMessagesSlice(); // No messages from the requested range, skip this split.
messagesCountLoaded(localSplitIndex, 0);
return;
} }
checkFirstMessageDate(localSplitIndex, count);
}); });
} }
void ApiWrap::checkFirstMessageDate(int localSplitIndex, int count) {
Expects(_chatProcess != nullptr);
Expects(localSplitIndex < _chatProcess->info.splits.size());
if (_settings->singlePeerTill <= 0) {
messagesCountLoaded(localSplitIndex, count);
return;
}
// Request first message in this split to check if its' date < till.
requestChatMessages(
_chatProcess->info.splits[localSplitIndex],
1, // offset_id
-1, // add_offset
1, // limit
[=](const MTPmessages_Messages &result) {
Expects(_chatProcess != nullptr);
const auto skipSplit = !Data::SingleMessageBefore(
result,
_settings->singlePeerTill);
messagesCountLoaded(localSplitIndex, skipSplit ? 0 : count);
});
}
void ApiWrap::messagesCountLoaded(int localSplitIndex, int count) {
Expects(_chatProcess != nullptr);
Expects(localSplitIndex < _chatProcess->info.splits.size());
_chatProcess->info.messagesCountPerSplit[localSplitIndex] = count;
if (localSplitIndex + 1 < _chatProcess->info.splits.size()) {
requestMessagesCount(localSplitIndex + 1);
} else if (_chatProcess->start(_chatProcess->info)) {
requestMessagesSlice();
}
}
void ApiWrap::finishExport(FnMut<void()> done) { void ApiWrap::finishExport(FnMut<void()> done) {
const auto guard = gsl::finally([&] { _takeoutId = std::nullopt; }); const auto guard = gsl::finally([&] { _takeoutId = std::nullopt; });
@ -1200,6 +1240,12 @@ void ApiWrap::appendChatsSlice(
void ApiWrap::requestMessagesSlice() { void ApiWrap::requestMessagesSlice() {
Expects(_chatProcess != nullptr); Expects(_chatProcess != nullptr);
const auto count = _chatProcess->info.messagesCountPerSplit[
_chatProcess->localSplitIndex];
if (!count) {
loadMessagesFiles({});
return;
}
requestChatMessages( requestChatMessages(
_chatProcess->info.splits[_chatProcess->localSplitIndex], _chatProcess->info.splits[_chatProcess->localSplitIndex],
_chatProcess->largestIdPlusOne, _chatProcess->largestIdPlusOne,
@ -1308,6 +1354,10 @@ void ApiWrap::loadNextMessageFile() {
for (auto &list = _chatProcess->slice->list for (auto &list = _chatProcess->slice->list
; _chatProcess->fileIndex < list.size() ; _chatProcess->fileIndex < list.size()
; ++_chatProcess->fileIndex) { ; ++_chatProcess->fileIndex) {
const auto &message = list[_chatProcess->fileIndex];
if (Data::SkipMessageByDate(message, *_settings)) {
continue;
}
const auto fileProgress = [=](FileProgress value) { const auto fileProgress = [=](FileProgress value) {
return loadMessageFileProgress(value); return loadMessageFileProgress(value);
}; };
@ -1452,7 +1502,10 @@ bool ApiWrap::processFileLoad(
}) : Type(0); }) : Type(0);
const auto limit = _settings->media.sizeLimit; const auto limit = _settings->media.sizeLimit;
if ((_settings->media.types & type) != type) { if (message && Data::SkipMessageByDate(*message, *_settings)) {
file.skipReason = SkipReason::DateLimits;
return true;
} else if ((_settings->media.types & type) != type) {
file.skipReason = SkipReason::FileType; file.skipReason = SkipReason::FileType;
return true; return true;
} else if ((message ? message->file().size : file.size) >= limit) { } else if ((message ? message->file().size : file.size) >= limit) {

View File

@ -141,6 +141,8 @@ private:
int splitIndex); int splitIndex);
void requestMessagesCount(int localSplitIndex); void requestMessagesCount(int localSplitIndex);
void checkFirstMessageDate(int localSplitIndex, int count);
void messagesCountLoaded(int localSplitIndex, int count);
void requestMessagesSlice(); void requestMessagesSlice();
void requestChatMessages( void requestChatMessages(
int splitIndex, int splitIndex,

View File

@ -2279,6 +2279,9 @@ Result HtmlWriter::writeDialogSlice(const Data::MessagesSlice &data) {
auto saved = std::optional<MessageInfo>(); auto saved = std::optional<MessageInfo>();
auto block = QByteArray(); auto block = QByteArray();
for (const auto &message : data.list) { for (const auto &message : data.list) {
if (Data::SkipMessageByDate(message, _settings)) {
continue;
}
const auto newIndex = (_messagesCount / kMessagesInFile); const auto newIndex = (_messagesCount / kMessagesInFile);
if (oldIndex != newIndex) { if (oldIndex != newIndex) {
if (const auto result = _chat->writeBlock(block); !result) { if (const auto result = _chat->writeBlock(block); !result) {
@ -2328,7 +2331,7 @@ Result HtmlWriter::writeDialogSlice(const Data::MessagesSlice &data) {
if (saved) { if (saved) {
_lastMessageInfo = std::make_unique<MessageInfo>(*saved); _lastMessageInfo = std::make_unique<MessageInfo>(*saved);
} }
return _chat->writeBlock(block); return block.isEmpty() ? Result::Success() : _chat->writeBlock(block);
} }
Result HtmlWriter::writeEmptySinglePeer() { Result HtmlWriter::writeEmptySinglePeer() {
@ -2345,7 +2348,7 @@ Result HtmlWriter::writeEmptySinglePeer() {
--_dateMessageId, --_dateMessageId,
_dialog, _dialog,
_settings.path, _settings.path,
"Empty chat")); "No exported messages"));
} }
Result HtmlWriter::writeDialogEnd() { Result HtmlWriter::writeDialogEnd() {

View File

@ -1010,13 +1010,16 @@ Result JsonWriter::writeDialogSlice(const Data::MessagesSlice &data) {
auto block = QByteArray(); auto block = QByteArray();
for (const auto &message : data.list) { for (const auto &message : data.list) {
if (Data::SkipMessageByDate(message, _settings)) {
continue;
}
block.append(prepareArrayItemStart() + SerializeMessage( block.append(prepareArrayItemStart() + SerializeMessage(
_context, _context,
message, message,
data.peers, data.peers,
_environment.internalLinksDomain)); _environment.internalLinksDomain));
} }
return _output->writeBlock(block); return block.isEmpty() ? Result::Success() : _output->writeBlock(block);
} }
Result JsonWriter::writeDialogEnd() { Result JsonWriter::writeDialogEnd() {

View File

@ -830,14 +830,20 @@ Result TextWriter::writeDialogSlice(const Data::MessagesSlice &data) {
Expects(_chat != nullptr); Expects(_chat != nullptr);
Expects(!data.list.empty()); Expects(!data.list.empty());
_messagesCount += data.list.size();
auto list = std::vector<QByteArray>(); auto list = std::vector<QByteArray>();
list.reserve(data.list.size()); list.reserve(data.list.size());
for (const auto &message : data.list) { for (const auto &message : data.list) {
if (Data::SkipMessageByDate(message, _settings)) {
continue;
}
list.push_back(SerializeMessage( list.push_back(SerializeMessage(
message, message,
data.peers, data.peers,
_environment.internalLinksDomain)); _environment.internalLinksDomain));
++_messagesCount;
}
if (list.empty()) {
return Result::Success();
} }
const auto full = _chat->empty() const auto full = _chat->empty()
? JoinList(kLineBreak, list) ? JoinList(kLineBreak, list)

View File

@ -119,6 +119,9 @@ void ResolveSettings(Settings &settings) {
} else { } else {
settings.forceSubPath = IsDefaultPath(settings.path); settings.forceSubPath = IsDefaultPath(settings.path);
} }
if (!settings.onlySinglePeer()) {
settings.singlePeerFrom = settings.singlePeerTill = 0;
}
} }
PanelController::PanelController(not_null<ControllerWrap*> process) PanelController::PanelController(not_null<ControllerWrap*> process)