diff --git a/API.Tests/ParserTest.cs b/API.Tests/ParserTest.cs index 2a70ee429..eaebc727a 100644 --- a/API.Tests/ParserTest.cs +++ b/API.Tests/ParserTest.cs @@ -15,6 +15,7 @@ namespace API.Tests //[InlineData("Dance in the Vampire Bund v16-17 (Digital) (NiceDragon)", "16-17")] [InlineData("Akame ga KILL! ZERO v01 (2016) (Digital) (LuCaZ).cbz", "1")] [InlineData("v001", "1")] + [InlineData("U12 (Under 12) Vol. 0001 Ch. 0001 - Reiwa Scans (gb)", "1")] [InlineData("[Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip", "1")] public void ParseVolumeTest(string filename, string expected) { @@ -31,6 +32,7 @@ namespace API.Tests [InlineData("Gokukoku no Brynhildr - c001-008 (v01) [TrinityBAKumA]", "Gokukoku no Brynhildr")] [InlineData("Dance in the Vampire Bund v16-17 (Digital) (NiceDragon)", "Dance in the Vampire Bund")] [InlineData("v001", "")] + [InlineData("U12 (Under 12) Vol. 0001 Ch. 0001 - Reiwa Scans (gb)", "U12 (Under 12)")] [InlineData("Akame ga KILL! ZERO (2016-2019) (Digital) (LuCaZ)", "Akame ga KILL! ZERO")] public void ParseSeriesTest(string filename, string expected) { @@ -42,10 +44,10 @@ namespace API.Tests [InlineData("Killing Bites Vol. 0001 Ch. 0001 - Galactica Scanlations (gb)", "1")] [InlineData("My Girlfriend Is Shobitch v01 - ch. 09 - pg. 008.png", "9")] [InlineData("Historys Strongest Disciple Kenichi_v11_c90-98.zip", "90-98")] - [InlineData("B_Gata_H_Kei_v01[SlowManga&OverloadScans]", "")] - [InlineData("BTOOOM! v01 (2013) (Digital) (Shadowcat-Empire)", "")] + [InlineData("B_Gata_H_Kei_v01[SlowManga&OverloadScans]", "0")] + [InlineData("BTOOOM! v01 (2013) (Digital) (Shadowcat-Empire)", "0")] [InlineData("Gokukoku no Brynhildr - c001-008 (v01) [TrinityBAKumA]", "1-8")] - [InlineData("Dance in the Vampire Bund v16-17 (Digital) (NiceDragon)", "")] + [InlineData("Dance in the Vampire Bund v16-17 (Digital) (NiceDragon)", "0")] [InlineData("c001", "1")] [InlineData("[Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.12.zip", "12")] [InlineData("Adding volume 1 with File: Ana Satsujin Vol. 1 Ch. 5 - Manga Box (gb).cbz", "5")] diff --git a/API/Controllers/LibraryController.cs b/API/Controllers/LibraryController.cs index e4a29cb59..9cc9202e8 100644 --- a/API/Controllers/LibraryController.cs +++ b/API/Controllers/LibraryController.cs @@ -159,13 +159,13 @@ namespace API.Controllers var username = User.GetUsername(); _logger.LogInformation($"Library {libraryId} is being deleted by {username}."); var series = await _seriesRepository.GetSeriesDtoForLibraryIdAsync(libraryId); - var volumes = (await _seriesRepository.GetVolumesForSeriesAsync(series.Select(x => x.Id).ToArray())).ToList(); + var volumes = (await _seriesRepository.GetVolumesForSeriesAsync(series.Select(x => x.Id).ToArray())) + .Select(x => x.Id).ToArray(); var result = await _libraryRepository.DeleteLibrary(libraryId); - if (result && volumes.Any()) { - BackgroundJob.Enqueue(() => _cacheService.CleanupLibrary(libraryId, volumes.Select(x => x.Id).ToArray())); + BackgroundJob.Enqueue(() => _cacheService.CleanupVolumes(volumes)); } return Ok(result); diff --git a/API/Controllers/SeriesController.cs b/API/Controllers/SeriesController.cs index 9be846807..199c5971c 100644 --- a/API/Controllers/SeriesController.cs +++ b/API/Controllers/SeriesController.cs @@ -1,8 +1,12 @@ using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using API.DTOs; +using API.Extensions; using API.Interfaces; using AutoMapper; +using Hangfire; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; @@ -14,14 +18,17 @@ namespace API.Controllers private readonly IMapper _mapper; private readonly ITaskScheduler _taskScheduler; private readonly ISeriesRepository _seriesRepository; + private readonly ICacheService _cacheService; public SeriesController(ILogger logger, IMapper mapper, - ITaskScheduler taskScheduler, ISeriesRepository seriesRepository) + ITaskScheduler taskScheduler, ISeriesRepository seriesRepository, + ICacheService cacheService) { _logger = logger; _mapper = mapper; _taskScheduler = taskScheduler; _seriesRepository = seriesRepository; + _cacheService = cacheService; } [HttpGet("{seriesId}")] @@ -30,6 +37,22 @@ namespace API.Controllers return Ok(await _seriesRepository.GetSeriesDtoByIdAsync(seriesId)); } + [Authorize(Policy = "RequireAdminRole")] + [HttpDelete("{seriesId}")] + public async Task> DeleteSeries(int seriesId) + { + var username = User.GetUsername(); + var volumes = (await _seriesRepository.GetVolumesForSeriesAsync(new []{seriesId})).Select(x => x.Id).ToArray(); + _logger.LogInformation($"Series {seriesId} is being deleted by {username}."); + var result = await _seriesRepository.DeleteSeriesAsync(seriesId); + + if (result) + { + BackgroundJob.Enqueue(() => _cacheService.CleanupVolumes(volumes)); + } + return Ok(result); + } + [HttpGet("volumes")] public async Task>> GetVolumes(int seriesId) { diff --git a/API/Data/LibraryRepository.cs b/API/Data/LibraryRepository.cs index 9c2c74b29..15cd38d8b 100644 --- a/API/Data/LibraryRepository.cs +++ b/API/Data/LibraryRepository.cs @@ -38,10 +38,12 @@ namespace API.Data public async Task> GetLibrariesDtoForUsernameAsync(string userName) { + // TODO: Speed this query up return await _context.Library .Include(l => l.AppUsers) .Where(library => library.AppUsers.Any(x => x.UserName == userName)) - .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); + .ProjectTo(_mapper.ConfigurationProvider) + .ToListAsync(); } public async Task GetLibraryForNameAsync(string libraryName) diff --git a/API/Data/SeriesRepository.cs b/API/Data/SeriesRepository.cs index 352ed2f54..932b5ca37 100644 --- a/API/Data/SeriesRepository.cs +++ b/API/Data/SeriesRepository.cs @@ -104,5 +104,13 @@ namespace API.Data .Where(v => seriesIds.Contains(v.SeriesId)) .ToListAsync(); } + + public async Task DeleteSeriesAsync(int seriesId) + { + var series = await _context.Series.Where(s => s.Id == seriesId).SingleOrDefaultAsync(); + _context.Series.Remove(series); + + return await _context.SaveChangesAsync() > 0; + } } } \ No newline at end of file diff --git a/API/Interfaces/ICacheService.cs b/API/Interfaces/ICacheService.cs index 57d6a4c11..81a4ef5fa 100644 --- a/API/Interfaces/ICacheService.cs +++ b/API/Interfaces/ICacheService.cs @@ -16,15 +16,13 @@ namespace API.Interfaces /// /// Clears cache directory of all folders and files. /// - /// void Cleanup(); /// - /// Clears cache directory of all volumes that belong to a given library. + /// Clears cache directory of all volumes. This can be invoked from deleting a library or a series. /// - /// /// Volumes that belong to that library. Assume the library might have been deleted before this invocation. - void CleanupLibrary(int libraryId, int[] volumeIds); + void CleanupVolumes(int[] volumeIds); /// diff --git a/API/Interfaces/ISeriesRepository.cs b/API/Interfaces/ISeriesRepository.cs index 6f34e0685..490628163 100644 --- a/API/Interfaces/ISeriesRepository.cs +++ b/API/Interfaces/ISeriesRepository.cs @@ -21,5 +21,6 @@ namespace API.Interfaces Task GetVolumeDtoAsync(int volumeId); Task> GetVolumesForSeriesAsync(int[] seriesIds); + Task DeleteSeriesAsync(int seriesId); } } \ No newline at end of file diff --git a/API/Services/CacheService.cs b/API/Services/CacheService.cs index 7a7ba1acf..1a78f1293 100644 --- a/API/Services/CacheService.cs +++ b/API/Services/CacheService.cs @@ -48,7 +48,6 @@ namespace API.Services return volume; } - public void Cleanup() { @@ -74,9 +73,9 @@ namespace API.Services _logger.LogInformation("Cache directory purged."); } - public void CleanupLibrary(int libraryId, int[] volumeIds) + public void CleanupVolumes(int[] volumeIds) { - _logger.LogInformation($"Running Cache cleanup on Library: {libraryId}"); + _logger.LogInformation($"Running Cache cleanup on Volumes"); foreach (var volume in volumeIds) { @@ -89,7 +88,7 @@ namespace API.Services } _logger.LogInformation("Cache directory purged"); } - + private string GetVolumeCachePath(int volumeId, MangaFile file) { diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs index 870d098a7..7081d1b49 100644 --- a/API/Services/DirectoryService.cs +++ b/API/Services/DirectoryService.cs @@ -343,6 +343,7 @@ namespace API.Services } using ZipArchive archive = ZipFile.OpenRead(archivePath); + Console.WriteLine(); return archive.Entries.Count(e => Parser.Parser.IsImage(e.FullName)); }