diff --git a/Source/FileLiberator/DownloadDecryptBook.cs b/Source/FileLiberator/DownloadDecryptBook.cs index 0bd013d5..eee6236d 100644 --- a/Source/FileLiberator/DownloadDecryptBook.cs +++ b/Source/FileLiberator/DownloadDecryptBook.cs @@ -597,14 +597,13 @@ public class DownloadDecryptBook : AudioDecodable, IProcessable Newtonsoft.Json.Linq.JObject.FromObject(reference, new Newtonsoft.Json.JsonSerializer + { + NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore + }); + /// /// Whether a catalog product carries no details at all. /// diff --git a/Source/LibationFileManager/CloudSyncedFolders.cs b/Source/LibationFileManager/CloudSyncedFolders.cs index 2dccb4d6..f103f4fc 100644 --- a/Source/LibationFileManager/CloudSyncedFolders.cs +++ b/Source/LibationFileManager/CloudSyncedFolders.cs @@ -9,8 +9,10 @@ public readonly record struct CloudSyncStatus(bool IsSynced, string? ProviderNam { public static readonly CloudSyncStatus NotSynced = new(false, null); - /// The provider's own name where Windows reported one, otherwise a generic description. - public string Description => ProviderName is { Length: > 0 } name ? name : "a cloud sync folder"; + /// Whether the folder is synced, naming the provider where Windows reported one. + public string Description => !IsSynced + ? "not a cloud sync folder" + : ProviderName is { Length: > 0 } name ? name : "a cloud sync folder"; } /// diff --git a/Source/_Tests/FileLiberator.Tests/CatalogMetadataTests.cs b/Source/_Tests/FileLiberator.Tests/CatalogMetadataTests.cs index f1636c88..c9cd453f 100644 --- a/Source/_Tests/FileLiberator.Tests/CatalogMetadataTests.cs +++ b/Source/_Tests/FileLiberator.Tests/CatalogMetadataTests.cs @@ -11,6 +11,36 @@ namespace FileLiberator.Tests; [TestClass] public class CatalogMetadataTests { + [TestMethod] + public void Podcast_content_reference_with_missing_required_fields_can_be_exported() + { + var reference = new AudibleApi.Common.ContentReference + { + Asin = "B0981FC27J", Version = "1", Acr = "CR!ACR", Codec = null!, + ContentFormat = null!, Marketplace = "AF2M0KC94RCEA", Sku = "BK_TEST_000001", Tempo = null! + }; + + // Reproduce the exception from the reported podcast download before exercising the export. + Assert.ThrowsExactly(() => JObject.FromObject(reference)); + var exported = DownloadDecryptBook.SerializeContentReference(reference); + + Assert.AreEqual("B0981FC27J", exported.Value("asin")); + Assert.AreEqual("1", exported.Value("version")); + Assert.IsNull(exported.Property("codec")); + } + + [TestMethod] + public void Complete_content_reference_keeps_its_existing_json_representation() + { + var reference = new AudibleApi.Common.ContentReference + { + Acr = "CR!ACR", Asin = "B0981FC27J", Codec = "mp4a", ContentFormat = "MPEG4_44_128", + Marketplace = "AF2M0KC94RCEA", Sku = "BK_TEST_000001", Tempo = "1.0", Version = "1" + }; + + Assert.IsTrue(JToken.DeepEquals(JObject.FromObject(reference), DownloadDecryptBook.SerializeContentReference(reference))); + } + /// /// Verbatim from api.audible.com/1.0/catalog/products/?asins=B089T8FSK6&response_groups=<all>, /// the response behind the empty metadata file in the report. The title itself is real and downloadable;