diff --git a/ApplicationServices/LibraryCommands.cs b/ApplicationServices/LibraryCommands.cs index 8410ade2..f4b3c057 100644 --- a/ApplicationServices/LibraryCommands.cs +++ b/ApplicationServices/LibraryCommands.cs @@ -6,7 +6,6 @@ using AudibleApi; using DataLayer; using Dinah.Core; using DtoImporterService; -using FileManager; using InternalUtilities; using Serilog; @@ -181,8 +180,8 @@ namespace ApplicationServices // this is a query, not command so maybe I should make a LibraryQueries. except there's already one of those... private enum AudioFileState { full, aax, none } private static AudioFileState getAudioFileState(string productId) - => AudibleFileStorage.Audio.Exists(productId) ? AudioFileState.full - : AudibleFileStorage.AAXC.Exists(productId) ? AudioFileState.aax + => TransitionalFileLocator.Audio_Exists(productId) ? AudioFileState.full + : TransitionalFileLocator.AAXC_Exists(productId) ? AudioFileState.aax : AudioFileState.none; public record LibraryStats(int booksFullyBackedUp, int booksDownloadedOnly, int booksNoProgress, int pdfsDownloaded, int pdfsNotDownloaded) { } public static LibraryStats GetCounts() @@ -202,7 +201,7 @@ namespace ApplicationServices var boolResults = libraryBooks .AsParallel() .Where(lb => lb.Book.Supplements.Any()) - .Select(lb => AudibleFileStorage.PDF.Exists(lb.Book.AudibleProductId)) + .Select(lb => TransitionalFileLocator.PDF_Exists(lb.Book.AudibleProductId)) .ToList(); var pdfsDownloaded = boolResults.Count(r => r); var pdfsNotDownloaded = boolResults.Count(r => !r); diff --git a/ApplicationServices/TransitionalFileLocator.cs b/ApplicationServices/TransitionalFileLocator.cs new file mode 100644 index 00000000..8b25065f --- /dev/null +++ b/ApplicationServices/TransitionalFileLocator.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using DataLayer; +using FileManager; + +namespace ApplicationServices +{ + public static class TransitionalFileLocator + { + public static string Audio_GetPath(string productId) + { + var book = DbContexts.GetContext().GetBook_Flat_NoTracking(productId); + var loc = book?.UserDefinedItem?.BookLocation ?? ""; + if (File.Exists(loc)) + return loc; + + return AudibleFileStorage.Audio.GetPath(productId); + } + + public static bool PDF_Exists(string productId) + { + var book = DbContexts.GetContext().GetBook_Flat_NoTracking(productId); + var status = book?.UserDefinedItem?.PdfStatus; + if (status.HasValue && status.Value == LiberatedStatus.Liberated) + return true; + + return AudibleFileStorage.PDF.Exists(productId); + } + + public static bool Audio_Exists(string productId) + { + var book = DbContexts.GetContext().GetBook_Flat_NoTracking(productId); + var status = book?.UserDefinedItem?.BookStatus; + // true since Error == libhack + if (status != LiberatedStatus.NotLiberated) + return true; + + return AudibleFileStorage.Audio.Exists(productId); + } + + public static bool AAXC_Exists(string productId) + { + // this one will actually stay the same. centralizing helps with organization in the interim though + return AudibleFileStorage.AAXC.Exists(productId); + } + } +} diff --git a/FileLiberator/BackupBook.cs b/FileLiberator/BackupBook.cs index 8c42fb19..85ff0f62 100644 --- a/FileLiberator/BackupBook.cs +++ b/FileLiberator/BackupBook.cs @@ -24,7 +24,7 @@ namespace FileLiberator public DownloadPdf DownloadPdf { get; } = new DownloadPdf(); public bool Validate(LibraryBook libraryBook) - => !AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId); + => !ApplicationServices.TransitionalFileLocator.Audio_Exists(libraryBook.Book.AudibleProductId); // do NOT use ConfigureAwait(false) on ProcessAsync() // often calls events which prints to forms in the UI context diff --git a/FileLiberator/ConvertToMp3.cs b/FileLiberator/ConvertToMp3.cs index ed4ae750..88ee925b 100644 --- a/FileLiberator/ConvertToMp3.cs +++ b/FileLiberator/ConvertToMp3.cs @@ -1,5 +1,6 @@ using AAXClean; using DataLayer; +using Dinah.Core; using Dinah.Core.ErrorHandling; using Dinah.Core.IO; using FileManager; @@ -28,23 +29,15 @@ namespace FileLiberator private Mp4File m4bBook; - private string Mp3FileName(LibraryBook libraryBook) + private string Mp3FileName(string m4bPath) => m4bPath is null ? string.Empty : PathLib.ReplaceExtension(m4bPath, ".mp3"); + + public void Cancel() => m4bBook?.Cancel(); + + public bool Validate(LibraryBook libraryBook) { - string m4bPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); - - if (m4bPath is null) - return string.Empty; - - return Path.Combine(Path.GetDirectoryName(m4bPath), Path.GetFileNameWithoutExtension(m4bPath) + ".mp3"); + var path = ApplicationServices.TransitionalFileLocator.Audio_GetPath(libraryBook.Book.AudibleProductId); + return path?.ToLower()?.EndsWith(".m4b") == true && !File.Exists(Mp3FileName(path)); } - public void Cancel() - { - m4bBook?.Cancel(); - } - - public bool Validate(LibraryBook libraryBook) => - AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId)?.ToLower()?.EndsWith(".m4b") == true && - !File.Exists(Mp3FileName(libraryBook)); public async Task ProcessAsync(LibraryBook libraryBook) { @@ -54,7 +47,7 @@ namespace FileLiberator try { - var m4bPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); + var m4bPath = ApplicationServices.TransitionalFileLocator.Audio_GetPath(libraryBook.Book.AudibleProductId); m4bBook = new Mp4File(m4bPath, FileAccess.Read); m4bBook.ConversionProgressUpdate += M4bBook_ConversionProgressUpdate; @@ -64,13 +57,13 @@ namespace FileLiberator NarratorsDiscovered?.Invoke(this, m4bBook.AppleTags.Narrator); CoverImageFilepathDiscovered?.Invoke(this, m4bBook.AppleTags.Cover); - var mp3File = File.OpenWrite(Path.GetTempFileName()); + using var mp3File = File.OpenWrite(Path.GetTempFileName()); var result = await Task.Run(() => m4bBook.ConvertToMp3(mp3File)); m4bBook.InputStream.Close(); mp3File.Close(); - var mp3Path = Mp3FileName(libraryBook); + var mp3Path = Mp3FileName(m4bPath); FileExt.SafeMove(mp3File.Name, mp3Path); @@ -101,6 +94,5 @@ namespace FileLiberator UpdateProgress?.Invoke(this, (int)progressPercent); } - } } diff --git a/FileLiberator/DownloadDecryptBook.cs b/FileLiberator/DownloadDecryptBook.cs index e49ffbf5..90cd77c4 100644 --- a/FileLiberator/DownloadDecryptBook.cs +++ b/FileLiberator/DownloadDecryptBook.cs @@ -34,7 +34,7 @@ namespace FileLiberator try { - if (AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId)) + if (ApplicationServices.TransitionalFileLocator.Audio_Exists(libraryBook.Book.AudibleProductId)) return new StatusHandler { "Cannot find decrypt. Final audio file already exists" }; var outputAudioFilename = await aaxToM4bConverterDecryptAsync(AudibleFileStorage.DownloadsInProgress, AudibleFileStorage.DecryptInProgress, libraryBook); @@ -46,14 +46,12 @@ namespace FileLiberator // moves files and returns dest dir _ = moveFilesToBooksDir(libraryBook.Book, outputAudioFilename); - var finalAudioExists = AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId); + var finalAudioExists = ApplicationServices.TransitionalFileLocator.Audio_Exists(libraryBook.Book.AudibleProductId); if (!finalAudioExists) return new StatusHandler { "Cannot find final audio file after decryption" }; - // GetPath() is very cheap when file exists - var finalAudioPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); // only need to update if success. if failure, it will remain at 0 == NotLiberated - ApplicationServices.LibraryCommands.UpdateBook(libraryBook, LiberatedStatus.Liberated, finalAudioPath); + ApplicationServices.LibraryCommands.UpdateBook(libraryBook, LiberatedStatus.Liberated, outputAudioFilename); return new StatusHandler(); } @@ -221,7 +219,7 @@ namespace FileLiberator } public bool Validate(LibraryBook libraryBook) - => !AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId); + => !ApplicationServices.TransitionalFileLocator.Audio_Exists(libraryBook.Book.AudibleProductId); public void Cancel() { diff --git a/FileLiberator/DownloadPdf.cs b/FileLiberator/DownloadPdf.cs index 6e3e9558..f6b525cc 100644 --- a/FileLiberator/DownloadPdf.cs +++ b/FileLiberator/DownloadPdf.cs @@ -15,7 +15,7 @@ namespace FileLiberator { public override bool Validate(LibraryBook libraryBook) => !string.IsNullOrWhiteSpace(getdownloadUrl(libraryBook)) - && !AudibleFileStorage.PDF.Exists(libraryBook.Book.AudibleProductId); + && !ApplicationServices.TransitionalFileLocator.PDF_Exists(libraryBook.Book.AudibleProductId); public override async Task ProcessItemAsync(LibraryBook libraryBook) { @@ -32,7 +32,7 @@ namespace FileLiberator private static string getProposedDownloadFilePath(LibraryBook libraryBook) { // if audio file exists, get it's dir. else return base Book dir - var existingPath = Path.GetDirectoryName(AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId)); + var existingPath = Path.GetDirectoryName(ApplicationServices.TransitionalFileLocator.Audio_GetPath(libraryBook.Book.AudibleProductId)); var file = getdownloadUrl(libraryBook); if (existingPath != null) @@ -61,7 +61,7 @@ namespace FileLiberator } private static StatusHandler verifyDownload(LibraryBook libraryBook) - => !AudibleFileStorage.PDF.Exists(libraryBook.Book.AudibleProductId) + => !ApplicationServices.TransitionalFileLocator.PDF_Exists(libraryBook.Book.AudibleProductId) ? new StatusHandler { "Downloaded PDF cannot be found" } : new StatusHandler(); } diff --git a/LibationLauncher/LibationLauncher.csproj b/LibationLauncher/LibationLauncher.csproj index cff62dcc..02e79ab2 100644 --- a/LibationLauncher/LibationLauncher.csproj +++ b/LibationLauncher/LibationLauncher.csproj @@ -13,7 +13,7 @@ win-x64 - 5.4.3.1 + 5.4.3.8 diff --git a/LibationSearchEngine/SearchEngine.cs b/LibationSearchEngine/SearchEngine.cs index a205b9e6..1f655b00 100644 --- a/LibationSearchEngine/SearchEngine.cs +++ b/LibationSearchEngine/SearchEngine.cs @@ -143,7 +143,9 @@ namespace LibationSearchEngine return authors.Intersect(narrators).Any(); } - private static bool isLiberated(Book book) => book.UserDefinedItem.BookStatus == LiberatedStatus.Liberated || AudibleFileStorage.Audio.Exists(book.AudibleProductId); + private static bool isLiberated(Book book) + => book.UserDefinedItem.BookStatus == LiberatedStatus.Liberated + || AudibleFileStorage.Audio.Exists(book.AudibleProductId); private static bool liberatedError(Book book) => book.UserDefinedItem.BookStatus == LiberatedStatus.Error; // use these common fields in the "all" default search field diff --git a/LibationWinForms/GridEntry.cs b/LibationWinForms/GridEntry.cs index 3d8c46ea..92b41699 100644 --- a/LibationWinForms/GridEntry.cs +++ b/LibationWinForms/GridEntry.cs @@ -26,15 +26,15 @@ namespace LibationWinForms public enum LiberatedState { NotDownloaded, PartialDownload, Liberated } [Browsable(false)] public LiberatedState Liberated_Status - => FileManager.AudibleFileStorage.Audio.Exists(book.AudibleProductId) ? LiberatedState.Liberated - : FileManager.AudibleFileStorage.AAXC.Exists(book.AudibleProductId) ? LiberatedState.PartialDownload + => ApplicationServices.TransitionalFileLocator.Audio_Exists(book.AudibleProductId) ? LiberatedState.Liberated + : ApplicationServices.TransitionalFileLocator.AAXC_Exists(book.AudibleProductId) ? LiberatedState.PartialDownload : LiberatedState.NotDownloaded; public enum PdfState { NoPdf, Downloaded, NotDownloaded } [Browsable(false)] public PdfState Pdf_Status => !book.Supplements.Any() ? PdfState.NoPdf - : FileManager.AudibleFileStorage.PDF.Exists(book.AudibleProductId) ? PdfState.Downloaded + : ApplicationServices.TransitionalFileLocator.PDF_Exists(book.AudibleProductId) ? PdfState.Downloaded : PdfState.NotDownloaded; // displayValues is what gets displayed diff --git a/LibationWinForms/ProductsGrid.cs b/LibationWinForms/ProductsGrid.cs index ad264170..ed400ed3 100644 --- a/LibationWinForms/ProductsGrid.cs +++ b/LibationWinForms/ProductsGrid.cs @@ -173,9 +173,9 @@ namespace LibationWinForms var productId = getGridEntry(e.RowIndex).GetBook().AudibleProductId; // liberated: open explorer to file - if (FileManager.AudibleFileStorage.Audio.Exists(productId)) + if (TransitionalFileLocator.Audio_Exists(productId)) { - var filePath = FileManager.AudibleFileStorage.Audio.GetPath(productId); + var filePath = TransitionalFileLocator.Audio_GetPath(productId); if (!Go.To.File(filePath)) MessageBox.Show($"File not found:\r\n{filePath}"); return;