From 5cdc563c9eee8dbf7fe4582739f90fc9dbe19ec5 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 28 Jun 2018 18:03:44 +0100 Subject: [PATCH] Add saving of shared contacts vcards in export. --- .../export/data/export_data_types.cpp | 35 +++++++++++++------ .../export/data/export_data_types.h | 33 +++++++++-------- .../SourceFiles/export/export_api_wrap.cpp | 11 ++++-- .../export/output/export_output_abstract.cpp | 4 ++- .../export/output/export_output_html.cpp | 11 +++--- .../export/output/export_output_json.cpp | 13 ++++--- .../export/output/export_output_text.cpp | 11 +++--- 7 files changed, 77 insertions(+), 41 deletions(-) diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index bfff0715f..8a0b859cc 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -364,6 +364,26 @@ Document ParseDocument( return result; } +SharedContact ParseSharedContact( + ParseMediaContext &context, + const MTPDmessageMediaContact &data, + const QString &suggestedFolder) { + auto result = SharedContact(); + result.info.userId = data.vuser_id.v; + result.info.firstName = ParseString(data.vfirst_name); + result.info.lastName = ParseString(data.vlast_name); + result.info.phoneNumber = ParseString(data.vphone_number); + if (!data.vvcard.v.isEmpty()) { + result.vcard.content = data.vvcard.v; + result.vcard.size = data.vvcard.v.size(); + result.vcard.suggestedPath = suggestedFolder + + "contacts/contact_" + + QString::number(++context.contacts) + + ".vcard"; + } + return result; +} + GeoPoint ParseGeoPoint(const MTPGeoPoint &data) { auto result = GeoPoint(); data.match([&](const MTPDgeoPoint &data) { @@ -439,15 +459,6 @@ ContactInfo ParseContactInfo(const MTPUser &data) { return result; } -ContactInfo ParseContactInfo(const MTPDmessageMediaContact &data) { - auto result = ContactInfo(); - result.userId = data.vuser_id.v; - result.firstName = ParseString(data.vfirst_name); - result.lastName = ParseString(data.vlast_name); - result.phoneNumber = ParseString(data.vphone_number); - return result; -} - User ParseUser(const MTPUser &data) { auto result = User(); result.info = ParseContactInfo(data); @@ -617,6 +628,8 @@ File &Media::file() { return data.image.file; }, [](Document &data) -> File& { return data.file; + }, [](SharedContact &data) -> File& { + return data.vcard; }, [](auto&) -> File& { static File result; return result; @@ -628,6 +641,8 @@ const File &Media::file() const { return data.image.file; }, [](const Document &data) -> const File& { return data.file; + }, [](const SharedContact &data) -> const File& { + return data.vcard; }, [](const auto &) -> const File& { static const File result; return result; @@ -654,7 +669,7 @@ Media ParseMedia( }, [&](const MTPDmessageMediaGeo &data) { result.content = ParseGeoPoint(data.vgeo); }, [&](const MTPDmessageMediaContact &data) { - result.content = ParseContactInfo(data); + result.content = ParseSharedContact(context, data, folder); }, [&](const MTPDmessageMediaUnsupported &data) { result.content = UnsupportedMedia(); }, [&](const MTPDmessageMediaDocument &data) { diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h index 5292954c9..c71a1e413 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.h +++ b/Telegram/SourceFiles/export/data/export_data_types.h @@ -77,6 +77,18 @@ struct Image { File file; }; +struct ContactInfo { + int32 userId = 0; + Utf8String firstName; + Utf8String lastName; + Utf8String phoneNumber; + TimeId date = 0; + + Utf8String name() const; +}; + +ContactInfo ParseContactInfo(const MTPUser &data); + struct Photo { uint64 id = 0; TimeId date = 0; @@ -108,6 +120,11 @@ struct Document { bool isAudioFile = false; }; +struct SharedContact { + ContactInfo info; + File vcard; +}; + struct GeoPoint { float64 latitude = 0.; float64 longitude = 0.; @@ -145,19 +162,6 @@ UserpicsSlice ParseUserpicsSlice( const MTPVector &data, int baseIndex); -struct ContactInfo { - int32 userId = 0; - Utf8String firstName; - Utf8String lastName; - Utf8String phoneNumber; - TimeId date = 0; - - Utf8String name() const; -}; - -ContactInfo ParseContactInfo(const MTPUser &data); -ContactInfo ParseContactInfo(const MTPDmessageMediaContact &data); - struct User { ContactInfo info; Utf8String username; @@ -264,7 +268,7 @@ struct Media { base::optional_variant< Photo, Document, - ContactInfo, + SharedContact, GeoPoint, Venue, Game, @@ -281,6 +285,7 @@ struct ParseMediaContext { int audios = 0; int videos = 0; int files = 0; + int contacts = 0; int32 botId = 0; }; diff --git a/Telegram/SourceFiles/export/export_api_wrap.cpp b/Telegram/SourceFiles/export/export_api_wrap.cpp index d665ecb4d..34ddd1b5a 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.cpp +++ b/Telegram/SourceFiles/export/export_api_wrap.cpp @@ -297,6 +297,9 @@ ApiWrap::LoadedFileCache::LoadedFileCache(int limit) : _limit(limit) { void ApiWrap::LoadedFileCache::save( const Location &location, const QString &relativePath) { + if (!location) { + return; + } const auto key = ComputeLocationKey(location); _map[key] = relativePath; _list.push_back(key); @@ -309,6 +312,9 @@ void ApiWrap::LoadedFileCache::save( base::optional ApiWrap::LoadedFileCache::find( const Location &location) const { + if (!location) { + return base::none; + } const auto key = ComputeLocationKey(location); if (const auto i = _map.find(key); i != end(_map)) { return i->second; @@ -1307,7 +1313,7 @@ bool ApiWrap::processFileLoad( if (!file.relativePath.isEmpty()) { return true; - } else if (!file.location) { + } else if (!file.location && file.content.isEmpty()) { file.skipReason = SkipReason::Unavailable; return true; } else if (writePreloadedFile(file)) { @@ -1355,8 +1361,7 @@ bool ApiWrap::writePreloadedFile(Data::File &file) { return true; } else if (!file.content.isEmpty()) { const auto process = prepareFileProcess(file); - auto &output = _fileProcess->file; - if (const auto result = output.writeBlock(file.content)) { + if (const auto result = process->file.writeBlock(file.content)) { file.relativePath = process->relativePath; _fileCache->save(file.location, file.relativePath); } else { diff --git a/Telegram/SourceFiles/export/output/export_output_abstract.cpp b/Telegram/SourceFiles/export/output/export_output_abstract.cpp index 76f92cd4e..3e1e9d0be 100644 --- a/Telegram/SourceFiles/export/output/export_output_abstract.cpp +++ b/Telegram/SourceFiles/export/output/export_output_abstract.cpp @@ -239,7 +239,9 @@ Stats AbstractWriter::produceTestExample(const QString &path) { }()); sliceBot1.list.push_back([&] { auto message = sampleMessage(); - message.media.content = user.info; + auto contact = Data::SharedContact(); + contact.info = user.info; + message.media.content = contact; return message; }()); auto sliceBot2 = Data::MessagesSlice(); diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp index 5c35060ee..a3e7e5e8d 100644 --- a/Telegram/SourceFiles/export/output/export_output_html.cpp +++ b/Telegram/SourceFiles/export/output/export_output_html.cpp @@ -482,12 +482,15 @@ QByteArray SerializeMessage( push("Height", NumberToString(data.height)); } pushTTL(); - }, [&](const ContactInfo &data) { + }, [&](const SharedContact &data) { pushBare("Contact information", SerializeKeyValue({ - { "First name", data.firstName }, - { "Last name", data.lastName }, - { "Phone number", FormatPhoneNumber(data.phoneNumber) }, + { "First name", data.info.firstName }, + { "Last name", data.info.lastName }, + { "Phone number", FormatPhoneNumber(data.info.phoneNumber) }, })); + if (!data.vcard.content.isEmpty()) { + pushPath(data.vcard, "Contact vcard"); + } }, [&](const GeoPoint &data) { pushBare("Location", data.valid ? SerializeKeyValue({ { "Latitude", NumberToString(data.latitude) }, diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp index 4a051ed3a..59b2c4ef8 100644 --- a/Telegram/SourceFiles/export/output/export_output_json.cpp +++ b/Telegram/SourceFiles/export/output/export_output_json.cpp @@ -513,15 +513,18 @@ QByteArray SerializeMessage( push("height", data.height); } pushTTL(); - }, [&](const ContactInfo &data) { + }, [&](const SharedContact &data) { pushBare("contact_information", SerializeObject(context, { - { "first_name", SerializeString(data.firstName) }, - { "last_name", SerializeString(data.lastName) }, + { "first_name", SerializeString(data.info.firstName) }, + { "last_name", SerializeString(data.info.lastName) }, { "phone_number", - SerializeString(FormatPhoneNumber(data.phoneNumber)) - }, + SerializeString(FormatPhoneNumber(data.info.phoneNumber)) + } })); + if (!data.vcard.content.isEmpty()) { + pushPath(data.vcard, "contact_vcard"); + } }, [&](const GeoPoint &data) { pushBare( "location_information", diff --git a/Telegram/SourceFiles/export/output/export_output_text.cpp b/Telegram/SourceFiles/export/output/export_output_text.cpp index b5b4e6e2a..f7fd6d634 100644 --- a/Telegram/SourceFiles/export/output/export_output_text.cpp +++ b/Telegram/SourceFiles/export/output/export_output_text.cpp @@ -382,12 +382,15 @@ QByteArray SerializeMessage( push("Height", NumberToString(data.height)); } pushTTL(); - }, [&](const ContactInfo &data) { + }, [&](const SharedContact &data) { push("Contact information", SerializeKeyValue({ - { "First name", data.firstName }, - { "Last name", data.lastName }, - { "Phone number", FormatPhoneNumber(data.phoneNumber) }, + { "First name", data.info.firstName }, + { "Last name", data.info.lastName }, + { "Phone number", FormatPhoneNumber(data.info.phoneNumber) }, })); + if (!data.vcard.content.isEmpty()) { + pushPath(data.vcard, "Contact vcard"); + } }, [&](const GeoPoint &data) { push("Location", data.valid ? SerializeKeyValue({ { "Latitude", NumberToString(data.latitude) },