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

Light Novel Library Type #2682

Merged
merged 16 commits into from
Feb 8, 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
38 changes: 0 additions & 38 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,48 +26,10 @@ jobs:
- name: Install dependencies
run: dotnet restore

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '17'

- uses: actions/upload-artifact@v3
with:
name: csproj
path: Kavita.Common/Kavita.Common.csproj

- name: Cache SonarCloud packages
uses: actions/cache@v3
with:
path: ~\sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar

- name: Cache SonarCloud scanner
id: cache-sonar-scanner
uses: actions/cache@v3
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
restore-keys: ${{ runner.os }}-sonar-scanner

- name: Install SonarCloud scanner
if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
shell: powershell
run: |
New-Item -Path .\.sonar\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner

- name: Sonar Scan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: |
.\.sonar\scanner\dotnet-sonarscanner begin /k:"Kareadita_Kavita" /o:"kareadita" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io"
dotnet build --configuration Release
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"

- name: Test
run: dotnet test --no-restore --verbosity normal
14 changes: 7 additions & 7 deletions .github/workflows/release-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,23 @@ jobs:
id: parse-body
run: |
body="${{ steps.findPr.outputs.body }}"
body=${body//\'/}
body=${body//'%'/'%25'}
body=${body//$'\n'/'%0A'}
body=${body//$'\r'/'%0D'}
body=${body//$'`'/'%60'}
body=${body//$'>'/'%3E'}

if [[ ${#body} -gt 1870 ]] ; then
body=${body:0:1870}
body="${body}...and much more.

Read full changelog: https://github.com/Kareadita/Kavita/releases/latest"
fi

body=${body//\'/}
body=${body//'%'/'%25'}
body=${body//$'\n'/'%0A'}
body=${body//$'\r'/'%0D'}
body=${body//$'`'/'%60'}
body=${body//$'>'/'%3E'}
echo $body
echo "BODY=$body" >> $GITHUB_OUTPUT


- name: Check Out Repo
uses: actions/checkout@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion API/API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
5 changes: 5 additions & 0 deletions API/Entities/Enums/LibraryType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
2 changes: 1 addition & 1 deletion API/Helpers/Builders/LibraryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public LibraryBuilder(string name, LibraryType type = LibraryType.Manga)
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
};
}

Expand Down
2 changes: 1 addition & 1 deletion API/Helpers/LibraryTypeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static MediaFormat GetFormat(LibraryType libraryType)
{
LibraryType.Manga => MediaFormat.Manga,
LibraryType.Comic => MediaFormat.Comic,
LibraryType.Book => MediaFormat.LightNovel,
LibraryType.LightNovel => MediaFormat.LightNovel,
};
}
}
3 changes: 2 additions & 1 deletion API/Services/Plus/ExternalMetadataService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -420,6 +420,7 @@ private static MediaFormat ConvertToMediaFormat(LibraryType libraryType, MangaFo
LibraryType.Manga => seriesFormat == MangaFormat.Epub ? MediaFormat.LightNovel : MediaFormat.Manga,
LibraryType.Comic => MediaFormat.Comic,
LibraryType.Book => MediaFormat.Book,
LibraryType.LightNovel => MediaFormat.LightNovel,
_ => MediaFormat.Unknown
};
}
Expand Down
9 changes: 9 additions & 0 deletions API/Services/Plus/ScrobblingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down Expand Up @@ -877,6 +880,12 @@ private static bool DoesUserHaveProviderAndValid(ScrobbleEvent readEvent)
return true;
}

if (readEvent.Series.Library.Type == LibraryType.LightNovel &&
LightNovelProviders.Intersect(userProviders).Any())
{
return true;
}

return false;
}

Expand Down
1 change: 1 addition & 0 deletions API/Services/ReaderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ public static string FormatChapterName(LibraryType libraryType, bool includeHash
}
return "Issue" + (includeSpace ? " " : string.Empty);
case LibraryType.Book:
case LibraryType.LightNovel:
return "Book" + (includeSpace ? " " : string.Empty);
default:
throw new ArgumentOutOfRangeException(nameof(libraryType), libraryType, null);
Expand Down
13 changes: 9 additions & 4 deletions API/Services/SeriesService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ public async Task<SeriesDetailDto> GetSeriesDetail(int seriesId, int userId)

// 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)
Expand Down Expand Up @@ -533,7 +533,7 @@ public async Task<SeriesDetailDto> GetSeriesDetail(int seriesId, int userId)

// 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
Expand Down Expand Up @@ -576,7 +576,7 @@ private static bool ShouldIncludeChapter(ChapterDto chapter)

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))
{
Expand All @@ -587,6 +587,7 @@ public static void RenameVolumeName(ChapterDto firstChapter, VolumeDto volume, L
}
else if (volume.Name != "0")
{
// If the titleName has Volume inside it, let's just send that back?
volume.Name += $" - {firstChapter.TitleName}";
}
// else
Expand Down Expand Up @@ -614,6 +615,7 @@ public async Task<string> FormatChapterTitle(int userId, bool isSpecial, Library
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", ' ')
Expand All @@ -636,6 +638,7 @@ public async Task<string> FormatChapterName(int userId, LibraryType libraryType,
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", ' ')
Expand Down Expand Up @@ -723,7 +726,8 @@ public async Task<NextExpectedChapterDto> GetEstimatedChapterCreationDate(int se
{
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;
}
Expand Down Expand Up @@ -803,6 +807,7 @@ public async Task<NextExpectedChapterDto> GetEstimatedChapterCreationDate(int se
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)
};
}
Expand Down
3 changes: 2 additions & 1 deletion API/Services/StatisticService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,8 @@ public async Task<IEnumerable<TopReadDto>> GetTopUsers(int days)
{
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,
})
Expand Down
4 changes: 3 additions & 1 deletion API/Services/Tasks/ScannerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ public async Task ScanFolder(string folder)
_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))
{
Expand Down
2 changes: 0 additions & 2 deletions API/Services/Tasks/VersionUpdaterService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
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;
Expand Down
2 changes: 1 addition & 1 deletion Kavita.Common/Kavita.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<Company>kavitareader.com</Company>
<Product>Kavita</Product>
<AssemblyVersion>0.7.14.0</AssemblyVersion>
<AssemblyVersion>0.8.0.0</AssemblyVersion>
<NeutralLanguage>en</NeutralLanguage>
<TieredPGO>true</TieredPGO>
</PropertyGroup>
Expand Down
3 changes: 2 additions & 1 deletion UI/Web/src/app/_models/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export enum LibraryType {
Manga = 0,
Comic = 1,
Book = 2,
Images = 3
Images = 3,
LightNovel = 4
}

export interface Library {
Expand Down
3 changes: 3 additions & 0 deletions UI/Web/src/app/cards/entity-title/entity-title.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@
<ng-container *ngSwitchCase="LibraryType.Book">
{{volumeTitle}}
</ng-container>
<ng-container *ngSwitchCase="LibraryType.LightNovel">
{{volumeTitle}}
</ng-container>
</ng-container>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ <h4 class="offcanvas-title" id="offcanvas-basic-title">{{t('page-settings-title'

</div>

<div class="row" [ngClass]="{'pt-3': !seriesMetadata || seriesMetadata?.summary?.length === 0}">
<div class="row" [ngClass]="{'pt-3': !seriesMetadata || seriesMetadata.summary.length === 0}">
<app-carousel-reel [items]="reviews" [alwaysShow]="true" [title]="t('user-reviews-alt')"
iconClasses="fa-solid fa-{{getUserReview().length > 0 ? 'pen' : 'plus'}}"
[clickableTitle]="true" (sectionClick)="openReviewModal()">
Expand All @@ -153,7 +153,7 @@ <h4 class="offcanvas-title" id="offcanvas-basic-title">{{t('page-settings-title'
<ng-container *ngIf="series">

<ul ngbNav #nav="ngbNav" [(activeId)]="activeTabId" class="nav nav-tabs mb-2" [destroyOnHide]="false" (navChange)="onNavChange($event)">
<li [ngbNavItem]="TabID.Storyline" *ngIf="libraryType !== LibraryType.Book && (volumes.length > 0 || chapters.length > 0)">
<li [ngbNavItem]="TabID.Storyline" *ngIf="ShowStorylineTab">
<a ngbNavLink>{{t('storyline-tab')}}</a>
<ng-template ngbNavContent>
<virtual-scroller #scroll [items]="storylineItems" [bufferAmount]="1" [parentScroll]="scrollingBlock" [childHeight]="1">
Expand Down Expand Up @@ -181,8 +181,8 @@ <h4 class="offcanvas-title" id="offcanvas-basic-title">{{t('page-settings-title'
</ng-template>
</li>

<li [ngbNavItem]="TabID.Volumes" *ngIf="volumes.length > 0">
<a ngbNavLink>{{libraryType === LibraryType.Book ? t('books-tab') : t('volumes-tab')}}</a>
<li [ngbNavItem]="TabID.Volumes" *ngIf="ShowVolumeTab">
<a ngbNavLink>{{UseBookLogic ? t('books-tab') : t('volumes-tab')}}</a>
<ng-template ngbNavContent>
<virtual-scroller #scroll [items]="volumes" [parentScroll]="scrollingBlock" [childHeight]="1">
<ng-container *ngIf="renderMode === PageLayoutMode.Cards; else volumeListLayout">
Expand All @@ -202,7 +202,7 @@ <h4 class="offcanvas-title" id="offcanvas-basic-title">{{t('page-settings-title'
</ng-template>
</li>

<li [ngbNavItem]="TabID.Chapters" *ngIf="chapters.length > 0">
<li [ngbNavItem]="TabID.Chapters" *ngIf="ShowChaptersTab">
<a ngbNavLink>{{utilityService.formatChapterName(libraryType) + 's'}}</a>
<ng-template ngbNavContent>
<virtual-scroller #scroll [items]="chapters" [parentScroll]="scrollingBlock" [childHeight]="1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

.image-container {
max-height: 400px;
max-width: 280px;
}

.info-container {
Expand All @@ -63,4 +64,4 @@
border-bottom-right-radius: 6px !important;
border-top-left-radius: 0px !important;
border-bottom-left-radius: 0px !important;
}
}
Loading
Loading