From 841abc2e87f6fe660acd1e9c921c0dfb20fb4225 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 6 Oct 2018 15:17:29 +0300 Subject: [PATCH] Limit single chat export by dates. --- .../export/data/export_data_types.cpp | 38 +++++++++++ .../export/data/export_data_types.h | 9 +++ .../SourceFiles/export/export_api_wrap.cpp | 67 +++++++++++++++++-- Telegram/SourceFiles/export/export_api_wrap.h | 2 + .../export/output/export_output_html.cpp | 7 +- .../export/output/export_output_json.cpp | 5 +- .../export/output/export_output_text.cpp | 8 ++- .../view/export_view_panel_controller.cpp | 3 + 8 files changed, 128 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index 54798914c..a2e26ed35 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -1569,6 +1569,44 @@ MessagesSlice ParseMessagesSlice( 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) { return phoneNumber.isEmpty() ? Utf8String() diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h index fb6e03f84..f6605dac4 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.h +++ b/Telegram/SourceFiles/export/data/export_data_types.h @@ -66,6 +66,7 @@ struct File { Unavailable, FileType, FileSize, + DateLimits, }; FileLocation location; int size = 0; @@ -568,6 +569,14 @@ MessagesSlice ParseMessagesSlice( const MTPVector &chats, 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 FormatDateTime( TimeId date, diff --git a/Telegram/SourceFiles/export/export_api_wrap.cpp b/Telegram/SourceFiles/export/export_api_wrap.cpp index dee4a0949..f183f3b86 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.cpp +++ b/Telegram/SourceFiles/export/export_api_wrap.cpp @@ -931,7 +931,7 @@ void ApiWrap::requestMessagesCount(int localSplitIndex) { Expects(_chatProcess != nullptr); const auto count = result.match( - [](const MTPDmessages_messages &data) { + [](const MTPDmessages_messages &data) { return data.vmessages.v.size(); }, [](const MTPDmessages_messagesSlice &data) { return data.vcount.v; @@ -944,15 +944,55 @@ void ApiWrap::requestMessagesCount(int localSplitIndex) { 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(); + const auto skipSplit = !Data::SingleMessageAfter( + result, + _settings->singlePeerFrom); + if (skipSplit) { + // 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 done) { const auto guard = gsl::finally([&] { _takeoutId = std::nullopt; }); @@ -1200,6 +1240,12 @@ void ApiWrap::appendChatsSlice( void ApiWrap::requestMessagesSlice() { Expects(_chatProcess != nullptr); + const auto count = _chatProcess->info.messagesCountPerSplit[ + _chatProcess->localSplitIndex]; + if (!count) { + loadMessagesFiles({}); + return; + } requestChatMessages( _chatProcess->info.splits[_chatProcess->localSplitIndex], _chatProcess->largestIdPlusOne, @@ -1308,6 +1354,10 @@ void ApiWrap::loadNextMessageFile() { for (auto &list = _chatProcess->slice->list ; _chatProcess->fileIndex < list.size() ; ++_chatProcess->fileIndex) { + const auto &message = list[_chatProcess->fileIndex]; + if (Data::SkipMessageByDate(message, *_settings)) { + continue; + } const auto fileProgress = [=](FileProgress value) { return loadMessageFileProgress(value); }; @@ -1452,7 +1502,10 @@ bool ApiWrap::processFileLoad( }) : Type(0); 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; return true; } else if ((message ? message->file().size : file.size) >= limit) { diff --git a/Telegram/SourceFiles/export/export_api_wrap.h b/Telegram/SourceFiles/export/export_api_wrap.h index 991008746..c0f28d819 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.h +++ b/Telegram/SourceFiles/export/export_api_wrap.h @@ -141,6 +141,8 @@ private: int splitIndex); void requestMessagesCount(int localSplitIndex); + void checkFirstMessageDate(int localSplitIndex, int count); + void messagesCountLoaded(int localSplitIndex, int count); void requestMessagesSlice(); void requestChatMessages( int splitIndex, diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp index 7cd6eb494..c5f2a7cfe 100644 --- a/Telegram/SourceFiles/export/output/export_output_html.cpp +++ b/Telegram/SourceFiles/export/output/export_output_html.cpp @@ -2279,6 +2279,9 @@ Result HtmlWriter::writeDialogSlice(const Data::MessagesSlice &data) { auto saved = std::optional(); auto block = QByteArray(); for (const auto &message : data.list) { + if (Data::SkipMessageByDate(message, _settings)) { + continue; + } const auto newIndex = (_messagesCount / kMessagesInFile); if (oldIndex != newIndex) { if (const auto result = _chat->writeBlock(block); !result) { @@ -2328,7 +2331,7 @@ Result HtmlWriter::writeDialogSlice(const Data::MessagesSlice &data) { if (saved) { _lastMessageInfo = std::make_unique(*saved); } - return _chat->writeBlock(block); + return block.isEmpty() ? Result::Success() : _chat->writeBlock(block); } Result HtmlWriter::writeEmptySinglePeer() { @@ -2345,7 +2348,7 @@ Result HtmlWriter::writeEmptySinglePeer() { --_dateMessageId, _dialog, _settings.path, - "Empty chat")); + "No exported messages")); } Result HtmlWriter::writeDialogEnd() { diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp index 02f70c901..03b487864 100644 --- a/Telegram/SourceFiles/export/output/export_output_json.cpp +++ b/Telegram/SourceFiles/export/output/export_output_json.cpp @@ -1010,13 +1010,16 @@ Result JsonWriter::writeDialogSlice(const Data::MessagesSlice &data) { auto block = QByteArray(); for (const auto &message : data.list) { + if (Data::SkipMessageByDate(message, _settings)) { + continue; + } block.append(prepareArrayItemStart() + SerializeMessage( _context, message, data.peers, _environment.internalLinksDomain)); } - return _output->writeBlock(block); + return block.isEmpty() ? Result::Success() : _output->writeBlock(block); } Result JsonWriter::writeDialogEnd() { diff --git a/Telegram/SourceFiles/export/output/export_output_text.cpp b/Telegram/SourceFiles/export/output/export_output_text.cpp index 784c8a9d9..c2a97d43e 100644 --- a/Telegram/SourceFiles/export/output/export_output_text.cpp +++ b/Telegram/SourceFiles/export/output/export_output_text.cpp @@ -830,14 +830,20 @@ Result TextWriter::writeDialogSlice(const Data::MessagesSlice &data) { Expects(_chat != nullptr); Expects(!data.list.empty()); - _messagesCount += data.list.size(); auto list = std::vector(); list.reserve(data.list.size()); for (const auto &message : data.list) { + if (Data::SkipMessageByDate(message, _settings)) { + continue; + } list.push_back(SerializeMessage( message, data.peers, _environment.internalLinksDomain)); + ++_messagesCount; + } + if (list.empty()) { + return Result::Success(); } const auto full = _chat->empty() ? JoinList(kLineBreak, list) diff --git a/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp b/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp index be010aabe..74630a794 100644 --- a/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp +++ b/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp @@ -119,6 +119,9 @@ void ResolveSettings(Settings &settings) { } else { settings.forceSubPath = IsDefaultPath(settings.path); } + if (!settings.onlySinglePeer()) { + settings.singlePeerFrom = settings.singlePeerTill = 0; + } } PanelController::PanelController(not_null process)