mirror of
https://github.com/gotson/komga.git
synced 2025-12-17 22:13:47 +01:00
feat(api): batch update book metadata
This commit is contained in:
parent
2ddfec2e5c
commit
ae9a19af62
2 changed files with 54 additions and 28 deletions
|
|
@ -11,7 +11,6 @@ import org.gotson.komga.application.events.EventPublisher
|
|||
import org.gotson.komga.application.tasks.HIGHEST_PRIORITY
|
||||
import org.gotson.komga.application.tasks.HIGH_PRIORITY
|
||||
import org.gotson.komga.application.tasks.TaskReceiver
|
||||
import org.gotson.komga.domain.model.Author
|
||||
import org.gotson.komga.domain.model.BookSearchWithReadProgress
|
||||
import org.gotson.komga.domain.model.DomainEvent
|
||||
import org.gotson.komga.domain.model.ImageConversionException
|
||||
|
|
@ -40,6 +39,7 @@ import org.gotson.komga.interfaces.rest.dto.BookMetadataUpdateDto
|
|||
import org.gotson.komga.interfaces.rest.dto.PageDto
|
||||
import org.gotson.komga.interfaces.rest.dto.ReadListDto
|
||||
import org.gotson.komga.interfaces.rest.dto.ReadProgressUpdateDto
|
||||
import org.gotson.komga.interfaces.rest.dto.patch
|
||||
import org.gotson.komga.interfaces.rest.dto.restrictUrl
|
||||
import org.gotson.komga.interfaces.rest.dto.toDto
|
||||
import org.gotson.komga.interfaces.rest.persistence.BookDtoRepository
|
||||
|
|
@ -452,39 +452,37 @@ class BookController(
|
|||
@PathVariable bookId: String,
|
||||
@Parameter(description = "Metadata fields to update. Set a field to null to unset the metadata. You can omit fields you don't want to update.")
|
||||
@Valid @RequestBody newMetadata: BookMetadataUpdateDto,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
) =
|
||||
bookMetadataRepository.findByIdOrNull(bookId)?.let { existing ->
|
||||
val updated = with(newMetadata) {
|
||||
existing.copy(
|
||||
title = title ?: existing.title,
|
||||
titleLock = titleLock ?: existing.titleLock,
|
||||
summary = if (isSet("summary")) summary ?: "" else existing.summary,
|
||||
summaryLock = summaryLock ?: existing.summaryLock,
|
||||
number = number ?: existing.number,
|
||||
numberLock = numberLock ?: existing.numberLock,
|
||||
numberSort = numberSort ?: existing.numberSort,
|
||||
numberSortLock = numberSortLock ?: existing.numberSortLock,
|
||||
releaseDate = if (isSet("releaseDate")) releaseDate else existing.releaseDate,
|
||||
releaseDateLock = releaseDateLock ?: existing.releaseDateLock,
|
||||
authors = if (isSet("authors")) {
|
||||
if (authors != null) authors!!.map { Author(it.name ?: "", it.role ?: "") } else emptyList()
|
||||
} else existing.authors,
|
||||
authorsLock = authorsLock ?: existing.authorsLock,
|
||||
tags = if (isSet("tags")) {
|
||||
if (tags != null) tags!! else emptySet()
|
||||
} else existing.tags,
|
||||
tagsLock = tagsLock ?: existing.tagsLock,
|
||||
isbn = if (isSet("isbn")) isbn?.filter { it.isDigit() } ?: "" else existing.isbn,
|
||||
isbnLock = isbnLock ?: existing.isbnLock
|
||||
)
|
||||
}
|
||||
val updated = existing.patch(newMetadata)
|
||||
bookMetadataRepository.update(updated)
|
||||
taskReceiver.aggregateSeriesMetadata(bookRepository.findByIdOrNull(bookId)!!.seriesId)
|
||||
|
||||
bookRepository.findByIdOrNull(bookId)?.let { eventPublisher.publishEvent(DomainEvent.BookUpdated(it)) }
|
||||
bookRepository.findByIdOrNull(bookId)?.let { updatedBook ->
|
||||
taskReceiver.aggregateSeriesMetadata(updatedBook.seriesId)
|
||||
updatedBook.let { eventPublisher.publishEvent(DomainEvent.BookUpdated(it)) }
|
||||
}
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
@PatchMapping("api/v1/books/metadata")
|
||||
@PreAuthorize("hasRole('$ROLE_ADMIN')")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun updateBatchMetadata(
|
||||
@Parameter(description = "A map of book IDs which values are the metadata fields to update. Set a field to null to unset the metadata. You can omit fields you don't want to update.")
|
||||
@Valid @RequestBody newMetadatas: Map<String, BookMetadataUpdateDto>,
|
||||
) {
|
||||
val updatedBooks = newMetadatas.mapNotNull { (bookId, newMetadata) ->
|
||||
bookMetadataRepository.findByIdOrNull(bookId)?.let { existing ->
|
||||
val updated = existing.patch(newMetadata)
|
||||
bookMetadataRepository.update(updated)
|
||||
|
||||
bookRepository.findByIdOrNull(bookId)
|
||||
}
|
||||
}
|
||||
|
||||
updatedBooks.forEach { eventPublisher.publishEvent(DomainEvent.BookUpdated(it)) }
|
||||
updatedBooks.map { it.seriesId }.distinct().forEach { taskReceiver.aggregateSeriesMetadata(it) }
|
||||
}
|
||||
|
||||
@PatchMapping("api/v1/books/{bookId}/read-progress")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun markReadProgress(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package org.gotson.komga.interfaces.rest.dto
|
||||
|
||||
import org.gotson.komga.domain.model.Author
|
||||
import org.gotson.komga.domain.model.BookMetadata
|
||||
import org.gotson.komga.infrastructure.validation.NullOrBlankOrISBN
|
||||
import org.gotson.komga.infrastructure.validation.NullOrNotBlank
|
||||
import java.time.LocalDate
|
||||
|
|
@ -70,3 +72,29 @@ class AuthorUpdateDto {
|
|||
@get:NotBlank
|
||||
val role: String? = null
|
||||
}
|
||||
|
||||
fun BookMetadata.patch(patch: BookMetadataUpdateDto) =
|
||||
patch.let {
|
||||
this.copy(
|
||||
title = patch.title ?: this.title,
|
||||
titleLock = patch.titleLock ?: this.titleLock,
|
||||
summary = if (patch.isSet("summary")) patch.summary ?: "" else this.summary,
|
||||
summaryLock = patch.summaryLock ?: this.summaryLock,
|
||||
number = patch.number ?: this.number,
|
||||
numberLock = patch.numberLock ?: this.numberLock,
|
||||
numberSort = patch.numberSort ?: this.numberSort,
|
||||
numberSortLock = patch.numberSortLock ?: this.numberSortLock,
|
||||
releaseDate = if (patch.isSet("releaseDate")) patch.releaseDate else this.releaseDate,
|
||||
releaseDateLock = patch.releaseDateLock ?: this.releaseDateLock,
|
||||
authors = if (patch.isSet("authors")) {
|
||||
if (patch.authors != null) patch.authors!!.map { Author(it.name ?: "", it.role ?: "") } else emptyList()
|
||||
} else this.authors,
|
||||
authorsLock = patch.authorsLock ?: this.authorsLock,
|
||||
tags = if (patch.isSet("tags")) {
|
||||
if (patch.tags != null) patch.tags!! else emptySet()
|
||||
} else this.tags,
|
||||
tagsLock = patch.tagsLock ?: this.tagsLock,
|
||||
isbn = if (patch.isSet("isbn")) patch.isbn?.filter { it.isDigit() } ?: "" else this.isbn,
|
||||
isbnLock = patch.isbnLock ?: this.isbnLock
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue