Light Novel Library Type (#2682)

This commit is contained in:
Joe Milazzo 2024-02-08 12:35:05 -06:00 committed by GitHub
parent a40c019ddb
commit 8b2649302c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 237 additions and 148 deletions

View file

@ -69,7 +69,7 @@
<PackageReference Include="Hangfire.InMemory" Version="0.7.0" />
<PackageReference Include="Hangfire.MaximumConcurrentExecutions" Version="1.1.0" />
<PackageReference Include="Hangfire.Storage.SQLite" Version="0.4.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.57" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.58" />
<PackageReference Include="MarkdownDeep.NET.Core" Version="1.5.0.4" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.9" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />

View file

@ -24,4 +24,9 @@ public enum LibraryType
/// </summary>
[Description("Image")]
Image = 3,
/// <summary>
/// Allows Books to Scrobble with AniList for Kavita+
/// </summary>
[Description("Light Novel")]
LightNovel = 4,
}

View file

@ -20,7 +20,7 @@ public class LibraryBuilder : IEntityBuilder<Library>
Series = new List<Series>(),
Folders = new List<FolderPath>(),
AppUsers = new List<AppUser>(),
AllowScrobbling = type is LibraryType.Book or LibraryType.Manga
AllowScrobbling = type is LibraryType.LightNovel or LibraryType.Manga
};
}

View file

@ -13,7 +13,7 @@ public static class LibraryTypeHelper
{
LibraryType.Manga => MediaFormat.Manga,
LibraryType.Comic => MediaFormat.Comic,
LibraryType.Book => MediaFormat.LightNovel,
LibraryType.LightNovel => MediaFormat.LightNovel,
};
}
}

View file

@ -69,7 +69,7 @@ public class ExternalMetadataService : IExternalMetadataService
private readonly IMapper _mapper;
private readonly ILicenseService _licenseService;
private readonly TimeSpan _externalSeriesMetadataCache = TimeSpan.FromDays(30);
public static readonly ImmutableArray<LibraryType> NonEligibleLibraryTypes = ImmutableArray.Create<LibraryType>(LibraryType.Comic);
public static readonly ImmutableArray<LibraryType> NonEligibleLibraryTypes = ImmutableArray.Create<LibraryType>(LibraryType.Comic, LibraryType.Book);
private readonly SeriesDetailPlusDto _defaultReturn = new()
{
Recommendations = null,
@ -420,6 +420,7 @@ public class ExternalMetadataService : IExternalMetadataService
LibraryType.Manga => seriesFormat == MangaFormat.Epub ? MediaFormat.LightNovel : MediaFormat.Manga,
LibraryType.Comic => MediaFormat.Comic,
LibraryType.Book => MediaFormat.Book,
LibraryType.LightNovel => MediaFormat.LightNovel,
_ => MediaFormat.Unknown
};
}

View file

@ -80,6 +80,9 @@ public class ScrobblingService : IScrobblingService
private const int ScrobbleSleepTime = 1000; // We can likely tie this to AniList's 90 rate / min ((60 * 1000) / 90)
private static readonly IList<ScrobbleProvider> BookProviders = new List<ScrobbleProvider>()
{
};
private static readonly IList<ScrobbleProvider> LightNovelProviders = new List<ScrobbleProvider>()
{
ScrobbleProvider.AniList
};
@ -877,6 +880,12 @@ public class ScrobblingService : IScrobblingService
return true;
}
if (readEvent.Series.Library.Type == LibraryType.LightNovel &&
LightNovelProviders.Intersect(userProviders).Any())
{
return true;
}
return false;
}

View file

@ -776,6 +776,7 @@ public class ReaderService : IReaderService
}
return "Issue" + (includeSpace ? " " : string.Empty);
case LibraryType.Book:
case LibraryType.LightNovel:
return "Book" + (includeSpace ? " " : string.Empty);
default:
throw new ArgumentOutOfRangeException(nameof(libraryType), libraryType, null);

View file

