Implemented a Generic Library that uses Regex from the admin to parse the files. Still a bit of a WIP on how it's actually going to work or if it will be usable.
This commit is contained in:
parent
9d31262448
commit
6f4162d793
22 changed files with 224 additions and 60 deletions
|
@ -154,5 +154,25 @@ public class VolumeListExtensionsTests
|
|||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Single volume (comicvine type style) with negative or non-numerical
|
||||
/// </summary>
|
||||
public void GetCoverImage_LooseChapters_WithSub1_InOneVolume()
|
||||
{
|
||||
var volumes = new List<Volume>()
|
||||
{
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,5 +34,10 @@ public enum LibraryType
|
|||
/// </summary>
|
||||
[Description("Comic (ComicVine)")]
|
||||
ComicVine = 5,
|
||||
/// <summary>
|
||||
/// This library requires custom regex from admin
|
||||
/// </summary>
|
||||
[Description("Generic")]
|
||||
Generic = 6,
|
||||
|
||||
}
|
||||
|
|
|
@ -43,6 +43,6 @@ public static class ChapterListExtensions
|
|||
/// <returns></returns>
|
||||
public static int MinimumReleaseYear(this IList<Chapter> 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Chapter>();
|
||||
var firstChapter = volume.Chapters.MinBy(x => x.MinNumber, ChapterSortComparerDefaultFirst.Default);
|
||||
|
||||
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));
|
||||
|
|
|
@ -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<ReadingItemService> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -71,9 +74,9 @@ public class ReadingItemService : IReadingItemService
|
|||
/// <param name="path">Path of a file</param>
|
||||
/// <param name="rootPath"></param>
|
||||
/// <param name="type">Library type to determine parsing to perform</param>
|
||||
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
|
|||
/// <param name="rootPath"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
|
|
|
@ -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<ParserInfo> infos = files
|
||||
.Select(file => _readingItemService.ParseFile(file, folder, libraryRoot, library.Type))
|
||||
.Select(file => _readingItemService.ParseFile(file, folder, libraryRoot, library))
|
||||
.Where(info => info != null)
|
||||
.ToList()!;
|
||||
|
||||
|
|
|
@ -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;
|
|||
/// </summary>
|
||||
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<string>? 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.
|
||||
|
|
|
@ -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<string>? extraRegex = null)
|
||||
{
|
||||
var info = bookService.ParseInfo(filePath);
|
||||
if (info == null) return null;
|
||||
|
|
|
@ -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
|
|||
/// <summary>
|
||||
/// This Parser generates Series name to be defined as Series + first Issue Volume, so "Batman (2020)".
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="rootPath"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
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<string>? extraRegex = null)
|
||||
{
|
||||
if (type != LibraryType.ComicVine) return null;
|
||||
|
||||
|
|
|
@ -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<string>? 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
|
|||
/// <param name="filePath"></param>
|
||||
/// <param name="rootPath">Root folder</param>
|
||||
/// <param name="type">Allows different Regex to be used for parsing.</param>
|
||||
/// <param name="comicInfo">ComicInfo if present (for epub it si always present)</param>
|
||||
/// <param name="extraRegex">The regex for the Generic Parser</param>
|
||||
/// <returns><see cref="ParserInfo"/> or null if Series was empty</returns>
|
||||
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<string>? extraRegex = null);
|
||||
|
||||
/// <summary>
|
||||
/// Fills out <see cref="ParserInfo"/> by trying to parse volume, chapters, and series from folders
|
||||
|
|
90
API/Services/Tasks/Scanner/Parser/GenericLibraryParser.cs
Normal file
90
API/Services/Tasks/Scanner/Parser/GenericLibraryParser.cs
Normal file
|
@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Uses an at-runtime array of Regex to parse out information
|
||||
/// </summary>
|
||||
/// <param name="directoryService"></param>
|
||||
public class GenericLibraryParser(IDirectoryService directoryService) : DefaultParser(directoryService)
|
||||
{
|
||||
public override ParserInfo? Parse(string filePath, string rootPath, string libraryRoot, LibraryType type,
|
||||
ComicInfo? comicInfo = null, IEnumerable<string>? 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;
|
||||
}
|
||||
}
|
|
@ -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<string>? extraRegex = null)
|
||||
{
|
||||
if (type != LibraryType.Image || !Parser.IsImage(filePath)) return null;
|
||||
|
||||
|
|
|
@ -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<string>? extraRegex = null)
|
||||
{
|
||||
var fileName = directoryService.FileSystem.Path.GetFileNameWithoutExtension(filePath);
|
||||
var ret = new ParserInfo
|
||||
|
|
|
@ -6,7 +6,8 @@ export enum LibraryType {
|
|||
Book = 2,
|
||||
Images = 3,
|
||||
LightNovel = 4,
|
||||
ComicVine = 5
|
||||
ComicVine = 5,
|
||||
Generic = 6
|
||||
}
|
||||
|
||||
export interface Library {
|
||||
|
|
|
@ -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 '';
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -502,7 +502,9 @@
|
|||
"comic": "Comic",
|
||||
"manga": "Manga",
|
||||
"comicVine": "ComicVine",
|
||||
"image": "Image"
|
||||
"image": "Image",
|
||||
"lightNovel": "Light Novel",
|
||||
"generic": "Generic"
|
||||
},
|
||||
|
||||
"age-rating-pipe": {
|
||||
|
|
35
openapi.json
35
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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue