diff --git a/ApplicationServices/LibraryCommands.cs b/ApplicationServices/LibraryCommands.cs index 52a8d3d2..96012f68 100644 --- a/ApplicationServices/LibraryCommands.cs +++ b/ApplicationServices/LibraryCommands.cs @@ -202,7 +202,7 @@ namespace ApplicationServices } } - public static int UpdateBook(LibraryBook libraryBook, LiberatedStatus liberatedStatus, string finalAudioPath) + public static int UpdateBook(LibraryBook libraryBook, LiberatedStatus liberatedStatus) { try { @@ -210,12 +210,11 @@ namespace ApplicationServices var udi = libraryBook.Book.UserDefinedItem; - if (udi.BookStatus == liberatedStatus && udi.BookLocation == finalAudioPath) + if (udi.BookStatus == liberatedStatus) return 0; // Attach() NoTracking entities before SaveChanges() udi.BookStatus = liberatedStatus; - udi.BookLocation = finalAudioPath; context.Attach(udi).State = Microsoft.EntityFrameworkCore.EntityState.Modified; var qtyChanges = context.SaveChanges(); if (qtyChanges > 0) diff --git a/ApplicationServices/LibraryExporter.cs b/ApplicationServices/LibraryExporter.cs index a2707fc9..22434d92 100644 --- a/ApplicationServices/LibraryExporter.cs +++ b/ApplicationServices/LibraryExporter.cs @@ -92,9 +92,6 @@ namespace ApplicationServices [Name("Book Liberation Status")] public string BookStatus { get; set; } - [Name("Book File Location")] - public string BookLocation { get; set; } - [Name("PDF Liberation Status")] public string PdfStatus { get; set; } } @@ -127,7 +124,6 @@ namespace ApplicationServices MyRatingStory = a.Book.UserDefinedItem.Rating.StoryRating, MyLibationTags = a.Book.UserDefinedItem.Tags, BookStatus = a.Book.UserDefinedItem.BookStatus.ToString(), - BookLocation = a.Book.UserDefinedItem.BookLocation, PdfStatus = a.Book.UserDefinedItem.PdfStatus.ToString() }).ToList(); } @@ -201,7 +197,6 @@ namespace ApplicationServices nameof (ExportDto.MyRatingStory), nameof (ExportDto.MyLibationTags), nameof (ExportDto.BookStatus), - nameof (ExportDto.BookLocation), nameof (ExportDto.PdfStatus) }; var col = 0; @@ -265,7 +260,6 @@ namespace ApplicationServices row.CreateCell(col++).SetCellValue(dto.MyLibationTags); row.CreateCell(col++).SetCellValue(dto.BookStatus); - row.CreateCell(col++).SetCellValue(dto.BookLocation); row.CreateCell(col++).SetCellValue(dto.PdfStatus); rowIndex++; diff --git a/ApplicationServices/TransitionalFileLocator.cs b/ApplicationServices/TransitionalFileLocator.cs deleted file mode 100644 index aabf6189..00000000 --- a/ApplicationServices/TransitionalFileLocator.cs +++ /dev/null @@ -1,21 +0,0 @@ -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(Book book) - { - var loc = book?.UserDefinedItem?.BookLocation ?? ""; - if (File.Exists(loc)) - return loc; - - return AudibleFileStorage.Audio.GetPath(book.AudibleProductId); - } - } -} diff --git a/DataLayer/EfClasses/UserDefinedItem.cs b/DataLayer/EfClasses/UserDefinedItem.cs index 97292fe5..4178a20e 100644 --- a/DataLayer/EfClasses/UserDefinedItem.cs +++ b/DataLayer/EfClasses/UserDefinedItem.cs @@ -94,9 +94,8 @@ namespace DataLayer => Rating.Update(overallRating, performanceRating, storyRating); #endregion - #region LiberatedStatuses and book file location + #region LiberatedStatuses public LiberatedStatus BookStatus { get; set; } - public string BookLocation { get; set; } public LiberatedStatus? PdfStatus { get; set; } #endregion diff --git a/DataLayer/Migrations/20210821012137_RemoveUdiBookLocation.Designer.cs b/DataLayer/Migrations/20210821012137_RemoveUdiBookLocation.Designer.cs new file mode 100644 index 00000000..84b5a683 --- /dev/null +++ b/DataLayer/Migrations/20210821012137_RemoveUdiBookLocation.Designer.cs @@ -0,0 +1,387 @@ +// +using System; +using DataLayer; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace DataLayer.Migrations +{ + [DbContext(typeof(LibationContext))] + [Migration("20210821012137_RemoveUdiBookLocation")] + partial class RemoveUdiBookLocation + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "5.0.5"); + + modelBuilder.Entity("DataLayer.Book", b => + { + b.Property("BookId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudibleProductId") + .HasColumnType("TEXT"); + + b.Property("CategoryId") + .HasColumnType("INTEGER"); + + b.Property("DatePublished") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsAbridged") + .HasColumnType("INTEGER"); + + b.Property("LengthInMinutes") + .HasColumnType("INTEGER"); + + b.Property("Locale") + .HasColumnType("TEXT"); + + b.Property("PictureId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("BookId"); + + b.HasIndex("AudibleProductId"); + + b.HasIndex("CategoryId"); + + b.ToTable("Books"); + }); + + modelBuilder.Entity("DataLayer.BookContributor", b => + { + b.Property("BookId") + .HasColumnType("INTEGER"); + + b.Property("ContributorId") + .HasColumnType("INTEGER"); + + b.Property("Role") + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.HasKey("BookId", "ContributorId", "Role"); + + b.HasIndex("BookId"); + + b.HasIndex("ContributorId"); + + b.ToTable("BookContributor"); + }); + + modelBuilder.Entity("DataLayer.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudibleCategoryId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("ParentCategoryCategoryId") + .HasColumnType("INTEGER"); + + b.HasKey("CategoryId"); + + b.HasIndex("AudibleCategoryId"); + + b.HasIndex("ParentCategoryCategoryId"); + + b.ToTable("Categories"); + + b.HasData( + new + { + CategoryId = -1, + AudibleCategoryId = "", + Name = "" + }); + }); + + modelBuilder.Entity("DataLayer.Contributor", b => + { + b.Property("ContributorId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudibleContributorId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("ContributorId"); + + b.HasIndex("Name"); + + b.ToTable("Contributors"); + + b.HasData( + new + { + ContributorId = -1, + Name = "" + }); + }); + + modelBuilder.Entity("DataLayer.LibraryBook", b => + { + b.Property("BookId") + .HasColumnType("INTEGER"); + + b.Property("Account") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.HasKey("BookId"); + + b.ToTable("Library"); + }); + + modelBuilder.Entity("DataLayer.Series", b => + { + b.Property("SeriesId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudibleSeriesId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("SeriesId"); + + b.HasIndex("AudibleSeriesId"); + + b.ToTable("Series"); + }); + + modelBuilder.Entity("DataLayer.SeriesBook", b => + { + b.Property("SeriesId") + .HasColumnType("INTEGER"); + + b.Property("BookId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("REAL"); + + b.HasKey("SeriesId", "BookId"); + + b.HasIndex("BookId"); + + b.HasIndex("SeriesId"); + + b.ToTable("SeriesBook"); + }); + + modelBuilder.Entity("DataLayer.Book", b => + { + b.HasOne("DataLayer.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DataLayer.Rating", "Rating", b1 => + { + b1.Property("BookId") + .HasColumnType("INTEGER"); + + b1.Property("OverallRating") + .HasColumnType("REAL"); + + b1.Property("PerformanceRating") + .HasColumnType("REAL"); + + b1.Property("StoryRating") + .HasColumnType("REAL"); + + b1.HasKey("BookId"); + + b1.ToTable("Books"); + + b1.WithOwner() + .HasForeignKey("BookId"); + }); + + b.OwnsMany("DataLayer.Supplement", "Supplements", b1 => + { + b1.Property("SupplementId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b1.Property("BookId") + .HasColumnType("INTEGER"); + + b1.Property("Url") + .HasColumnType("TEXT"); + + b1.HasKey("SupplementId"); + + b1.HasIndex("BookId"); + + b1.ToTable("Supplement"); + + b1.WithOwner("Book") + .HasForeignKey("BookId"); + + b1.Navigation("Book"); + }); + + b.OwnsOne("DataLayer.UserDefinedItem", "UserDefinedItem", b1 => + { + b1.Property("BookId") + .HasColumnType("INTEGER"); + + b1.Property("BookStatus") + .HasColumnType("INTEGER"); + + b1.Property("PdfStatus") + .HasColumnType("INTEGER"); + + b1.Property("Tags") + .HasColumnType("TEXT"); + + b1.HasKey("BookId"); + + b1.ToTable("UserDefinedItem"); + + b1.WithOwner("Book") + .HasForeignKey("BookId"); + + b1.OwnsOne("DataLayer.Rating", "Rating", b2 => + { + b2.Property("UserDefinedItemBookId") + .HasColumnType("INTEGER"); + + b2.Property("OverallRating") + .HasColumnType("REAL"); + + b2.Property("PerformanceRating") + .HasColumnType("REAL"); + + b2.Property("StoryRating") + .HasColumnType("REAL"); + + b2.HasKey("UserDefinedItemBookId"); + + b2.ToTable("UserDefinedItem"); + + b2.WithOwner() + .HasForeignKey("UserDefinedItemBookId"); + }); + + b1.Navigation("Book"); + + b1.Navigation("Rating"); + }); + + b.Navigation("Category"); + + b.Navigation("Rating"); + + b.Navigation("Supplements"); + + b.Navigation("UserDefinedItem"); + }); + + modelBuilder.Entity("DataLayer.BookContributor", b => + { + b.HasOne("DataLayer.Book", "Book") + .WithMany("ContributorsLink") + .HasForeignKey("BookId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DataLayer.Contributor", "Contributor") + .WithMany("BooksLink") + .HasForeignKey("ContributorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Book"); + + b.Navigation("Contributor"); + }); + + modelBuilder.Entity("DataLayer.Category", b => + { + b.HasOne("DataLayer.Category", "ParentCategory") + .WithMany() + .HasForeignKey("ParentCategoryCategoryId"); + + b.Navigation("ParentCategory"); + }); + + modelBuilder.Entity("DataLayer.LibraryBook", b => + { + b.HasOne("DataLayer.Book", "Book") + .WithOne() + .HasForeignKey("DataLayer.LibraryBook", "BookId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Book"); + }); + + modelBuilder.Entity("DataLayer.SeriesBook", b => + { + b.HasOne("DataLayer.Book", "Book") + .WithMany("SeriesLink") + .HasForeignKey("BookId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DataLayer.Series", "Series") + .WithMany("BooksLink") + .HasForeignKey("SeriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Book"); + + b.Navigation("Series"); + }); + + modelBuilder.Entity("DataLayer.Book", b => + { + b.Navigation("ContributorsLink"); + + b.Navigation("SeriesLink"); + }); + + modelBuilder.Entity("DataLayer.Contributor", b => + { + b.Navigation("BooksLink"); + }); + + modelBuilder.Entity("DataLayer.Series", b => + { + b.Navigation("BooksLink"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DataLayer/Migrations/20210821012137_RemoveUdiBookLocation.cs b/DataLayer/Migrations/20210821012137_RemoveUdiBookLocation.cs new file mode 100644 index 00000000..3dd74a30 --- /dev/null +++ b/DataLayer/Migrations/20210821012137_RemoveUdiBookLocation.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DataLayer.Migrations +{ + public partial class RemoveUdiBookLocation : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "BookLocation", + table: "UserDefinedItem"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "BookLocation", + table: "UserDefinedItem", + type: "TEXT", + nullable: true); + } + } +} diff --git a/DataLayer/Migrations/LibationContextModelSnapshot.cs b/DataLayer/Migrations/LibationContextModelSnapshot.cs index 6ecd7a8a..73814c05 100644 --- a/DataLayer/Migrations/LibationContextModelSnapshot.cs +++ b/DataLayer/Migrations/LibationContextModelSnapshot.cs @@ -253,9 +253,6 @@ namespace DataLayer.Migrations b1.Property("BookId") .HasColumnType("INTEGER"); - b1.Property("BookLocation") - .HasColumnType("TEXT"); - b1.Property("BookStatus") .HasColumnType("INTEGER"); diff --git a/FileLiberator/ConvertToMp3.cs b/FileLiberator/ConvertToMp3.cs index 6c682b20..a7df973c 100644 --- a/FileLiberator/ConvertToMp3.cs +++ b/FileLiberator/ConvertToMp3.cs @@ -37,7 +37,7 @@ namespace FileLiberator public bool Validate(LibraryBook libraryBook) { - var path = ApplicationServices.TransitionalFileLocator.Audio_GetPath(libraryBook.Book); + var path = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); return path?.ToLower()?.EndsWith(".m4b") == true && !File.Exists(Mp3FileName(path)); } @@ -49,7 +49,7 @@ namespace FileLiberator try { - var m4bPath = ApplicationServices.TransitionalFileLocator.Audio_GetPath(libraryBook.Book); + var m4bPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); m4bBook = new Mp4File(m4bPath, FileAccess.Read); m4bBook.ConversionProgressUpdate += M4bBook_ConversionProgressUpdate; diff --git a/FileLiberator/DownloadDecryptBook.cs b/FileLiberator/DownloadDecryptBook.cs index 1dfcf3c2..e0d960ef 100644 --- a/FileLiberator/DownloadDecryptBook.cs +++ b/FileLiberator/DownloadDecryptBook.cs @@ -53,7 +53,7 @@ namespace FileLiberator return new StatusHandler { "Cannot find final audio file after decryption" }; // only need to update if success. if failure, it will remain at 0 == NotLiberated - ApplicationServices.LibraryCommands.UpdateBook(libraryBook, LiberatedStatus.Liberated, outputAudioFilename); + ApplicationServices.LibraryCommands.UpdateBook(libraryBook, LiberatedStatus.Liberated); return new StatusHandler(); } diff --git a/FileLiberator/DownloadPdf.cs b/FileLiberator/DownloadPdf.cs index 809775d8..356cb13a 100644 --- a/FileLiberator/DownloadPdf.cs +++ b/FileLiberator/DownloadPdf.cs @@ -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(ApplicationServices.TransitionalFileLocator.Audio_GetPath(libraryBook.Book)); + var existingPath = Path.GetDirectoryName(AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId)); var file = getdownloadUrl(libraryBook); if (existingPath != null) diff --git a/FileManager/AudibleFileStorage.cs b/FileManager/AudibleFileStorage.cs index 1c20b78c..b88d7ca7 100644 --- a/FileManager/AudibleFileStorage.cs +++ b/FileManager/AudibleFileStorage.cs @@ -17,12 +17,14 @@ namespace FileManager public static string DownloadsInProgress => Directory.CreateDirectory(Path.Combine(Configuration.Instance.InProgress, "DownloadsInProgress")).FullName; public static string DecryptInProgress => Directory.CreateDirectory(Path.Combine(Configuration.Instance.InProgress, "DecryptInProgress")).FullName; + public static string PdfStorageDirectory => BooksDirectory; + + private static AaxcFileStorage AAXC { get; } = new AaxcFileStorage(); public static bool AaxcExists(string productId) => AAXC.Exists(productId); #region static public static AudioFileStorage Audio { get; } = new AudioFileStorage(); - public static AaxcFileStorage AAXC { get; } = new AaxcFileStorage(); public static string BooksDirectory { @@ -50,26 +52,25 @@ namespace FileManager BookDirectoryFiles ??= new BackgroundFileSystem(BooksDirectory, "*.*", SearchOption.AllDirectories); } - public string GetPath(string productId) + protected string GetFilePath(string productId) { var cachedFile = FilePathCache.GetPath(productId, FileType); if (cachedFile != null) return cachedFile; - string storageDir = StorageDirectory; string regexPattern = $@"{productId}.*?\.({extAggr})$"; string firstOrNull; - if (storageDir == BooksDirectory) + if (StorageDirectory == BooksDirectory) { //If user changed the BooksDirectory, reinitialize. - if (storageDir != BookDirectoryFiles.RootDirectory) + if (StorageDirectory != BookDirectoryFiles.RootDirectory) { lock (BookDirectoryFiles) { - if (storageDir != BookDirectoryFiles.RootDirectory) + if (StorageDirectory != BookDirectoryFiles.RootDirectory) { - BookDirectoryFiles = new BackgroundFileSystem(storageDir, "*.*", SearchOption.AllDirectories); + BookDirectoryFiles = new BackgroundFileSystem(StorageDirectory, "*.*", SearchOption.AllDirectories); } } } @@ -80,7 +81,7 @@ namespace FileManager { firstOrNull = Directory - .EnumerateFiles(storageDir, "*.*", SearchOption.AllDirectories) + .EnumerateFiles(StorageDirectory, "*.*", SearchOption.AllDirectories) .FirstOrDefault(s => Regex.IsMatch(s, regexPattern, RegexOptions.IgnoreCase)); } @@ -133,6 +134,8 @@ namespace FileManager public bool IsFileTypeMatch(FileInfo fileInfo) => extensions_noDots.ContainsInsensative(fileInfo.Extension.Trim('.')); + + public string GetPath(string productId) => GetFilePath(productId); } public class AaxcFileStorage : AudibleFileStorage @@ -152,6 +155,6 @@ namespace FileManager /// - a directory name has the product id and an audio file is immediately inside /// - any audio filename contains the product id /// - public bool Exists(string productId) => GetPath(productId) != null; + public bool Exists(string productId) => GetFilePath(productId) != null; } } diff --git a/LibationLauncher/LibationLauncher.csproj b/LibationLauncher/LibationLauncher.csproj index a9921d8b..bc29d580 100644 --- a/LibationLauncher/LibationLauncher.csproj +++ b/LibationLauncher/LibationLauncher.csproj @@ -13,7 +13,7 @@ win-x64 - 5.5.1.11 + 5.5.1.20 diff --git a/LibationLauncher/Program.cs b/LibationLauncher/Program.cs index 07897927..93aeaed8 100644 --- a/LibationLauncher/Program.cs +++ b/LibationLauncher/Program.cs @@ -274,10 +274,7 @@ namespace LibationLauncher book.UserDefinedItem.PdfStatus = LiberatedStatus.Liberated; if (fileType == FileType.Audio) - { book.UserDefinedItem.BookStatus = LiberatedStatus.Liberated; - book.UserDefinedItem.BookLocation = path; - } } context.SaveChanges(); diff --git a/LibationWinForms/BookLiberation/ProcessorAutomationController.cs b/LibationWinForms/BookLiberation/ProcessorAutomationController.cs index f30618ae..9eff3348 100644 --- a/LibationWinForms/BookLiberation/ProcessorAutomationController.cs +++ b/LibationWinForms/BookLiberation/ProcessorAutomationController.cs @@ -246,7 +246,7 @@ $@" Title: {libraryBook.Book.Title} if (dialogResult == CreateSkipFileResult) { - ApplicationServices.LibraryCommands.UpdateBook(libraryBook, LiberatedStatus.Error, null); + ApplicationServices.LibraryCommands.UpdateBook(libraryBook, LiberatedStatus.Error); var path = FileManager.AudibleFileStorage.Audio.CreateSkipFile(libraryBook.Book.Title, libraryBook.Book.AudibleProductId, logMessage); LogMe.Info($@" Created new 'skip' file diff --git a/LibationWinForms/ProductsGrid.cs b/LibationWinForms/ProductsGrid.cs index 1c156020..8e37cf8c 100644 --- a/LibationWinForms/ProductsGrid.cs +++ b/LibationWinForms/ProductsGrid.cs @@ -79,7 +79,7 @@ namespace LibationWinForms // liberated: open explorer to file if (libraryBook.Book.Audio_Exists) { - var filePath = TransitionalFileLocator.Audio_GetPath(libraryBook.Book); + var filePath = FileManager.AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); if (!Go.To.File(filePath)) MessageBox.Show($"File not found:\r\n{filePath}"); return;