mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-09-20 11:32:25 -04:00
Merge pull request #2078 from rmcrackan/rmcrackan/2071-serialization
bug fix #2071 -- better metadata serialization
This commit is contained in:
3 files changed
+46
-7
No files matched your search
@@ -597,14 +597,13 @@ public class DownloadDecryptBook : AudioDecodable, IProcessable<DownloadDecryptB
|
||||
extension: ".metadata.json",
|
||||
returnFirstExisting: Configuration.OverwriteExisting);
|
||||
|
||||
if (File.Exists(metadataPath))
|
||||
FileUtility.SaferDelete(metadataPath);
|
||||
|
||||
sourceJson.Add(nameof(ContentMetadata.ChapterInfo), Newtonsoft.Json.Linq.JObject.FromObject(options.ContentMetadata.ChapterInfo));
|
||||
sourceJson.Add(nameof(ContentMetadata.ContentReference), Newtonsoft.Json.Linq.JObject.FromObject(options.ContentMetadata.ContentReference));
|
||||
sourceJson.Add(nameof(ContentMetadata.ContentReference), SerializeContentReference(options.ContentMetadata.ContentReference));
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
File.WriteAllText(metadataPath, sourceJson.ToString());
|
||||
// Serialize before touching the destination, then replace it atomically so a failed export
|
||||
// cannot delete or truncate metadata saved by an earlier download.
|
||||
Dinah.Core.IO.AtomicFileWriter.WriteAllText(metadataPath, sourceJson.ToString());
|
||||
SetFileTime(options.LibraryBook, metadataPath);
|
||||
OnFileCreated(options.LibraryBook, metadataPath);
|
||||
}
|
||||
@@ -617,6 +616,14 @@ public class DownloadDecryptBook : AudioDecodable, IProcessable<DownloadDecryptB
|
||||
}
|
||||
}
|
||||
|
||||
internal static Newtonsoft.Json.Linq.JObject SerializeContentReference(ContentReference reference)
|
||||
// Unencrypted podcast licenses can omit codec and other fields required by the API model.
|
||||
// Preserve the fields we have without inventing values for this optional metadata export.
|
||||
=> Newtonsoft.Json.Linq.JObject.FromObject(reference, new Newtonsoft.Json.JsonSerializer
|
||||
{
|
||||
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Whether a catalog product carries no details at all.
|
||||
/// <para>
|
||||
|
||||
@@ -9,8 +9,10 @@ public readonly record struct CloudSyncStatus(bool IsSynced, string? ProviderNam
|
||||
{
|
||||
public static readonly CloudSyncStatus NotSynced = new(false, null);
|
||||
|
||||
/// <summary>The provider's own name where Windows reported one, otherwise a generic description.</summary>
|
||||
public string Description => ProviderName is { Length: > 0 } name ? name : "a cloud sync folder";
|
||||
/// <summary>Whether the folder is synced, naming the provider where Windows reported one.</summary>
|
||||
public string Description => !IsSynced
|
||||
? "not a cloud sync folder"
|
||||
: ProviderName is { Length: > 0 } name ? name : "a cloud sync folder";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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<Newtonsoft.Json.JsonSerializationException>(() => JObject.FromObject(reference));
|
||||
var exported = DownloadDecryptBook.SerializeContentReference(reference);
|
||||
|
||||
Assert.AreEqual("B0981FC27J", exported.Value<string>("asin"));
|
||||
Assert.AreEqual("1", exported.Value<string>("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)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verbatim from <c>api.audible.com/1.0/catalog/products/?asins=B089T8FSK6&response_groups=<all></c>,
|
||||
/// the response behind the empty metadata file in the report. The title itself is real and downloadable;
|
||||
|
||||
Reference in new issue
Block a user