Skip to content

Commit

Permalink
feat: handle archives without images
Browse files Browse the repository at this point in the history
closes #56
  • Loading branch information
gotson committed Jan 6, 2020
1 parent 98efa9b commit 70a2da5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -19,24 +20,27 @@ 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<String> = CaseInsensitiveSimpleNaturalComparator.getInstance()

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" }

Expand All @@ -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" }
Expand All @@ -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" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 70a2da5

Please sign in to comment.