mirror of
https://github.com/gotson/komga.git
synced 2025-12-25 18:03:56 +01:00
added endpoint to regenerate thumbnails
This commit is contained in:
parent
ff54f08867
commit
69bacd15a2
4 changed files with 94 additions and 14 deletions
|
|
@ -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)}" } })
|
||||
}
|
||||
}
|
||||
|
|
@ -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}" }
|
||||
|
||||
|
|
|
|||
|
|
@ -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)})" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue