Light Novel Library Type (#2682)
This commit is contained in:
parent
a40c019ddb
commit
8b2649302c
26 changed files with 237 additions and 148 deletions
|
@ -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" />
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ public static class LibraryTypeHelper
|
|||
{
|
||||
LibraryType.Manga => MediaFormat.Manga,
|
||||
LibraryType.Comic => MediaFormat.Comic,
|
||||
LibraryType.Book => MediaFormat.LightNovel,
|
||||
LibraryType.LightNovel => MediaFormat.LightNovel,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue