added endpoint to regenerate thumbnails

This commit is contained in:
Gauthier Roebroeck 2019-08-22 15:02:29 +08:00
parent ff54f08867
commit 69bacd15a2
4 changed files with 94 additions and 14 deletions

View file

@ -39,4 +39,18 @@ class BookManager(
}.also { logger.info { "Parsing finished in ${DurationFormatUtils.formatDurationHMS(it)}" } })
}
@Transactional
@Async("parseBookTaskExecutor")
fun regenerateThumbnailAndPersist(book: Book): Future<Long> {
logger.info { "Regenerate thumbnail and persist book: ${book.url}" }
return AsyncResult(measureTimeMillis {
try {
book.metadata = bookParser.regenerateThumbnail(book)
} catch (ex: Exception) {
logger.error(ex) { "Error while recreating thumbnail" }
book.metadata = BookMetadata(status = Status.ERROR)
}
bookRepository.save(book)
}.also { logger.info { "Thumbnail generated in ${DurationFormatUtils.formatDurationHMS(it)}" } })
}
}

View file

@ -46,24 +46,45 @@ class BookParser(
logger.info { "Book has ${pages.size} pages" }
logger.info { "Trying to generate cover for book: ${book.url}" }
val thumbnail = try {
ByteArrayOutputStream().use {
supportedMediaTypes.getValue(mediaType).getPageStream(book.path(), pages.first().fileName).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.url}" }
null
}
val thumbnail = generateThumbnail(book, mediaType, pages.first().fileName)
return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pages, thumbnail = thumbnail)
}
fun regenerateThumbnail(book: Book): BookMetadata {
logger.info { "Regenerate thumbnail for book: ${book.url}" }
if (book.metadata.status != Status.READY) {
logger.warn { "Book metadata is not ready, cannot generate thumbnail" }
throw MetadataNotReadyException()
}
val thumbnail = generateThumbnail(book, book.metadata.mediaType!!, book.metadata.pages.first().fileName)
return BookMetadata(
mediaType = book.metadata.mediaType,
status = Status.READY,
pages = book.metadata.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()
}
}
} catch (ex: Exception) {
logger.warn(ex) { "Could not generate thumbnail for book: ${book.url}" }
null
}
fun getPageContent(book: Book, number: Int): ByteArray {
logger.info { "Get page #$number for book: ${book.url}" }

View file

@ -94,4 +94,26 @@ class LibraryManager(
logger.info { "Parsed ${booksToParse.size} books in ${DurationFormatUtils.formatDurationHMS(it)} (virtual: ${DurationFormatUtils.formatDurationHMS(sumOfTasksTime)})" }
}
}
@Synchronized
fun regenerateAllThumbnails() {
logger.info { "Regenerate thumbnail for all books" }
val booksToProcess = bookRepository.findAll()
var sumOfTasksTime = 0L
measureTimeMillis {
sumOfTasksTime = booksToProcess
.map { bookManager.regenerateThumbnailAndPersist(it) }
.map {
try {
it.get()
} catch (ex: Exception) {
0L
}
}
.sum()
}.also {
logger.info { "Generated ${booksToProcess.size} thumbnails in ${DurationFormatUtils.formatDurationHMS(it)} (virtual: ${DurationFormatUtils.formatDurationHMS(sumOfTasksTime)})" }
}
}
}

View file

@ -0,0 +1,23 @@
package org.gotson.komga.interfaces.web
import org.gotson.komga.domain.service.LibraryManager
import org.springframework.http.HttpStatus
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("api/v1/admin")
@PreAuthorize("hasRole('ROLE_ADMIN')")
class AdminController(
private val libraryManager: LibraryManager
) {
@PostMapping("rpc/thumbnails/regenerateall")
@ResponseStatus(HttpStatus.ACCEPTED)
fun regenerateAllThumbnails() {
libraryManager.regenerateAllThumbnails()
}
}