@ -489,7 +489,7 @@ public class SeriesService : ISeriesService
// For books, the Name of the Volume is remapped to the actual name of the book, rather than Volume number.
var processedVolumes = new List<VolumeDto>();
if (libraryType == LibraryType.Book)
if (libraryType is LibraryType.Book or LibraryType.LightNovel)
{
var volumeLabel = await _localizationService.Translate(userId, "volume-num", string.Empty);
foreach (var volume in volumes)
@ -533,7 +533,7 @@ public class SeriesService : ISeriesService
// Don't show chapter 0 (aka single volume chapters) in the Chapters tab or books that are just single numbers (they show as volumes)
IEnumerable<ChapterDto> retChapters;
if (libraryType == LibraryType.Book)
if (libraryType is LibraryType.Book or LibraryType.LightNovel)
{
retChapters = Array.Empty<ChapterDto>();
} else
@ -576,7 +576,7 @@ public class SeriesService : ISeriesService
public static void RenameVolumeName(ChapterDto firstChapter, VolumeDto volume, LibraryType libraryType, string volumeLabel = "Volume")
{
if (libraryType == LibraryType.Book)
if (libraryType is LibraryType.Book or LibraryType.LightNovel)
{
if (string.IsNullOrEmpty(firstChapter.TitleName))
{
@ -587,6 +587,7 @@ public class SeriesService : ISeriesService
}
else if (volume.Name != "0")
{
// If the titleName has Volume inside it, let's just send that back?
volume.Name += $" - {firstChapter.TitleName}";
}
// else
@ -614,6 +615,7 @@ public class SeriesService : ISeriesService
return libraryType switch
{
LibraryType.Book => await _localizationService.Translate(userId, "book-num", chapterTitle),
LibraryType.LightNovel => await _localizationService.Translate(userId, "book-num", chapterTitle),
LibraryType.Comic => await _localizationService.Translate(userId, "issue-num", hashSpot, chapterTitle),
LibraryType.Manga => await _localizationService.Translate(userId, "chapter-num", chapterTitle),
_ => await _localizationService.Translate(userId, "chapter-num", ' ')
@ -636,6 +638,7 @@ public class SeriesService : ISeriesService
return (libraryType switch
{
LibraryType.Book => await _localizationService.Translate(userId, "book-num", string.Empty),
LibraryType.LightNovel => await _localizationService.Translate(userId, "book-num", string.Empty),
LibraryType.Comic => await _localizationService.Translate(userId, "issue-num", hashSpot, string.Empty),
LibraryType.Manga => await _localizationService.Translate(userId, "chapter-num", string.Empty),
_ => await _localizationService.Translate(userId, "chapter-num", ' ')
@ -723,7 +726,8 @@ public class SeriesService : ISeriesService
{
throw new UnauthorizedAccessException("user-no-access-library-from-series");
}
if (series.Metadata.PublicationStatus is not (PublicationStatus.OnGoing or PublicationStatus.Ended) || series.Library.Type == LibraryType.Book)
if (series.Metadata.PublicationStatus is not (PublicationStatus.OnGoing or PublicationStatus.Ended) ||
(series.Library.Type is LibraryType.Book or LibraryType.LightNovel))
{
return _emptyExpectedChapter;
}
@ -803,6 +807,7 @@ public class SeriesService : ISeriesService
LibraryType.Manga => await _localizationService.Translate(userId, "chapter-num", result.ChapterNumber),
LibraryType.Comic => await _localizationService.Translate(userId, "issue-num", "#", result.ChapterNumber),
LibraryType.Book => await _localizationService.Translate(userId, "book-num", result.ChapterNumber),
LibraryType.LightNovel => await _localizationService.Translate(userId, "book-num", result.ChapterNumber),
_ => await _localizationService.Translate(userId, "chapter-num", result.ChapterNumber)
};
}

View file

@ -595,7 +595,8 @@ public class StatisticService : IStatisticService
{
UserId = userId,
Username = users.First(u => u.Id == userId).UserName,
BooksTime = user[userId].TryGetValue(LibraryType.Book, out var bookTime) ? bookTime : 0,
BooksTime = user[userId].TryGetValue(LibraryType.Book, out var bookTime) ? bookTime : 0 +
(user[userId].TryGetValue(LibraryType.LightNovel, out var bookTime2) ? bookTime2 : 0),
ComicsTime = user[userId].TryGetValue(LibraryType.Comic, out var comicTime) ? comicTime : 0,
MangaTime = user[userId].TryGetValue(LibraryType.Manga, out var mangaTime) ? mangaTime : 0,
})

View file

@ -152,7 +152,9 @@ public class ScannerService : IScannerService
_logger.LogCritical("[ScannerService] Multiple series map to this folder. Library scan will be used for ScanFolder");
}
}
if (series != null && series.Library.Type != LibraryType.Book)
// TODO: Figure out why we have the library type restriction here
if (series != null && (series.Library.Type != LibraryType.Book || series.Library.Type != LibraryType.LightNovel))
{
if (TaskScheduler.HasScanTaskRunningForSeries(series.Id))
{

View file

@ -5,11 +5,9 @@ using System.Threading.Tasks;
using API.DTOs.Update;
using API.SignalR;
using Flurl.Http;
using HtmlAgilityPack;
using Kavita.Common.EnvironmentInfo;
using Kavita.Common.Helpers;
using MarkdownDeep;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace API.Services.Tasks;