diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index 5f2e3aa196..e079d3eb21 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -30,6 +30,19 @@ constexpr auto kUserPeerIdShift = (1ULL << 32); constexpr auto kChatPeerIdShift = (2ULL << 32); constexpr auto kMaxImageSize = 10000; +QString PrepareFileNameDatePart(TimeId date) { + return date + ? ('@' + QString::fromUtf8(FormatDateTime(date, '-', '-', '_'))) + : QString(); +} + +QString PreparePhotoFileName(int index, TimeId date) { + return "photo_" + + QString::number(index) + + PrepareFileNameDatePart(date) + + ".jpg"; +} + } // namespace PeerId UserPeerId(int32 userId) { @@ -288,7 +301,8 @@ void ParseAttributes( QString ComputeDocumentName( ParseMediaContext &context, - const Document &data) { + const Document &data, + TimeId date) { if (!data.name.isEmpty()) { return QString::fromUtf8(data.name); } @@ -303,6 +317,7 @@ QString ComputeDocumentName( const auto isMP3 = hasMimeType(qstr("audio/mp3")); return qsl("audio_") + QString::number(++context.audios) + + PrepareFileNameDatePart(date) + (isMP3 ? qsl(".mp3") : qsl(".ogg")); } else if (data.isVideoFile) { const auto extension = pattern.isEmpty() @@ -310,6 +325,7 @@ QString ComputeDocumentName( : QString(pattern).replace('*', QString()); return qsl("video_") + QString::number(++context.videos) + + PrepareFileNameDatePart(date) + extension; } else { const auto extension = pattern.isEmpty() @@ -317,6 +333,7 @@ QString ComputeDocumentName( : QString(pattern).replace('*', QString()); return qsl("file_") + QString::number(++context.files) + + PrepareFileNameDatePart(date) + extension; } } @@ -386,7 +403,8 @@ QString DocumentFolder(const Document &data) { Document ParseDocument( ParseMediaContext &context, const MTPDocument &data, - const QString &suggestedFolder) { + const QString &suggestedFolder, + TimeId date) { auto result = Document(); data.match([&](const MTPDdocument &data) { result.id = data.vid.v; @@ -402,7 +420,7 @@ Document ParseDocument( data.vfile_reference); const auto path = result.file.suggestedPath = suggestedFolder + DocumentFolder(result) + '/' - + CleanDocumentName(ComputeDocumentName(context, result)); + + CleanDocumentName(ComputeDocumentName(context, result, date)); result.thumb = data.vthumb.match([](const MTPDphotoSizeEmpty &) { return Image(); @@ -497,7 +515,11 @@ UserpicsSlice ParseUserpicsSlice( result.list.reserve(list.size()); for (const auto &photo : list) { const auto suggestedPath = "profile_pictures/" - "photo_" + QString::number(++baseIndex) + ".jpg"; + + PreparePhotoFileName( + ++baseIndex, + (photo.type() == mtpc_photo + ? photo.c_photo().vdate.v + : TimeId(0))); result.list.push_back(ParsePhoto(photo, suggestedPath)); } return result; @@ -802,7 +824,8 @@ const Image &Media::thumb() const { Media ParseMedia( ParseMediaContext &context, const MTPMessageMedia &data, - const QString &folder) { + const QString &folder, + TimeId date) { Expects(folder.isEmpty() || folder.endsWith(QChar('/'))); auto result = Media(); @@ -810,8 +833,9 @@ Media ParseMedia( auto photo = data.has_photo() ? ParsePhoto( data.vphoto, - folder + "photos/" - "photo_" + QString::number(++context.photos) + ".jpg") + folder + + "photos/" + + PreparePhotoFileName(++context.photos, date)) : Photo(); if (data.has_ttl_seconds()) { result.ttl = data.vttl_seconds.v; @@ -826,7 +850,7 @@ Media ParseMedia( result.content = UnsupportedMedia(); }, [&](const MTPDmessageMediaDocument &data) { auto document = data.has_document() - ? ParseDocument(context, data.vdocument, folder) + ? ParseDocument(context, data.vdocument, folder, date) : Document(); if (data.has_ttl_seconds()) { result.ttl = data.vttl_seconds.v; @@ -851,7 +875,8 @@ Media ParseMedia( ServiceAction ParseServiceAction( ParseMediaContext &context, const MTPMessageAction &data, - const QString &mediaFolder) { + const QString &mediaFolder, + TimeId date) { auto result = ServiceAction(); data.match([&](const MTPDmessageActionChatCreate &data) { auto content = ActionChatCreate(); @@ -869,8 +894,9 @@ ServiceAction ParseServiceAction( auto content = ActionChatEditPhoto(); content.photo = ParsePhoto( data.vphoto, - mediaFolder + "photos/" - "photo_" + QString::number(++context.photos) + ".jpg"); + mediaFolder + + "photos/" + + PreparePhotoFileName(++context.photos, date)); result.content = content; }, [&](const MTPDmessageActionChatDeletePhoto &data) { result.content = ActionChatDeletePhoto(); @@ -1083,7 +1109,8 @@ Message ParseMessage( result.media = ParseMedia( context, data.vmedia, - mediaFolder); + mediaFolder, + result.date); if (result.media.ttl && !data.is_out()) { result.media.file() = File(); result.media.thumb().file = File(); @@ -1099,7 +1126,8 @@ Message ParseMessage( result.action = ParseServiceAction( context, data.vaction, - mediaFolder); + mediaFolder, + result.date); }, [&](const MTPDmessageEmpty &data) { result.id = data.vid.v; }); diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h index 997199cb97..b9437e1367 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.h +++ b/Telegram/SourceFiles/export/data/export_data_types.h @@ -318,7 +318,8 @@ struct ParseMediaContext { Media ParseMedia( ParseMediaContext &context, const MTPMessageMedia &data, - const QString &folder); + const QString &folder, + TimeId date); struct ActionChatCreate { Utf8String title;