FileManager: separate generic from Libation-specific

This commit is contained in:
Robert McRackan 2021-10-11 16:06:50 -04:00
parent 1de7edd9df
commit c43e03b228
37 changed files with 87 additions and 76 deletions

View File

@ -12,7 +12,6 @@ namespace AaxDecrypter
{
public class AaxcDownloadConverter : AudiobookDownloadBase
{
const int MAX_FILENAME_LENGTH = 255;
private static readonly TimeSpan minChapterLength = TimeSpan.FromSeconds(3);
protected override StepSequence Steps { get; }
@ -207,9 +206,10 @@ That naming may not be desirable for everyone, but it's an easy change to instea
});
}
// return. cache name for event call at end of processing
private string GetMultipartFileName(int chapterCount, int chaptersTotal, string chapterTitle)
{
const int MAX_FILENAME_LENGTH = 255;
// 1-9 => 1-9
// 10-99 => 01-99
// 100-999 => 001-999

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Version>6.2.5.0</Version>
<Version>6.2.6.1</Version>
</PropertyGroup>
<ItemGroup>

View File

@ -6,8 +6,8 @@ using System.Reflection;
using Dinah.Core;
using Dinah.Core.IO;
using Dinah.Core.Logging;
using FileManager;
using InternalUtilities;
using LibationFileManager;
using Newtonsoft.Json.Linq;
using Serilog;

View File

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using DataLayer;
using FileManager;
using LibationFileManager;
namespace ApplicationServices
{

View File

@ -7,6 +7,7 @@ using DataLayer;
using Dinah.Core;
using DtoImporterService;
using InternalUtilities;
using LibationFileManager;
using Serilog;
using static DtoImporterService.PerfLogger;
@ -43,7 +44,7 @@ namespace ApplicationServices
}
catch (AudibleApi.Authentication.LoginFailedException lfEx)
{
lfEx.SaveFiles(FileManager.Configuration.Instance.LibationFiles);
lfEx.SaveFiles(Configuration.Instance.LibationFiles);
// nuget Serilog.Exceptions would automatically log custom properties
// However, it comes with a scary warning when used with EntityFrameworkCore which I'm not yet ready to implement:
@ -98,7 +99,7 @@ namespace ApplicationServices
}
catch (AudibleApi.Authentication.LoginFailedException lfEx)
{
lfEx.SaveFiles(FileManager.Configuration.Instance.LibationFiles);
lfEx.SaveFiles(Configuration.Instance.LibationFiles);
// nuget Serilog.Exceptions would automatically log custom properties
// However, it comes with a scary warning when used with EntityFrameworkCore which I'm not yet ready to implement:
@ -155,7 +156,7 @@ namespace ApplicationServices
logTime($"pre scanAccountAsync {account.AccountName}");
var dtoItems = await apiExtended.GetLibraryValidatedAsync(libraryResponseGroups, FileManager.Configuration.Instance.ImportEpisodes);
var dtoItems = await apiExtended.GetLibraryValidatedAsync(libraryResponseGroups, Configuration.Instance.ImportEpisodes);
logTime($"post scanAccountAsync {account.AccountName} qty: {dtoItems.Count}");
@ -244,7 +245,7 @@ namespace ApplicationServices
// must be here instead of in db layer due to AaxcExists
public static LiberatedStatus Liberated_Status(Book book)
=> book.Audio_Exists ? book.UserDefinedItem.BookStatus
: FileManager.AudibleFileStorage.AaxcExists(book.AudibleProductId) ? LiberatedStatus.PartialDownload
: AudibleFileStorage.AaxcExists(book.AudibleProductId) ? LiberatedStatus.PartialDownload
: LiberatedStatus.NotLiberated;
// exists here for feature predictability. It makes sense for this to be where Liberated_Status is

View File

@ -25,7 +25,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FileManager\FileManager.csproj" />
<ProjectReference Include="..\LibationFileManager\LibationFileManager.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -33,7 +33,7 @@ namespace DataLayer
// import previously saved tags
ArgumentValidator.EnsureNotNullOrWhiteSpace(book.AudibleProductId, nameof(book.AudibleProductId));
Tags = FileManager.TagsPersistence.GetTags(book.AudibleProductId);
Tags = LibationFileManager.TagsPersistence.GetTags(book.AudibleProductId);
}
#region Tags

View File

@ -24,7 +24,7 @@ namespace DataLayer
.Select(t => (t.Book.AudibleProductId, t.Tags))
.ToList();
FileManager.TagsPersistence.Save(tagsCollection);
LibationFileManager.TagsPersistence.Save(tagsCollection);
}
}
}

