fix(metadata): improve cover errors, reduce metadata fetch count, and hide attach option (#2690)

* fix(metadata): improve cover regen errors and reduce detailed metadata fetch count

* fix(metadata): hide attach-to-book option in single-format libraries

---------

Co-authored-by: acx10 <acx10@users.noreply.github.com>
This commit is contained in:
ACX
2026-02-10 21:14:46 -07:00
committed by GitHub
parent ff11ec57b8
commit 6da6e8e373
5 changed files with 13 additions and 8 deletions

View File

@@ -34,7 +34,7 @@ public enum ApiError {
SCHEDULE_REFRESH_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to schedule metadata refresh job. Error: %s"),
ANOTHER_METADATA_JOB_RUNNING(HttpStatus.CONFLICT, "A metadata refresh job is currently running. Please wait for it to complete before initiating a new one."),
METADATA_SOURCE_NOT_IMPLEMENT_OR_DOES_NOT_EXIST(HttpStatus.BAD_REQUEST, "Metadata source not implement or does not exist"),
FAILED_TO_REGENERATE_COVER(HttpStatus.BAD_REQUEST, "Failed to regenerate cover"),
FAILED_TO_REGENERATE_COVER(HttpStatus.BAD_REQUEST, "Failed to regenerate cover: %s"),
NO_COVER_IN_FILE(HttpStatus.BAD_REQUEST, "No embedded cover image found in the audiobook file"),
FAILED_TO_DOWNLOAD_FILE(HttpStatus.INTERNAL_SERVER_ERROR, "Error while downloading file, bookId: %s"),
INVALID_REFRESH_TYPE(HttpStatus.BAD_REQUEST, "The refresh type is invalid"),

View File

@@ -172,12 +172,12 @@ public class BookCoverService {
var audiobookFile = bookEntity.getBookFiles().stream()
.filter(f -> f.getBookType() == BookFileType.AUDIOBOOK)
.findFirst()
.orElseThrow(ApiError.FAILED_TO_REGENERATE_COVER::createException);
.orElseThrow(() -> ApiError.FAILED_TO_REGENERATE_COVER.createException("no audiobook file found"));
BookFileProcessor processor = processorRegistry.getProcessorOrThrow(audiobookFile.getBookType());
boolean success = processor.generateAudiobookCover(bookEntity);
if (!success) {
throw ApiError.FAILED_TO_REGENERATE_COVER.createException();
throw ApiError.FAILED_TO_REGENERATE_COVER.createException("no embedded cover image found in the audiobook file");
}
updateAudiobookCoverMetadata(bookEntity);
bookRepository.save(bookEntity);
@@ -233,13 +233,13 @@ public class BookCoverService {
BookFileEntity ebookFile = findEbookFile(bookEntity);
if (ebookFile == null) {
throw ApiError.FAILED_TO_REGENERATE_COVER.createException();
throw ApiError.FAILED_TO_REGENERATE_COVER.createException("no ebook file found for the book");
}
BookFileProcessor processor = processorRegistry.getProcessorOrThrow(ebookFile.getBookType());
boolean success = processor.generateCover(bookEntity, ebookFile);
if (!success) {
throw ApiError.FAILED_TO_REGENERATE_COVER.createException();
throw ApiError.FAILED_TO_REGENERATE_COVER.createException("no embedded cover image found in the file");
}
updateBookCoverMetadata(bookEntity);
bookRepository.save(bookEntity);

View File

@@ -45,7 +45,7 @@ public class AmazonBookParser implements BookParser, DetailedMetadataProvider {
}
}
private static final int COUNT_DETAILED_METADATA_TO_GET = 4;
private static final int COUNT_DETAILED_METADATA_TO_GET = 3;
private static final String BASE_BOOK_URL_SUFFIX = "/dp/";
private static final Pattern NON_DIGIT_PATTERN = Pattern.compile("[^\\d]");
private static final Pattern SERIES_FORMAT_PATTERN = Pattern.compile("Book (\\d+(?:\\.\\d+)?) of (\\d+)");

View File

@@ -36,7 +36,7 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public class AudibleParser implements BookParser, DetailedMetadataProvider {
private static final int COUNT_DETAILED_METADATA_TO_GET = 4;
private static final int COUNT_DETAILED_METADATA_TO_GET = 3;
private static final long MIN_REQUEST_INTERVAL_MS = 1500;
private static final String DEFAULT_DOMAIN = "com";