diff --git a/API.Tests/Extensions/VolumeListExtensionsTests.cs b/API.Tests/Extensions/VolumeListExtensionsTests.cs index b8b734c51..92a3e93ff 100644 --- a/API.Tests/Extensions/VolumeListExtensionsTests.cs +++ b/API.Tests/Extensions/VolumeListExtensionsTests.cs @@ -154,5 +154,25 @@ public class VolumeListExtensionsTests } + /// + /// Single volume (comicvine type style) with negative or non-numerical + /// + public void GetCoverImage_LooseChapters_WithSub1_InOneVolume() + { + var volumes = new List() + { + new VolumeBuilder("2") + .WithChapter(new ChapterBuilder("-1").WithCoverImage("Chapter -1").Build()) + .WithChapter(new ChapterBuilder("1").WithCoverImage("Chapter 1").Build()) + .Build(), + }; + + // Not testable due to the code not actually doing the heavy lifting + // var actual = volumes.GetCoverImage(MangaFormat.Archive); + // Assert.NotNull(actual); + // Assert.Equal("Chapter 1", actual.CoverImage); + } + + #endregion } diff --git a/API.Tests/Services/CacheServiceTests.cs b/API.Tests/Services/CacheServiceTests.cs index ba06525a3..cd60ed579 100644 --- a/API.Tests/Services/CacheServiceTests.cs +++ b/API.Tests/Services/CacheServiceTests.cs @@ -52,12 +52,12 @@ internal class MockReadingItemServiceForCacheService : IReadingItemService throw new System.NotImplementedException(); } - public ParserInfo Parse(string path, string rootPath, string libraryRoot, LibraryType type) + public ParserInfo Parse(string path, string rootPath, string libraryRoot, Library library) { throw new System.NotImplementedException(); } - public ParserInfo ParseFile(string path, string rootPath, string libraryRoot, LibraryType type) + public ParserInfo ParseFile(string path, string rootPath, string libraryRoot, Library library) { throw new System.NotImplementedException(); } diff --git a/API.Tests/Services/ParseScannedFilesTests.cs b/API.Tests/Services/ParseScannedFilesTests.cs index 04dc20522..03e97530c 100644 --- a/API.Tests/Services/ParseScannedFilesTests.cs +++ b/API.Tests/Services/ParseScannedFilesTests.cs @@ -54,14 +54,14 @@ internal class MockReadingItemService : IReadingItemService throw new NotImplementedException(); } - public ParserInfo Parse(string path, string rootPath, string libraryRoot, LibraryType type) + public ParserInfo Parse(string path, string rootPath, string libraryRoot, Library library) { - return _defaultParser.Parse(path, rootPath, libraryRoot, type); + return _defaultParser.Parse(path, rootPath, libraryRoot, library.Type); } - public ParserInfo ParseFile(string path, string rootPath, string libraryRoot, LibraryType type) + public ParserInfo ParseFile(string path, string rootPath, string libraryRoot, Library library) { - return _defaultParser.Parse(path, rootPath, libraryRoot, type); + return _defaultParser.Parse(path, rootPath, libraryRoot, library.Type); } } diff --git a/API/Entities/Enums/LibraryType.cs b/API/Entities/Enums/LibraryType.cs index ad17e62b1..c9e04238b 100644 --- a/API/Entities/Enums/LibraryType.cs +++ b/API/Entities/Enums/LibraryType.cs @@ -34,5 +34,10 @@ public enum LibraryType /// [Description("Comic (ComicVine)")] ComicVine = 5, + /// + /// This library requires custom regex from admin + /// + [Description("Generic")] + Generic = 6, } diff --git a/API/Extensions/ChapterListExtensions.cs b/API/Extensions/ChapterListExtensions.cs index 0a21cc5ad..db707a5f9 100644 --- a/API/Extensions/ChapterListExtensions.cs +++ b/API/Extensions/ChapterListExtensions.cs @@ -43,6 +43,6 @@ public static class ChapterListExtensions /// public static int MinimumReleaseYear(this IList chapters) { - return chapters.Select(v => v.ReleaseDate.Year).Where(y => NumberHelper.IsValidYear(y)).DefaultIfEmpty().Min(); + return chapters.Select(v => v.ReleaseDate.Year).Where(NumberHelper.IsValidYear).DefaultIfEmpty().Min(); } } diff --git a/API/Services/MetadataService.cs b/API/Services/MetadataService.cs index d0c9d78c2..af46505c7 100644 --- a/API/Services/MetadataService.cs +++ b/API/Services/MetadataService.cs @@ -107,10 +107,16 @@ public class MetadataService : IMetadataService _directoryService.FileSystem.Path.Join(_directoryService.CoverImageDirectory, volume.CoverImage), null, volume.Created, forceUpdate)) return Task.FromResult(false); - + // For cover selection, chapters need to try for issue 1 first, then fallback to first sort order volume.Chapters ??= new List(); - var firstChapter = volume.Chapters.MinBy(x => x.MinNumber, ChapterSortComparerDefaultFirst.Default); - if (firstChapter == null) return Task.FromResult(false); + + var firstChapter = volume.Chapters.FirstOrDefault(x => x.MinNumber.Is(1f)); + if (firstChapter == null) + { + firstChapter = volume.Chapters.MinBy(x => x.SortOrder, ChapterSortComparerDefaultFirst.Default); + if (firstChapter == null) return Task.FromResult(false); + } + volume.CoverImage = firstChapter.CoverImage; _updateEvents.Add(MessageFactory.CoverUpdateEvent(volume.Id, MessageFactoryEntityTypes.Volume)); diff --git a/API/Services/ReadingItemService.cs b/API/Services/ReadingItemService.cs index cd1c508e2..2545c031b 100644 --- a/API/Services/ReadingItemService.cs +++ b/API/Services/ReadingItemService.cs @@ -1,5 +1,6 @@ using System; using API.Data.Metadata; +using API.Entities; using API.Entities.Enums; using API.Services.Tasks.Scanner.Parser; using Microsoft.Extensions.Logging; @@ -13,7 +14,7 @@ public interface IReadingItemService int GetNumberOfPages(string filePath, MangaFormat format); string GetCoverImage(string filePath, string fileName, MangaFormat format, EncodeFormat encodeFormat, CoverImageSize size = CoverImageSize.Default); void Extract(string fileFilePath, string targetDirectory, MangaFormat format, int imageCount = 1); - ParserInfo? ParseFile(string path, string rootPath, string libraryRoot, LibraryType type); + ParserInfo? ParseFile(string path, string rootPath, string libraryRoot, Library library); } public class ReadingItemService : IReadingItemService @@ -28,6 +29,7 @@ public class ReadingItemService : IReadingItemService private readonly ImageParser _imageParser; private readonly BookParser _bookParser; private readonly PdfParser _pdfParser; + private readonly GenericLibraryParser _genericLibraryParser; public ReadingItemService(IArchiveService archiveService, IBookService bookService, IImageService imageService, IDirectoryService directoryService, ILogger logger) @@ -43,6 +45,7 @@ public class ReadingItemService : IReadingItemService _bookParser = new BookParser(directoryService, bookService, _basicParser); _pdfParser = new PdfParser(directoryService); _basicParser = new BasicParser(directoryService, _imageParser); + _genericLibraryParser = new GenericLibraryParser(directoryService); } /// @@ -71,9 +74,9 @@ public class ReadingItemService : IReadingItemService /// Path of a file /// /// Library type to determine parsing to perform - public ParserInfo? ParseFile(string path, string rootPath, string libraryRoot, LibraryType type) + public ParserInfo? ParseFile(string path, string rootPath, string libraryRoot, Library library) { - var info = Parse(path, rootPath, libraryRoot, type); + var info = Parse(path, rootPath, libraryRoot, library); if (info == null) { _logger.LogError("Unable to parse any meaningful information out of file {FilePath}", path); @@ -166,27 +169,31 @@ public class ReadingItemService : IReadingItemService /// /// /// - private ParserInfo? Parse(string path, string rootPath, string libraryRoot, LibraryType type) + private ParserInfo? Parse(string path, string rootPath, string libraryRoot, Library library) { - if (_comicVineParser.IsApplicable(path, type)) + if (_comicVineParser.IsApplicable(path, library.Type)) { - return _comicVineParser.Parse(path, rootPath, libraryRoot, type, GetComicInfo(path)); + return _comicVineParser.Parse(path, rootPath, libraryRoot, library.Type, GetComicInfo(path)); } - if (_imageParser.IsApplicable(path, type)) + if (_imageParser.IsApplicable(path, library.Type)) { - return _imageParser.Parse(path, rootPath, libraryRoot, type, GetComicInfo(path)); + return _imageParser.Parse(path, rootPath, libraryRoot, library.Type, GetComicInfo(path)); } - if (_bookParser.IsApplicable(path, type)) + if (_bookParser.IsApplicable(path, library.Type)) { - return _bookParser.Parse(path, rootPath, libraryRoot, type, GetComicInfo(path)); + return _bookParser.Parse(path, rootPath, libraryRoot, library.Type, GetComicInfo(path)); } - if (_pdfParser.IsApplicable(path, type)) + if (_genericLibraryParser.IsApplicable(path, library.Type)) { - return _pdfParser.Parse(path, rootPath, libraryRoot, type, GetComicInfo(path)); + return _genericLibraryParser.Parse(path, rootPath, libraryRoot, library.Type, GetComicInfo(path)); } - if (_basicParser.IsApplicable(path, type)) + if (_pdfParser.IsApplicable(path, library.Type)) { - return _basicParser.Parse(path, rootPath, libraryRoot, type, GetComicInfo(path)); + return _pdfParser.Parse(path, rootPath, libraryRoot, library.Type, GetComicInfo(path)); + } + if (_basicParser.IsApplicable(path, library.Type)) + { + return _basicParser.Parse(path, rootPath, libraryRoot, library.Type, GetComicInfo(path)); } return null; diff --git a/API/Services/Tasks/Scanner/ParseScannedFiles.cs b/API/Services/Tasks/Scanner/ParseScannedFiles.cs index 498e59d47..a5aafc36e 100644 --- a/API/Services/Tasks/Scanner/ParseScannedFiles.cs +++ b/API/Services/Tasks/Scanner/ParseScannedFiles.cs @@ -411,7 +411,7 @@ public class ParseScannedFiles // Multiple Series can exist within a folder. We should instead put these infos on the result and perform merging above IList infos = files - .Select(file => _readingItemService.ParseFile(file, folder, libraryRoot, library.Type)) + .Select(file => _readingItemService.ParseFile(file, folder, libraryRoot, library)) .Where(info => info != null) .ToList()!; diff --git a/API/Services/Tasks/Scanner/Parser/BasicParser.cs b/API/Services/Tasks/Scanner/Parser/BasicParser.cs index 9df68abb9..459c93fb7 100644 --- a/API/Services/Tasks/Scanner/Parser/BasicParser.cs +++ b/API/Services/Tasks/Scanner/Parser/BasicParser.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; using API.Data.Metadata; using API.Entities.Enums; @@ -11,7 +12,8 @@ namespace API.Services.Tasks.Scanner.Parser; /// public class BasicParser(IDirectoryService directoryService, IDefaultParser imageParser) : DefaultParser(directoryService) { - public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null) + public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, + ComicInfo? comicInfo = null, IEnumerable? extraRegex = null) { var fileName = directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath); // TODO: Potential Bug: This will return null, but on Image libraries, if all images, we would want to include this. diff --git a/API/Services/Tasks/Scanner/Parser/BookParser.cs b/API/Services/Tasks/Scanner/Parser/BookParser.cs index 9c7ed9a16..b72bd7e20 100644 --- a/API/Services/Tasks/Scanner/Parser/BookParser.cs +++ b/API/Services/Tasks/Scanner/Parser/BookParser.cs @@ -1,11 +1,13 @@ -using API.Data.Metadata; +using System.Collections.Generic; +using API.Data.Metadata; using API.Entities.Enums; namespace API.Services.Tasks.Scanner.Parser; public class BookParser(IDirectoryService directoryService, IBookService bookService, IDefaultParser basicParser) : DefaultParser(directoryService) { - public override ParserInfo Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo comicInfo = null) + public override ParserInfo Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, + ComicInfo? comicInfo = null, IEnumerable? extraRegex = null) { var info = bookService.ParseInfo(filePath); if (info == null) return null; diff --git a/API/Services/Tasks/Scanner/Parser/ComicVineParser.cs b/API/Services/Tasks/Scanner/Parser/ComicVineParser.cs index 79830c86c..0b46ad473 100644 --- a/API/Services/Tasks/Scanner/Parser/ComicVineParser.cs +++ b/API/Services/Tasks/Scanner/Parser/ComicVineParser.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; using System.Linq; using API.Data.Metadata; using API.Entities.Enums; @@ -15,11 +16,8 @@ public class ComicVineParser(IDirectoryService directoryService) : DefaultParser /// /// This Parser generates Series name to be defined as Series + first Issue Volume, so "Batman (2020)". /// - /// - /// - /// - /// - public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null) + public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, + ComicInfo? comicInfo = null, IEnumerable? extraRegex = null) { if (type != LibraryType.ComicVine) return null; diff --git a/API/Services/Tasks/Scanner/Parser/DefaultParser.cs b/API/Services/Tasks/Scanner/Parser/DefaultParser.cs index abf59f83a..4aca1a77f 100644 --- a/API/Services/Tasks/Scanner/Parser/DefaultParser.cs +++ b/API/Services/Tasks/Scanner/Parser/DefaultParser.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.IO; using System.Linq; using API.Data.Metadata; @@ -8,7 +9,7 @@ namespace API.Services.Tasks.Scanner.Parser; public interface IDefaultParser { - ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null); + ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null, IEnumerable? extraRegex = null); void ParseFromFallbackFolders(string filePath, string rootPath, LibraryType type, ref ParserInfo ret); bool IsApplicable(string filePath, LibraryType type); } @@ -26,8 +27,11 @@ public abstract class DefaultParser(IDirectoryService directoryService) : IDefau /// /// Root folder /// Allows different Regex to be used for parsing. + /// ComicInfo if present (for epub it si always present) + /// The regex for the Generic Parser /// or null if Series was empty - public abstract ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null); + public abstract ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, + ComicInfo? comicInfo = null, IEnumerable? extraRegex = null); /// /// Fills out by trying to parse volume, chapters, and series from folders diff --git a/API/Services/Tasks/Scanner/Parser/GenericLibraryParser.cs b/API/Services/Tasks/Scanner/Parser/GenericLibraryParser.cs new file mode 100644 index 000000000..ebcb1264c --- /dev/null +++ b/API/Services/Tasks/Scanner/Parser/GenericLibraryParser.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using API.Data.Metadata; +using API.Entities.Enums; + +namespace API.Services.Tasks.Scanner.Parser; +#nullable enable + +/// +/// Uses an at-runtime array of Regex to parse out information +/// +/// +public class GenericLibraryParser(IDirectoryService directoryService) : DefaultParser(directoryService) +{ + public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, + ComicInfo? comicInfo = null, IEnumerable? extraRegex = null) + { + if (extraRegex == null) return null; + + // The idea is this is passed in as a default param. Only Generic will use it + var fileName = directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath); + var info = new ParserInfo() + { + Filename = Path.GetFileName(filePath), + Format = Parser.ParseFormat(filePath), + Title = Parser.RemoveExtensionIfSupported(fileName)!, + FullFilePath = filePath, + Series = string.Empty, + ComicInfo = comicInfo, + Chapters = Parser.ParseComicChapter(fileName), + Volumes = Parser.ParseComicVolume(fileName) + }; + + + foreach (var regex in extraRegex) + { + var matches = new Regex(regex, RegexOptions.IgnoreCase).Matches(fileName); + foreach (var group in matches.Select(match => match.Groups)) + { + foreach (var matchKey in group.Keys) + { + var matchValue = group[matchKey].Value; + switch (matchKey) + { + case "Series": + info.Series = SetIfNotDefault(matchValue, info.Series); + break; + case "Chapter": + info.Chapters = SetIfNotDefault(matchValue, info.Chapters); + break; + } + } + } + } + + // Process the final info here: (cleaning values, setting internal encoding overrides) + if (info.IsSpecial) + { + info.Volumes = Parser.SpecialVolume; + } + + if (string.IsNullOrEmpty(info.Chapters)) + { + info.Chapters = Parser.DefaultChapter; + } + + if (!info.IsSpecial && string.IsNullOrEmpty(info.Volumes)) + { + info.Chapters = Parser.LooseLeafVolume; + } + + + return string.IsNullOrEmpty(info.Series) ? null : info; + } + + private static string SetIfNotDefault(string value, string originalValue) + { + if (string.IsNullOrEmpty(value)) return originalValue; + if (string.IsNullOrEmpty(originalValue)) return value; + + return originalValue; + } + + public override bool IsApplicable(string filePath, LibraryType type) + { + return type == LibraryType.Generic; + } +} diff --git a/API/Services/Tasks/Scanner/Parser/ImageParser.cs b/API/Services/Tasks/Scanner/Parser/ImageParser.cs index a1227d841..a2e08dea9 100644 --- a/API/Services/Tasks/Scanner/Parser/ImageParser.cs +++ b/API/Services/Tasks/Scanner/Parser/ImageParser.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; using API.Data.Metadata; using API.Entities.Enums; @@ -7,7 +8,8 @@ namespace API.Services.Tasks.Scanner.Parser; public class ImageParser(IDirectoryService directoryService) : DefaultParser(directoryService) { - public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo? comicInfo = null) + public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, + ComicInfo? comicInfo = null, IEnumerable? extraRegex = null) { if (type != LibraryType.Image || !Parser.IsImage(filePath)) return null; diff --git a/API/Services/Tasks/Scanner/Parser/PdfParser.cs b/API/Services/Tasks/Scanner/Parser/PdfParser.cs index 1b90a95e7..aa203887b 100644 --- a/API/Services/Tasks/Scanner/Parser/PdfParser.cs +++ b/API/Services/Tasks/Scanner/Parser/PdfParser.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; using API.Data.Metadata; using API.Entities.Enums; @@ -6,7 +7,8 @@ namespace API.Services.Tasks.Scanner.Parser; public class PdfParser(IDirectoryService directoryService) : DefaultParser(directoryService) { - public override ParserInfo Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, ComicInfo comicInfo = null) + public override ParserInfo Parse(string filePath, string rootPath, string libraryRoot, LibraryType type, + ComicInfo? comicInfo = null, IEnumerable? extraRegex = null) { var fileName = directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath); var ret = new ParserInfo diff --git a/UI/Web/src/app/_models/library/library.ts b/UI/Web/src/app/_models/library/library.ts index c8b55bd1d..f53492694 100644 --- a/UI/Web/src/app/_models/library/library.ts +++ b/UI/Web/src/app/_models/library/library.ts @@ -1,12 +1,13 @@ import {FileTypeGroup} from "./file-type-group.enum"; export enum LibraryType { - Manga = 0, - Comic = 1, - Book = 2, - Images = 3, - LightNovel = 4, - ComicVine = 5 + Manga = 0, + Comic = 1, + Book = 2, + Images = 3, + LightNovel = 4, + ComicVine = 5, + Generic = 6 } export interface Library { diff --git a/UI/Web/src/app/_pipes/library-type.pipe.ts b/UI/Web/src/app/_pipes/library-type.pipe.ts index b9f74dc05..ee29367a6 100644 --- a/UI/Web/src/app/_pipes/library-type.pipe.ts +++ b/UI/Web/src/app/_pipes/library-type.pipe.ts @@ -24,6 +24,10 @@ export class LibraryTypePipe implements PipeTransform { return this.translocoService.translate('library-type-pipe.image'); case LibraryType.Manga: return this.translocoService.translate('library-type-pipe.manga'); + case LibraryType.LightNovel: + return this.translocoService.translate('library-type-pipe.lightNovel'); + case LibraryType.Generic: + return this.translocoService.translate('library-type-pipe.generic'); default: return ''; } diff --git a/UI/Web/src/app/shared/_services/utility.service.ts b/UI/Web/src/app/shared/_services/utility.service.ts index 496d58aad..c4676efcd 100644 --- a/UI/Web/src/app/shared/_services/utility.service.ts +++ b/UI/Web/src/app/shared/_services/utility.service.ts @@ -65,6 +65,7 @@ export class UtilityService { switch(libraryType) { case LibraryType.Book: case LibraryType.LightNovel: + case LibraryType.Generic: return this.translocoService.translate('common.book-num') + (includeSpace ? ' ' : ''); case LibraryType.Comic: case LibraryType.ComicVine: diff --git a/UI/Web/src/app/sidenav/_components/side-nav/side-nav.component.ts b/UI/Web/src/app/sidenav/_components/side-nav/side-nav.component.ts index 39efc38be..b85e9933e 100644 --- a/UI/Web/src/app/sidenav/_components/side-nav/side-nav.component.ts +++ b/UI/Web/src/app/sidenav/_components/side-nav/side-nav.component.ts @@ -185,6 +185,7 @@ export class SideNavComponent implements OnInit { getLibraryTypeIcon(format: LibraryType) { switch (format) { case LibraryType.Book: + case LibraryType.Generic: case LibraryType.LightNovel: return 'fa-book'; case LibraryType.Comic: diff --git a/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.ts b/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.ts index 141fd99d7..10ec6ec22 100644 --- a/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.ts +++ b/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.ts @@ -196,6 +196,12 @@ export class LibrarySettingsModalComponent implements OnInit { this.libraryForm.get(FileTypeGroup.Pdf + '')?.setValue(false); this.libraryForm.get(FileTypeGroup.Epub + '')?.setValue(false); break; + case LibraryType.Generic: + this.libraryForm.get(FileTypeGroup.Archive + '')?.setValue(false); + this.libraryForm.get(FileTypeGroup.Images + '')?.setValue(false); + this.libraryForm.get(FileTypeGroup.Pdf + '')?.setValue(true); + this.libraryForm.get(FileTypeGroup.Epub + '')?.setValue(false); + break; } }), takeUntilDestroyed(this.destroyRef) diff --git a/UI/Web/src/assets/langs/en.json b/UI/Web/src/assets/langs/en.json index 535962fab..52f46ade3 100644 --- a/UI/Web/src/assets/langs/en.json +++ b/UI/Web/src/assets/langs/en.json @@ -502,7 +502,9 @@ "comic": "Comic", "manga": "Manga", "comicVine": "ComicVine", - "image": "Image" + "image": "Image", + "lightNovel": "Light Novel", + "generic": "Generic" }, "age-rating-pipe": { diff --git a/openapi.json b/openapi.json index d75eba614..43509ccb9 100644 --- a/openapi.json +++ b/openapi.json @@ -7,7 +7,7 @@ "name": "GPL-3.0", "url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE" }, - "version": "0.7.14.9" + "version": "0.7.14.10" }, "servers": [ { @@ -2924,7 +2924,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -2938,7 +2939,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -2952,7 +2954,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -3640,7 +3643,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -13549,7 +13553,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -14174,7 +14179,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "description": "Library type", @@ -15965,7 +15971,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -16080,7 +16087,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -17082,7 +17090,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -17136,7 +17145,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32" @@ -19528,7 +19538,8 @@ 2, 3, 4, - 5 + 5, + 6 ], "type": "integer", "format": "int32"