Move DownloadOptions to FileLiberator
This commit is contained in:
parent
fdee254020
commit
b2992da370
@ -11,8 +11,8 @@ namespace AaxDecrypter
|
|||||||
|
|
||||||
protected AaxFile AaxFile;
|
protected AaxFile AaxFile;
|
||||||
|
|
||||||
protected AaxcDownloadConvertBase(string outFileName, string cacheDirectory, DownloadOptions dlLic)
|
protected AaxcDownloadConvertBase(string outFileName, string cacheDirectory, IDownloadOptions dlOptions)
|
||||||
: base(outFileName, cacheDirectory, dlLic) { }
|
: base(outFileName, cacheDirectory, dlOptions) { }
|
||||||
|
|
||||||
/// <summary>Setting cover art by this method will insert the art into the audiobook metadata</summary>
|
/// <summary>Setting cover art by this method will insert the art into the audiobook metadata</summary>
|
||||||
public override void SetCoverArt(byte[] coverArt)
|
public override void SetCoverArt(byte[] coverArt)
|
||||||
|
|||||||
@ -13,24 +13,12 @@ namespace AaxDecrypter
|
|||||||
public class AaxcDownloadMultiConverter : AaxcDownloadConvertBase
|
public class AaxcDownloadMultiConverter : AaxcDownloadConvertBase
|
||||||
{
|
{
|
||||||
protected override StepSequence Steps { get; }
|
protected override StepSequence Steps { get; }
|
||||||
|
|
||||||
private Func<MultiConvertFileProperties, string> multipartFileNameCallback { get; }
|
|
||||||
private Func<MultiConvertFileProperties, string> multipartTitleNameCallback { get; }
|
|
||||||
|
|
||||||
private static TimeSpan minChapterLength { get; } = TimeSpan.FromSeconds(3);
|
private static TimeSpan minChapterLength { get; } = TimeSpan.FromSeconds(3);
|
||||||
private List<string> multiPartFilePaths { get; } = new List<string>();
|
private List<string> multiPartFilePaths { get; } = new List<string>();
|
||||||
|
|
||||||
public AaxcDownloadMultiConverter(
|
public AaxcDownloadMultiConverter(string outFileName, string cacheDirectory, IDownloadOptions dlOptions)
|
||||||
string outFileName,
|
: base(outFileName, cacheDirectory, dlOptions)
|
||||||
string cacheDirectory,
|
|
||||||
DownloadOptions dlLic,
|
|
||||||
Func<MultiConvertFileProperties, string> multipartFileNameCallback,
|
|
||||||
Func<MultiConvertFileProperties, string> multipartTitleNameCallback
|
|
||||||
)
|
|
||||||
: base(outFileName, cacheDirectory, dlLic)
|
|
||||||
{
|
{
|
||||||
ArgumentValidator.EnsureNotNull(multipartFileNameCallback, nameof(multipartFileNameCallback));
|
|
||||||
ArgumentValidator.EnsureNotNull(multipartTitleNameCallback, nameof(multipartTitleNameCallback));
|
|
||||||
Steps = new StepSequence
|
Steps = new StepSequence
|
||||||
{
|
{
|
||||||
Name = "Download and Convert Aaxc To " + DownloadOptions.OutputFormat,
|
Name = "Download and Convert Aaxc To " + DownloadOptions.OutputFormat,
|
||||||
@ -39,8 +27,6 @@ namespace AaxDecrypter
|
|||||||
["Step 2: Download Decrypted Audiobook"] = Step_DownloadAudiobookAsMultipleFilesPerChapter,
|
["Step 2: Download Decrypted Audiobook"] = Step_DownloadAudiobookAsMultipleFilesPerChapter,
|
||||||
["Step 3: Cleanup"] = Step_Cleanup,
|
["Step 3: Cleanup"] = Step_Cleanup,
|
||||||
};
|
};
|
||||||
this.multipartFileNameCallback = multipartFileNameCallback;
|
|
||||||
this.multipartTitleNameCallback = multipartTitleNameCallback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -147,14 +133,14 @@ That naming may not be desirable for everyone, but it's an easy change to instea
|
|||||||
Title = newSplitCallback?.Chapter?.Title,
|
Title = newSplitCallback?.Chapter?.Title,
|
||||||
};
|
};
|
||||||
newSplitCallback.OutputFile = createOutputFileStream(props);
|
newSplitCallback.OutputFile = createOutputFileStream(props);
|
||||||
newSplitCallback.TrackTitle = multipartTitleNameCallback(props);
|
newSplitCallback.TrackTitle = DownloadOptions.GetMultipartTitleName(props);
|
||||||
newSplitCallback.TrackNumber = currentChapter;
|
newSplitCallback.TrackNumber = currentChapter;
|
||||||
newSplitCallback.TrackCount = splitChapters.Count;
|
newSplitCallback.TrackCount = splitChapters.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileStream createOutputFileStream(MultiConvertFileProperties multiConvertFileProperties)
|
private FileStream createOutputFileStream(MultiConvertFileProperties multiConvertFileProperties)
|
||||||
{
|
{
|
||||||
var fileName = multipartFileNameCallback(multiConvertFileProperties);
|
var fileName = DownloadOptions.GetMultipartFileName(multiConvertFileProperties);
|
||||||
fileName = FileUtility.GetValidFilename(fileName);
|
fileName = FileUtility.GetValidFilename(fileName);
|
||||||
|
|
||||||
multiPartFilePaths.Add(fileName);
|
multiPartFilePaths.Add(fileName);
|
||||||
|
|||||||
@ -11,8 +11,8 @@ namespace AaxDecrypter
|
|||||||
{
|
{
|
||||||
protected override StepSequence Steps { get; }
|
protected override StepSequence Steps { get; }
|
||||||
|
|
||||||
public AaxcDownloadSingleConverter(string outFileName, string cacheDirectory, DownloadOptions dlLic)
|
public AaxcDownloadSingleConverter(string outFileName, string cacheDirectory, IDownloadOptions dlOptions)
|
||||||
: base(outFileName, cacheDirectory, dlLic)
|
: base(outFileName, cacheDirectory, dlOptions)
|
||||||
{
|
{
|
||||||
Steps = new StepSequence
|
Steps = new StepSequence
|
||||||
{
|
{
|
||||||
|
|||||||
@ -25,7 +25,7 @@ namespace AaxDecrypter
|
|||||||
public string TempFilePath { get; }
|
public string TempFilePath { get; }
|
||||||
|
|
||||||
protected string OutputFileName { get; private set; }
|
protected string OutputFileName { get; private set; }
|
||||||
protected DownloadOptions DownloadOptions { get; }
|
protected IDownloadOptions DownloadOptions { get; }
|
||||||
protected NetworkFileStream InputFileStream => (nfsPersister ??= OpenNetworkFileStream()).NetworkFileStream;
|
protected NetworkFileStream InputFileStream => (nfsPersister ??= OpenNetworkFileStream()).NetworkFileStream;
|
||||||
|
|
||||||
// Don't give the property a 'set'. This should have to be an obvious choice; not accidental
|
// Don't give the property a 'set'. This should have to be an obvious choice; not accidental
|
||||||
@ -36,7 +36,7 @@ namespace AaxDecrypter
|
|||||||
|
|
||||||
private string jsonDownloadState { get; }
|
private string jsonDownloadState { get; }
|
||||||
|
|
||||||
protected AudiobookDownloadBase(string outFileName, string cacheDirectory, DownloadOptions dlLic)
|
protected AudiobookDownloadBase(string outFileName, string cacheDirectory, IDownloadOptions dlOptions)
|
||||||
{
|
{
|
||||||
OutputFileName = ArgumentValidator.EnsureNotNullOrWhiteSpace(outFileName, nameof(outFileName));
|
OutputFileName = ArgumentValidator.EnsureNotNullOrWhiteSpace(outFileName, nameof(outFileName));
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ namespace AaxDecrypter
|
|||||||
jsonDownloadState = Path.Combine(cacheDirectory, Path.GetFileName(Path.ChangeExtension(OutputFileName, ".json")));
|
jsonDownloadState = Path.Combine(cacheDirectory, Path.GetFileName(Path.ChangeExtension(OutputFileName, ".json")));
|
||||||
TempFilePath = Path.ChangeExtension(jsonDownloadState, ".aaxc");
|
TempFilePath = Path.ChangeExtension(jsonDownloadState, ".aaxc");
|
||||||
|
|
||||||
DownloadOptions = ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic));
|
DownloadOptions = ArgumentValidator.EnsureNotNull(dlOptions, nameof(dlOptions));
|
||||||
|
|
||||||
// delete file after validation is complete
|
// delete file after validation is complete
|
||||||
FileUtility.SaferDelete(OutputFileName);
|
FileUtility.SaferDelete(OutputFileName);
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
using AAXClean;
|
|
||||||
using Dinah.Core;
|
|
||||||
|
|
||||||
namespace AaxDecrypter
|
|
||||||
{
|
|
||||||
public class DownloadOptions
|
|
||||||
{
|
|
||||||
public string DownloadUrl { get; }
|
|
||||||
public string UserAgent { get; }
|
|
||||||
public string AudibleKey { get; init; }
|
|
||||||
public string AudibleIV { get; init; }
|
|
||||||
public OutputFormat OutputFormat { get; init; }
|
|
||||||
public bool TrimOutputToChapterLength { get; init; }
|
|
||||||
public bool RetainEncryptedFile { get; init; }
|
|
||||||
public bool StripUnabridged { get; init; }
|
|
||||||
public bool CreateCueSheet { get; init; }
|
|
||||||
public ChapterInfo ChapterInfo { get; set; }
|
|
||||||
public NAudio.Lame.LameConfig LameConfig { get; set; }
|
|
||||||
public bool Downsample { get; set; }
|
|
||||||
public bool MatchSourceBitrate { get; set; }
|
|
||||||
|
|
||||||
public DownloadOptions(string downloadUrl, string userAgent)
|
|
||||||
{
|
|
||||||
DownloadUrl = ArgumentValidator.EnsureNotNullOrEmpty(downloadUrl, nameof(downloadUrl));
|
|
||||||
UserAgent = ArgumentValidator.EnsureNotNullOrEmpty(userAgent, nameof(userAgent));
|
|
||||||
|
|
||||||
// no null/empty check for key/iv. unencrypted files do not have them
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
23
Source/AaxDecrypter/IDownloadOptions.cs
Normal file
23
Source/AaxDecrypter/IDownloadOptions.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using AAXClean;
|
||||||
|
|
||||||
|
namespace AaxDecrypter
|
||||||
|
{
|
||||||
|
public interface IDownloadOptions
|
||||||
|
{
|
||||||
|
string DownloadUrl { get; }
|
||||||
|
string UserAgent { get; }
|
||||||
|
string AudibleKey { get; }
|
||||||
|
string AudibleIV { get; }
|
||||||
|
OutputFormat OutputFormat { get; }
|
||||||
|
bool TrimOutputToChapterLength { get; }
|
||||||
|
bool RetainEncryptedFile { get; }
|
||||||
|
bool StripUnabridged { get; }
|
||||||
|
bool CreateCueSheet { get; }
|
||||||
|
ChapterInfo ChapterInfo { get; set; }
|
||||||
|
NAudio.Lame.LameConfig LameConfig { get; set; }
|
||||||
|
bool Downsample { get; set; }
|
||||||
|
bool MatchSourceBitrate { get; set; }
|
||||||
|
string GetMultipartFileName(MultiConvertFileProperties props);
|
||||||
|
string GetMultipartTitleName(MultiConvertFileProperties props);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,7 +11,7 @@ namespace AaxDecrypter
|
|||||||
{
|
{
|
||||||
protected override StepSequence Steps { get; }
|
protected override StepSequence Steps { get; }
|
||||||
|
|
||||||
public UnencryptedAudiobookDownloader(string outFileName, string cacheDirectory, DownloadOptions dlLic)
|
public UnencryptedAudiobookDownloader(string outFileName, string cacheDirectory, IDownloadOptions dlLic)
|
||||||
: base(outFileName, cacheDirectory, dlLic)
|
: base(outFileName, cacheDirectory, dlLic)
|
||||||
{
|
{
|
||||||
Steps = new StepSequence
|
Steps = new StepSequence
|
||||||
|
|||||||
@ -8,32 +8,6 @@ namespace FileLiberator
|
|||||||
{
|
{
|
||||||
public static class AudioFileStorageExt
|
public static class AudioFileStorageExt
|
||||||
{
|
{
|
||||||
private class MultipartRenamer
|
|
||||||
{
|
|
||||||
private LibraryBook libraryBook { get; }
|
|
||||||
|
|
||||||
internal MultipartRenamer(LibraryBook libraryBook) => this.libraryBook = libraryBook;
|
|
||||||
|
|
||||||
internal string MultipartFilename(AaxDecrypter.MultiConvertFileProperties props)
|
|
||||||
=> Templates.ChapterFile.GetFilename(libraryBook.ToDto(), props);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MultipartTitleNamer
|
|
||||||
{
|
|
||||||
private LibraryBook libraryBook { get; }
|
|
||||||
|
|
||||||
internal MultipartTitleNamer(LibraryBook libraryBook) => this.libraryBook = libraryBook;
|
|
||||||
|
|
||||||
internal string MultipartTitle(AaxDecrypter.MultiConvertFileProperties props)
|
|
||||||
=> Templates.ChapterTitle.GetTitle(libraryBook.ToDto(), props);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Func<AaxDecrypter.MultiConvertFileProperties, string> CreateMultipartRenamerFunc(this AudioFileStorage _, LibraryBook libraryBook)
|
|
||||||
=> new MultipartRenamer(libraryBook).MultipartFilename;
|
|
||||||
|
|
||||||
public static Func<AaxDecrypter.MultiConvertFileProperties, string> CreateMultipartTitleNamer(this AudioFileStorage _, LibraryBook libraryBook)
|
|
||||||
=> new MultipartTitleNamer(libraryBook).MultipartTitle;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DownloadDecryptBook:
|
/// DownloadDecryptBook:
|
||||||
/// File path for where to move files into.
|
/// File path for where to move files into.
|
||||||
|
|||||||
@ -101,24 +101,19 @@ namespace FileLiberator
|
|||||||
|
|
||||||
var api = await libraryBook.GetApiAsync();
|
var api = await libraryBook.GetApiAsync();
|
||||||
var contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId);
|
var contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId);
|
||||||
var audiobookDlLic = BuildDownloadOptions(config, contentLic);
|
var dlOptions = BuildDownloadOptions(libraryBook, config, contentLic);
|
||||||
|
|
||||||
var outFileName = AudibleFileStorage.Audio.GetInProgressFilename(libraryBook, audiobookDlLic.OutputFormat.ToString().ToLower());
|
var outFileName = AudibleFileStorage.Audio.GetInProgressFilename(libraryBook, dlOptions.OutputFormat.ToString().ToLower());
|
||||||
var cacheDir = AudibleFileStorage.DownloadsInProgressDirectory;
|
var cacheDir = AudibleFileStorage.DownloadsInProgressDirectory;
|
||||||
|
|
||||||
if (contentLic.DrmType != AudibleApi.Common.DrmType.Adrm)
|
if (contentLic.DrmType != AudibleApi.Common.DrmType.Adrm)
|
||||||
abDownloader = new UnencryptedAudiobookDownloader(outFileName, cacheDir, audiobookDlLic);
|
abDownloader = new UnencryptedAudiobookDownloader(outFileName, cacheDir, dlOptions);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AaxcDownloadConvertBase converter
|
AaxcDownloadConvertBase converter
|
||||||
= config.SplitFilesByChapter ?
|
= config.SplitFilesByChapter ?
|
||||||
new AaxcDownloadMultiConverter
|
new AaxcDownloadMultiConverter(outFileName, cacheDir, dlOptions) :
|
||||||
(
|
new AaxcDownloadSingleConverter(outFileName, cacheDir, dlOptions);
|
||||||
outFileName, cacheDir, audiobookDlLic,
|
|
||||||
AudibleFileStorage.Audio.CreateMultipartRenamerFunc(libraryBook),
|
|
||||||
AudibleFileStorage.Audio.CreateMultipartTitleNamer(libraryBook)
|
|
||||||
) :
|
|
||||||
new AaxcDownloadSingleConverter(outFileName, cacheDir, audiobookDlLic);
|
|
||||||
|
|
||||||
if (config.AllowLibationFixup)
|
if (config.AllowLibationFixup)
|
||||||
converter.RetrievedMetadata += (_, tags) => tags.Generes = string.Join(", ", libraryBook.Book.CategoriesNames());
|
converter.RetrievedMetadata += (_, tags) => tags.Generes = string.Join(", ", libraryBook.Book.CategoriesNames());
|
||||||
@ -140,7 +135,7 @@ namespace FileLiberator
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DownloadOptions BuildDownloadOptions(Configuration config, AudibleApi.Common.ContentLicense contentLic)
|
private DownloadOptions BuildDownloadOptions(LibraryBook libraryBook, Configuration config, AudibleApi.Common.ContentLicense contentLic)
|
||||||
{
|
{
|
||||||
//I assume if ContentFormat == "MPEG" that the delivered file is an unencrypted mp3.
|
//I assume if ContentFormat == "MPEG" that the delivered file is an unencrypted mp3.
|
||||||
//I also assume that if DrmType != Adrm, the file will be an mp3.
|
//I also assume that if DrmType != Adrm, the file will be an mp3.
|
||||||
@ -153,21 +148,22 @@ namespace FileLiberator
|
|||||||
|
|
||||||
var dlOptions = new DownloadOptions
|
var dlOptions = new DownloadOptions
|
||||||
(
|
(
|
||||||
contentLic?.ContentMetadata?.ContentUrl?.OfflineUrl,
|
libraryBook,
|
||||||
Resources.USER_AGENT
|
contentLic?.ContentMetadata?.ContentUrl?.OfflineUrl,
|
||||||
|
Resources.USER_AGENT
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
AudibleKey = contentLic?.Voucher?.Key,
|
AudibleKey = contentLic?.Voucher?.Key,
|
||||||
AudibleIV = contentLic?.Voucher?.Iv,
|
AudibleIV = contentLic?.Voucher?.Iv,
|
||||||
OutputFormat = outputFormat,
|
OutputFormat = outputFormat,
|
||||||
TrimOutputToChapterLength = config.AllowLibationFixup && config.StripAudibleBrandAudio,
|
TrimOutputToChapterLength = config.AllowLibationFixup && config.StripAudibleBrandAudio,
|
||||||
RetainEncryptedFile = config.RetainAaxFile && encrypted,
|
RetainEncryptedFile = config.RetainAaxFile && encrypted,
|
||||||
StripUnabridged = config.AllowLibationFixup && config.StripUnabridged,
|
StripUnabridged = config.AllowLibationFixup && config.StripUnabridged,
|
||||||
Downsample = config.AllowLibationFixup && config.LameDownsampleMono,
|
Downsample = config.AllowLibationFixup && config.LameDownsampleMono,
|
||||||
MatchSourceBitrate = config.AllowLibationFixup && config.LameMatchSourceBR && config.LameTargetBitrate,
|
MatchSourceBitrate = config.AllowLibationFixup && config.LameMatchSourceBR && config.LameTargetBitrate,
|
||||||
CreateCueSheet = config.CreateCueSheet,
|
CreateCueSheet = config.CreateCueSheet,
|
||||||
LameConfig = GetLameOptions(config)
|
LameConfig = GetLameOptions(config)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (config.AllowLibationFixup || outputFormat == OutputFormat.Mp3)
|
if (config.AllowLibationFixup || outputFormat == OutputFormat.Mp3)
|
||||||
{
|
{
|
||||||
|
|||||||
44
Source/FileLiberator/DownloadOptions.cs
Normal file
44
Source/FileLiberator/DownloadOptions.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using AaxDecrypter;
|
||||||
|
using AAXClean;
|
||||||
|
using Dinah.Core;
|
||||||
|
using DataLayer;
|
||||||
|
using LibationFileManager;
|
||||||
|
|
||||||
|
namespace FileLiberator
|
||||||
|
{
|
||||||
|
public class DownloadOptions : IDownloadOptions
|
||||||
|
{
|
||||||
|
public LibraryBook LibraryBook { get; }
|
||||||
|
public LibraryBookDto LibraryBookDto { get; }
|
||||||
|
public string DownloadUrl { get; }
|
||||||
|
public string UserAgent { get; }
|
||||||
|
public string AudibleKey { get; init; }
|
||||||
|
public string AudibleIV { get; init; }
|
||||||
|
public AaxDecrypter.OutputFormat OutputFormat { get; init; }
|
||||||
|
public bool TrimOutputToChapterLength { get; init; }
|
||||||
|
public bool RetainEncryptedFile { get; init; }
|
||||||
|
public bool StripUnabridged { get; init; }
|
||||||
|
public bool CreateCueSheet { get; init; }
|
||||||
|
public ChapterInfo ChapterInfo { get; set; }
|
||||||
|
public NAudio.Lame.LameConfig LameConfig { get; set; }
|
||||||
|
public bool Downsample { get; set; }
|
||||||
|
public bool MatchSourceBitrate { get; set; }
|
||||||
|
|
||||||
|
public string GetMultipartFileName(MultiConvertFileProperties props)
|
||||||
|
=> Templates.ChapterFile.GetFilename(LibraryBookDto, props);
|
||||||
|
|
||||||
|
public string GetMultipartTitleName(MultiConvertFileProperties props)
|
||||||
|
=> Templates.ChapterTitle.GetTitle(LibraryBookDto, props);
|
||||||
|
|
||||||
|
public DownloadOptions(LibraryBook libraryBook, string downloadUrl, string userAgent)
|
||||||
|
{
|
||||||
|
LibraryBook = ArgumentValidator.EnsureNotNull(libraryBook, nameof(libraryBook));
|
||||||
|
DownloadUrl = ArgumentValidator.EnsureNotNullOrEmpty(downloadUrl, nameof(downloadUrl));
|
||||||
|
UserAgent = ArgumentValidator.EnsureNotNullOrEmpty(userAgent, nameof(userAgent));
|
||||||
|
|
||||||
|
LibraryBookDto = LibraryBook.ToDto();
|
||||||
|
|
||||||
|
// no null/empty check for key/iv. unencrypted files do not have them
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user