Feature/tech debt (#199)

* Added an icon for building the exe

* Technical debt
This commit is contained in:
Joseph Milazzo 2021-05-05 21:00:50 -05:00 committed by GitHub
parent d92e9e7602
commit f694145cd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 76 additions and 112 deletions

View File

@ -1,6 +1,4 @@
using System;
using API.Data;
using API.Tests.Helpers;
using API.Data;
using Xunit;
namespace API.Tests.Entities

View File

@ -1,10 +1,4 @@
using System;
using System.IO;
using API.Extensions;
using NSubstitute;
using Xunit;
namespace API.Tests.Extensions
namespace API.Tests.Extensions
{
public class FileInfoExtensionsTests
{

View File

@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using API.Entities;
using API.Entities.Enums;
using API.Extensions;
using API.Parser;
@ -12,7 +11,7 @@ namespace API.Tests.Extensions
public class ParserInfoListExtensions
{
[Theory]
[InlineData(new string[] {"1", "1", "3-5", "5", "8", "0", "0"}, new string[] {"1", "3-5", "5", "8", "0"})]
[InlineData(new[] {"1", "1", "3-5", "5", "8", "0", "0"}, new[] {"1", "3-5", "5", "8", "0"})]
public void DistinctVolumesTest(string[] volumeNumbers, string[] expectedNumbers)
{
var infos = volumeNumbers.Select(n => new ParserInfo() {Volumes = n}).ToList();
@ -20,9 +19,9 @@ namespace API.Tests.Extensions
}
[Theory]
[InlineData(new string[] {@"Cynthia The Mission - c000-006 (v06) [Desudesu&Brolen].zip"}, new string[] {@"E:\Manga\Cynthia the Mission\Cynthia The Mission - c000-006 (v06) [Desudesu&Brolen].zip"}, true)]
[InlineData(new string[] {@"Cynthia The Mission - c000-006 (v06-07) [Desudesu&Brolen].zip"}, new string[] {@"E:\Manga\Cynthia the Mission\Cynthia The Mission - c000-006 (v06) [Desudesu&Brolen].zip"}, true)]
[InlineData(new string[] {@"Cynthia The Mission v20 c12-20 [Desudesu&Brolen].zip"}, new string[] {@"E:\Manga\Cynthia the Mission\Cynthia The Mission - c000-006 (v06) [Desudesu&Brolen].zip"}, false)]
[InlineData(new[] {@"Cynthia The Mission - c000-006 (v06) [Desudesu&Brolen].zip"}, new[] {@"E:\Manga\Cynthia the Mission\Cynthia The Mission - c000-006 (v06) [Desudesu&Brolen].zip"}, true)]
[InlineData(new[] {@"Cynthia The Mission - c000-006 (v06-07) [Desudesu&Brolen].zip"}, new[] {@"E:\Manga\Cynthia the Mission\Cynthia The Mission - c000-006 (v06) [Desudesu&Brolen].zip"}, true)]
[InlineData(new[] {@"Cynthia The Mission v20 c12-20 [Desudesu&Brolen].zip"}, new[] {@"E:\Manga\Cynthia the Mission\Cynthia The Mission - c000-006 (v06) [Desudesu&Brolen].zip"}, false)]
public void HasInfoTest(string[] inputInfos, string[] inputChapters, bool expectedHasInfo)
{
var infos = new List<ParserInfo>();

View File

@ -1,5 +1,4 @@
using System;
using API.Entities;
using API.Entities;
using API.Extensions;
using Xunit;

View File

@ -1,6 +1,4 @@
using System.Collections.Generic;
using System.IO;
using API.Services;
using System.IO;
namespace API.Tests.Helpers
{

View File

@ -1,5 +1,4 @@
using API.Services;
using Xunit;
using Xunit;
namespace API.Tests.Parser
{

View File

@ -1,5 +1,4 @@
using System.IO;
using API.Entities.Interfaces;
using API.Interfaces;
using API.Services;
using Microsoft.Extensions.Logging;

View File

@ -2,7 +2,6 @@
using System.IO;
using System.Linq;
using API.Services;
using API.Tests.Helpers;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
@ -20,16 +19,15 @@ namespace API.Tests.Services
_directoryService = new DirectoryService(_logger);
}
[Theory]
[InlineData("Manga-testcase.txt", 28)]
public void GetFilesTest(string file, int expectedFileCount)
[Fact]
public void GetFilesTest_Should_Be28()
{
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ScannerService/Manga");
var files = new List<string>();
var fileCount = DirectoryService.TraverseTreeParallelForEach(testDirectory, s => files.Add(s),
API.Parser.Parser.ArchiveFileExtensions, _logger);
Assert.Equal(expectedFileCount, fileCount);
Assert.Equal(28, fileCount);
}
[Fact]

View File

@ -29,10 +29,8 @@ namespace API.Tests.Services
private readonly ITestOutputHelper _testOutputHelper;
private readonly ScannerService _scannerService;
private readonly ILogger<ScannerService> _logger = Substitute.For<ILogger<ScannerService>>();
private readonly IUnitOfWork _unitOfWork;
private readonly IArchiveService _archiveService = Substitute.For<IArchiveService>();
private readonly IBookService _bookService = Substitute.For<IBookService>();
private readonly IMetadataService _metadataService;
private readonly ILogger<MetadataService> _metadataLogger = Substitute.For<ILogger<MetadataService>>();
private readonly DbConnection _connection;
@ -58,13 +56,12 @@ namespace API.Tests.Services
// Substitute.For<UserManager<AppUser>>() - Not needed because only for UserService
_unitOfWork = new UnitOfWork(_context, Substitute.For<IMapper>(), null,
Substitute.For<ILogger<UnitOfWork>>());
IUnitOfWork unitOfWork = new UnitOfWork(_context, Substitute.For<IMapper>(), null);
_testOutputHelper = testOutputHelper;
_metadataService= Substitute.For<MetadataService>(_unitOfWork, _metadataLogger, _archiveService, _bookService);
_scannerService = new ScannerService(_unitOfWork, _logger, _archiveService, _metadataService, _bookService);
IMetadataService metadataService = Substitute.For<MetadataService>(unitOfWork, _metadataLogger, _archiveService, _bookService);
_scannerService = new ScannerService(unitOfWork, _logger, _archiveService, metadataService, _bookService);
}
private async Task<bool> SeedDb()
@ -118,10 +115,9 @@ namespace API.Tests.Services
OriginalName = "Darker Than Black",
NormalizedName = API.Parser.Parser.Normalize("Darker Than Black")
});
var expectedSeries = new List<Series>();
Assert.Empty(_scannerService.FindSeriesNotOnDisk(existingSeries, infos));
}

View File

@ -9,6 +9,7 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>false</DebugSymbols>
<ApplicationIcon>../favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>

View File

@ -2,9 +2,9 @@
namespace API.Comparators
{
public class ChapterSortComparer : IComparer<float>
public class ChapterSortComparer : IComparer<double>
{
public int Compare(float x, float y)
public int Compare(double x, double y)
{
if (x == 0.0 && y == 0.0) return 0;
// if x is 0, it comes second

View File

@ -6,10 +6,13 @@ using static System.String;
namespace API.Comparators
{
public class NaturalSortComparer : IComparer<string>, IDisposable
public sealed class NaturalSortComparer : IComparer<string>, IDisposable
{
private readonly bool _isAscending;
private Dictionary<string, string[]> _table = new();
private bool _disposed;
public NaturalSortComparer(bool inAscendingOrder = true)
{
@ -20,17 +23,17 @@ namespace API.Comparators
{
if (x == y) return 0;
if (!_table.TryGetValue(x, out var x1))
if (!_table.TryGetValue(x ?? Empty, out var x1))
{
// .Replace(" ", Empty)
x1 = Regex.Split(x, "([0-9]+)");
_table.Add(x, x1);
x1 = Regex.Split(x ?? Empty, "([0-9]+)");
_table.Add(x ?? Empty, x1);
}
if (!_table.TryGetValue(y, out var y1))
if (!_table.TryGetValue(y ?? Empty, out var y1))
{
y1 = Regex.Split(y, "([0-9]+)");
_table.Add(y, y1);
y1 = Regex.Split(y ?? Empty, "([0-9]+)");
_table.Add(y ?? Empty, y1);
}
int returnVal;
@ -69,11 +72,31 @@ namespace API.Comparators
return x.CompareTo(y);
}
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// called via myClass.Dispose().
_table.Clear();
_table = null;
}
// Release unmanaged resources.
// Set large fields to null.
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
SuppressFinalize(this);
_table.Clear();
_table = null;
}
~NaturalSortComparer() // the finalizer
{
Dispose(false);
}
}
}

View File

@ -2,7 +2,6 @@
using System.Linq;
using System.Threading.Tasks;
using API.DTOs;
using API.Entities.Interfaces;
using API.Extensions;
using API.Interfaces;
using API.Services;

View File

@ -276,12 +276,13 @@ namespace API.Controllers
}
return Ok(-1);
}
/// <summary>
/// Returns the previous logical volume from the series.
/// </summary>
/// <param name="seriesId"></param>
/// <param name="volumeId"></param>
/// <param name="currentChapterId"></param>
/// <returns>chapter id for next manga</returns>
[HttpGet("prev-chapter")]
public async Task<ActionResult<int>> GetPreviousChapter(int seriesId, int volumeId, int currentChapterId)

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using API.DTOs;
using API.Entities;

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using API.DTOs;
@ -10,7 +9,6 @@ using API.Interfaces;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace API.Data
{
@ -18,13 +16,11 @@ namespace API.Data
{
private readonly DataContext _context;
private readonly IMapper _mapper;
private readonly ILogger _logger;
public SeriesRepository(DataContext context, IMapper mapper, ILogger logger)
public SeriesRepository(DataContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
_logger = logger;
}
public void Add(Series series)
@ -289,6 +285,7 @@ namespace API.Data
/// <summary>
/// Returns a list of Series that were added, ordered by Created desc
/// </summary>
/// <param name="userId"></param>
/// <param name="libraryId">Library to restrict to, if 0, will apply to all libraries</param>
/// <param name="limit">How many series to pick.</param>
/// <returns></returns>

View File

@ -3,7 +3,6 @@ using API.Entities;
using API.Interfaces;
using AutoMapper;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
namespace API.Data
{
@ -12,17 +11,15 @@ namespace API.Data
private readonly DataContext _context;
private readonly IMapper _mapper;
private readonly UserManager<AppUser> _userManager;
private readonly ILogger<UnitOfWork> _logger;
public UnitOfWork(DataContext context, IMapper mapper, UserManager<AppUser> userManager, ILogger<UnitOfWork> logger)
public UnitOfWork(DataContext context, IMapper mapper, UserManager<AppUser> userManager)
{
_context = context;
_mapper = mapper;
_userManager = userManager;
_logger = logger;
}
public ISeriesRepository SeriesRepository => new SeriesRepository(_context, _mapper, _logger);
public ISeriesRepository SeriesRepository => new SeriesRepository(_context, _mapper);
public IUserRepository UserRepository => new UserRepository(_context, _userManager);
public ILibraryRepository LibraryRepository => new LibraryRepository(_context, _mapper);

View File

@ -1,5 +1,4 @@
using API.Data;
using API.Entities.Interfaces;
using API.Helpers;
using API.Interfaces;
using API.Interfaces.Services;

View File

@ -1,5 +1,4 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using API.Entities;
using API.Parser;

View File

@ -48,7 +48,7 @@ namespace API.Parser
/// <summary>
/// If the file contains no volume/chapter information or contains Special Keywords <see cref="Parser.MangaSpecialRegex"/>
/// </summary>
public bool IsSpecial { get; set; } = false;
public bool IsSpecial { get; set; }
/// <summary>
/// Used for specials or books, stores what the UI should show.

View File

@ -4,6 +4,7 @@ using API.Data;
using API.Entities;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@ -49,38 +50,12 @@ namespace API
{
webBuilder.UseKestrel((opts) =>
{
opts.ListenAnyIP(HttpPort);
opts.ListenAnyIP(HttpPort, options =>
{
options.Protocols = HttpProtocols.Http1AndHttp2;
});
});
webBuilder.UseStartup<Startup>();
});
// private static void StartNewInstance()
// {
// //_logger.LogInformation("Starting new instance");
//
// var module = options.RestartPath;
//
// if (string.IsNullOrWhiteSpace(module))
// {
// module = Environment.GetCommandLineArgs()[0];
// }
//
// // string commandLineArgsString;
// // if (options.RestartArgs != null)
// // {
// // commandLineArgsString = options.RestartArgs ?? string.Empty;
// // }
// // else
// // {
// // commandLineArgsString = string.Join(
// // ' ',
// // Environment.GetCommandLineArgs().Skip(1).Select(NormalizeCommandLineArgument));
// // }
//
// //_logger.LogInformation("Executable: {0}", module);
// //_logger.LogInformation("Arguments: {0}", commandLineArgsString);
//
// Process.Start(module, Array.Empty<string>);
// }
}
}

View File

@ -168,7 +168,7 @@ namespace API.Services
{
_logger.LogDebug("Using SharpCompress compression handling");
using var archive = ArchiveFactory.Open(archivePath);
var entryNames = archive.Entries.Where(entry => !entry.IsDirectory).Select(e => e.Key).ToList();
var entryNames = archive.Entries.Where(archiveEntry => !archiveEntry.IsDirectory).Select(e => e.Key).ToList();
var entryName = FindFolderEntry(entryNames) ?? FirstFileEntry(entryNames);
var entry = archive.Entries.Single(e => e.Key == entryName);

View File

@ -4,7 +4,6 @@ using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using API.Interfaces.Services;
using Microsoft.Extensions.Logging;

View File

@ -4,9 +4,9 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using API.Comparators;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Interfaces;
using API.Extensions;
using API.Interfaces;
using API.Interfaces.Services;
@ -20,6 +20,7 @@ namespace API.Services
private readonly ILogger<MetadataService> _logger;
private readonly IArchiveService _archiveService;
private readonly IBookService _bookService;
private readonly ChapterSortComparer _chapterSortComparer = new ChapterSortComparer();
public MetadataService(IUnitOfWork unitOfWork, ILogger<MetadataService> logger, IArchiveService archiveService, IBookService bookService)
{
@ -61,10 +62,9 @@ namespace API.Services
{
if (volume != null && ShouldFindCoverImage(volume.CoverImage, forceUpdate))
{
// TODO: Replace this with ChapterSortComparator
volume.Chapters ??= new List<Chapter>();
var firstChapter = volume.Chapters.OrderBy(x => double.Parse(x.Number)).FirstOrDefault();
var firstChapter = volume.Chapters.OrderBy(x => double.Parse(x.Number), _chapterSortComparer).FirstOrDefault();
// Skip calculating Cover Image (I/O) if the chapter already has it set
if (firstChapter == null || ShouldFindCoverImage(firstChapter.CoverImage))
{
@ -83,7 +83,6 @@ namespace API.Services
public void UpdateMetadata(Series series, bool forceUpdate)
{
// TODO: Use new ChapterSortComparer() here instead
if (series == null) return;
if (ShouldFindCoverImage(series.CoverImage, forceUpdate))
{
@ -95,13 +94,13 @@ namespace API.Services
// If firstCover is null and one volume, the whole series is Chapters under Vol 0.
if (series.Volumes.Count == 1)
{
coverImage = series.Volumes[0].Chapters.OrderBy(c => double.Parse(c.Number))
coverImage = series.Volumes[0].Chapters.OrderBy(c => double.Parse(c.Number), _chapterSortComparer)
.FirstOrDefault(c => !c.IsSpecial)?.CoverImage;
}
if (coverImage == null)
{
coverImage = series.Volumes[0].Chapters.OrderBy(c => double.Parse(c.Number))
coverImage = series.Volumes[0].Chapters.OrderBy(c => double.Parse(c.Number), _chapterSortComparer)
.FirstOrDefault()?.CoverImage;
}
}

View File

@ -203,7 +203,7 @@ namespace API.Services.Tasks
foreach (var (key, infos) in parsedSeries)
{
// Key is normalized already
Series existingSeries = null;
Series existingSeries;
try
{
existingSeries = library.Series.SingleOrDefault(s => s.NormalizedName == key || Parser.Parser.Normalize(s.OriginalName) == key);
@ -212,16 +212,12 @@ namespace API.Services.Tasks
{
_logger.LogCritical(e, "There are multiple series that map to normalized key {Key}. You can manually delete the entity via UI and rescan to fix it", key);
var duplicateSeries = library.Series.Where(s => s.NormalizedName == key || Parser.Parser.Normalize(s.OriginalName) == key).ToList();
//var firstSeries = duplicateSeries.First();
//duplicateSeries.
foreach (var series in duplicateSeries)
{
_logger.LogCritical("{Key} maps with {Series}", key, series.OriginalName);
}
// Merge them together?
//_unitOfWork.AppUserProgressRepository.MapSeriesProgressFromTo(firstSeries.Id, );
continue;
}
if (existingSeries == null)
@ -366,7 +362,7 @@ namespace API.Services.Tasks
foreach (var info in parsedInfos)
{
var specialTreatment = info.IsSpecialInfo();
Chapter chapter = null;
Chapter chapter;
try
{
chapter = volume.Chapters.GetChapterByRange(info);

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB