diff --git a/FileLiberator/AaxcDownloadDecrypt/DownloadBookDummy.cs b/FileLiberator/AaxcDownloadDecrypt/DownloadBookDummy.cs deleted file mode 100644 index 6ebc8329..00000000 --- a/FileLiberator/AaxcDownloadDecrypt/DownloadBookDummy.cs +++ /dev/null @@ -1,16 +0,0 @@ -using DataLayer; -using Dinah.Core.ErrorHandling; -using System.Threading.Tasks; - -namespace FileLiberator.AaxcDownloadDecrypt -{ - public class DownloadBookDummy : DownloadableBase - { - public override Task ProcessItemAsync(LibraryBook libraryBook) => Task.FromResult(new StatusHandler()); - - public override bool Validate(LibraryBook libraryBook) - { - return true; - } - } -} diff --git a/FileLiberator/AaxcDownloadDecrypt/DownloadDecryptBook.cs b/FileLiberator/AaxcDownloadDecrypt/DownloadDecryptBook.cs deleted file mode 100644 index 6b5c2a78..00000000 --- a/FileLiberator/AaxcDownloadDecrypt/DownloadDecryptBook.cs +++ /dev/null @@ -1,207 +0,0 @@ -using DataLayer; -using Dinah.Core; -using Dinah.Core.ErrorHandling; -using FileManager; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using AaxDecrypter; -using AudibleApi; - -namespace FileLiberator.AaxcDownloadDecrypt -{ - public class DownloadDecryptBook : IDecryptable - { - public event EventHandler Begin; - public event EventHandler DecryptBegin; - public event EventHandler TitleDiscovered; - public event EventHandler AuthorsDiscovered; - public event EventHandler NarratorsDiscovered; - public event EventHandler CoverImageFilepathDiscovered; - public event EventHandler UpdateProgress; - public event EventHandler UpdateRemainingTime; - public event EventHandler DecryptCompleted; - public event EventHandler Completed; - public event EventHandler StatusUpdate; - - private AaxcDownloadConverter aaxcDownloader; - public async Task ProcessAsync(LibraryBook libraryBook) - { - Begin?.Invoke(this, libraryBook); - - try - { - - if (AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId)) - return new StatusHandler { "Cannot find decrypt. Final audio file already exists" }; - - var outputAudioFilename = await aaxToM4bConverterDecryptAsync(AudibleFileStorage.DecryptInProgress, libraryBook); - - // decrypt failed - if (outputAudioFilename is null) - return new StatusHandler { "Decrypt failed" }; - - // moves files and returns dest dir. Do not put inside of if(RetainAaxFiles) - _ = moveFilesToBooksDir(libraryBook.Book, outputAudioFilename); - - var finalAudioExists = AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId); - if (!finalAudioExists) - return new StatusHandler { "Cannot find final audio file after decryption" }; - - return new StatusHandler(); - } - finally - { - Completed?.Invoke(this, libraryBook); - } - - } - - private async Task aaxToM4bConverterDecryptAsync(string destinationDir, LibraryBook libraryBook) - { - DecryptBegin?.Invoke(this, $"Begin decrypting {libraryBook}"); - - try - { - validate(libraryBook); - - var api = await InternalUtilities.AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale); - - var dlLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId); - - var aaxcDecryptDlLic = new DownloadLicense(dlLic.DownloadUrl, dlLic.AudibleKey, dlLic.AudibleIV, Resources.UserAgent); - - var destinationDirectory = Path.GetDirectoryName(destinationDir); - - if (Configuration.Instance.DownloadChapters) - { - var contentMetadata = await api.GetLibraryBookMetadataAsync(libraryBook.Book.AudibleProductId); - - var aaxcDecryptChapters = new ChapterInfo(); - - foreach (var chap in contentMetadata?.ChapterInfo?.Chapters) - aaxcDecryptChapters.AddChapter(new Chapter(chap.Title, chap.StartOffsetMs, chap.LengthMs)); - - aaxcDownloader = await AaxcDownloadConverter.CreateAsync(destinationDirectory, aaxcDecryptDlLic, aaxcDecryptChapters); - } - else - { - aaxcDownloader = await AaxcDownloadConverter.CreateAsync(destinationDirectory, aaxcDecryptDlLic); - } - - aaxcDownloader.AppName = "Libation"; - - TitleDiscovered?.Invoke(this, aaxcDownloader.Title); - AuthorsDiscovered?.Invoke(this, aaxcDownloader.Author); - NarratorsDiscovered?.Invoke(this, aaxcDownloader.Narrator); - - if (aaxcDownloader.CoverArt is not null) - CoverImageFilepathDiscovered?.Invoke(this, aaxcDownloader.CoverArt); - - // override default which was set in CreateAsync - var proposedOutputFile = Path.Combine(destinationDir, $"{PathLib.ToPathSafeString(libraryBook.Book.Title)} [{libraryBook.Book.AudibleProductId}].m4b"); - aaxcDownloader.SetOutputFilename(proposedOutputFile); - aaxcDownloader.DecryptProgressUpdate += (s, progress) => UpdateProgress?.Invoke(this, progress); - aaxcDownloader.DecryptTimeRemaining += (s, remaining) => UpdateRemainingTime?.Invoke(this, remaining); - - // REAL WORK DONE HERE - var success = await Task.Run(() => aaxcDownloader.Run()); - - // decrypt failed - if (!success) - return null; - - return aaxcDownloader.outputFileName; - } - finally - { - DecryptCompleted?.Invoke(this, $"Completed downloading and decrypting {libraryBook.Book.Title}"); - } - } - - private static string moveFilesToBooksDir(Book product, string outputAudioFilename) - { - // create final directory. move each file into it. MOVE AUDIO FILE LAST - // new dir: safetitle_limit50char + " [" + productId + "]" - - var destinationDir = AudibleFileStorage.Audio.GetDestDir(product.Title, product.AudibleProductId); - Directory.CreateDirectory(destinationDir); - - var sortedFiles = getProductFilesSorted(product, outputAudioFilename); - - var musicFileExt = Path.GetExtension(outputAudioFilename).Trim('.'); - - // audio filename: safetitle_limit50char + " [" + productId + "]." + audio_ext - var audioFileName = FileUtility.GetValidFilename(destinationDir, product.Title, musicFileExt, product.AudibleProductId); - - foreach (var f in sortedFiles) - { - var dest - = AudibleFileStorage.Audio.IsFileTypeMatch(f) - ? audioFileName - // non-audio filename: safetitle_limit50char + " [" + productId + "][" + audio_ext +"]." + non_audio_ext - : FileUtility.GetValidFilename(destinationDir, product.Title, f.Extension, product.AudibleProductId, musicFileExt); - - if (Path.GetExtension(dest).Trim('.').ToLower() == "cue") - Cue.UpdateFileName(f, audioFileName); - - File.Move(f.FullName, dest); - } - - return destinationDir; - } - - private static List getProductFilesSorted(Book product, string outputAudioFilename) - { - // files are: temp path\author\[asin].ext - var m4bDir = new FileInfo(outputAudioFilename).Directory; - var files = m4bDir - .EnumerateFiles() - .Where(f => f.Name.ContainsInsensitive(product.AudibleProductId)) - .ToList(); - - // move audio files to the end of the collection so these files are moved last - var musicFiles = files.Where(f => AudibleFileStorage.Audio.IsFileTypeMatch(f)); - var sortedFiles = files - .Except(musicFiles) - .Concat(musicFiles) - .ToList(); - - return sortedFiles; - } - - private static void validate(LibraryBook libraryBook) - { - string errorString(string field) - => $"{errorTitle()}\r\nCannot download book. {field} is not known. Try re-importing the account which owns this book."; - - string errorTitle() - { - var title - = (libraryBook.Book.Title.Length > 53) - ? $"{libraryBook.Book.Title.Truncate(50)}..." - : libraryBook.Book.Title; - var errorBookTitle = $"{title} [{libraryBook.Book.AudibleProductId}]"; - return errorBookTitle; - }; - - if (string.IsNullOrWhiteSpace(libraryBook.Account)) - throw new Exception(errorString("Account")); - - if (string.IsNullOrWhiteSpace(libraryBook.Book.Locale)) - throw new Exception(errorString("Locale")); - } - - public bool Validate(LibraryBook libraryBook) - => !AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId) - && !AudibleFileStorage.AAX.Exists(libraryBook.Book.AudibleProductId); - - public void Cancel() - { - aaxcDownloader.Cancel(); - } - } -} diff --git a/LibationWinForms/BookLiberation/ProcessorAutomationController.cs b/LibationWinForms/BookLiberation/ProcessorAutomationController.cs index 6efc3550..fea8c061 100644 --- a/LibationWinForms/BookLiberation/ProcessorAutomationController.cs +++ b/LibationWinForms/BookLiberation/ProcessorAutomationController.cs @@ -70,7 +70,6 @@ namespace LibationWinForms.BookLiberation { var backupBook = new BackupBook(); - backupBook.DownloadBook.Begin += (_, __) => wireUpEvents(backupBook.DownloadBook); backupBook.DecryptBook.Begin += (_, __) => wireUpEvents(backupBook.DecryptBook); backupBook.DownloadPdf.Begin += (_, __) => wireUpEvents(backupBook.DownloadPdf); @@ -80,13 +79,11 @@ namespace LibationWinForms.BookLiberation // completedAction is to refresh grid // - want to see that book disappear from grid // also for this to work, updateIsLiberated can NOT be async - backupBook.DownloadBook.Completed += updateIsLiberated; backupBook.DecryptBook.Completed += updateIsLiberated; backupBook.DownloadPdf.Completed += updateIsLiberated; if (completedAction != null) { - backupBook.DownloadBook.Completed += completedAction; backupBook.DecryptBook.Completed += completedAction; backupBook.DownloadPdf.Completed += completedAction; } @@ -116,9 +113,6 @@ namespace LibationWinForms.BookLiberation #endregion #region subscribe new form to model's events - backupBook.DownloadBook.Begin += downloadBookBegin; - backupBook.DownloadBook.StatusUpdate += statusUpdate; - backupBook.DownloadBook.Completed += downloadBookCompleted; backupBook.DecryptBook.Begin += decryptBookBegin; backupBook.DecryptBook.StatusUpdate += statusUpdate; backupBook.DecryptBook.Completed += decryptBookCompleted; @@ -131,9 +125,6 @@ namespace LibationWinForms.BookLiberation // unsubscribe so disposed forms aren't still trying to receive notifications automatedBackupsForm.FormClosing += (_, __) => { - backupBook.DownloadBook.Begin -= downloadBookBegin; - backupBook.DownloadBook.StatusUpdate -= statusUpdate; - backupBook.DownloadBook.Completed -= downloadBookCompleted; backupBook.DecryptBook.Begin -= decryptBookBegin; backupBook.DecryptBook.StatusUpdate -= statusUpdate; backupBook.DecryptBook.Completed -= decryptBookCompleted;