diff --git a/AppScaffolding/AppScaffolding.csproj b/AppScaffolding/AppScaffolding.csproj index 14f95f36..fc1c1dc7 100644 --- a/AppScaffolding/AppScaffolding.csproj +++ b/AppScaffolding/AppScaffolding.csproj @@ -3,7 +3,7 @@ net5.0 - 6.2.6.1 + 6.2.6.4 diff --git a/FileLiberator/DownloadDecryptBook.cs b/FileLiberator/DownloadDecryptBook.cs index e8690b71..cf665dfe 100644 --- a/FileLiberator/DownloadDecryptBook.cs +++ b/FileLiberator/DownloadDecryptBook.cs @@ -45,10 +45,20 @@ namespace FileLiberator if (libraryBook.Book.Audio_Exists) return new StatusHandler { "Cannot find decrypt. Final audio file already exists" }; - FilePathCache.Inserted += FilePathCache_Inserted; - FilePathCache.Removed += FilePathCache_Removed; + bool success = false; + try + { + FilePathCache.Inserted += FilePathCache_Inserted; + FilePathCache.Removed += FilePathCache_Removed; + + success = await downloadAudiobookAsync(libraryBook); + } + finally + { + FilePathCache.Inserted -= FilePathCache_Inserted; + FilePathCache.Removed -= FilePathCache_Removed; + } - var success = await downloadAudiobookAsync(libraryBook); // decrypt failed if (!success) @@ -67,9 +77,6 @@ namespace FileLiberator } finally { - FilePathCache.Inserted -= FilePathCache_Inserted; - FilePathCache.Removed -= FilePathCache_Removed; - OnCompleted(libraryBook); } } @@ -109,7 +116,7 @@ namespace FileLiberator audiobookDlLic.ChapterInfo.AddChapter(chap.Title, TimeSpan.FromMilliseconds(chap.LengthMs)); } - var outFileName = Path.Combine(AudibleFileStorage.DecryptInProgressDirectory, $"{PathLib.ToPathSafeString(libraryBook.Book.Title)} [{libraryBook.Book.AudibleProductId}].{outputFormat.ToString().ToLower()}"); + var outFileName = FileUtility.GetValidFilename(AudibleFileStorage.DecryptInProgressDirectory, libraryBook.Book.Title, outputFormat.ToString().ToLower(), libraryBook.Book.AudibleProductId); var cacheDir = AudibleFileStorage.DownloadsInProgressDirectory; @@ -170,10 +177,16 @@ namespace FileLiberator /// True if audiobook file(s) were successfully created and can be located on disk. Else false. private static bool moveFilesToBooksDir(Book book, List entries) { - // create final directory. move each file into it. MOVE AUDIO FILE LAST - // new dir: safetitle_limit50char + " [" + productId + "]" - // TODO make this method handle multiple audio files or a single audio file. - var destinationDir = AudibleFileStorage.Audio.GetDestDir(book.Title, book.AudibleProductId); + // create final directory. move each file into it + var title = book.Title; + var asin = book.AudibleProductId; + // to prevent the paths from getting too long, we don't need after the 1st ":" for the folder + var underscoreIndex = title.IndexOf(':'); + var titleDir + = underscoreIndex < 4 + ? title + : title.Substring(0, underscoreIndex); + var destinationDir = FileUtility.GetValidFilename(AudibleFileStorage.BooksDirectory, titleDir, null, asin); Directory.CreateDirectory(destinationDir); var music = entries.FirstOrDefault(f => f.FileType == FileType.Audio); @@ -183,18 +196,15 @@ namespace FileLiberator var musicFileExt = Path.GetExtension(music.Path).Trim('.'); - // audio filename: safetitle_limit50char + " [" + productId + "]." + audio_ext var audioFileName = FileUtility.GetValidFilename(destinationDir, book.Title, musicFileExt, book.AudibleProductId); foreach (var entry in entries) { var fileInfo = new FileInfo(entry.Path); - var isAudio = entry.FileType == FileType.Audio; var dest - = isAudio + = entry.FileType == FileType.Audio ? Path.Join(destinationDir, fileInfo.Name) - // non-audio filename: safetitle_limit50char + " [" + productId + "][" + audio_ext + "]." + non_audio_ext : FileUtility.GetValidFilename(destinationDir, book.Title, fileInfo.Extension, book.AudibleProductId, musicFileExt); if (Path.GetExtension(dest).Trim('.').ToLower() == "cue") diff --git a/FileManager.Tests/FileManager.Tests.csproj b/FileManager.Tests/FileManager.Tests.csproj new file mode 100644 index 00000000..25bece55 --- /dev/null +++ b/FileManager.Tests/FileManager.Tests.csproj @@ -0,0 +1,20 @@ + + + + net5.0 + + false + + + + + + + + + + + + + + diff --git a/FileManager.Tests/FileUtilityTests.cs b/FileManager.Tests/FileUtilityTests.cs new file mode 100644 index 00000000..cce74f3d --- /dev/null +++ b/FileManager.Tests/FileUtilityTests.cs @@ -0,0 +1,13 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace FileUtilityTests +{ + [TestClass] + public class GetValidFilename + { + [TestMethod] + public void TestMethod1() + { + } + } +} diff --git a/FileManager/FileUtility.cs b/FileManager/FileUtility.cs index e489bd9e..7e9fa9ea 100644 --- a/FileManager/FileUtility.cs +++ b/FileManager/FileUtility.cs @@ -1,10 +1,13 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; namespace FileManager { public static class FileUtility { +//public static string GetValidFilename(string template, Dictionary parameters) { } public static string GetValidFilename(string dirFullPath, string filename, string extension, params string[] metadataSuffixes) { if (string.IsNullOrWhiteSpace(dirFullPath)) @@ -26,7 +29,7 @@ namespace FileManager if (metadataSuffixes != null && metadataSuffixes.Length > 0) filename += " [" + string.Join("][", metadataSuffixes) + "]"; - // this method may also be used for directory names, so no guarantee of extension + // extension is null when this method is used for directory names if (!string.IsNullOrWhiteSpace(extension)) extension = '.' + extension.Trim('.'); diff --git a/Libation.sln b/Libation.sln index c926a6b1..12810992 100644 --- a/Libation.sln +++ b/Libation.sln @@ -58,6 +58,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppScaffolding", "AppScaffo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileManager", "FileManager\FileManager.csproj", "{E86014F9-E4B3-4CD4-A210-2B3DB571DD86}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileManager.Tests", "FileManager.Tests\FileManager.Tests.csproj", "{3B58450C-FBDA-4D48-8418-A3C750596D7D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -124,6 +126,10 @@ Global {E86014F9-E4B3-4CD4-A210-2B3DB571DD86}.Debug|Any CPU.Build.0 = Debug|Any CPU {E86014F9-E4B3-4CD4-A210-2B3DB571DD86}.Release|Any CPU.ActiveCfg = Release|Any CPU {E86014F9-E4B3-4CD4-A210-2B3DB571DD86}.Release|Any CPU.Build.0 = Release|Any CPU + {3B58450C-FBDA-4D48-8418-A3C750596D7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B58450C-FBDA-4D48-8418-A3C750596D7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B58450C-FBDA-4D48-8418-A3C750596D7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B58450C-FBDA-4D48-8418-A3C750596D7D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -144,6 +150,7 @@ Global {428163C3-D558-4914-B570-A92069521877} = {8679CAC8-9164-4007-BDD2-F004810EDA14} {595E7C4D-506D-486D-98B7-5FDDF398D033} = {8679CAC8-9164-4007-BDD2-F004810EDA14} {E86014F9-E4B3-4CD4-A210-2B3DB571DD86} = {43E3ACB3-E0BC-4370-8DBB-E3720C8C8FD1} + {3B58450C-FBDA-4D48-8418-A3C750596D7D} = {67E66E82-5532-4440-AFB3-9FB1DF9DEF53} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {615E00ED-BAEF-4E8E-A92A-9B82D87942A9} diff --git a/LibationFileManager/AudibleFileStorage.cs b/LibationFileManager/AudibleFileStorage.cs index e3aceb26..6182eed1 100644 --- a/LibationFileManager/AudibleFileStorage.cs +++ b/LibationFileManager/AudibleFileStorage.cs @@ -87,18 +87,6 @@ namespace LibationFileManager public void Refresh() => BookDirectoryFiles.RefreshFiles(); - public string GetDestDir(string title, string asin) - { - // to prevent the paths from getting too long, we don't need after the 1st ":" for the folder - var underscoreIndex = title.IndexOf(':'); - var titleDir - = underscoreIndex < 4 - ? title - : title.Substring(0, underscoreIndex); - var finalDir = FileUtility.GetValidFilename(BooksDirectory, titleDir, null, asin); - return finalDir; - } - public string GetPath(string productId) => GetFilePath(productId); } diff --git a/LibationFileManager/FilePathCache.cs b/LibationFileManager/FilePathCache.cs index 6f0ffb59..43b75bbc 100644 --- a/LibationFileManager/FilePathCache.cs +++ b/LibationFileManager/FilePathCache.cs @@ -39,7 +39,7 @@ namespace LibationFileManager public static string GetFirstPath(string id, FileType type) => getEntries(entry => entry.Id == id && entry.FileType == type) - .FirstOrDefault() + ?.FirstOrDefault() ?.Path; private static List getEntries(Func predicate) diff --git a/LibationWinForms/BookLiberation/AudioConvertForm.cs b/LibationWinForms/BookLiberation/AudioConvertForm.cs index 7c5c9e9d..2fe1c398 100644 --- a/LibationWinForms/BookLiberation/AudioConvertForm.cs +++ b/LibationWinForms/BookLiberation/AudioConvertForm.cs @@ -1,6 +1,6 @@ -using DataLayer; -using FileManager; -using System; +using System; +using DataLayer; +using LibationFileManager; namespace LibationWinForms.BookLiberation { diff --git a/LibationWinForms/BookLiberation/AudioDecodeForm.cs b/LibationWinForms/BookLiberation/AudioDecodeForm.cs index 3890eb01..a2228ac3 100644 --- a/LibationWinForms/BookLiberation/AudioDecodeForm.cs +++ b/LibationWinForms/BookLiberation/AudioDecodeForm.cs @@ -2,6 +2,7 @@ using DataLayer; using Dinah.Core.Net.Http; using Dinah.Core.Threading; +using LibationFileManager; using LibationWinForms.BookLiberation.BaseForms; namespace LibationWinForms.BookLiberation @@ -23,20 +24,20 @@ namespace LibationWinForms.BookLiberation { base.Processable_Begin(sender, libraryBook); - GetCoverArtDelegate = () => FileManager.PictureStorage.GetPictureSynchronously( - new FileManager.PictureDefinition( + GetCoverArtDelegate = () => PictureStorage.GetPictureSynchronously( + new PictureDefinition( libraryBook.Book.PictureId, - FileManager.PictureSize._500x500)); + PictureSize._500x500)); //Set default values from library AudioDecodable_TitleDiscovered(sender, libraryBook.Book.Title); AudioDecodable_AuthorsDiscovered(sender, string.Join(", ", libraryBook.Book.Authors)); AudioDecodable_NarratorsDiscovered(sender, string.Join(", ", libraryBook.Book.NarratorNames)); AudioDecodable_CoverImageDiscovered(sender, - FileManager.PictureStorage.GetPicture( - new FileManager.PictureDefinition( + PictureStorage.GetPicture( + new PictureDefinition( libraryBook.Book.PictureId, - FileManager.PictureSize._80x80)).bytes); + PictureSize._80x80)).bytes); } #endregion diff --git a/LibationWinForms/BookLiberation/AudioDecryptForm.cs b/LibationWinForms/BookLiberation/AudioDecryptForm.cs index 15570b64..e7af1981 100644 --- a/LibationWinForms/BookLiberation/AudioDecryptForm.cs +++ b/LibationWinForms/BookLiberation/AudioDecryptForm.cs @@ -1,6 +1,6 @@ -using DataLayer; -using FileManager; -using System; +using System; +using DataLayer; +using LibationFileManager; namespace LibationWinForms.BookLiberation { diff --git a/LibationWinForms/BookLiberation/ProcessorAutomationController.cs b/LibationWinForms/BookLiberation/ProcessorAutomationController.cs index 339f4c31..064b012e 100644 --- a/LibationWinForms/BookLiberation/ProcessorAutomationController.cs +++ b/LibationWinForms/BookLiberation/ProcessorAutomationController.cs @@ -1,11 +1,11 @@ -using DataLayer; -using Dinah.Core; -using FileLiberator; -using LibationWinForms.BookLiberation.BaseForms; -using System; -using System.Linq; +using System; using System.Threading.Tasks; using System.Windows.Forms; +using DataLayer; +using Dinah.Core; +using FileLiberator; +using LibationFileManager; +using LibationWinForms.BookLiberation.BaseForms; namespace LibationWinForms.BookLiberation { @@ -218,12 +218,12 @@ namespace LibationWinForms.BookLiberation { LogMe.Error("ERROR. All books have not been processed. Most recent book: processing failed"); - DialogResult? dialogResult = FileManager.Configuration.Instance.BadBook switch + DialogResult? dialogResult = Configuration.Instance.BadBook switch { - FileManager.Configuration.BadBookAction.Abort => DialogResult.Abort, - FileManager.Configuration.BadBookAction.Retry => DialogResult.Retry, - FileManager.Configuration.BadBookAction.Ignore => DialogResult.Ignore, - FileManager.Configuration.BadBookAction.Ask => null, + Configuration.BadBookAction.Abort => DialogResult.Abort, + Configuration.BadBookAction.Retry => DialogResult.Retry, + Configuration.BadBookAction.Ignore => DialogResult.Ignore, + Configuration.BadBookAction.Ask => null, _ => null }; diff --git a/LibationWinForms/Dialogs/BookDetailsDialog.cs b/LibationWinForms/Dialogs/BookDetailsDialog.cs index 94391926..3e20b74b 100644 --- a/LibationWinForms/Dialogs/BookDetailsDialog.cs +++ b/LibationWinForms/Dialogs/BookDetailsDialog.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Windows.Forms; using DataLayer; using Dinah.Core; +using LibationFileManager; namespace LibationWinForms.Dialogs { @@ -39,7 +40,7 @@ namespace LibationWinForms.Dialogs { this.Text = Book.Title; - (var isDefault, var picture) = FileManager.PictureStorage.GetPicture(new FileManager.PictureDefinition(Book.PictureId, FileManager.PictureSize._80x80)); + (_, var picture) = PictureStorage.GetPicture(new PictureDefinition(Book.PictureId, PictureSize._80x80)); this.coverPb.Image = Dinah.Core.Drawing.ImageReader.ToImage(picture); var t = @$" diff --git a/LibationWinForms/Dialogs/EditQuickFilters.cs b/LibationWinForms/Dialogs/EditQuickFilters.cs index 999e9b2f..9b504c72 100644 --- a/LibationWinForms/Dialogs/EditQuickFilters.cs +++ b/LibationWinForms/Dialogs/EditQuickFilters.cs @@ -1,7 +1,7 @@ -using FileManager; -using System; +using System; using System.Linq; using System.Windows.Forms; +using LibationFileManager; namespace LibationWinForms.Dialogs { diff --git a/LibationWinForms/Dialogs/LibationFilesDialog.cs b/LibationWinForms/Dialogs/LibationFilesDialog.cs index f827beb8..a222a878 100644 --- a/LibationWinForms/Dialogs/LibationFilesDialog.cs +++ b/LibationWinForms/Dialogs/LibationFilesDialog.cs @@ -1,7 +1,6 @@ -using FileManager; -using System; -using System.Linq; +using System; using System.Windows.Forms; +using LibationFileManager; namespace LibationWinForms.Dialogs { diff --git a/LibationWinForms/Dialogs/MessageBoxAlertAdminDialog.cs b/LibationWinForms/Dialogs/MessageBoxAlertAdminDialog.cs index 6bb97d7c..6630d747 100644 --- a/LibationWinForms/Dialogs/MessageBoxAlertAdminDialog.cs +++ b/LibationWinForms/Dialogs/MessageBoxAlertAdminDialog.cs @@ -50,7 +50,7 @@ namespace LibationWinForms.Dialogs string dir = ""; try { - dir = FileManager.Configuration.Instance.LibationFiles; + dir = LibationFileManager.Configuration.Instance.LibationFiles; } catch { } diff --git a/LibationWinForms/Dialogs/RemoveBooksDialog.cs b/LibationWinForms/Dialogs/RemoveBooksDialog.cs index 7c504414..538a5925 100644 --- a/LibationWinForms/Dialogs/RemoveBooksDialog.cs +++ b/LibationWinForms/Dialogs/RemoveBooksDialog.cs @@ -1,8 +1,8 @@ using ApplicationServices; using DataLayer; using Dinah.Core.DataBinding; -using FileManager; using InternalUtilities; +using LibationFileManager; using LibationWinForms.Login; using System; using System.Collections; diff --git a/LibationWinForms/Form1.cs b/LibationWinForms/Form1.cs index b02257bb..a554e26d 100644 --- a/LibationWinForms/Form1.cs +++ b/LibationWinForms/Form1.cs @@ -6,8 +6,8 @@ using ApplicationServices; using Dinah.Core; using Dinah.Core.Drawing; using Dinah.Core.Threading; -using FileManager; using InternalUtilities; +using LibationFileManager; using LibationWinForms.Dialogs; namespace LibationWinForms diff --git a/LibationWinForms/ProductsGrid.cs b/LibationWinForms/ProductsGrid.cs index 9fcfe145..1154db8f 100644 --- a/LibationWinForms/ProductsGrid.cs +++ b/LibationWinForms/ProductsGrid.cs @@ -78,7 +78,7 @@ namespace LibationWinForms // liberated: open explorer to file if (libraryBook.Book.Audio_Exists) { - var filePath = FileManager.AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); + var filePath = LibationFileManager.AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId); if (!Go.To.File(filePath)) { var suffix = string.IsNullOrWhiteSpace(filePath) ? "" : $":\r\n{filePath}";