A boatload of Bugs (#3704)
Co-authored-by: Amelia <77553571+Fesaa@users.noreply.github.com>
This commit is contained in:
parent
ea9b7ad0d1
commit
37734554ba
102 changed files with 2051 additions and 1115 deletions
|
|
@ -85,11 +85,32 @@ public class BookService : IBookService
|
|||
},
|
||||
Epub2NcxReaderOptions = new Epub2NcxReaderOptions
|
||||
{
|
||||
IgnoreMissingContentForNavigationPoints = true
|
||||
IgnoreMissingContentForNavigationPoints = false
|
||||
},
|
||||
SpineReaderOptions = new SpineReaderOptions
|
||||
{
|
||||
IgnoreMissingManifestItems = true
|
||||
IgnoreMissingManifestItems = false
|
||||
},
|
||||
BookCoverReaderOptions = new BookCoverReaderOptions
|
||||
{
|
||||
Epub2MetadataIgnoreMissingManifestItem = false
|
||||
}
|
||||
};
|
||||
|
||||
public static readonly EpubReaderOptions LenientBookReaderOptions = new()
|
||||
{
|
||||
PackageReaderOptions = new PackageReaderOptions
|
||||
{
|
||||
IgnoreMissingToc = true,
|
||||
SkipInvalidManifestItems = true,
|
||||
},
|
||||
Epub2NcxReaderOptions = new Epub2NcxReaderOptions
|
||||
{
|
||||
IgnoreMissingContentForNavigationPoints = false
|
||||
},
|
||||
SpineReaderOptions = new SpineReaderOptions
|
||||
{
|
||||
IgnoreMissingManifestItems = false
|
||||
},
|
||||
BookCoverReaderOptions = new BookCoverReaderOptions
|
||||
{
|
||||
|
|
@ -455,9 +476,12 @@ public class BookService : IBookService
|
|||
|
||||
private ComicInfo? GetEpubComicInfo(string filePath)
|
||||
{
|
||||
EpubBookRef? epubBook = null;
|
||||
|
||||
try
|
||||
{
|
||||
using var epubBook = EpubReader.OpenBook(filePath, BookReaderOptions);
|
||||
epubBook = OpenEpubWithFallback(filePath, epubBook);
|
||||
|
||||
var publicationDate =
|
||||
epubBook.Schema.Package.Metadata.Dates.Find(pDate => pDate.Event == "publication")?.Date;
|
||||
|
||||
|
|
@ -465,6 +489,7 @@ public class BookService : IBookService
|
|||
{
|
||||
publicationDate = epubBook.Schema.Package.Metadata.Dates.FirstOrDefault()?.Date;
|
||||
}
|
||||
|
||||
var (year, month, day) = GetPublicationDate(publicationDate);
|
||||
|
||||
var summary = epubBook.Schema.Package.Metadata.Descriptions.FirstOrDefault();
|
||||
|
|
@ -476,7 +501,8 @@ public class BookService : IBookService
|
|||
Day = day,
|
||||
Year = year,
|
||||
Title = epubBook.Title,
|
||||
Genre = string.Join(",", epubBook.Schema.Package.Metadata.Subjects.Select(s => s.Subject.ToLower().Trim())),
|
||||
Genre = string.Join(",",
|
||||
epubBook.Schema.Package.Metadata.Subjects.Select(s => s.Subject.ToLower().Trim())),
|
||||
LanguageISO = ValidateLanguage(epubBook.Schema.Package.Metadata.Languages
|
||||
.Select(l => l.Language)
|
||||
.FirstOrDefault())
|
||||
|
|
@ -487,7 +513,8 @@ public class BookService : IBookService
|
|||
foreach (var identifier in epubBook.Schema.Package.Metadata.Identifiers)
|
||||
{
|
||||
if (string.IsNullOrEmpty(identifier.Identifier)) continue;
|
||||
if (!string.IsNullOrEmpty(identifier.Scheme) && identifier.Scheme.Equals("ISBN", StringComparison.InvariantCultureIgnoreCase))
|
||||
if (!string.IsNullOrEmpty(identifier.Scheme) &&
|
||||
identifier.Scheme.Equals("ISBN", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var isbn = identifier.Identifier.Replace("urn:isbn:", string.Empty).Replace("isbn:", string.Empty);
|
||||
if (!ArticleNumberHelper.IsValidIsbn10(isbn) && !ArticleNumberHelper.IsValidIsbn13(isbn))
|
||||
|
|
@ -495,11 +522,13 @@ public class BookService : IBookService
|
|||
_logger.LogDebug("[BookService] {File} has invalid ISBN number", filePath);
|
||||
continue;
|
||||
}
|
||||
|
||||
info.Isbn = isbn;
|
||||
}
|
||||
|
||||
if ((!string.IsNullOrEmpty(identifier.Scheme) && identifier.Scheme.Equals("URL", StringComparison.InvariantCultureIgnoreCase)) ||
|
||||
identifier.Identifier.StartsWith("url:"))
|
||||
if ((!string.IsNullOrEmpty(identifier.Scheme) &&
|
||||
identifier.Scheme.Equals("URL", StringComparison.InvariantCultureIgnoreCase)) ||
|
||||
identifier.Identifier.StartsWith("url:"))
|
||||
{
|
||||
var url = identifier.Identifier.Replace("url:", string.Empty);
|
||||
weblinks.Add(url.Trim());
|
||||
|
|
@ -529,6 +558,7 @@ public class BookService : IBookService
|
|||
{
|
||||
info.SeriesSort = metadataItem.Content;
|
||||
}
|
||||
|
||||
break;
|
||||
case "calibre:series_index":
|
||||
info.Volume = metadataItem.Content;
|
||||
|
|
@ -548,6 +578,7 @@ public class BookService : IBookService
|
|||
{
|
||||
info.SeriesSort = metadataItem.Content;
|
||||
}
|
||||
|
||||
break;
|
||||
case "collection-type":
|
||||
// These look to be genres from https://manual.calibre-ebook.com/sub_groups.html or can be "series"
|
||||
|
|
@ -578,7 +609,8 @@ public class BookService : IBookService
|
|||
}
|
||||
|
||||
// If this is a single book and not a collection, set publication status to Completed
|
||||
if (string.IsNullOrEmpty(info.Volume) && Parser.ParseVolume(filePath, LibraryType.Manga).Equals(Parser.LooseLeafVolume))
|
||||
if (string.IsNullOrEmpty(info.Volume) &&
|
||||
Parser.ParseVolume(filePath, LibraryType.Manga).Equals(Parser.LooseLeafVolume))
|
||||
{
|
||||
info.Count = 1;
|
||||
}
|
||||
|
|
@ -590,7 +622,8 @@ public class BookService : IBookService
|
|||
var hasVolumeInSeries = !Parser.ParseVolume(info.Title, LibraryType.Manga)
|
||||
.Equals(Parser.LooseLeafVolume);
|
||||
|
||||
if (string.IsNullOrEmpty(info.Volume) && hasVolumeInSeries && (!info.Series.Equals(info.Title) || string.IsNullOrEmpty(info.Series)))
|
||||
if (string.IsNullOrEmpty(info.Volume) && hasVolumeInSeries &&
|
||||
(!info.Series.Equals(info.Title) || string.IsNullOrEmpty(info.Series)))
|
||||
{
|
||||
// This is likely a light novel for which we can set series from parsed title
|
||||
info.Series = Parser.ParseSeries(info.Title, LibraryType.Manga);
|
||||
|
|
@ -601,14 +634,40 @@ public class BookService : IBookService
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "[GetComicInfo] There was an exception parsing metadata");
|
||||
_logger.LogWarning(ex, "[GetComicInfo] There was an exception parsing metadata: {FilePath}", filePath);
|
||||
_mediaErrorService.ReportMediaIssue(filePath, MediaErrorProducer.BookService,
|
||||
"There was an exception parsing metadata", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
epubBook?.Dispose();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private EpubBookRef? OpenEpubWithFallback(string filePath, EpubBookRef? epubBook)
|
||||
{
|
||||
try
|
||||
{
|
||||
epubBook = EpubReader.OpenBook(filePath, BookReaderOptions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex,
|
||||
"[GetComicInfo] There was an exception parsing metadata, falling back to a more lenient parsing method: {FilePath}",
|
||||
filePath);
|
||||
_mediaErrorService.ReportMediaIssue(filePath, MediaErrorProducer.BookService,
|
||||
"There was an exception parsing metadata", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
epubBook ??= EpubReader.OpenBook(filePath, LenientBookReaderOptions);
|
||||
}
|
||||
|
||||
return epubBook;
|
||||
}
|
||||
|
||||
public ComicInfo? GetComicInfo(string filePath)
|
||||
{
|
||||
if (!IsValidFile(filePath)) return null;
|
||||
|
|
@ -765,7 +824,7 @@ public class BookService : IBookService
|
|||
return docReader.GetPageCount();
|
||||
}
|
||||
|
||||
using var epubBook = EpubReader.OpenBook(filePath, BookReaderOptions);
|
||||
using var epubBook = EpubReader.OpenBook(filePath, LenientBookReaderOptions);
|
||||
return epubBook.GetReadingOrder().Count;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -823,7 +882,7 @@ public class BookService : IBookService
|
|||
|
||||
try
|
||||
{
|
||||
using var epubBook = EpubReader.OpenBook(filePath, BookReaderOptions);
|
||||
using var epubBook = EpubReader.OpenBook(filePath, LenientBookReaderOptions);
|
||||
|
||||
// <meta content="The Dark Tower" name="calibre:series"/>
|
||||
// <meta content="Wolves of the Calla" name="calibre:title_sort"/>
|
||||
|
|
@ -1027,7 +1086,7 @@ public class BookService : IBookService
|
|||
/// <returns></returns>
|
||||
public async Task<ICollection<BookChapterItem>> GenerateTableOfContents(Chapter chapter)
|
||||
{
|
||||
using var book = await EpubReader.OpenBookAsync(chapter.Files.ElementAt(0).FilePath, BookReaderOptions);
|
||||
using var book = await EpubReader.OpenBookAsync(chapter.Files.ElementAt(0).FilePath, LenientBookReaderOptions);
|
||||
var mappings = await CreateKeyToPageMappingAsync(book);
|
||||
|
||||
var navItems = await book.GetNavigationAsync();
|
||||
|
|
@ -1155,7 +1214,7 @@ public class BookService : IBookService
|
|||
/// <exception cref="KavitaException">All exceptions throw this</exception>
|
||||
public async Task<string> GetBookPage(int page, int chapterId, string cachedEpubPath, string baseUrl)
|
||||
{
|
||||
using var book = await EpubReader.OpenBookAsync(cachedEpubPath, BookReaderOptions);
|
||||
using var book = await EpubReader.OpenBookAsync(cachedEpubPath, LenientBookReaderOptions);
|
||||
var mappings = await CreateKeyToPageMappingAsync(book);
|
||||
var apiBase = baseUrl + "book/" + chapterId + "/" + BookApiUrl;
|
||||
|
||||
|
|
@ -1257,7 +1316,7 @@ public class BookService : IBookService
|
|||
return GetPdfCoverImage(fileFilePath, fileName, outputDirectory, encodeFormat, size);
|
||||
}
|
||||
|
||||
using var epubBook = EpubReader.OpenBook(fileFilePath, BookReaderOptions);
|
||||
using var epubBook = EpubReader.OpenBook(fileFilePath, LenientBookReaderOptions);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue