mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-08-11 09:13:42 -04:00
Feature/tech debt (#199)
* Added an icon for building the exe * Technical debt
This commit is contained in:
parent
d92e9e7602
commit
f694145cd9
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using API.Data;
|
||||
using API.Tests.Helpers;
|
||||
using API.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace API.Tests.Entities
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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>();
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using API.Entities;
|
||||
using API.Entities;
|
||||
using API.Extensions;
|
||||
using Xunit;
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using API.Services;
|
||||
using System.IO;
|
||||
|
||||
namespace API.Tests.Helpers
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
using API.Services;
|
||||
using Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace API.Tests.Parser
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using API.Entities.Interfaces;
|
||||
using API.Interfaces;
|
||||
using API.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -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]
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<ApplicationIcon>../favicon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
using API.Data;
|
||||
using API.Entities.Interfaces;
|
||||
using API.Helpers;
|
||||
using API.Interfaces;
|
||||
using API.Interfaces.Services;
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using API.Entities;
|
||||
using API.Parser;
|
||||
|
@ -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.
|
||||
|
@ -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>);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Loading…
x
Reference in New Issue
Block a user