View File

@ -1,14 +1,14 @@
using AAXClean;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AAXClean;
using DataLayer;
using Dinah.Core;
using Dinah.Core.ErrorHandling;
using Dinah.Core.IO;
using Dinah.Core.Net.Http;
using FileManager;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using LibationFileManager;
namespace FileLiberator
{

View File

@ -9,6 +9,7 @@ using DataLayer;
using Dinah.Core;
using Dinah.Core.ErrorHandling;
using FileManager;
using LibationFileManager;
namespace FileLiberator
{

View File

@ -8,6 +8,7 @@ using DataLayer;
using Dinah.Core.ErrorHandling;
using Dinah.Core.Net.Http;
using FileManager;
using LibationFileManager;
namespace FileLiberator
{

View File

@ -7,7 +7,6 @@
<ItemGroup>
<ProjectReference Include="..\AaxDecrypter\AaxDecrypter.csproj" />
<ProjectReference Include="..\DataLayer\DataLayer.csproj" />
<ProjectReference Include="..\FileManager\FileManager.csproj" />
<ProjectReference Include="..\InternalUtilities\InternalUtilities.csproj" />
</ItemGroup>

View File

@ -27,7 +27,7 @@ namespace FileLiberator
public IEnumerable<LibraryBook> GetValidLibraryBooks(IEnumerable<LibraryBook> library)
=> library.Where(libraryBook =>
Validate(libraryBook)
&& (libraryBook.Book.ContentType != ContentType.Episode || FileManager.Configuration.Instance.DownloadEpisodes)
&& (libraryBook.Book.ContentType != ContentType.Episode || LibationFileManager.Configuration.Instance.DownloadEpisodes)
);
public async Task<StatusHandler> ProcessSingleAsync(LibraryBook libraryBook, bool validate)

View File

@ -37,7 +37,7 @@ namespace FileLiberator
protected void OnFileCreated(string id, string path)
{
Serilog.Log.Logger.Information("File created {@DebugInfo}", new { Name = nameof(FileCreated), id, path });
FileManager.FilePathCache.Insert(id, path);
LibationFileManager.FilePathCache.Insert(id, path);
FileCreated?.Invoke(this, (id, path));
}
}

View File

@ -8,13 +8,9 @@ using System.Threading.Tasks;
namespace FileManager
{
/// <summary>
/// Tracks actual locations of files. This is especially useful for clicking button to navigate to the book's files.
///
/// Note: this is no longer how Libation manages "Liberated" state. That is now statefully managed in the database.
/// This paradigm is what allows users to manually choose to not download books. Also allows them to manually toggle
/// this state and download again.
/// Tracks actual locations of files.
/// </summary>
internal class BackgroundFileSystem
public class BackgroundFileSystem
{
public string RootDirectory { get; private set; }
public string SearchPattern { get; private set; }

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
@ -6,8 +6,6 @@
<ItemGroup>
<PackageReference Include="Dinah.Core" Version="1.1.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Polly" Version="7.2.2" />
</ItemGroup>
</Project>

View File

@ -10,15 +10,19 @@ namespace FileManager
if (string.IsNullOrWhiteSpace(dirFullPath))
throw new ArgumentException($"{nameof(dirFullPath)} may not be null or whitespace", nameof(dirFullPath));
filename ??= "";
// file max length = 255. dir max len = 247
// sanitize
filename = getAsciiTag(filename);
// sanitize. omit invalid characters. exception: colon => underscore
filename = filename.Replace(':', '_');
filename = Dinah.Core.PathLib.ToPathSafeString(filename);
// manage length
if (filename.Length > 50)
filename = filename.Substring(0, 50) + "[...]";
// append id. it is 10 or 14 char in the common cases
// append metadata
if (metadataSuffixes != null && metadataSuffixes.Length > 0)
filename += " [" + string.Join("][", metadataSuffixes) + "]";
@ -34,19 +38,5 @@ namespace FileManager
return fullfilename;
}
private static string getAsciiTag(string property)
{
if (property == null)
return "";
// omit characters which are invalid. EXCEPTION: change colon to underscore
property = property.Replace(':', '_');
// GetInvalidFileNameChars contains everything in GetInvalidPathChars plus ':', '*', '?', '\\', '/'
foreach (var ch in Path.GetInvalidFileNameChars())
property = property.Replace(ch.ToString(), "");
return property;
}
}
}

View File

@ -1,6 +1,6 @@
using System;
using System.IO;
using FileManager;
using LibationFileManager;
using Newtonsoft.Json;
namespace InternalUtilities

View File

@ -9,7 +9,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FileManager\FileManager.csproj" />
<ProjectReference Include="..\LibationFileManager\LibationFileManager.csproj" />
</ItemGroup>
</Project>

View File

@ -23,7 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2 Utilities (domain ignoran
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AaxDecrypter", "AaxDecrypter\AaxDecrypter.csproj", "{8BD8E012-F44F-4EE2-A234-D66C14D5FE4B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileManager", "FileManager\FileManager.csproj", "{1AE65B61-9C05-4C80-ABFF-48F16E22FDF1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibationFileManager", "LibationFileManager\LibationFileManager.csproj", "{1AE65B61-9C05-4C80-ABFF-48F16E22FDF1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataLayer", "DataLayer\DataLayer.csproj", "{59A10DF3-63EC-43F1-A3BF-4000CFA118D2}"
EndProject
@ -56,6 +56,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibationCli", "LibationCli\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppScaffolding", "AppScaffolding\AppScaffolding.csproj", "{595E7C4D-506D-486D-98B7-5FDDF398D033}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileManager", "FileManager\FileManager.csproj", "{E86014F9-E4B3-4CD4-A210-2B3DB571DD86}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -118,6 +120,10 @@ Global
{595E7C4D-506D-486D-98B7-5FDDF398D033}.Debug|Any CPU.Build.0 = Debug|Any CPU
{595E7C4D-506D-486D-98B7-5FDDF398D033}.Release|Any CPU.ActiveCfg = Release|Any CPU
{595E7C4D-506D-486D-98B7-5FDDF398D033}.Release|Any CPU.Build.0 = Release|Any CPU
{E86014F9-E4B3-4CD4-A210-2B3DB571DD86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -137,6 +143,7 @@ Global
{D8F56E5A-3E65-41A6-B7E7-C4515A264B1F} = {7FBBB086-0807-4998-85BF-6D1A49C8AD05}
{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}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {615E00ED-BAEF-4E8E-A92A-9B82D87942A9}

View File

@ -3,8 +3,9 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using FileManager;
namespace FileManager
namespace LibationFileManager
{
public abstract class AudibleFileStorage
{

View File

@ -5,13 +5,14 @@ using System.IO;
using System.Linq;
using Dinah.Core;
using Dinah.Core.Logging;
using FileManager;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serilog;
using Serilog.Events;
namespace FileManager
namespace LibationFileManager
{
public class Configuration
{

View File

@ -5,7 +5,7 @@ using System.Linq;
using Dinah.Core.Collections.Immutable;
using Newtonsoft.Json;
namespace FileManager
namespace LibationFileManager
{
public static class FilePathCache
{

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace FileManager
namespace LibationFileManager
{
public enum FileType { Unknown, Audio, AAXC, PDF, Zip, Cue }

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Polly" Version="7.2.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FileManager\FileManager.csproj" />
</ItemGroup>
</Project>

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace FileManager
namespace LibationFileManager
{
public enum PictureSize { _80x80 = 80, _300x300 = 300, _500x500 = 500 }
public class PictureCachedEventArgs : EventArgs

View File

@ -5,7 +5,7 @@ using System.Linq;
using Dinah.Core.Collections.Generic;
using Newtonsoft.Json;
namespace FileManager
namespace LibationFileManager
{
public static class QuickFilters
{

View File

@ -1,6 +1,6 @@
using System.IO;
namespace FileManager
namespace LibationFileManager
{
public static class SqliteStorage
{

View File

@ -6,7 +6,7 @@ using Newtonsoft.Json;
using Polly;
using Polly.Retry;
namespace FileManager
namespace LibationFileManager
{
/// <summary>
/// Tags must also be stored in db for search performance. Stored in json file to survive a db reset.

View File

@ -14,7 +14,6 @@
<ItemGroup>
<ProjectReference Include="..\DataLayer\DataLayer.csproj" />
<ProjectReference Include="..\FileManager\FileManager.csproj" />
</ItemGroup>
</Project>

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using DataLayer;
using Dinah.Core;
using FileManager;
using LibationFileManager;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;

View File

@ -1,8 +1,8 @@
using FileManager;
using System;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Windows.Forms;
using LibationFileManager;
namespace LibationWinForms.Dialogs
{

View File

@ -1,9 +1,9 @@
using Dinah.Core;
using FileManager;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Dinah.Core;
using LibationFileManager;
namespace LibationWinForms.Dialogs
{

View File

@ -1,9 +1,9 @@
using Dinah.Core;
using FileManager;
using System;
using System;
using System.Linq;
using System.IO;
using System.Windows.Forms;
using Dinah.Core;
using LibationFileManager;
namespace LibationWinForms.Dialogs
{

View File

@ -1,7 +1,7 @@
using FileManager;
using System.Drawing;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using LibationFileManager;
namespace LibationWinForms
{

View File

@ -9,6 +9,7 @@ using DataLayer;
using Dinah.Core.DataBinding;
using Dinah.Core;
using Dinah.Core.Drawing;
using LibationFileManager;
namespace LibationWinForms
{
@ -39,10 +40,10 @@ namespace LibationWinForms
//Get cover art. If it's default, subscribe to PictureCached
{
(bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(new FileManager.PictureDefinition(Book.PictureId, FileManager.PictureSize._80x80));
(bool isDefault, byte[] picture) = PictureStorage.GetPicture(new PictureDefinition(Book.PictureId, PictureSize._80x80));
if (isDefault)
FileManager.PictureStorage.PictureCached += PictureStorage_PictureCached;
PictureStorage.PictureCached += PictureStorage_PictureCached;
//Mutable property. Set the field so PropertyChanged isn't fired.
_cover = ImageReader.ToImage(picture);
@ -66,12 +67,12 @@ namespace LibationWinForms
UserDefinedItem.ItemChanged += UserDefinedItem_ItemChanged;
}
private void PictureStorage_PictureCached(object sender, FileManager.PictureCachedEventArgs e)
private void PictureStorage_PictureCached(object sender, PictureCachedEventArgs e)
{
if (e.Definition.PictureId == Book.PictureId)
{
Cover = ImageReader.ToImage(e.Picture);
FileManager.PictureStorage.PictureCached -= PictureStorage_PictureCached;
PictureStorage.PictureCached -= PictureStorage_PictureCached;
}
}
@ -294,7 +295,7 @@ namespace LibationWinForms
~GridEntry()
{
UserDefinedItem.ItemChanged -= UserDefinedItem_ItemChanged;
FileManager.PictureStorage.PictureCached -= PictureStorage_PictureCached;
PictureStorage.PictureCached -= PictureStorage_PictureCached;
}
}
}

View File

@ -6,8 +6,8 @@ using System.Windows.Forms;
using AudibleApi.Authorization;
using DataLayer;
using Dinah.Core;
using FileManager;
using InternalUtilities;
using LibationFileManager;
using LibationWinForms.Dialogs;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;