Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.8.4.1 - Hotfix #3419

Merged
merged 14 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions API.Tests/Parsing/ParsingTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using Xunit;
using static API.Services.Tasks.Scanner.Parser.Parser;

Expand All @@ -15,6 +16,16 @@ public void ShouldWork()
Assert.Equal(6.5f, a);
}

// [Theory]
// [InlineData("de-DE")]
// [InlineData("en-US")]
// public void ShouldParse(string culture)
// {
// var s = 6.5f + "";
// var a = float.Parse(s, CultureInfo.CreateSpecificCulture(culture));
// Assert.Equal(6.5f, a);
// }

[Theory]
[InlineData("Joe Shmo, Green Blue", "Joe Shmo, Green Blue")]
[InlineData("Shmo, Joe", "Shmo, Joe")]
Expand Down
2 changes: 1 addition & 1 deletion API/API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
<PackageReference Include="Serilog.Sinks.SignalR.Core" Version="0.1.2" />
<PackageReference Include="SharpCompress" Version="0.38.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167">
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.3.0.106239">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
66 changes: 58 additions & 8 deletions API/Controllers/LibraryController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using AutoMapper;
using EasyCaching.Core;
using Hangfire;
using Kavita.Common;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -447,12 +448,58 @@
return Ok();
}

/// <summary>
/// Deletes the library and all series within it.
/// </summary>
/// <remarks>This does not touch any files</remarks>
/// <param name="libraryId"></param>
/// <returns></returns>
[Authorize(Policy = "RequireAdminRole")]
[HttpDelete("delete")]
public async Task<ActionResult<bool>> DeleteLibrary(int libraryId)
{
_logger.LogInformation("Library {LibraryId} is being deleted by {UserName}", libraryId, User.GetUsername());

try
{
return Ok(await DeleteLibrary(libraryId, User.GetUserId()));
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}

/// <summary>
/// Deletes multiple libraries and all series within it.
/// </summary>
/// <remarks>This does not touch any files</remarks>
/// <param name="libraryIds"></param>
/// <returns></returns>
[Authorize(Policy = "RequireAdminRole")]
[HttpDelete("delete-multiple")]
public async Task<ActionResult<bool>> DeleteMultipleLibraries([FromQuery] List<int> libraryIds)
{
var username = User.GetUsername();
_logger.LogInformation("Library {LibraryId} is being deleted by {UserName}", libraryId, username);
_logger.LogInformation("Libraries {LibraryIds} are being deleted by {UserName}", libraryIds, username);
Dismissed Show dismissed Hide dismissed

foreach (var libraryId in libraryIds)
{
try
{
await DeleteLibrary(libraryId, User.GetUserId());
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}

return Ok();
}

private async Task<bool> DeleteLibrary(int libraryId, int userId)
{
var series = await _unitOfWork.SeriesRepository.GetSeriesForLibraryIdAsync(libraryId);
var seriesIds = series.Select(x => x.Id).ToArray();
var chapterIds =
Expand All @@ -463,16 +510,19 @@
if (TaskScheduler.HasScanTaskRunningForLibrary(libraryId))
{
_logger.LogInformation("User is attempting to delete a library while a scan is in progress");
return BadRequest(await _localizationService.Translate(User.GetUserId(), "delete-library-while-scan"));
throw new KavitaException(await _localizationService.Translate(userId, "delete-library-while-scan"));
}

var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryId);
if (library == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "library-doesnt-exist"));
if (library == null)
{
throw new KavitaException(await _localizationService.Translate(userId, "library-doesnt-exist"));
}


// Due to a bad schema that I can't figure out how to fix, we need to erase all RelatedSeries before we delete the library
// Aka SeriesRelation has an invalid foreign key
foreach (var s in await _unitOfWork.SeriesRepository.GetSeriesForLibraryIdAsync(library.Id,
SeriesIncludes.Related))
foreach (var s in await _unitOfWork.SeriesRepository.GetSeriesForLibraryIdAsync(library.Id, SeriesIncludes.Related))
{
s.Relations = new List<SeriesRelation>();
_unitOfWork.SeriesRepository.Update(s);
Expand All @@ -489,7 +539,7 @@

await _libraryCacheProvider.RemoveByPrefixAsync(CacheKey);
await _eventHub.SendMessageAsync(MessageFactory.SideNavUpdate,
MessageFactory.SideNavUpdateEvent(User.GetUserId()), false);
MessageFactory.SideNavUpdateEvent(userId), false);

if (chapterIds.Any())
{
Expand All @@ -508,13 +558,13 @@

await _eventHub.SendMessageAsync(MessageFactory.LibraryModified,
MessageFactory.LibraryModifiedEvent(libraryId, "delete"), false);
return Ok(true);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "There was a critical issue. Please try again");
await _unitOfWork.RollbackAsync();
return Ok(false);
return false;
}
}

