From e180032a8e62958816404d83f051c41f0a68fb58 Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Tue, 19 Jan 2021 14:35:24 -0600 Subject: [PATCH] ScanLibrary now respects the library a series belongs to, doesn't reset series every run but updates/removes/inserts as needed. --- API/Controllers/LibraryController.cs | 2 +- API/Data/LibraryRepository.cs | 1 + API/Data/SeriesRepository.cs | 15 ++++++- API/Interfaces/ISeriesRepository.cs | 5 ++- API/Services/DirectoryService.cs | 60 ++++++++++++++++------------ 5 files changed, 54 insertions(+), 29 deletions(-) diff --git a/API/Controllers/LibraryController.cs b/API/Controllers/LibraryController.cs index acf0ce24c..f6e8afd9a 100644 --- a/API/Controllers/LibraryController.cs +++ b/API/Controllers/LibraryController.cs @@ -170,7 +170,7 @@ namespace API.Controllers { var username = User.GetUsername(); _logger.LogInformation($"Library {libraryId} is being deleted by {username}."); - var series = await _unitOfWork.SeriesRepository.GetSeriesDtoForLibraryIdAsync(libraryId); + var series = await _unitOfWork.SeriesRepository.GetSeriesForLibraryIdAsync(libraryId); var volumes = (await _unitOfWork.SeriesRepository.GetVolumesForSeriesAsync(series.Select(x => x.Id).ToArray())) .Select(x => x.Id).ToArray(); var result = await _unitOfWork.LibraryRepository.DeleteLibrary(libraryId); diff --git a/API/Data/LibraryRepository.cs b/API/Data/LibraryRepository.cs index ef21ffd55..a85435df2 100644 --- a/API/Data/LibraryRepository.cs +++ b/API/Data/LibraryRepository.cs @@ -81,6 +81,7 @@ namespace API.Data return await _context.Library .Where(x => x.Id == libraryId) .Include(f => f.Folders) + .Include(l => l.Series) .SingleAsync(); } diff --git a/API/Data/SeriesRepository.cs b/API/Data/SeriesRepository.cs index 060175c20..d5106e15e 100644 --- a/API/Data/SeriesRepository.cs +++ b/API/Data/SeriesRepository.cs @@ -23,6 +23,11 @@ namespace API.Data _mapper = mapper; } + public void Add(Series series) + { + _context.Series.Add(series); + } + public void Update(Series series) { _context.Entry(series).State = EntityState.Modified; @@ -48,7 +53,15 @@ namespace API.Data return _context.Series.SingleOrDefault(x => x.Name == name); } - public async Task> GetSeriesDtoForLibraryIdAsync(int libraryId, int userId = 0) + public async Task> GetSeriesForLibraryIdAsync(int libraryId) + { + return await _context.Series + .Where(s => s.LibraryId == libraryId) + .OrderBy(s => s.SortName) + .ToListAsync(); + } + + public async Task> GetSeriesDtoForLibraryIdAsync(int libraryId, int userId) { // if (userId > 0) // { diff --git a/API/Interfaces/ISeriesRepository.cs b/API/Interfaces/ISeriesRepository.cs index d2fe75353..1e72cef3c 100644 --- a/API/Interfaces/ISeriesRepository.cs +++ b/API/Interfaces/ISeriesRepository.cs @@ -7,10 +7,12 @@ namespace API.Interfaces { public interface ISeriesRepository { + void Add(Series series); void Update(Series series); Task GetSeriesByNameAsync(string name); Series GetSeriesByName(string name); - Task> GetSeriesDtoForLibraryIdAsync(int libraryId, int userId = 0); + Task> GetSeriesDtoForLibraryIdAsync(int libraryId, int userId); + Task> GetSeriesForLibraryIdAsync(int libraryId); Task> GetVolumesDtoAsync(int seriesId, int userId = 0); IEnumerable GetVolumes(int seriesId); Task GetSeriesDtoByIdAsync(int seriesId); @@ -21,5 +23,6 @@ namespace API.Interfaces Task> GetVolumesForSeriesAsync(int[] seriesIds); Task DeleteSeriesAsync(int seriesId); Task GetVolumeByIdAsync(int volumeId); + } } \ No newline at end of file diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs index a67cd66a2..d652ee149 100644 --- a/API/Services/DirectoryService.cs +++ b/API/Services/DirectoryService.cs @@ -40,7 +40,7 @@ namespace API.Services /// Regex version of search pattern (ie \.mp3|\.mp4). Defaults to * meaning all files. /// SearchOption to use, defaults to TopDirectoryOnly /// List of file paths - public static IEnumerable GetFilesWithCertainExtensions(string path, + private static IEnumerable GetFilesWithCertainExtensions(string path, string searchPatternExpression = "", SearchOption searchOption = SearchOption.TopDirectoryOnly) { @@ -57,9 +57,7 @@ namespace API.Services return Directory.GetFiles(path); } - - - public IEnumerable ListDirectory(string rootPath) + public IEnumerable ListDirectory(string rootPath) { if (!Directory.Exists(rootPath)) return ImmutableList.Empty; @@ -72,13 +70,6 @@ namespace API.Services return dirs; } - // public IList ListFiles(string rootPath) - // { - // if (!Directory.Exists(rootPath)) return ImmutableList.Empty; - // return Directory.GetFiles(rootPath); - // } - - /// /// Processes files found during a library scan. Generates a collection of series->volume->files for DB processing later. /// @@ -117,20 +108,20 @@ namespace API.Services } } - private Series UpdateSeries(string seriesName, ParserInfo[] infos, bool forceUpdate) + private Series UpdateSeries(Series series, ParserInfo[] infos, bool forceUpdate) { - var series = _unitOfWork.SeriesRepository.GetSeriesByName(seriesName) ?? new Series - { - Name = seriesName, - OriginalName = seriesName, - SortName = seriesName, - Summary = "" // TODO: Check if comicInfo.xml in file and parse metadata out. - }; - var volumes = UpdateVolumes(series, infos, forceUpdate); series.Volumes = volumes; - series.CoverImage = volumes.OrderBy(x => x.Number).FirstOrDefault()?.CoverImage; series.Pages = volumes.Sum(v => v.Pages); + if (series.CoverImage == null || forceUpdate) + { + series.CoverImage = volumes.OrderBy(x => x.Number).FirstOrDefault()?.CoverImage; + } + if (string.IsNullOrEmpty(series.Summary) || forceUpdate) + { + series.Summary = ""; // TODO: Check if comicInfo.xml in file and parse metadata out. + } + return series; } @@ -262,17 +253,34 @@ namespace API.Services var series = filtered.ToImmutableDictionary(v => v.Key, v => v.Value); // Perform DB activities - library.Series = new List(); // Temp delete everything until we can mark items Unavailable + var allSeries = Task.Run(() => _unitOfWork.SeriesRepository.GetSeriesForLibraryIdAsync(libraryId)).Result.ToList(); foreach (var seriesKey in series.Keys) { - // TODO: Critical bug: Code is not taking libraryId into account and series are being linked across libraries. - var mangaSeries = UpdateSeries(seriesKey, series[seriesKey].ToArray(), forceUpdate); - _logger.LogInformation($"Created/Updated series {mangaSeries.Name}"); + var mangaSeries = allSeries.SingleOrDefault(s => s.Name == seriesKey) ?? new Series + { + Name = seriesKey, + OriginalName = seriesKey, + SortName = seriesKey, + Summary = "" + }; + mangaSeries = UpdateSeries(mangaSeries, series[seriesKey].ToArray(), forceUpdate); + _logger.LogInformation($"Created/Updated series {mangaSeries.Name} for {library.Name} library"); + library.Series ??= new List(); library.Series.Add(mangaSeries); } + + // Remove series that are no longer on disk + foreach (var existingSeries in allSeries) + { + if (!series.ContainsKey(existingSeries.Name) || !series.ContainsKey(existingSeries.OriginalName)) + { + // Delete series, there is no file to backup any longer. + library.Series.Remove(existingSeries); + } + } _unitOfWork.LibraryRepository.Update(library); - + if (Task.Run(() => _unitOfWork.Complete()).Result) { _logger.LogInformation($"Scan completed on {library.Name}. Parsed {series.Keys.Count()} series.");