refactor(komga): rename class

This commit is contained in:
Gauthier Roebroeck 2023-11-29 16:45:16 +08:00
parent 5a71cf757b
commit 74210f86c3
15 changed files with 45 additions and 45 deletions

View file

@ -1,6 +1,6 @@
package org.gotson.komga.domain.model
class BookPageContent(
val content: ByteArray,
class TypedBytes(
val bytes: ByteArray,
val mediaType: String,
)

View file

@ -3,7 +3,6 @@ package org.gotson.komga.domain.service
import mu.KotlinLogging
import org.gotson.komga.domain.model.Book
import org.gotson.komga.domain.model.BookPage
import org.gotson.komga.domain.model.BookPageContent
import org.gotson.komga.domain.model.BookWithMedia
import org.gotson.komga.domain.model.Dimension
import org.gotson.komga.domain.model.Media
@ -14,6 +13,7 @@ import org.gotson.komga.domain.model.MediaProfile
import org.gotson.komga.domain.model.MediaType
import org.gotson.komga.domain.model.MediaUnsupportedException
import org.gotson.komga.domain.model.ThumbnailBook
import org.gotson.komga.domain.model.TypedBytes
import org.gotson.komga.infrastructure.configuration.KomgaSettingsProvider
import org.gotson.komga.infrastructure.hash.Hasher
import org.gotson.komga.infrastructure.image.ImageAnalyzer
@ -137,7 +137,7 @@ class BookAnalyzer(
val thumbnail = try {
getPoster(book)?.let { cover ->
imageConverter.resizeImageToByteArray(cover.content, thumbnailType, komgaSettingsProvider.thumbnailSize.maxEdge)
imageConverter.resizeImageToByteArray(cover.bytes, thumbnailType, komgaSettingsProvider.thumbnailSize.maxEdge)
}
} catch (ex: Exception) {
logger.warn(ex) { "Could not generate thumbnail for book: $book" }
@ -154,9 +154,9 @@ class BookAnalyzer(
)
}
fun getPoster(book: BookWithMedia): BookPageContent? = when (book.media.profile) {
fun getPoster(book: BookWithMedia): TypedBytes? = when (book.media.profile) {
MediaProfile.DIVINA -> divinaExtractors[book.media.mediaType]?.getEntryStream(book.book.path, book.media.pages.first().fileName)?.let {
BookPageContent(
TypedBytes(
it,
book.media.pages.first().mediaType,
)
@ -186,7 +186,7 @@ class BookAnalyzer(
return when (book.media.profile) {
MediaProfile.DIVINA -> divinaExtractors.getValue(book.media.mediaType!!).getEntryStream(book.book.path, book.media.pages[number - 1].fileName)
MediaProfile.PDF -> pdfExtractor.getPageContentAsImage(book.book.path, number).content
MediaProfile.PDF -> pdfExtractor.getPageContentAsImage(book.book.path, number).bytes
MediaProfile.EPUB -> throw MediaUnsupportedException("Epub profile does not support getting page content")
null -> throw MediaNotReadyException()
}
@ -196,7 +196,7 @@ class BookAnalyzer(
MediaNotReadyException::class,
IndexOutOfBoundsException::class,
)
fun getPageContentRaw(book: BookWithMedia, number: Int): BookPageContent {
fun getPageContentRaw(book: BookWithMedia, number: Int): TypedBytes {
logger.debug { "Get raw page #$number for book: $book" }
if (book.media.profile != MediaProfile.PDF) throw MediaUnsupportedException("Extractor does not support raw extraction of pages")

View file

@ -3,7 +3,6 @@ package org.gotson.komga.domain.service
import mu.KotlinLogging
import org.gotson.komga.domain.model.Book
import org.gotson.komga.domain.model.BookAction
import org.gotson.komga.domain.model.BookPageContent
import org.gotson.komga.domain.model.BookSearch
import org.gotson.komga.domain.model.BookWithMedia
import org.gotson.komga.domain.model.DomainEvent
@ -16,6 +15,7 @@ import org.gotson.komga.domain.model.MediaNotReadyException
import org.gotson.komga.domain.model.MediaProfile
import org.gotson.komga.domain.model.ReadProgress
import org.gotson.komga.domain.model.ThumbnailBook
import org.gotson.komga.domain.model.TypedBytes
import org.gotson.komga.domain.persistence.BookMetadataRepository
import org.gotson.komga.domain.persistence.BookRepository
import org.gotson.komga.domain.persistence.HistoricalEventRepository
@ -181,7 +181,7 @@ class BookLifecycle(
return selected
}
fun getThumbnailBytes(bookId: String, resizeTo: Int? = null): BookPageContent? {
fun getThumbnailBytes(bookId: String, resizeTo: Int? = null): TypedBytes? {
getThumbnail(bookId)?.let {
val thumbnailBytes = when {
it.thumbnail != null -> it.thumbnail
@ -191,7 +191,7 @@ class BookLifecycle(
if (resizeTo != null) {
try {
return BookPageContent(
return TypedBytes(
imageConverter.resizeImageToByteArray(thumbnailBytes, resizeTargetFormat, resizeTo),
resizeTargetFormat.mediaType,
)
@ -200,12 +200,12 @@ class BookLifecycle(
}
}
return BookPageContent(thumbnailBytes, it.mediaType)
return TypedBytes(thumbnailBytes, it.mediaType)
}
return null
}
fun getThumbnailBytesOriginal(bookId: String): BookPageContent? {
fun getThumbnailBytesOriginal(bookId: String): TypedBytes? {
val thumbnail = getThumbnail(bookId) ?: return null
return if (thumbnail.type == ThumbnailBook.Type.GENERATED) {
val book = bookRepository.findByIdOrNull(bookId) ?: return null
@ -266,7 +266,7 @@ class BookLifecycle(
MediaNotReadyException::class,
IndexOutOfBoundsException::class,
)
fun getBookPage(book: Book, number: Int, convertTo: ImageType? = null, resizeTo: Int? = null): BookPageContent {
fun getBookPage(book: Book, number: Int, convertTo: ImageType? = null, resizeTo: Int? = null): TypedBytes {
val media = mediaRepository.findById(book.id)
val pageContent = bookAnalyzer.getPageContent(BookWithMedia(book, media), number)
val pageMediaType =
@ -280,7 +280,7 @@ class BookLifecycle(
logger.error(e) { "Resize page #$number of book $book to $resizeTo: failed" }
throw e
}
return BookPageContent(convertedPage, resizeTargetFormat.mediaType)
return TypedBytes(convertedPage, resizeTargetFormat.mediaType)
} else {
convertTo?.let {
val msg = "Convert page #$number of book $book from $pageMediaType to ${it.mediaType}"
@ -302,10 +302,10 @@ class BookLifecycle(
logger.error(e) { "$msg: conversion failed" }
throw e
}
return BookPageContent(convertedPage, it.mediaType)
return TypedBytes(convertedPage, it.mediaType)
}
return BookPageContent(pageContent, pageMediaType)
return TypedBytes(pageContent, pageMediaType)
}
}

View file

@ -1,11 +1,11 @@
package org.gotson.komga.domain.service
import mu.KotlinLogging
import org.gotson.komga.domain.model.BookPageContent
import org.gotson.komga.domain.model.BookPageNumbered
import org.gotson.komga.domain.model.Library
import org.gotson.komga.domain.model.MediaType
import org.gotson.komga.domain.model.PageHashKnown
import org.gotson.komga.domain.model.TypedBytes
import org.gotson.komga.domain.persistence.BookRepository
import org.gotson.komga.domain.persistence.MediaRepository
import org.gotson.komga.domain.persistence.PageHashRepository
@ -35,7 +35,7 @@ class PageHashLifecycle(
emptyList()
}
fun getPage(pageHash: String, resizeTo: Int? = null): BookPageContent? {
fun getPage(pageHash: String, resizeTo: Int? = null): TypedBytes? {
val match = pageHashRepository.findMatchesByHash(pageHash, Pageable.ofSize(1)).firstOrNull() ?: return null
val book = bookRepository.findByIdOrNull(match.bookId) ?: return null
@ -48,7 +48,7 @@ class PageHashLifecycle(
fun createOrUpdate(pageHash: PageHashKnown) {
val existing = pageHashRepository.findKnown(pageHash.hash)
if (existing == null) {
pageHashRepository.insert(pageHash, getPage(pageHash.hash, 500)?.content)
pageHashRepository.insert(pageHash, getPage(pageHash.hash, 500)?.bytes)
} else {
pageHashRepository.update(existing.copy(action = pageHash.action))
}

View file

@ -117,7 +117,7 @@ class ReadListLifecycle(
this.take(4)
}
val images = ids.mapNotNull { bookLifecycle.getThumbnailBytes(it)?.content }
val images = ids.mapNotNull { bookLifecycle.getThumbnailBytes(it)?.bytes }
return mosaicGenerator.createMosaic(images)
}

View file

@ -257,7 +257,7 @@ class SeriesLifecycle(
?: bookRepository.findLastIdInSeriesOrNull(seriesId)
Library.SeriesCover.LAST -> bookRepository.findLastIdInSeriesOrNull(seriesId)
}
if (bookId != null) return bookLifecycle.getThumbnailBytes(bookId)?.content
if (bookId != null) return bookLifecycle.getThumbnailBytes(bookId)?.bytes
}
return null

View file

@ -1,11 +1,11 @@
package org.gotson.komga.domain.service
import org.gotson.komga.domain.model.BookPageContent
import org.gotson.komga.domain.model.BookWithMedia
import org.gotson.komga.domain.model.Media
import org.gotson.komga.domain.model.MediaNotReadyException
import org.gotson.komga.domain.model.MediaProfile
import org.gotson.komga.domain.model.PathContainedInPath
import org.gotson.komga.domain.model.TypedBytes
import org.gotson.komga.domain.persistence.LibraryRepository
import org.gotson.komga.domain.persistence.TransientBookRepository
import org.gotson.komga.infrastructure.image.ImageType
@ -50,12 +50,12 @@ class TransientBookLifecycle(
MediaNotReadyException::class,
IndexOutOfBoundsException::class,
)
fun getBookPage(transientBook: BookWithMedia, number: Int): BookPageContent {
fun getBookPage(transientBook: BookWithMedia, number: Int): TypedBytes {
val pageContent = bookAnalyzer.getPageContent(transientBook, number)
val pageMediaType =
if (transientBook.media.profile == MediaProfile.PDF) pdfImageType.mediaType
else transientBook.media.pages[number - 1].mediaType
return BookPageContent(pageContent, pageMediaType)
return TypedBytes(pageContent, pageMediaType)
}
}

View file

@ -2,9 +2,9 @@ package org.gotson.komga.infrastructure.mediacontainer.epub
import org.apache.commons.compress.archivers.ArchiveEntry
import org.apache.commons.compress.archivers.zip.ZipFile
import org.gotson.komga.domain.model.BookPageContent
import org.gotson.komga.domain.model.EpubTocEntry
import org.gotson.komga.domain.model.MediaFile
import org.gotson.komga.domain.model.TypedBytes
import org.springframework.stereotype.Service
import java.nio.file.Path
import kotlin.math.ceil
@ -23,7 +23,7 @@ class EpubExtractor {
/**
* Retrieves the book cover along with its mediaType from the epub 2/3 manifest
*/
fun getCover(path: Path): BookPageContent? =
fun getCover(path: Path): TypedBytes? =
path.epub { (zip, opfDoc, opfDir, manifest) ->
val coverManifestItem =
// EPUB 3 - try to get cover from manifest properties 'cover-image'
@ -35,7 +35,7 @@ class EpubExtractor {
val href = coverManifestItem.href
val mediaType = coverManifestItem.mediaType
val coverPath = normalizeHref(opfDir, href)
BookPageContent(
TypedBytes(
zip.getInputStream(zip.getEntry(coverPath)).readAllBytes(),
mediaType,
)

View file

@ -7,10 +7,10 @@ import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.pdmodel.PDPage
import org.apache.pdfbox.rendering.ImageType.RGB
import org.apache.pdfbox.rendering.PDFRenderer
import org.gotson.komga.domain.model.BookPageContent
import org.gotson.komga.domain.model.Dimension
import org.gotson.komga.domain.model.MediaContainerEntry
import org.gotson.komga.domain.model.MediaType
import org.gotson.komga.domain.model.TypedBytes
import org.gotson.komga.infrastructure.image.ImageType
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Service
@ -37,7 +37,7 @@ class PdfExtractor(
}
}
fun getPageContentAsImage(path: Path, pageNumber: Int): BookPageContent {
fun getPageContentAsImage(path: Path, pageNumber: Int): TypedBytes {
PDDocument.load(path.toFile(), MemoryUsageSetting.setupTempFileOnly()).use { pdf ->
val page = pdf.getPage(pageNumber)
val image = PDFRenderer(pdf).renderImage(pageNumber - 1, page.getScale(), RGB)
@ -45,17 +45,17 @@ class PdfExtractor(
ImageIO.write(image, imageType.imageIOFormat, out)
out.toByteArray()
}
return BookPageContent(bytes, imageType.mediaType)
return TypedBytes(bytes, imageType.mediaType)
}
}
fun getPageContentAsPdf(path: Path, pageNumber: Int): BookPageContent {
fun getPageContentAsPdf(path: Path, pageNumber: Int): TypedBytes {
PDDocument.load(path.toFile(), MemoryUsageSetting.setupTempFileOnly()).use { pdf ->
val bytes = ByteArrayOutputStream().use { out ->
PageExtractor(pdf, pageNumber, pageNumber).extract().save(out)
out.toByteArray()
}
return BookPageContent(bytes, MediaType.PDF.type)
return TypedBytes(bytes, MediaType.PDF.type)
}
}

View file

@ -40,7 +40,7 @@ class OpdsCommonController(
): ByteArray {
principal.user.checkContentRestriction(bookId, bookRepository, seriesMetadataRepository)
val poster = bookLifecycle.getThumbnailBytesOriginal(bookId) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
return if (poster.mediaType != ImageType.JPEG.mediaType) imageConverter.convertImage(poster.content, ImageType.JPEG.imageIOFormat)
else poster.content
return if (poster.mediaType != ImageType.JPEG.mediaType) imageConverter.convertImage(poster.bytes, ImageType.JPEG.imageIOFormat)
else poster.bytes
}
}

View file

@ -670,7 +670,7 @@ class OpdsController(
principal.user.checkContentRestriction(bookId, bookRepository, seriesMetadataRepository)
val thumbnail = bookLifecycle.getThumbnail(bookId) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
return bookLifecycle.getThumbnailBytes(bookId, if (thumbnail.type == ThumbnailBook.Type.GENERATED) null else komgaSettingsProvider.thumbnailSize.maxEdge)?.content
return bookLifecycle.getThumbnailBytes(bookId, if (thumbnail.type == ThumbnailBook.Type.GENERATED) null else komgaSettingsProvider.thumbnailSize.maxEdge)?.bytes
?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
}

View file

@ -298,7 +298,7 @@ class BookController(
): ByteArray {
principal.user.checkContentRestriction(bookId, bookRepository, seriesMetadataRepository)
return bookLifecycle.getThumbnailBytes(bookId)?.content ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
return bookLifecycle.getThumbnailBytes(bookId)?.bytes ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
}
@ApiResponse(content = [Content(schema = Schema(type = "string", format = "binary"))])
@ -543,7 +543,7 @@ class BookController(
)
.contentType(getMediaTypeOrDefault(pageContent.mediaType))
.setNotModified(media)
.body(pageContent.content)
.body(pageContent.bytes)
} catch (ex: IndexOutOfBoundsException) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Page number does not exist")
} catch (ex: ImageConversionException) {
@ -596,7 +596,7 @@ class BookController(
)
.contentType(getMediaTypeOrDefault(pageContent.mediaType))
.setNotModified(media)
.body(pageContent.content)
.body(pageContent.bytes)
} catch (ex: IndexOutOfBoundsException) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Page number does not exist")
} catch (ex: MediaUnsupportedException) {
@ -636,7 +636,7 @@ class BookController(
ResponseEntity.ok()
.contentType(getMediaTypeOrDefault(pageContent.mediaType))
.setNotModified(media)
.body(pageContent.content)
.body(pageContent.bytes)
} catch (ex: IndexOutOfBoundsException) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Page number does not exist")
} catch (ex: ImageConversionException) {

View file

@ -87,7 +87,7 @@ class PageHashController(
pageHashLifecycle.getPage(pageHash, resize)?.let {
ResponseEntity.ok()
.contentType(getMediaTypeOrDefault(it.mediaType))
.body(it.content)
.body(it.bytes)
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
@PutMapping

View file

@ -71,7 +71,7 @@ class TransientBooksController(
ResponseEntity.ok()
.contentType(getMediaTypeOrDefault(pageContent.mediaType))
.body(pageContent.content)
.body(pageContent.bytes)
} catch (ex: IndexOutOfBoundsException) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Page number does not exist")
} catch (ex: MediaNotReadyException) {

View file

@ -4,8 +4,8 @@ import com.ninjasquad.springmockk.MockkBean
import com.ninjasquad.springmockk.SpykBean
import io.mockk.every
import org.gotson.komga.domain.model.BookPage
import org.gotson.komga.domain.model.BookPageContent
import org.gotson.komga.domain.model.Media
import org.gotson.komga.domain.model.TypedBytes
import org.gotson.komga.domain.model.makeBook
import org.gotson.komga.domain.model.makeLibrary
import org.gotson.komga.domain.model.makeSeries
@ -94,8 +94,8 @@ class BookControllerPageTest(
)
}
every { mockAnalyzer.getPageContentRaw(any(), 1) } returns BookPageContent(ByteArray(0), "application/pdf")
every { bookLifecycle.getBookPage(any(), 1, any(), any()) } returns BookPageContent(ByteArray(0), "image/jpeg")
every { mockAnalyzer.getPageContentRaw(any(), 1) } returns TypedBytes(ByteArray(0), "application/pdf")
every { bookLifecycle.getBookPage(any(), 1, any(), any()) } returns TypedBytes(ByteArray(0), "image/jpeg")
mockMvc.get("/api/v1/books/${book.id}/pages/1") {
if (acceptTypes.isNotEmpty()) accept(*acceptTypes.toTypedArray())