Merge pull request #33 from Mbucari/master
Work with updated Api Dtos and some minor readability edits.
This commit is contained in:
commit
797112740e
@ -3,10 +3,7 @@ using Dinah.Core.Diagnostics;
|
|||||||
using Dinah.Core.IO;
|
using Dinah.Core.IO;
|
||||||
using Dinah.Core.StepRunner;
|
using Dinah.Core.StepRunner;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AaxDecrypter
|
namespace AaxDecrypter
|
||||||
{
|
{
|
||||||
@ -20,7 +17,7 @@ namespace AaxDecrypter
|
|||||||
string AppName { get; set; }
|
string AppName { get; set; }
|
||||||
string outDir { get; }
|
string outDir { get; }
|
||||||
string outputFileName { get; }
|
string outputFileName { get; }
|
||||||
ChapterInfo chapters { get; }
|
DownloadLicense downloadLicense { get; }
|
||||||
AaxcTagLibFile aaxcTagLib { get; }
|
AaxcTagLibFile aaxcTagLib { get; }
|
||||||
byte[] coverArt { get; }
|
byte[] coverArt { get; }
|
||||||
void SetCoverArt(byte[] coverArt);
|
void SetCoverArt(byte[] coverArt);
|
||||||
@ -45,23 +42,22 @@ namespace AaxDecrypter
|
|||||||
public string AppName { get; set; } = nameof(AaxcDownloadConverter);
|
public string AppName { get; set; } = nameof(AaxcDownloadConverter);
|
||||||
public string outDir { get; private set; }
|
public string outDir { get; private set; }
|
||||||
public string outputFileName { get; private set; }
|
public string outputFileName { get; private set; }
|
||||||
public ChapterInfo chapters { get; private set; }
|
public DownloadLicense downloadLicense { get; private set; }
|
||||||
public AaxcTagLibFile aaxcTagLib { get; private set; }
|
public AaxcTagLibFile aaxcTagLib { get; private set; }
|
||||||
public byte[] coverArt { get; private set; }
|
public byte[] coverArt { get; private set; }
|
||||||
|
|
||||||
private StepSequence steps { get; }
|
private StepSequence steps { get; }
|
||||||
private DownloadLicense downloadLicense { get; set; }
|
|
||||||
private FFMpegAaxcProcesser aaxcProcesser;
|
private FFMpegAaxcProcesser aaxcProcesser;
|
||||||
private bool isCanceled { get; set; }
|
private bool isCanceled { get; set; }
|
||||||
|
|
||||||
public static AaxcDownloadConverter Create(string outDirectory, DownloadLicense dlLic, ChapterInfo chapters = null)
|
public static AaxcDownloadConverter Create(string outDirectory, DownloadLicense dlLic)
|
||||||
{
|
{
|
||||||
var converter = new AaxcDownloadConverter(outDirectory, dlLic, chapters);
|
var converter = new AaxcDownloadConverter(outDirectory, dlLic);
|
||||||
converter.SetOutputFilename(Path.GetTempFileName());
|
converter.SetOutputFilename(Path.GetTempFileName());
|
||||||
return converter;
|
return converter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AaxcDownloadConverter(string outDirectory, DownloadLicense dlLic, ChapterInfo chapters)
|
private AaxcDownloadConverter(string outDirectory, DownloadLicense dlLic)
|
||||||
{
|
{
|
||||||
ArgumentValidator.EnsureNotNullOrWhiteSpace(outDirectory, nameof(outDirectory));
|
ArgumentValidator.EnsureNotNullOrWhiteSpace(outDirectory, nameof(outDirectory));
|
||||||
ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic));
|
ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic));
|
||||||
@ -86,7 +82,6 @@ namespace AaxDecrypter
|
|||||||
aaxcProcesser.ProgressUpdate += AaxcProcesser_ProgressUpdate;
|
aaxcProcesser.ProgressUpdate += AaxcProcesser_ProgressUpdate;
|
||||||
|
|
||||||
downloadLicense = dlLic;
|
downloadLicense = dlLic;
|
||||||
this.chapters = chapters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetOutputFilename(string outFileName)
|
public void SetOutputFilename(string outFileName)
|
||||||
@ -147,13 +142,14 @@ namespace AaxDecrypter
|
|||||||
RetrievedTags?.Invoke(this, aaxcTagLib);
|
RetrievedTags?.Invoke(this, aaxcTagLib);
|
||||||
RetrievedCoverArt?.Invoke(this, coverArt);
|
RetrievedCoverArt?.Invoke(this, coverArt);
|
||||||
|
|
||||||
return !isCanceled;
|
return !isCanceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Step3_DownloadAndCombine()
|
public bool Step3_DownloadAndCombine()
|
||||||
{
|
{
|
||||||
DecryptProgressUpdate?.Invoke(this, int.MaxValue);
|
DecryptProgressUpdate?.Invoke(this, int.MaxValue);
|
||||||
bool userSuppliedChapters = chapters != null;
|
|
||||||
|
bool userSuppliedChapters = downloadLicense.ChapterInfo != null;
|
||||||
|
|
||||||
string metadataPath = null;
|
string metadataPath = null;
|
||||||
|
|
||||||
@ -162,7 +158,7 @@ namespace AaxDecrypter
|
|||||||
//Only write chaopters to the metadata file. All other aaxc metadata will be
|
//Only write chaopters to the metadata file. All other aaxc metadata will be
|
||||||
//wiped out but is restored in Step 3.
|
//wiped out but is restored in Step 3.
|
||||||
metadataPath = Path.Combine(outDir, Path.GetFileName(outputFileName) + ".ffmeta");
|
metadataPath = Path.Combine(outDir, Path.GetFileName(outputFileName) + ".ffmeta");
|
||||||
File.WriteAllText(metadataPath, chapters.ToFFMeta(true));
|
File.WriteAllText(metadataPath, downloadLicense.ChapterInfo.ToFFMeta(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
aaxcProcesser.ProcessBook(
|
aaxcProcesser.ProcessBook(
|
||||||
@ -172,7 +168,7 @@ namespace AaxDecrypter
|
|||||||
.GetResult();
|
.GetResult();
|
||||||
|
|
||||||
if (!userSuppliedChapters && aaxcProcesser.Succeeded)
|
if (!userSuppliedChapters && aaxcProcesser.Succeeded)
|
||||||
chapters = new ChapterInfo(outputFileName);
|
downloadLicense.ChapterInfo = new ChapterInfo(outputFileName);
|
||||||
|
|
||||||
if (userSuppliedChapters)
|
if (userSuppliedChapters)
|
||||||
FileExt.SafeDelete(metadataPath);
|
FileExt.SafeDelete(metadataPath);
|
||||||
@ -188,7 +184,7 @@ namespace AaxDecrypter
|
|||||||
double estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed;
|
double estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed;
|
||||||
|
|
||||||
if (double.IsNormal(estTimeRemaining))
|
if (double.IsNormal(estTimeRemaining))
|
||||||
DecryptTimeRemaining?.Invoke(this, TimeSpan.FromSeconds(estTimeRemaining));
|
DecryptTimeRemaining?.Invoke(this, TimeSpan.FromSeconds(estTimeRemaining));
|
||||||
|
|
||||||
double progressPercent = 100 * e.ProcessPosition.TotalSeconds / aaxcTagLib.Properties.Duration.TotalSeconds;
|
double progressPercent = 100 * e.ProcessPosition.TotalSeconds / aaxcTagLib.Properties.Duration.TotalSeconds;
|
||||||
|
|
||||||
@ -215,13 +211,13 @@ namespace AaxDecrypter
|
|||||||
|
|
||||||
public bool Step5_CreateCue()
|
public bool Step5_CreateCue()
|
||||||
{
|
{
|
||||||
File.WriteAllText(PathLib.ReplaceExtension(outputFileName, ".cue"), Cue.CreateContents(Path.GetFileName(outputFileName), chapters));
|
File.WriteAllText(PathLib.ReplaceExtension(outputFileName, ".cue"), Cue.CreateContents(Path.GetFileName(outputFileName), downloadLicense.ChapterInfo));
|
||||||
return !isCanceled;
|
return !isCanceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Step6_CreateNfo()
|
public bool Step6_CreateNfo()
|
||||||
{
|
{
|
||||||
File.WriteAllText(PathLib.ReplaceExtension(outputFileName, ".nfo"), NFO.CreateContents(AppName, aaxcTagLib, chapters));
|
File.WriteAllText(PathLib.ReplaceExtension(outputFileName, ".nfo"), NFO.CreateContents(AppName, aaxcTagLib, downloadLicense.ChapterInfo));
|
||||||
return !isCanceled;
|
return !isCanceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Dinah.Core;
|
using Dinah.Core;
|
||||||
using Dinah.Core.Diagnostics;
|
using Dinah.Core.Diagnostics;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@ -66,8 +67,8 @@ namespace AaxDecrypter
|
|||||||
public class Chapter
|
public class Chapter
|
||||||
{
|
{
|
||||||
public string Title { get; }
|
public string Title { get; }
|
||||||
public long StartOffsetMs { get; }
|
public TimeSpan StartOffset { get; }
|
||||||
public long EndOffsetMs { get; }
|
public TimeSpan EndOffset { get; }
|
||||||
public Chapter(string title, long startOffsetMs, long lengthMs)
|
public Chapter(string title, long startOffsetMs, long lengthMs)
|
||||||
{
|
{
|
||||||
ArgumentValidator.EnsureNotNullOrEmpty(title, nameof(title));
|
ArgumentValidator.EnsureNotNullOrEmpty(title, nameof(title));
|
||||||
@ -75,16 +76,16 @@ namespace AaxDecrypter
|
|||||||
ArgumentValidator.EnsureGreaterThan(lengthMs, nameof(lengthMs), 0);
|
ArgumentValidator.EnsureGreaterThan(lengthMs, nameof(lengthMs), 0);
|
||||||
|
|
||||||
Title = title;
|
Title = title;
|
||||||
StartOffsetMs = startOffsetMs;
|
StartOffset = TimeSpan.FromMilliseconds(startOffsetMs);
|
||||||
EndOffsetMs = StartOffsetMs + lengthMs;
|
EndOffset = StartOffset + TimeSpan.FromMilliseconds(lengthMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToFFMeta()
|
public string ToFFMeta()
|
||||||
{
|
{
|
||||||
return "[CHAPTER]\n" +
|
return "[CHAPTER]\n" +
|
||||||
"TIMEBASE=1/1000\n" +
|
"TIMEBASE=1/1000\n" +
|
||||||
"START=" + StartOffsetMs + "\n" +
|
"START=" + StartOffset.TotalMilliseconds + "\n" +
|
||||||
"END=" + EndOffsetMs + "\n" +
|
"END=" + EndOffset.TotalMilliseconds + "\n" +
|
||||||
"title=" + Title;
|
"title=" + Title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,11 +17,10 @@ namespace AaxDecrypter
|
|||||||
foreach (var c in chapters.Chapters)
|
foreach (var c in chapters.Chapters)
|
||||||
{
|
{
|
||||||
trackCount++;
|
trackCount++;
|
||||||
var startTime = TimeSpan.FromMilliseconds(c.StartOffsetMs);
|
|
||||||
|
|
||||||
stringBuilder.AppendLine($"TRACK {trackCount} AUDIO");
|
stringBuilder.AppendLine($"TRACK {trackCount} AUDIO");
|
||||||
stringBuilder.AppendLine($" TITLE \"{c.Title}\"");
|
stringBuilder.AppendLine($" TITLE \"{c.Title}\"");
|
||||||
stringBuilder.AppendLine($" INDEX 01 {(int)startTime.TotalMinutes}:{startTime:ss\\:ff}");
|
stringBuilder.AppendLine($" INDEX 01 {(int)c.StartOffset.TotalMinutes}:{c.StartOffset:ss\\:ff}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return stringBuilder.ToString();
|
return stringBuilder.ToString();
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
using Dinah.Core;
|
using Dinah.Core;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AaxDecrypter
|
namespace AaxDecrypter
|
||||||
{
|
{
|
||||||
@ -13,6 +8,7 @@ namespace AaxDecrypter
|
|||||||
public string AudibleKey { get; }
|
public string AudibleKey { get; }
|
||||||
public string AudibleIV { get; }
|
public string AudibleIV { get; }
|
||||||
public string UserAgent { get; }
|
public string UserAgent { get; }
|
||||||
|
public ChapterInfo ChapterInfo { get; set; }
|
||||||
|
|
||||||
public DownloadLicense(string downloadUrl, string audibleKey, string audibleIV, string userAgent)
|
public DownloadLicense(string downloadUrl, string audibleKey, string audibleIV, string userAgent)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using DataLayer;
|
using DataLayer;
|
||||||
using Dinah.Core.ErrorHandling;
|
using Dinah.Core.ErrorHandling;
|
||||||
using FileLiberator;
|
|
||||||
using FileManager;
|
using FileManager;
|
||||||
|
|
||||||
namespace FileLiberator
|
namespace FileLiberator
|
||||||
|
|||||||
@ -69,24 +69,30 @@ namespace FileLiberator
|
|||||||
|
|
||||||
var api = await InternalUtilities.AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale);
|
var api = await InternalUtilities.AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale);
|
||||||
|
|
||||||
var dlLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId);
|
var contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId);
|
||||||
|
|
||||||
var aaxcDecryptDlLic = new DownloadLicense(dlLic.DownloadUrl, dlLic.AudibleKey, dlLic.AudibleIV, Resources.UserAgent);
|
var aaxcDecryptDlLic = new DownloadLicense
|
||||||
|
(
|
||||||
|
contentLic.ContentMetadata?.ContentUrl?.OfflineUrl,
|
||||||
|
contentLic.Voucher?.Key,
|
||||||
|
contentLic.Voucher?.Iv,
|
||||||
|
Resources.UserAgent
|
||||||
|
);
|
||||||
|
|
||||||
if (Configuration.Instance.AllowLibationFixup)
|
if (Configuration.Instance.AllowLibationFixup)
|
||||||
{
|
{
|
||||||
var contentMetadata = await api.GetLibraryBookMetadataAsync(libraryBook.Book.AudibleProductId);
|
aaxcDecryptDlLic.ChapterInfo = new ChapterInfo();
|
||||||
var aaxcDecryptChapters = new ChapterInfo();
|
|
||||||
|
|
||||||
foreach (var chap in contentMetadata?.ChapterInfo?.Chapters)
|
foreach (var chap in contentLic.ContentMetadata?.ChapterInfo?.Chapters)
|
||||||
aaxcDecryptChapters.AddChapter(new Chapter(chap.Title, chap.StartOffsetMs, chap.LengthMs));
|
aaxcDecryptDlLic.ChapterInfo.AddChapter(
|
||||||
|
new Chapter(
|
||||||
|
chap.Title,
|
||||||
|
chap.StartOffsetMs,
|
||||||
|
chap.LengthMs
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
aaxcDownloader = AaxcDownloadConverter.Create(destinationDir, aaxcDecryptDlLic, aaxcDecryptChapters);
|
aaxcDownloader = AaxcDownloadConverter.Create(destinationDir, aaxcDecryptDlLic);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aaxcDownloader = AaxcDownloadConverter.Create(destinationDir, aaxcDecryptDlLic);
|
|
||||||
}
|
|
||||||
|
|
||||||
aaxcDownloader.AppName = "Libation";
|
aaxcDownloader.AppName = "Libation";
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.IO;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ApplicationServices;
|
using ApplicationServices;
|
||||||
|
|||||||
@ -265,25 +265,32 @@ namespace LibationWinForms.BookLiberation
|
|||||||
void coverImageFilepathDiscovered(object _, byte[] coverBytes) => decryptDialog.SetCoverImage(Dinah.Core.Drawing.ImageReader.ToImage(coverBytes));
|
void coverImageFilepathDiscovered(object _, byte[] coverBytes) => decryptDialog.SetCoverImage(Dinah.Core.Drawing.ImageReader.ToImage(coverBytes));
|
||||||
void updateProgress(object _, int percentage) => decryptDialog.UpdateProgress(percentage);
|
void updateProgress(object _, int percentage) => decryptDialog.UpdateProgress(percentage);
|
||||||
void updateRemainingTime(object _, TimeSpan remaining) => decryptDialog.UpdateRemainingTime(remaining);
|
void updateRemainingTime(object _, TimeSpan remaining) => decryptDialog.UpdateRemainingTime(remaining);
|
||||||
|
|
||||||
void decryptCompleted(object _, string __) => decryptDialog.Close();
|
void decryptCompleted(object _, string __) => decryptDialog.Close();
|
||||||
|
|
||||||
void requestCoverArt(object _, Action<byte[]> setArt)
|
void requestCoverArt(object _, Action<byte[]> setCoverArtDelegate)
|
||||||
{
|
{
|
||||||
var picDef = new FileManager.PictureDefinition(libraryBook.Book.PictureId, FileManager.PictureSize._500x500);
|
var picDef = new FileManager.PictureDefinition(libraryBook.Book.PictureId, FileManager.PictureSize._500x500);
|
||||||
(bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(picDef);
|
(bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(picDef);
|
||||||
|
|
||||||
if (isDefault)
|
if (isDefault)
|
||||||
{
|
{
|
||||||
void pictureCached(object _, string pictureId) => onPictureCached(libraryBook, pictureId, setArt, pictureCached);
|
void pictureCached(object _, string pictureId)
|
||||||
|
{
|
||||||
|
if (pictureId == libraryBook.Book.PictureId)
|
||||||
|
{
|
||||||
|
FileManager.PictureStorage.PictureCached -= pictureCached;
|
||||||
|
|
||||||
|
var picDef = new FileManager.PictureDefinition(libraryBook.Book.PictureId, FileManager.PictureSize._500x500);
|
||||||
|
(_, picture) = FileManager.PictureStorage.GetPicture(picDef);
|
||||||
|
|
||||||
|
setCoverArtDelegate(picture);
|
||||||
|
}
|
||||||
|
};
|
||||||
FileManager.PictureStorage.PictureCached += pictureCached;
|
FileManager.PictureStorage.PictureCached += pictureCached;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
setArt(picture);
|
setCoverArtDelegate(picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region subscribe new form to model's events
|
#region subscribe new form to model's events
|
||||||
@ -319,18 +326,7 @@ namespace LibationWinForms.BookLiberation
|
|||||||
};
|
};
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
private static void onPictureCached(LibraryBook libraryBook, string picId, Action<byte[]> setArt, EventHandler<string> pictureCacheDelegate)
|
|
||||||
{
|
|
||||||
if (picId == libraryBook.Book.PictureId)
|
|
||||||
{
|
|
||||||
FileManager.PictureStorage.PictureCached -= pictureCacheDelegate;
|
|
||||||
|
|
||||||
var picDef = new FileManager.PictureDefinition(libraryBook.Book.PictureId, FileManager.PictureSize._500x500);
|
|
||||||
(_, byte[] picture) = FileManager.PictureStorage.GetPicture(picDef);
|
|
||||||
|
|
||||||
setArt(picture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static (AutomatedBackupsForm, LogMe) attachToBackupsForm(IDownloadableProcessable downloadable)
|
private static (AutomatedBackupsForm, LogMe) attachToBackupsForm(IDownloadableProcessable downloadable)
|
||||||
{
|
{
|
||||||
#region create form and logger
|
#region create form and logger
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user