From 70a2da532160a10ae56fda017478f2b0ecd92ef1 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Mon, 6 Jan 2020 14:56:45 +0800 Subject: [PATCH] feat: handle archives without images closes #56 --- .../gotson/komga/domain/model/Exceptions.kt | 1 + .../komga/domain/service/BookAnalyzer.kt | 59 ++++++++++--------- .../komga/domain/service/BookLifecycle.kt | 6 +- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/komga/src/main/kotlin/org/gotson/komga/domain/model/Exceptions.kt b/komga/src/main/kotlin/org/gotson/komga/domain/model/Exceptions.kt index 4646eab9e0..04c0918004 100644 --- a/komga/src/main/kotlin/org/gotson/komga/domain/model/Exceptions.kt +++ b/komga/src/main/kotlin/org/gotson/komga/domain/model/Exceptions.kt @@ -1,6 +1,7 @@ package org.gotson.komga.domain.model class MediaNotReadyException : Exception() +class EmptyBookException(val mediaType: String) : Exception() class UnsupportedMediaTypeException(message: String, val mediaType: String) : Exception(message) class DirectoryNotFoundException(message: String) : Exception(message) class DuplicateNameException(message: String) : Exception(message) diff --git a/komga/src/main/kotlin/org/gotson/komga/domain/service/BookAnalyzer.kt b/komga/src/main/kotlin/org/gotson/komga/domain/service/BookAnalyzer.kt index d0e802491d..2b2e679934 100644 --- a/komga/src/main/kotlin/org/gotson/komga/domain/service/BookAnalyzer.kt +++ b/komga/src/main/kotlin/org/gotson/komga/domain/service/BookAnalyzer.kt @@ -4,6 +4,7 @@ import mu.KotlinLogging import net.coobird.thumbnailator.Thumbnails import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator import org.gotson.komga.domain.model.Book +import org.gotson.komga.domain.model.EmptyBookException import org.gotson.komga.domain.model.Media import org.gotson.komga.domain.model.MediaNotReadyException import org.gotson.komga.domain.model.UnsupportedMediaTypeException @@ -19,16 +20,16 @@ private val logger = KotlinLogging.logger {} @Service class BookAnalyzer( - private val contentDetector: ContentDetector, - private val zipExtractor: ZipExtractor, - private val rarExtractor: RarExtractor, - private val pdfExtractor: PdfExtractor + private val contentDetector: ContentDetector, + private val zipExtractor: ZipExtractor, + private val rarExtractor: RarExtractor, + private val pdfExtractor: PdfExtractor ) { val supportedMediaTypes = mapOf( - "application/zip" to zipExtractor, - "application/x-rar-compressed" to rarExtractor, - "application/pdf" to pdfExtractor + "application/zip" to zipExtractor, + "application/x-rar-compressed" to rarExtractor, + "application/pdf" to pdfExtractor ) private val natSortComparator: Comparator = CaseInsensitiveSimpleNaturalComparator.getInstance() @@ -36,7 +37,10 @@ class BookAnalyzer( private val thumbnailSize = 300 private val thumbnailFormat = "jpeg" - @Throws(UnsupportedMediaTypeException::class) + @Throws( + UnsupportedMediaTypeException::class, + EmptyBookException::class + ) fun analyze(book: Book): Media { logger.info { "Trying to analyze book: $book" } @@ -46,7 +50,8 @@ class BookAnalyzer( throw UnsupportedMediaTypeException("Unsupported mime type: $mediaType. File: $book", mediaType) val pages = supportedMediaTypes.getValue(mediaType).getPagesList(book.path()) - .sortedWith(compareBy(natSortComparator) { it.fileName }) + .sortedWith(compareBy(natSortComparator) { it.fileName }) + if (pages.isEmpty()) throw EmptyBookException(mediaType) logger.info { "Book has ${pages.size} pages" } logger.info { "Trying to generate cover for book: $book" } @@ -67,32 +72,32 @@ class BookAnalyzer( val thumbnail = generateThumbnail(book, book.media.mediaType!!, book.media.pages.first().fileName) return Media( - mediaType = book.media.mediaType, - status = Media.Status.READY, - pages = book.media.pages, - thumbnail = thumbnail + mediaType = book.media.mediaType, + status = Media.Status.READY, + pages = book.media.pages, + thumbnail = thumbnail ) } private fun generateThumbnail(book: Book, mediaType: String, entry: String): ByteArray? = - try { - ByteArrayOutputStream().use { - supportedMediaTypes.getValue(mediaType).getPageStream(book.path(), entry).let { cover -> - Thumbnails.of(cover.inputStream()) - .size(thumbnailSize, thumbnailSize) - .outputFormat(thumbnailFormat) - .toOutputStream(it) - it.toByteArray() - } + try { + ByteArrayOutputStream().use { + supportedMediaTypes.getValue(mediaType).getPageStream(book.path(), entry).let { cover -> + Thumbnails.of(cover.inputStream()) + .size(thumbnailSize, thumbnailSize) + .outputFormat(thumbnailFormat) + .toOutputStream(it) + it.toByteArray() } - } catch (ex: Exception) { - logger.warn(ex) { "Could not generate thumbnail for book: $book" } - null } + } catch (ex: Exception) { + logger.warn(ex) { "Could not generate thumbnail for book: $book" } + null + } @Throws( - MediaNotReadyException::class, - IndexOutOfBoundsException::class + MediaNotReadyException::class, + IndexOutOfBoundsException::class ) fun getPageContent(book: Book, number: Int): ByteArray { logger.info { "Get page #$number for book: $book" } diff --git a/komga/src/main/kotlin/org/gotson/komga/domain/service/BookLifecycle.kt b/komga/src/main/kotlin/org/gotson/komga/domain/service/BookLifecycle.kt index d2798451ce..6a6df27287 100644 --- a/komga/src/main/kotlin/org/gotson/komga/domain/service/BookLifecycle.kt +++ b/komga/src/main/kotlin/org/gotson/komga/domain/service/BookLifecycle.kt @@ -4,6 +4,7 @@ import mu.KotlinLogging import org.apache.commons.lang3.time.DurationFormatUtils import org.gotson.komga.domain.model.Book import org.gotson.komga.domain.model.BookPageContent +import org.gotson.komga.domain.model.EmptyBookException import org.gotson.komga.domain.model.Media import org.gotson.komga.domain.model.MediaNotReadyException import org.gotson.komga.domain.model.UnsupportedMediaTypeException @@ -34,8 +35,11 @@ class BookLifecycle( try { book.media = bookAnalyzer.analyze(book) } catch (ex: UnsupportedMediaTypeException) { - logger.info(ex) { "Unsupported media type: ${ex.mediaType}. Book: $book" } + logger.warn { "Unsupported media type: ${ex.mediaType}. Book: $book" } book.media = Media(status = Media.Status.UNSUPPORTED, mediaType = ex.mediaType) + } catch (ex: EmptyBookException) { + logger.warn { "Book does not contain any images: $book" } + book.media = Media(status = Media.Status.ERROR, mediaType = ex.mediaType) } catch (ex: Exception) { logger.error(ex) { "Error while parsing. Book: $book" } book.media = Media(status = Media.Status.ERROR)