ScanLibrary now respects the library a series belongs to, doesn't reset series every run but updates/removes/inserts as needed.

This commit is contained in:
Joseph Milazzo 2021-01-19 14:35:24 -06:00
parent 44ebca36ec
commit e180032a8e
5 changed files with 54 additions and 29 deletions

View File

@ -170,7 +170,7 @@ namespace API.Controllers
{ {
var username = User.GetUsername(); var username = User.GetUsername();
_logger.LogInformation($"Library {libraryId} is being deleted by {username}."); _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())) var volumes = (await _unitOfWork.SeriesRepository.GetVolumesForSeriesAsync(series.Select(x => x.Id).ToArray()))
.Select(x => x.Id).ToArray(); .Select(x => x.Id).ToArray();
var result = await _unitOfWork.LibraryRepository.DeleteLibrary(libraryId); var result = await _unitOfWork.LibraryRepository.DeleteLibrary(libraryId);

View File

@ -81,6 +81,7 @@ namespace API.Data
return await _context.Library return await _context.Library
.Where(x => x.Id == libraryId) .Where(x => x.Id == libraryId)
.Include(f => f.Folders) .Include(f => f.Folders)
.Include(l => l.Series)
.SingleAsync(); .SingleAsync();
} }

View File

@ -23,6 +23,11 @@ namespace API.Data
_mapper = mapper; _mapper = mapper;
} }
public void Add(Series series)
{
_context.Series.Add(series);
}
public void Update(Series series) public void Update(Series series)
{ {
_context.Entry(series).State = EntityState.Modified; _context.Entry(series).State = EntityState.Modified;
@ -48,7 +53,15 @@ namespace API.Data
return _context.Series.SingleOrDefault(x => x.Name == name); return _context.Series.SingleOrDefault(x => x.Name == name);
} }
public async Task<IEnumerable<SeriesDto>> GetSeriesDtoForLibraryIdAsync(int libraryId, int userId = 0) public async Task<IEnumerable<Series>> GetSeriesForLibraryIdAsync(int libraryId)
{
return await _context.Series
.Where(s => s.LibraryId == libraryId)
.OrderBy(s => s.SortName)
.ToListAsync();
}
public async Task<IEnumerable<SeriesDto>> GetSeriesDtoForLibraryIdAsync(int libraryId, int userId)
{ {
// if (userId > 0) // if (userId > 0)
// { // {

View File

@ -7,10 +7,12 @@ namespace API.Interfaces
{ {
public interface ISeriesRepository public interface ISeriesRepository
{ {
void Add(Series series);
void Update(Series series); void Update(Series series);
Task<Series> GetSeriesByNameAsync(string name); Task<Series> GetSeriesByNameAsync(string name);
Series GetSeriesByName(string name); Series GetSeriesByName(string name);
Task<IEnumerable<SeriesDto>> GetSeriesDtoForLibraryIdAsync(int libraryId, int userId = 0); Task<IEnumerable<SeriesDto>> GetSeriesDtoForLibraryIdAsync(int libraryId, int userId);
Task<IEnumerable<Series>> GetSeriesForLibraryIdAsync(int libraryId);
Task<IEnumerable<VolumeDto>> GetVolumesDtoAsync(int seriesId, int userId = 0); Task<IEnumerable<VolumeDto>> GetVolumesDtoAsync(int seriesId, int userId = 0);
IEnumerable<Volume> GetVolumes(int seriesId); IEnumerable<Volume> GetVolumes(int seriesId);
Task<SeriesDto> GetSeriesDtoByIdAsync(int seriesId); Task<SeriesDto> GetSeriesDtoByIdAsync(int seriesId);
@ -21,5 +23,6 @@ namespace API.Interfaces
Task<IEnumerable<Volume>> GetVolumesForSeriesAsync(int[] seriesIds); Task<IEnumerable<Volume>> GetVolumesForSeriesAsync(int[] seriesIds);
Task<bool> DeleteSeriesAsync(int seriesId); Task<bool> DeleteSeriesAsync(int seriesId);
Task<Volume> GetVolumeByIdAsync(int volumeId); Task<Volume> GetVolumeByIdAsync(int volumeId);
} }
} }

View File

@ -40,7 +40,7 @@ namespace API.Services
/// <param name="searchPatternExpression">Regex version of search pattern (ie \.mp3|\.mp4). Defaults to * meaning all files.</param> /// <param name="searchPatternExpression">Regex version of search pattern (ie \.mp3|\.mp4). Defaults to * meaning all files.</param>
/// <param name="searchOption">SearchOption to use, defaults to TopDirectoryOnly</param> /// <param name="searchOption">SearchOption to use, defaults to TopDirectoryOnly</param>
/// <returns>List of file paths</returns> /// <returns>List of file paths</returns>
public static IEnumerable<string> GetFilesWithCertainExtensions(string path, private static IEnumerable<string> GetFilesWithCertainExtensions(string path,
string searchPatternExpression = "", string searchPatternExpression = "",
SearchOption searchOption = SearchOption.TopDirectoryOnly) SearchOption searchOption = SearchOption.TopDirectoryOnly)
{ {
@ -57,9 +57,7 @@ namespace API.Services
return Directory.GetFiles(path); return Directory.GetFiles(path);
} }
public IEnumerable<string> ListDirectory(string rootPath)
public IEnumerable<string> ListDirectory(string rootPath)
{ {
if (!Directory.Exists(rootPath)) return ImmutableList<string>.Empty; if (!Directory.Exists(rootPath)) return ImmutableList<string>.Empty;
@ -72,13 +70,6 @@ namespace API.Services
return dirs; return dirs;
} }
// public IList<string> ListFiles(string rootPath)
// {
// if (!Directory.Exists(rootPath)) return ImmutableList<string>.Empty;
// return Directory.GetFiles(rootPath);
// }
/// <summary> /// <summary>
/// Processes files found during a library scan. Generates a collection of series->volume->files for DB processing later. /// Processes files found during a library scan. Generates a collection of series->volume->files for DB processing later.
/// </summary> /// </summary>
@ -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); var volumes = UpdateVolumes(series, infos, forceUpdate);
series.Volumes = volumes; series.Volumes = volumes;
series.CoverImage = volumes.OrderBy(x => x.Number).FirstOrDefault()?.CoverImage;
series.Pages = volumes.Sum(v => v.Pages); 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; return series;
} }
@ -262,17 +253,34 @@ namespace API.Services
var series = filtered.ToImmutableDictionary(v => v.Key, v => v.Value); var series = filtered.ToImmutableDictionary(v => v.Key, v => v.Value);
// Perform DB activities // Perform DB activities
library.Series = new List<Series>(); // 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) 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 = allSeries.SingleOrDefault(s => s.Name == seriesKey) ?? new Series
var mangaSeries = UpdateSeries(seriesKey, series[seriesKey].ToArray(), forceUpdate); {
_logger.LogInformation($"Created/Updated series {mangaSeries.Name}"); 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<Series>();
library.Series.Add(mangaSeries); 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); _unitOfWork.LibraryRepository.Update(library);
if (Task.Run(() => _unitOfWork.Complete()).Result) if (Task.Run(() => _unitOfWork.Complete()).Result)
{ {
_logger.LogInformation($"Scan completed on {library.Name}. Parsed {series.Keys.Count()} series."); _logger.LogInformation($"Scan completed on {library.Name}. Parsed {series.Keys.Count()} series.");