Expand Down
2 changes: 2 additions & 0 deletions API/Controllers/ReaderController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,8 @@ public async Task<ActionResult> MarkMultipleSeriesAsUnread(MarkMultipleSeriesAsR
public async Task<ActionResult<ProgressDto>> GetProgress(int chapterId)
{
var progress = await _unitOfWork.AppUserProgressRepository.GetUserProgressDtoAsync(chapterId, User.GetUserId());
_logger.LogDebug("Get Progress for {ChapterId} is {Pages}", chapterId, progress?.PageNum ?? 0);

if (progress == null) return Ok(new ProgressDto()
{
PageNum = 0,
Expand Down
3 changes: 2 additions & 1 deletion API/Data/ManualMigrations/MigrateChapterRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Threading.Tasks;
using API.Entities;
using API.Extensions;
using API.Helpers.Builders;
using API.Services.Tasks.Scanner.Parser;
using Kavita.Common.EnvironmentInfo;
Expand All @@ -28,7 +29,7 @@ public static async Task Migrate(DataContext dataContext, IUnitOfWork unitOfWork
var chapters = await dataContext.Chapter.ToListAsync();
foreach (var chapter in chapters)
{
if (Parser.MinNumberFromRange(chapter.Range) == 0.0f)
if (Parser.MinNumberFromRange(chapter.Range).Is(0.0f))
{
chapter.Range = chapter.GetNumberTitle();
}
Expand Down
30 changes: 20 additions & 10 deletions API/Entities/Chapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,32 @@ public void UpdateFrom(ParserInfo info)
/// <returns></returns>
public string GetNumberTitle()
{
if (MinNumber.Is(MaxNumber))
// BUG: TODO: On non-english locales, for floats, the range will be 20,5 but the NumberTitle will return 20.5
// Have I fixed this with TryParse CultureInvariant
try
{
if (MinNumber.Is(Parser.DefaultChapterNumber) && IsSpecial)
if (MinNumber.Is(MaxNumber))
{
return Parser.RemoveExtensionIfSupported(Title);
}
if (MinNumber.Is(Parser.DefaultChapterNumber) && IsSpecial)
{
return Parser.RemoveExtensionIfSupported(Title);
}

if (MinNumber.Is(0) && !float.TryParse(Range, CultureInfo.InvariantCulture, out _))
{
return $"{Range}";
}
if (MinNumber.Is(0f) && !float.TryParse(Range, CultureInfo.InvariantCulture, out _))
{
return $"{Range.ToString(CultureInfo.InvariantCulture)}";
}

return $"{MinNumber}";
return $"{MinNumber.ToString(CultureInfo.InvariantCulture)}";

}

return $"{MinNumber.ToString(CultureInfo.InvariantCulture)}-{MaxNumber.ToString(CultureInfo.InvariantCulture)}";
}
catch (Exception)
{
return MinNumber.ToString(CultureInfo.InvariantCulture);
}
return $"{MinNumber}-{MaxNumber}";
}

/// <summary>
Expand Down
8 changes: 5 additions & 3 deletions API/Entities/Volume.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using API.Entities.Interfaces;
using API.Extensions;
using API.Services.Tasks.Scanner.Parser;
Expand Down Expand Up @@ -67,11 +68,12 @@ public class Volume : IEntityDate, IHasReadTimeEstimate, IHasCoverImage
/// <returns></returns>
public string GetNumberTitle()
{
if (MinNumber.Is(MaxNumber))
if (MinNumber.Equals(MaxNumber))
{
return $"{MinNumber}";
return MinNumber.ToString(CultureInfo.InvariantCulture);
}
return $"{MinNumber}-{MaxNumber}";

return $"{MinNumber.ToString(CultureInfo.InvariantCulture)}-{MaxNumber.ToString(CultureInfo.InvariantCulture)}";
}

public void ResetColorScape()
Expand Down
2 changes: 1 addition & 1 deletion API/Extensions/ChapterListExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static class ChapterListExtensions
fakeChapter.UpdateFrom(info);
return specialTreatment
? chapters.FirstOrDefault(c => c.Range == Parser.RemoveExtensionIfSupported(info.Filename) || c.Files.Select(f => Parser.NormalizePath(f.FilePath)).Contains(normalizedPath))
: chapters.FirstOrDefault(c => c.Range == fakeChapter.GetNumberTitle()); // BUG: TODO: On non-english locales, for floats, the range will be 20,5 but the NumberTitle will return 20.5
: chapters.FirstOrDefault(c => c.Range == fakeChapter.GetNumberTitle());
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion API/Services/BookService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ public async Task<Dictionary<string, int>> CreateKeyToPageMappingAsync(EpubBookR
}

/// <summary>
/// Extracts a pdf into images to a target directory. Uses multi-threaded implementation since docnet is slow normally.
/// Extracts a pdf into images to a target directory. Uses multithreaded implementation since docnet is slow normally.
/// </summary>
/// <param name="fileFilePath"></param>
/// <param name="targetDirectory"></param>
Expand Down
2 changes: 1 addition & 1 deletion API/Services/DirectoryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ public IEnumerable<string> GetAllDirectories(string folderPath, GlobMatcher? mat
if (!FileSystem.Directory.Exists(folderPath)) return ImmutableArray<string>.Empty;
var directories = new List<string>();

var foundDirs = GetDirectories(folderPath);
var foundDirs = GetDirectories(folderPath, matcher);
foreach (var foundDir in foundDirs)
{
directories.Add(foundDir);
Expand Down
4 changes: 2 additions & 2 deletions API/Services/Tasks/Scanner/ParseScannedFiles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -818,11 +818,11 @@ private static void UpdateSortOrder(ConcurrentDictionary<ParsedSeries, List<Pars
chapter.IssueOrder = counter;

// Increment for next chapter (unless the next has a similar value, then add 0.1)
if (!string.IsNullOrEmpty(prevIssue) && float.TryParse(prevIssue, CultureInfo.InvariantCulture, out var prevIssueFloat) && parsedChapter.Is(prevIssueFloat))
if (!string.IsNullOrEmpty(prevIssue) && float.TryParse(prevIssue, NumberStyles.Any, CultureInfo.InvariantCulture, out var prevIssueFloat) && parsedChapter.Is(prevIssueFloat))
{
counter += 0.1f; // bump if same value as the previous issue
}
prevIssue = $"{parsedChapter}";
prevIssue = $"{parsedChapter.ToString(CultureInfo.InvariantCulture)}";
}
else
{
Expand Down
15 changes: 10 additions & 5 deletions API/Services/Tasks/Scanner/Parser/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace API.Services.Tasks.Scanner.Parser;
#nullable enable

public static class Parser
public static partial class Parser
{
// NOTE: If you change this, don't forget to change in the UI (see Series Detail)
public const string DefaultChapter = "-100000"; // -2147483648
Expand Down Expand Up @@ -1054,7 +1054,7 @@ public static float MinNumberFromRange(string range)
}

// Check if there is a range or not
if (Regex.IsMatch(range, @"\d-{1}\d"))
if (NumberRangeRegex().IsMatch(range))
{

var tokens = range.Replace("_", string.Empty).Split("-", StringSplitOptions.RemoveEmptyEntries);
Expand All @@ -1081,7 +1081,7 @@ public static float MaxNumberFromRange(string range)
}

// Check if there is a range or not
if (Regex.IsMatch(range, @"\d-{1}\d"))
if (NumberRangeRegex().IsMatch(range))
{

var tokens = range.Replace("_", string.Empty).Split("-", StringSplitOptions.RemoveEmptyEntries);
Expand Down Expand Up @@ -1244,10 +1244,15 @@ public static string ParseYear(string? name)
{
if (string.IsNullOrEmpty(filename)) return filename;

if (Regex.IsMatch(filename, SupportedExtensions))
if (SupportedExtensionsRegex().IsMatch(filename))
{
return Regex.Replace(filename, SupportedExtensions, string.Empty);
return SupportedExtensionsRegex().Replace(filename, string.Empty);
}
return filename;
}

[GeneratedRegex(SupportedExtensions)]
private static partial Regex SupportedExtensionsRegex();
[GeneratedRegex(@"\d-{1}\d")]
private static partial Regex NumberRangeRegex();
}
7 changes: 7 additions & 0 deletions UI/Web/src/app/_services/library.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ export class LibraryService {
return this.httpClient.delete(this.baseUrl + 'library/delete?libraryId=' + libraryId, {});
}

deleteMultiple(libraryIds: Array<number>) {
if (libraryIds.length === 0) {
return of();
}
return this.httpClient.delete(this.baseUrl + 'library/delete-multiple?libraryIds=' + libraryIds.join(','), {});
}

update(model: {name: string, folders: string[], id: number}) {
return this.httpClient.post(this.baseUrl + 'library/update', model);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
selector: 'app-actionable-modal',
standalone: true,
imports: [
NgClass,
TranslocoDirective
],
templateUrl: './actionable-modal.component.html',
Expand Down Expand Up @@ -66,7 +65,8 @@ export class ActionableModalComponent implements OnInit {
...item,
children: [], // Required as dynamic list is only one deep
title: di.title,
_extra: di
_extra: di,
action: item.children[0].action // override action to be correct from child
}));
});
} else {
Expand Down
Loading
Loading