From b2992da3705700c53552e1998f6f30f615bd6c7b Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Mon, 20 Jun 2022 10:22:21 -0600 Subject: [PATCH] Move DownloadOptions to FileLiberator --- .../AaxDecrypter/AaxcDownloadConvertBase.cs | 4 +- .../AaxcDownloadMultiConverter.cs | 22 ++------- .../AaxcDownloadSingleConverter.cs | 4 +- Source/AaxDecrypter/AudiobookDownloadBase.cs | 6 +-- Source/AaxDecrypter/DownloadOptions.cs | 30 ------------ Source/AaxDecrypter/IDownloadOptions.cs | 23 ++++++++++ .../UnencryptedAudiobookDownloader.cs | 2 +- Source/FileLiberator/AudioFileStorageExt.cs | 26 ----------- Source/FileLiberator/DownloadDecryptBook.cs | 46 +++++++++---------- Source/FileLiberator/DownloadOptions.cs | 44 ++++++++++++++++++ 10 files changed, 100 insertions(+), 107 deletions(-) delete mode 100644 Source/AaxDecrypter/DownloadOptions.cs create mode 100644 Source/AaxDecrypter/IDownloadOptions.cs create mode 100644 Source/FileLiberator/DownloadOptions.cs diff --git a/Source/AaxDecrypter/AaxcDownloadConvertBase.cs b/Source/AaxDecrypter/AaxcDownloadConvertBase.cs index f66e27c3..773e11de 100644 --- a/Source/AaxDecrypter/AaxcDownloadConvertBase.cs +++ b/Source/AaxDecrypter/AaxcDownloadConvertBase.cs @@ -11,8 +11,8 @@ namespace AaxDecrypter protected AaxFile AaxFile; - protected AaxcDownloadConvertBase(string outFileName, string cacheDirectory, DownloadOptions dlLic) - : base(outFileName, cacheDirectory, dlLic) { } + protected AaxcDownloadConvertBase(string outFileName, string cacheDirectory, IDownloadOptions dlOptions) + : base(outFileName, cacheDirectory, dlOptions) { } /// Setting cover art by this method will insert the art into the audiobook metadata public override void SetCoverArt(byte[] coverArt) diff --git a/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs b/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs index f3382f6c..25cac87b 100644 --- a/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs +++ b/Source/AaxDecrypter/AaxcDownloadMultiConverter.cs @@ -13,24 +13,12 @@ namespace AaxDecrypter public class AaxcDownloadMultiConverter : AaxcDownloadConvertBase { protected override StepSequence Steps { get; } - - private Func multipartFileNameCallback { get; } - private Func multipartTitleNameCallback { get; } - private static TimeSpan minChapterLength { get; } = TimeSpan.FromSeconds(3); private List multiPartFilePaths { get; } = new List(); - public AaxcDownloadMultiConverter( - string outFileName, - string cacheDirectory, - DownloadOptions dlLic, - Func multipartFileNameCallback, - Func multipartTitleNameCallback - ) - : base(outFileName, cacheDirectory, dlLic) + public AaxcDownloadMultiConverter(string outFileName, string cacheDirectory, IDownloadOptions dlOptions) + : base(outFileName, cacheDirectory, dlOptions) { - ArgumentValidator.EnsureNotNull(multipartFileNameCallback, nameof(multipartFileNameCallback)); - ArgumentValidator.EnsureNotNull(multipartTitleNameCallback, nameof(multipartTitleNameCallback)); Steps = new StepSequence { Name = "Download and Convert Aaxc To " + DownloadOptions.OutputFormat, @@ -39,8 +27,6 @@ namespace AaxDecrypter ["Step 2: Download Decrypted Audiobook"] = Step_DownloadAudiobookAsMultipleFilesPerChapter, ["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, }; newSplitCallback.OutputFile = createOutputFileStream(props); - newSplitCallback.TrackTitle = multipartTitleNameCallback(props); + newSplitCallback.TrackTitle = DownloadOptions.GetMultipartTitleName(props); newSplitCallback.TrackNumber = currentChapter; newSplitCallback.TrackCount = splitChapters.Count; } private FileStream createOutputFileStream(MultiConvertFileProperties multiConvertFileProperties) { - var fileName = multipartFileNameCallback(multiConvertFileProperties); + var fileName = DownloadOptions.GetMultipartFileName(multiConvertFileProperties); fileName = FileUtility.GetValidFilename(fileName); multiPartFilePaths.Add(fileName); diff --git a/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs b/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs index 4e25aed7..fbed8894 100644 --- a/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs +++ b/Source/AaxDecrypter/AaxcDownloadSingleConverter.cs @@ -11,8 +11,8 @@ namespace AaxDecrypter { protected override StepSequence Steps { get; } - public AaxcDownloadSingleConverter(string outFileName, string cacheDirectory, DownloadOptions dlLic) - : base(outFileName, cacheDirectory, dlLic) + public AaxcDownloadSingleConverter(string outFileName, string cacheDirectory, IDownloadOptions dlOptions) + : base(outFileName, cacheDirectory, dlOptions) { Steps = new StepSequence { diff --git a/Source/AaxDecrypter/AudiobookDownloadBase.cs b/Source/AaxDecrypter/AudiobookDownloadBase.cs index 5980fb93..27ce3025 100644 --- a/Source/AaxDecrypter/AudiobookDownloadBase.cs +++ b/Source/AaxDecrypter/AudiobookDownloadBase.cs @@ -25,7 +25,7 @@ namespace AaxDecrypter public string TempFilePath { get; } protected string OutputFileName { get; private set; } - protected DownloadOptions DownloadOptions { get; } + protected IDownloadOptions DownloadOptions { get; } protected NetworkFileStream InputFileStream => (nfsPersister ??= OpenNetworkFileStream()).NetworkFileStream; // 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; } - protected AudiobookDownloadBase(string outFileName, string cacheDirectory, DownloadOptions dlLic) + protected AudiobookDownloadBase(string outFileName, string cacheDirectory, IDownloadOptions dlOptions) { OutputFileName = ArgumentValidator.EnsureNotNullOrWhiteSpace(outFileName, nameof(outFileName)); @@ -50,7 +50,7 @@ namespace AaxDecrypter jsonDownloadState = Path.Combine(cacheDirectory, Path.GetFileName(Path.ChangeExtension(OutputFileName, ".json"))); TempFilePath = Path.ChangeExtension(jsonDownloadState, ".aaxc"); - DownloadOptions = ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic)); + DownloadOptions = ArgumentValidator.EnsureNotNull(dlOptions, nameof(dlOptions)); // delete file after validation is complete FileUtility.SaferDelete(OutputFileName); diff --git a/Source/AaxDecrypter/DownloadOptions.cs b/Source/AaxDecrypter/DownloadOptions.cs deleted file mode 100644 index efeb2664..00000000 --- a/Source/AaxDecrypter/DownloadOptions.cs +++ /dev/null @@ -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 - } - } -} diff --git a/Source/AaxDecrypter/IDownloadOptions.cs b/Source/AaxDecrypter/IDownloadOptions.cs new file mode 100644 index 00000000..64ae08e3 --- /dev/null +++ b/Source/AaxDecrypter/IDownloadOptions.cs @@ -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); + } +} diff --git a/Source/AaxDecrypter/UnencryptedAudiobookDownloader.cs b/Source/AaxDecrypter/UnencryptedAudiobookDownloader.cs index 1040684b..cd6dee88 100644 --- a/Source/AaxDecrypter/UnencryptedAudiobookDownloader.cs +++ b/Source/AaxDecrypter/UnencryptedAudiobookDownloader.cs @@ -11,7 +11,7 @@ namespace AaxDecrypter { 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) { Steps = new StepSequence diff --git a/Source/FileLiberator/AudioFileStorageExt.cs b/Source/FileLiberator/AudioFileStorageExt.cs index 80c704db..45b79aaf 100644 --- a/Source/FileLiberator/AudioFileStorageExt.cs +++ b/Source/FileLiberator/AudioFileStorageExt.cs @@ -8,32 +8,6 @@ namespace FileLiberator { 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 CreateMultipartRenamerFunc(this AudioFileStorage _, LibraryBook libraryBook) - => new MultipartRenamer(libraryBook).MultipartFilename; - - public static Func CreateMultipartTitleNamer(this AudioFileStorage _, LibraryBook libraryBook) - => new MultipartTitleNamer(libraryBook).MultipartTitle; - /// /// DownloadDecryptBook: /// File path for where to move files into. diff --git a/Source/FileLiberator/DownloadDecryptBook.cs b/Source/FileLiberator/DownloadDecryptBook.cs index 435e3fad..79cc5bf8 100644 --- a/Source/FileLiberator/DownloadDecryptBook.cs +++ b/Source/FileLiberator/DownloadDecryptBook.cs @@ -101,24 +101,19 @@ namespace FileLiberator var api = await libraryBook.GetApiAsync(); 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; if (contentLic.DrmType != AudibleApi.Common.DrmType.Adrm) - abDownloader = new UnencryptedAudiobookDownloader(outFileName, cacheDir, audiobookDlLic); + abDownloader = new UnencryptedAudiobookDownloader(outFileName, cacheDir, dlOptions); else { AaxcDownloadConvertBase converter = config.SplitFilesByChapter ? - new AaxcDownloadMultiConverter - ( - outFileName, cacheDir, audiobookDlLic, - AudibleFileStorage.Audio.CreateMultipartRenamerFunc(libraryBook), - AudibleFileStorage.Audio.CreateMultipartTitleNamer(libraryBook) - ) : - new AaxcDownloadSingleConverter(outFileName, cacheDir, audiobookDlLic); + new AaxcDownloadMultiConverter(outFileName, cacheDir, dlOptions) : + new AaxcDownloadSingleConverter(outFileName, cacheDir, dlOptions); if (config.AllowLibationFixup) converter.RetrievedMetadata += (_, tags) => tags.Generes = string.Join(", ", libraryBook.Book.CategoriesNames()); @@ -140,7 +135,7 @@ namespace FileLiberator 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 also assume that if DrmType != Adrm, the file will be an mp3. @@ -153,21 +148,22 @@ namespace FileLiberator var dlOptions = new DownloadOptions ( - contentLic?.ContentMetadata?.ContentUrl?.OfflineUrl, - Resources.USER_AGENT + libraryBook, + contentLic?.ContentMetadata?.ContentUrl?.OfflineUrl, + Resources.USER_AGENT ) - { - AudibleKey = contentLic?.Voucher?.Key, - AudibleIV = contentLic?.Voucher?.Iv, - OutputFormat = outputFormat, - TrimOutputToChapterLength = config.AllowLibationFixup && config.StripAudibleBrandAudio, - RetainEncryptedFile = config.RetainAaxFile && encrypted, - StripUnabridged = config.AllowLibationFixup && config.StripUnabridged, - Downsample = config.AllowLibationFixup && config.LameDownsampleMono, - MatchSourceBitrate = config.AllowLibationFixup && config.LameMatchSourceBR && config.LameTargetBitrate, - CreateCueSheet = config.CreateCueSheet, - LameConfig = GetLameOptions(config) - }; + { + AudibleKey = contentLic?.Voucher?.Key, + AudibleIV = contentLic?.Voucher?.Iv, + OutputFormat = outputFormat, + TrimOutputToChapterLength = config.AllowLibationFixup && config.StripAudibleBrandAudio, + RetainEncryptedFile = config.RetainAaxFile && encrypted, + StripUnabridged = config.AllowLibationFixup && config.StripUnabridged, + Downsample = config.AllowLibationFixup && config.LameDownsampleMono, + MatchSourceBitrate = config.AllowLibationFixup && config.LameMatchSourceBR && config.LameTargetBitrate, + CreateCueSheet = config.CreateCueSheet, + LameConfig = GetLameOptions(config) + }; if (config.AllowLibationFixup || outputFormat == OutputFormat.Mp3) { diff --git a/Source/FileLiberator/DownloadOptions.cs b/Source/FileLiberator/DownloadOptions.cs new file mode 100644 index 00000000..86b0a778 --- /dev/null +++ b/Source/FileLiberator/DownloadOptions.cs @@ -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 + } + } +}