Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Build output
[Bb]in/
[Oo]bj/

# VS Code workspace settings: keep shareable debug/task configs
.vscode/*
!.vscode/launch.json
!.vscode/tasks.json
*.cache
27 changes: 27 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "BookLibConnect (Development)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build-booklibconnect-debug",
"program": "${workspaceFolder}/src/Connect.app.gui.core/bin/Debug/net6.0-windows/BookLibConnect.exe",
"cwd": "${workspaceFolder}/src/Connect.app.gui.core",
"console": "internalConsole",
"stopAtEntry": false,
"justMyCode": true
},
{
"name": "BookLibConnect (Production)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build-booklibconnect-release",
"program": "${workspaceFolder}/src/Connect.app.gui.core/bin/Release/net6.0-windows/BookLibConnect.exe",
"cwd": "${workspaceFolder}/src/Connect.app.gui.core",
"console": "internalConsole",
"stopAtEntry": false,
"justMyCode": false
}
]
}
37 changes: 37 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build-booklibconnect-debug",
"type": "shell",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}/src/Connect.app.gui.core/Connect.app.gui.core.csproj",
"-c",
"Debug",
"-p:Platform=AnyCPU"
],
"group": "build",
"problemMatcher": [
"$msCompile"
]
},
{
"label": "build-booklibconnect-release",
"type": "shell",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}/src/Connect.app.gui.core/Connect.app.gui.core.csproj",
"-c",
"Release",
"-p:Platform=AnyCPU"
],
"group": "build",
"problemMatcher": [
"$msCompile"
]
}
]
}
8 changes: 8 additions & 0 deletions src/Audible.json.core/LicenseResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public partial class ContentLicense {
public string asin { get; set; }
public ContentMetadata content_metadata { get; set; }
public string drm_type { get; set; }
public LicenseDenialReason[] license_denial_reasons { get; set; }
public string license_id { get; set; }
public string license_response { get; set; }
public string message { get; set; }
Expand All @@ -25,6 +26,13 @@ public partial class ContentLicense {
public Voucher voucher { get; set; }
}

public class LicenseDenialReason {
public string message { get; set; }
public string rejectionReason { get; set; }
public string rejectionReasonCode { get; set; }
public string validationType { get; set; }
}

public class ContentMetadata {
public ChapterInfo chapter_info { get; set; }
public ContentReference content_reference { get; set; }
Expand Down
14 changes: 12 additions & 2 deletions src/BooksDatabase.core/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace core.audiamus.booksdb.ex {
public static class EntityExtensions {
public static EConversionState ApplicableState (this Book book, bool multipart) {
if (multipart && book.Components.Count > 0) {
if (useComponentDownloads (book, multipart)) {
var state = book.Components
.Select (c => c.Conversion.ApplicableState())
.Distinct ()
Expand All @@ -23,7 +23,7 @@ public static EConversionState ApplicableState (this Conversion conv) {
}

public static EDownloadQuality ApplicableDownloadQuality (this Book book, bool multipart) {
if (multipart && book.Components.Count > 0) {
if (useComponentDownloads (book, multipart)) {
var dnldqual = book.Components
.Select (c => c.ApplicableDownloadQuality())
.Distinct ()
Expand All @@ -44,5 +44,15 @@ public static Book GetBook (this IBookCommon common) {
_ => null,
};
}

private static bool useComponentDownloads (Book book, bool multipart) {
if (book is null || book.Components.Count == 0)
return false;

if (multipart)
return true;

return book.DeliveryType == EDeliveryType.Periodical;
}
}
}
60 changes: 39 additions & 21 deletions src/Connect.lib.core/AaxExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public class AaxExporter {

private IExportSettings ExportSettings { get; }
private IMultiPartSettings MultipartSettings { get; }
private List<List<ChapterExtract>> AccuChapters { get; } = new List<List<ChapterExtract>> ();

public IBookLibrary BookLibrary { private get; set; }

Expand All @@ -31,18 +30,22 @@ public AaxExporter (IExportSettings exportSettings, IMultiPartSettings multipart
}

public void Export (Book book, SimpleConversionContext context, Action<Conversion> onNewStateCallback) {
AccuChapters.Clear ();
using var _ = new LogGuard (3, this, () => book.ToString ());
if (book.Components.Count == 0 || !MultipartSettings.MultiPartDownload)
exportSinglePart (book, context, onNewStateCallback);
var accuChapters = new List<List<ChapterExtract>> ();
bool useComponentExport = book.Components.Count > 0
&& (MultipartSettings.MultiPartDownload || book.DeliveryType == EDeliveryType.Periodical);

if (!useComponentExport)
exportSinglePart (book, context, onNewStateCallback, accuChapters);
else
exportMultiPart (book, context, onNewStateCallback);
exportMultiPart (book, context, onNewStateCallback, accuChapters);
}

private void exportSinglePart (
IBookCommon book,
SimpleConversionContext context,
Action<Conversion> onNewStateCallback,
List<List<ChapterExtract>> accuChapters,
bool skipSeries = false
) {
Log (3, this, () => book.ToString ());
Expand All @@ -56,7 +59,7 @@ private void exportSinglePart (
onNewStateCallback?.Invoke (book.Conversion);
return;
}
exportChapters (book);
exportChapters (book, accuChapters);

exportProduct (book);

Expand All @@ -71,13 +74,14 @@ private void exportSinglePart (
private void exportMultiPart (
Book book,
SimpleConversionContext context,
Action<Conversion> onNewStateCallback
Action<Conversion> onNewStateCallback,
List<List<ChapterExtract>> accuChapters
) {
Log (3, this, () => book.ToString ());

bool skipSeries = false;
foreach (var comp in book.Components) {
exportSinglePart (comp, context, onNewStateCallback, skipSeries);
exportSinglePart (comp, context, onNewStateCallback, accuChapters, skipSeries);
skipSeries = true;
}
}
Expand Down Expand Up @@ -107,7 +111,7 @@ private bool copyFile (IBookCommon book, SimpleConversionContext context) {
}

// internal instead of private for testing only
internal string exportChapters (IBookCommon book) {
internal string exportChapters (IBookCommon book, List<List<ChapterExtract>> accuChapters) {
if (book.ChapterInfo is null)
BookLibrary?.GetChapters (book);

Expand Down Expand Up @@ -140,14 +144,14 @@ internal string exportChapters (IBookCommon book) {
ci.runtime_length_ms = chapterInfo.RuntimeLengthMs;
ci.runtime_length_sec = chapterInfo.RuntimeLengthMs / 1000;

var accuChapters = new List<List<ChapterExtract>> ();
var flattenedChapters = BookLibrary?.GetChaptersFlattened (book, accuChapters);
var partAccuChapters = new List<List<ChapterExtract>> ();
var flattenedChapters = BookLibrary?.GetChaptersFlattened (book, partAccuChapters);


if (!flattenedChapters.IsNullOrEmpty()) {
var chapters = new List<adb.json.Chapter> ();
foreach (var chapter in flattenedChapters) {
if (chapters.Count == 0 && skipChapter (chapter))
if (chapters.Count == 0 && skipChapter (chapter, accuChapters))
continue;

var ch = new adb.json.Chapter {
Expand All @@ -169,17 +173,17 @@ internal string exportChapters (IBookCommon book) {

File.WriteAllText (outpath, json);

updateAccuChapters (accuChapters);
updateAccuChapters (accuChapters, partAccuChapters);

return outpath;
}

private bool skipChapter (Chapter ch) {
if (AccuChapters.Count < 2)
private bool skipChapter (Chapter ch, List<List<ChapterExtract>> accuChapters) {
if (accuChapters.Count < 2)
return false;

for (int i = 0; i < AccuChapters.Count - 1; i++) {
var chextr = AccuChapters[i].FirstOrDefault (ce =>
for (int i = 0; i < accuChapters.Count - 1; i++) {
var chextr = accuChapters[i].FirstOrDefault (ce =>
string.Equals (ce.Title, ch.Title) &&
Math.Abs (ce.Length - ch.LengthMs) < 1500 && ch.LengthMs < 25000);
if (chextr is not null)
Expand All @@ -189,11 +193,16 @@ private bool skipChapter (Chapter ch) {
return false;
}

private void updateAccuChapters (List<List<ChapterExtract>> accuPart) {
private void updateAccuChapters (List<List<ChapterExtract>> accuChapters, List<List<ChapterExtract>> accuPart) {
if (accuPart.IsNullOrEmpty ())
return;

for (int i = 0; i < accuPart.Count; i++) {
if (AccuChapters.Count < i + 1)
AccuChapters.Add (new List<ChapterExtract> ());
AccuChapters[i].AddRange (accuPart[i]);
if (accuChapters.Count < i + 1)
accuChapters.Add (new List<ChapterExtract> ());

if (!accuPart[i].IsNullOrEmpty ())
accuChapters[i].AddRange (accuPart[i]);
}
}

Expand Down Expand Up @@ -301,6 +310,15 @@ private adb.json.Product makeProduct (IBookCommon prod) {
series.Add (s);
}
product.series = series.ToArray ();
} else if (prod is Component comp && !book.Title.IsNullOrWhiteSpace ()) {
// Some podcast episodes arrive without explicit series links. Keep season grouping stable.
product.series = new[] {
new adb.json.Series {
asin = book.Asin,
title = book.Title,
sequence = comp.PartNumber > 0 ? comp.PartNumber.ToString () : null
}
};
}

return product;
Expand Down
Loading