mirror of
https://github.com/gotson/komga.git
synced 2025-12-20 07:23:34 +01:00
parent
4f6f85c474
commit
5a464fd13e
10 changed files with 324 additions and 27 deletions
|
|
@ -0,0 +1,10 @@
|
|||
CREATE TABLE BOOK_METADATA_LINK
|
||||
(
|
||||
LABEL varchar NOT NULL,
|
||||
URL varchar NOT NULL,
|
||||
BOOK_ID varchar NOT NULL,
|
||||
FOREIGN KEY (BOOK_ID) REFERENCES BOOK (ID)
|
||||
);
|
||||
|
||||
alter table book_metadata
|
||||
add column LINKS_LOCK boolean NOT NULL DEFAULT 0;
|
||||
|
|
@ -12,6 +12,7 @@ class BookMetadata(
|
|||
val authors: List<Author> = emptyList(),
|
||||
tags: Set<String> = emptySet(),
|
||||
val isbn: String = "",
|
||||
val links: List<WebLink> = emptyList(),
|
||||
|
||||
val titleLock: Boolean = false,
|
||||
val summaryLock: Boolean = false,
|
||||
|
|
@ -21,6 +22,7 @@ class BookMetadata(
|
|||
val authorsLock: Boolean = false,
|
||||
val tagsLock: Boolean = false,
|
||||
val isbnLock: Boolean = false,
|
||||
val linksLock: Boolean = false,
|
||||
|
||||
val bookId: String = "",
|
||||
|
||||
|
|
@ -42,6 +44,7 @@ class BookMetadata(
|
|||
authors: List<Author> = this.authors.toList(),
|
||||
tags: Set<String> = this.tags,
|
||||
isbn: String = this.isbn,
|
||||
links: List<WebLink> = this.links,
|
||||
titleLock: Boolean = this.titleLock,
|
||||
summaryLock: Boolean = this.summaryLock,
|
||||
numberLock: Boolean = this.numberLock,
|
||||
|
|
@ -50,9 +53,10 @@ class BookMetadata(
|
|||
authorsLock: Boolean = this.authorsLock,
|
||||
tagsLock: Boolean = this.tagsLock,
|
||||
isbnLock: Boolean = this.isbnLock,
|
||||
linksLock: Boolean = this.linksLock,
|
||||
bookId: String = this.bookId,
|
||||
createdDate: LocalDateTime = this.createdDate,
|
||||
lastModifiedDate: LocalDateTime = this.lastModifiedDate
|
||||
lastModifiedDate: LocalDateTime = this.lastModifiedDate,
|
||||
) =
|
||||
BookMetadata(
|
||||
title = title,
|
||||
|
|
@ -63,6 +67,7 @@ class BookMetadata(
|
|||
authors = authors,
|
||||
tags = tags,
|
||||
isbn = isbn,
|
||||
links = links,
|
||||
titleLock = titleLock,
|
||||
summaryLock = summaryLock,
|
||||
numberLock = numberLock,
|
||||
|
|
@ -71,11 +76,12 @@ class BookMetadata(
|
|||
authorsLock = authorsLock,
|
||||
tagsLock = tagsLock,
|
||||
isbnLock = isbnLock,
|
||||
linksLock = linksLock,
|
||||
bookId = bookId,
|
||||
createdDate = createdDate,
|
||||
lastModifiedDate = lastModifiedDate
|
||||
lastModifiedDate = lastModifiedDate,
|
||||
)
|
||||
|
||||
override fun toString(): String =
|
||||
"BookMetadata(numberSort=$numberSort, releaseDate=$releaseDate, authors=$authors, isbn='$isbn', titleLock=$titleLock, summaryLock=$summaryLock, numberLock=$numberLock, numberSortLock=$numberSortLock, releaseDateLock=$releaseDateLock, authorsLock=$authorsLock, tagsLock=$tagsLock, isbnLock=$isbnLock, bookId='$bookId', createdDate=$createdDate, lastModifiedDate=$lastModifiedDate, title='$title', summary='$summary', number='$number', tags=$tags)"
|
||||
"BookMetadata(numberSort=$numberSort, releaseDate=$releaseDate, authors=$authors, isbn='$isbn', links=$links, titleLock=$titleLock, summaryLock=$summaryLock, numberLock=$numberLock, numberSortLock=$numberSortLock, releaseDateLock=$releaseDateLock, authorsLock=$authorsLock, tagsLock=$tagsLock, isbnLock=$isbnLock, linksLock=$linksLock, bookId='$bookId', createdDate=$createdDate, lastModifiedDate=$lastModifiedDate, title='$title', summary='$summary', number='$number', tags=$tags)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ data class BookMetadataPatch(
|
|||
val releaseDate: LocalDate? = null,
|
||||
val authors: List<Author>? = null,
|
||||
val isbn: String? = null,
|
||||
val links: List<WebLink>? = null,
|
||||
|
||||
val readLists: List<ReadListEntry> = emptyList()
|
||||
) {
|
||||
|
|
@ -30,4 +31,5 @@ enum class BookMetadataPatchCapability {
|
|||
ISBN,
|
||||
READ_LISTS,
|
||||
THUMBNAILS,
|
||||
LINKS,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package org.gotson.komga.domain.model
|
||||
|
||||
import java.net.URI
|
||||
|
||||
data class WebLink(
|
||||
val label: String,
|
||||
val url: URI,
|
||||
)
|
||||
|
|
@ -23,6 +23,7 @@ class MetadataApplier {
|
|||
releaseDate = getIfNotLocked(releaseDate, patch.releaseDate, releaseDateLock),
|
||||
authors = getIfNotLocked(authors, patch.authors, authorsLock),
|
||||
isbn = getIfNotLocked(isbn, patch.isbn, isbnLock),
|
||||
links = getIfNotLocked(links, patch.links, linksLock),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +39,7 @@ class MetadataApplier {
|
|||
publisher = getIfNotLocked(publisher, patch.publisher, publisherLock),
|
||||
language = getIfNotLocked(language, patch.language, languageLock),
|
||||
genres = getIfNotLocked(genres, patch.genres, genresLock),
|
||||
totalBookCount = getIfNotLocked(totalBookCount, patch.totalBookCount, totalBookCountLock)
|
||||
totalBookCount = getIfNotLocked(totalBookCount, patch.totalBookCount, totalBookCountLock),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.gotson.komga.infrastructure.jooq
|
|||
|
||||
import org.gotson.komga.domain.model.Author
|
||||
import org.gotson.komga.domain.model.BookMetadata
|
||||
import org.gotson.komga.domain.model.WebLink
|
||||
import org.gotson.komga.domain.persistence.BookMetadataRepository
|
||||
import org.gotson.komga.jooq.Tables
|
||||
import org.gotson.komga.jooq.tables.records.BookMetadataAuthorRecord
|
||||
|
|
@ -10,6 +11,7 @@ import org.jooq.DSLContext
|
|||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.net.URI
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
|
||||
|
|
@ -22,6 +24,7 @@ class BookMetadataDao(
|
|||
private val d = Tables.BOOK_METADATA
|
||||
private val a = Tables.BOOK_METADATA_AUTHOR
|
||||
private val bt = Tables.BOOK_METADATA_TAG
|
||||
private val bl = Tables.BOOK_METADATA_LINK
|
||||
|
||||
private val groupFields = arrayOf(*d.fields(), *a.fields())
|
||||
|
||||
|
|
@ -41,9 +44,9 @@ class BookMetadataDao(
|
|||
.where(d.BOOK_ID.`in`(bookIds))
|
||||
.groupBy(*groupFields)
|
||||
.fetchGroups(
|
||||
{ it.into(d) }, { it.into(a) }
|
||||
{ it.into(d) }, { it.into(a) },
|
||||
).map { (dr, ar) ->
|
||||
dr.toDomain(ar.filterNot { it.name == null }.map { it.toDomain() }, findTags(dr.bookId))
|
||||
dr.toDomain(ar.filterNot { it.name == null }.map { it.toDomain() }, findTags(dr.bookId), findLinks(dr.bookId))
|
||||
}
|
||||
|
||||
private fun findTags(bookId: String) =
|
||||
|
|
@ -54,6 +57,13 @@ class BookMetadataDao(
|
|||
.mapNotNull { it.tag }
|
||||
.toSet()
|
||||
|
||||
private fun findLinks(bookId: String) =
|
||||
dsl.select(bl.LABEL, bl.URL)
|
||||
.from(bl)
|
||||
.where(bl.BOOK_ID.eq(bookId))
|
||||
.fetchInto(bl)
|
||||
.map { WebLink(it.label, URI(it.url)) }
|
||||
|
||||
@Transactional
|
||||
override fun insert(metadata: BookMetadata) {
|
||||
insert(listOf(metadata))
|
||||
|
|
@ -80,8 +90,9 @@ class BookMetadataDao(
|
|||
d.AUTHORS_LOCK,
|
||||
d.TAGS_LOCK,
|
||||
d.ISBN,
|
||||
d.ISBN_LOCK
|
||||
).values(null as String?, null, null, null, null, null, null, null, null, null, null, null, null, null, null)
|
||||
d.ISBN_LOCK,
|
||||
d.LINKS_LOCK,
|
||||
).values(null as String?, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null),
|
||||
).also { step ->
|
||||
chunk.forEach {
|
||||
step.bind(
|
||||
|
|
@ -99,7 +110,8 @@ class BookMetadataDao(
|
|||
it.authorsLock,
|
||||
it.tagsLock,
|
||||
it.isbn,
|
||||
it.isbnLock
|
||||
it.isbnLock,
|
||||
it.linksLock,
|
||||
)
|
||||
}
|
||||
}.execute()
|
||||
|
|
@ -107,6 +119,7 @@ class BookMetadataDao(
|
|||
|
||||
insertAuthors(metadatas)
|
||||
insertTags(metadatas)
|
||||
insertLinks(metadatas)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,6 +149,7 @@ class BookMetadataDao(
|
|||
.set(d.TAGS_LOCK, metadata.tagsLock)
|
||||
.set(d.ISBN, metadata.isbn)
|
||||
.set(d.ISBN_LOCK, metadata.isbnLock)
|
||||
.set(d.LINKS_LOCK, metadata.linksLock)
|
||||
.set(d.LAST_MODIFIED_DATE, LocalDateTime.now(ZoneId.of("Z")))
|
||||
.where(d.BOOK_ID.eq(metadata.bookId))
|
||||
.execute()
|
||||
|
|
@ -146,9 +160,13 @@ class BookMetadataDao(
|
|||
dsl.deleteFrom(bt)
|
||||
.where(bt.BOOK_ID.eq(metadata.bookId))
|
||||
.execute()
|
||||
dsl.deleteFrom(bl)
|
||||
.where(bl.BOOK_ID.eq(metadata.bookId))
|
||||
.execute()
|
||||
|
||||
insertAuthors(listOf(metadata))
|
||||
insertTags(listOf(metadata))
|
||||
insertLinks(listOf(metadata))
|
||||
}
|
||||
|
||||
private fun insertAuthors(metadatas: Collection<BookMetadata>) {
|
||||
|
|
@ -156,7 +174,7 @@ class BookMetadataDao(
|
|||
metadatas.chunked(batchSize).forEach { chunk ->
|
||||
dsl.batch(
|
||||
dsl.insertInto(a, a.BOOK_ID, a.NAME, a.ROLE)
|
||||
.values(null as String?, null, null)
|
||||
.values(null as String?, null, null),
|
||||
).also { step ->
|
||||
chunk.forEach { metadata ->
|
||||
metadata.authors.forEach {
|
||||
|
|
@ -173,7 +191,7 @@ class BookMetadataDao(
|
|||
metadatas.chunked(batchSize).forEach { chunk ->
|
||||
dsl.batch(
|
||||
dsl.insertInto(bt, bt.BOOK_ID, bt.TAG)
|
||||
.values(null as String?, null)
|
||||
.values(null as String?, null),
|
||||
).also { step ->
|
||||
chunk.forEach { metadata ->
|
||||
metadata.tags.forEach {
|
||||
|
|
@ -185,10 +203,28 @@ class BookMetadataDao(
|
|||
}
|
||||
}
|
||||
|
||||
private fun insertLinks(metadatas: Collection<BookMetadata>) {
|
||||
if (metadatas.any { it.links.isNotEmpty() }) {
|
||||
metadatas.chunked(batchSize).forEach { chunk ->
|
||||
dsl.batch(
|
||||
dsl.insertInto(bl, bl.BOOK_ID, bl.LABEL, bl.URL)
|
||||
.values(null as String?, null, null),
|
||||
).also { step ->
|
||||
chunk.forEach { metadata ->
|
||||
metadata.links.forEach {
|
||||
step.bind(metadata.bookId, it.label, it.url.toString())
|
||||
}
|
||||
}
|
||||
}.execute()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
override fun delete(bookId: String) {
|
||||
dsl.deleteFrom(a).where(a.BOOK_ID.eq(bookId)).execute()
|
||||
dsl.deleteFrom(bt).where(bt.BOOK_ID.eq(bookId)).execute()
|
||||
dsl.deleteFrom(bl).where(bl.BOOK_ID.eq(bookId)).execute()
|
||||
dsl.deleteFrom(d).where(d.BOOK_ID.eq(bookId)).execute()
|
||||
}
|
||||
|
||||
|
|
@ -198,12 +234,13 @@ class BookMetadataDao(
|
|||
|
||||
dsl.deleteFrom(a).where(a.BOOK_ID.`in`(dsl.selectTempStrings())).execute()
|
||||
dsl.deleteFrom(bt).where(bt.BOOK_ID.`in`(dsl.selectTempStrings())).execute()
|
||||
dsl.deleteFrom(bl).where(bl.BOOK_ID.`in`(dsl.selectTempStrings())).execute()
|
||||
dsl.deleteFrom(d).where(d.BOOK_ID.`in`(dsl.selectTempStrings())).execute()
|
||||
}
|
||||
|
||||
override fun count(): Long = dsl.fetchCount(d).toLong()
|
||||
|
||||
private fun BookMetadataRecord.toDomain(authors: List<Author>, tags: Set<String>) =
|
||||
private fun BookMetadataRecord.toDomain(authors: List<Author>, tags: Set<String>, links: List<WebLink>) =
|
||||
BookMetadata(
|
||||
title = title,
|
||||
summary = summary,
|
||||
|
|
@ -213,6 +250,7 @@ class BookMetadataDao(
|
|||
authors = authors,
|
||||
tags = tags,
|
||||
isbn = isbn,
|
||||
links = links,
|
||||
|
||||
bookId = bookId,
|
||||
|
||||
|
|
@ -227,11 +265,12 @@ class BookMetadataDao(
|
|||
authorsLock = authorsLock,
|
||||
tagsLock = tagsLock,
|
||||
isbnLock = isbnLock,
|
||||
linksLock = linksLock,
|
||||
)
|
||||
|
||||
private fun BookMetadataAuthorRecord.toDomain() =
|
||||
Author(
|
||||
name = name,
|
||||
role = role
|
||||
role = role,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.gotson.komga.domain.model.BookMetadataPatchCapability
|
|||
import org.gotson.komga.domain.model.BookWithMedia
|
||||
import org.gotson.komga.domain.model.SeriesMetadata
|
||||
import org.gotson.komga.domain.model.SeriesMetadataPatch
|
||||
import org.gotson.komga.domain.model.WebLink
|
||||
import org.gotson.komga.domain.service.BookAnalyzer
|
||||
import org.gotson.komga.infrastructure.metadata.BookMetadataProvider
|
||||
import org.gotson.komga.infrastructure.metadata.SeriesMetadataFromBookProvider
|
||||
|
|
@ -16,6 +17,7 @@ import org.gotson.komga.infrastructure.metadata.comicrack.dto.Manga
|
|||
import org.gotson.komga.infrastructure.validation.BCP47TagValidator
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Service
|
||||
import java.net.URI
|
||||
import java.time.LocalDate
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
|
@ -37,6 +39,7 @@ class ComicInfoProvider(
|
|||
BookMetadataPatchCapability.RELEASE_DATE,
|
||||
BookMetadataPatchCapability.AUTHORS,
|
||||
BookMetadataPatchCapability.READ_LISTS,
|
||||
BookMetadataPatchCapability.LINKS,
|
||||
)
|
||||
|
||||
override fun getBookMetadataFromBook(book: BookWithMedia): BookMetadataPatch? {
|
||||
|
|
@ -81,6 +84,16 @@ class ComicInfoProvider(
|
|||
}
|
||||
}
|
||||
|
||||
val link = comicInfo.web?.let {
|
||||
try {
|
||||
val uri = URI(it)
|
||||
listOf(WebLink(uri.host, uri))
|
||||
} catch (e: Exception) {
|
||||
logger.error(e) { "Could not parse Web element as valid URI: $it" }
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
return BookMetadataPatch(
|
||||
title = comicInfo.title?.ifBlank { null },
|
||||
summary = comicInfo.summary?.ifBlank { null },
|
||||
|
|
@ -88,7 +101,8 @@ class ComicInfoProvider(
|
|||
numberSort = comicInfo.number?.toFloatOrNull(),
|
||||
releaseDate = releaseDate,
|
||||
authors = authors.ifEmpty { null },
|
||||
readLists = readLists
|
||||
readLists = readLists,
|
||||
links = link,
|
||||
)
|
||||
}
|
||||
return null
|
||||
|
|
|
|||
|
|
@ -0,0 +1,190 @@
|
|||
package org.gotson.komga.domain.service
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.gotson.komga.domain.model.Author
|
||||
import org.gotson.komga.domain.model.BookMetadata
|
||||
import org.gotson.komga.domain.model.BookMetadataPatch
|
||||
import org.gotson.komga.domain.model.SeriesMetadata
|
||||
import org.gotson.komga.domain.model.SeriesMetadataPatch
|
||||
import org.gotson.komga.domain.model.WebLink
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.net.URI
|
||||
import java.time.LocalDate
|
||||
|
||||
class MetadataApplierTest {
|
||||
|
||||
private val metadataApplier = MetadataApplier()
|
||||
|
||||
@Nested
|
||||
inner class Book {
|
||||
|
||||
@Test
|
||||
fun `given locked metadata when applying patch then metadata is not changed`() {
|
||||
val metadata = BookMetadata(
|
||||
title = "title",
|
||||
number = "1",
|
||||
numberSort = 1F,
|
||||
titleLock = true,
|
||||
summaryLock = true,
|
||||
numberLock = true,
|
||||
numberSortLock = true,
|
||||
releaseDateLock = true,
|
||||
authorsLock = true,
|
||||
tagsLock = true,
|
||||
isbnLock = true,
|
||||
linksLock = true,
|
||||
)
|
||||
|
||||
val patch = BookMetadataPatch(
|
||||
title = "new title",
|
||||
summary = "new summary",
|
||||
number = "2",
|
||||
numberSort = 2F,
|
||||
releaseDate = LocalDate.of(2020, 12, 2),
|
||||
authors = listOf(Author("Marcel", "writer")),
|
||||
isbn = "9782811632397",
|
||||
links = listOf(WebLink("Comixology", URI("https://www.comixology.com/Sandman/digital-comic/727888"))),
|
||||
)
|
||||
|
||||
val patched = metadataApplier.apply(patch, metadata)
|
||||
|
||||
assertThat(patched.title).isEqualTo(metadata.title)
|
||||
assertThat(patched.number).isEqualTo(metadata.number)
|
||||
assertThat(patched.numberSort).isEqualTo(metadata.numberSort)
|
||||
assertThat(patched.summary).isEqualTo("")
|
||||
assertThat(patched.authors).isEmpty()
|
||||
assertThat(patched.releaseDate).isNull()
|
||||
assertThat(patched.tags).isEmpty()
|
||||
assertThat(patched.isbn).isEqualTo("")
|
||||
assertThat(patched.links).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given unlocked metadata when applying patch then metadata is changed`() {
|
||||
val metadata = BookMetadata(
|
||||
title = "title",
|
||||
number = "1",
|
||||
numberSort = 1F,
|
||||
)
|
||||
|
||||
val patch = BookMetadataPatch(
|
||||
title = "new title",
|
||||
summary = "new summary",
|
||||
number = "2",
|
||||
numberSort = 2F,
|
||||
releaseDate = LocalDate.of(2020, 12, 2),
|
||||
authors = listOf(Author("Marcel", "writer")),
|
||||
isbn = "9782811632397",
|
||||
links = listOf(WebLink("Comixology", URI("https://www.comixology.com/Sandman/digital-comic/727888"))),
|
||||
)
|
||||
|
||||
val patched = metadataApplier.apply(patch, metadata)
|
||||
|
||||
assertThat(patched.title).isEqualTo(patch.title)
|
||||
assertThat(patched.number).isEqualTo(patch.number)
|
||||
assertThat(patched.numberSort).isEqualTo(patch.numberSort)
|
||||
assertThat(patched.summary).isEqualTo(patch.summary)
|
||||
assertThat(patched.authors)
|
||||
.hasSize(1)
|
||||
.containsExactlyInAnyOrder(
|
||||
Author("Marcel", "writer"),
|
||||
)
|
||||
assertThat(patched.releaseDate).isEqualTo(patch.releaseDate)
|
||||
assertThat(patched.tags).isEmpty()
|
||||
assertThat(patched.isbn).isEqualTo(patch.isbn)
|
||||
assertThat(patched.links)
|
||||
.hasSize(1)
|
||||
.containsExactlyInAnyOrder(
|
||||
WebLink("Comixology", URI("https://www.comixology.com/Sandman/digital-comic/727888")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class Series {
|
||||
|
||||
@Test
|
||||
fun `given locked metadata when applying patch then metadata is not changed`() {
|
||||
val metadata = SeriesMetadata(
|
||||
title = "title",
|
||||
statusLock = true,
|
||||
titleLock = true,
|
||||
titleSortLock = true,
|
||||
summaryLock = true,
|
||||
readingDirectionLock = true,
|
||||
publisherLock = true,
|
||||
ageRatingLock = true,
|
||||
languageLock = true,
|
||||
genresLock = true,
|
||||
tagsLock = true,
|
||||
totalBookCountLock = true,
|
||||
)
|
||||
|
||||
val patch = SeriesMetadataPatch(
|
||||
title = "new title",
|
||||
titleSort = "new title sort",
|
||||
status = SeriesMetadata.Status.ENDED,
|
||||
summary = "new summary",
|
||||
readingDirection = SeriesMetadata.ReadingDirection.VERTICAL,
|
||||
publisher = "new publisher",
|
||||
ageRating = 12,
|
||||
language = "en",
|
||||
genres = setOf("shonen"),
|
||||
totalBookCount = 12,
|
||||
collections = emptyList(),
|
||||
)
|
||||
|
||||
val patched = metadataApplier.apply(patch, metadata)
|
||||
|
||||
assertThat(patched.title).isEqualTo(metadata.title)
|
||||
assertThat(patched.titleSort).isEqualTo(metadata.titleSort)
|
||||
assertThat(patched.status).isEqualTo(metadata.status)
|
||||
assertThat(patched.summary).isEqualTo(metadata.summary)
|
||||
assertThat(patched.readingDirection).isEqualTo(metadata.readingDirection)
|
||||
assertThat(patched.publisher).isEqualTo(metadata.publisher)
|
||||
assertThat(patched.ageRating).isEqualTo(metadata.ageRating)
|
||||
assertThat(patched.language).isEqualTo(metadata.language)
|
||||
assertThat(patched.genres).isEmpty()
|
||||
assertThat(patched.totalBookCount).isNull()
|
||||
assertThat(patched.tags).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given unlocked metadata when applying patch then metadata is changed`() {
|
||||
val metadata = SeriesMetadata(
|
||||
title = "title",
|
||||
)
|
||||
|
||||
val patch = SeriesMetadataPatch(
|
||||
title = "new title",
|
||||
titleSort = "new title sort",
|
||||
status = SeriesMetadata.Status.ENDED,
|
||||
summary = "new summary",
|
||||
readingDirection = SeriesMetadata.ReadingDirection.VERTICAL,
|
||||
publisher = "new publisher",
|
||||
ageRating = 12,
|
||||
language = "en",
|
||||
genres = setOf("shonen"),
|
||||
totalBookCount = 12,
|
||||
collections = emptyList(),
|
||||
)
|
||||
|
||||
val patched = metadataApplier.apply(patch, metadata)
|
||||
|
||||
assertThat(patched.title).isEqualTo(patch.title)
|
||||
assertThat(patched.titleSort).isEqualTo(patch.titleSort)
|
||||
assertThat(patched.status).isEqualTo(patch.status)
|
||||
assertThat(patched.summary).isEqualTo(patch.summary)
|
||||
assertThat(patched.readingDirection).isEqualTo(patch.readingDirection)
|
||||
assertThat(patched.publisher).isEqualTo(patch.publisher)
|
||||
assertThat(patched.ageRating).isEqualTo(patch.ageRating)
|
||||
assertThat(patched.language).isEqualTo(patch.language)
|
||||
assertThat(patched.totalBookCount).isEqualTo(patch.totalBookCount)
|
||||
assertThat(patched.genres)
|
||||
.hasSize(1)
|
||||
.containsExactlyInAnyOrder("shonen")
|
||||
assertThat(patched.tags).isEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import org.assertj.core.api.Assertions.assertThat
|
|||
import org.assertj.core.api.Assertions.catchThrowable
|
||||
import org.gotson.komga.domain.model.Author
|
||||
import org.gotson.komga.domain.model.BookMetadata
|
||||
import org.gotson.komga.domain.model.WebLink
|
||||
import org.gotson.komga.domain.model.makeBook
|
||||
import org.gotson.komga.domain.model.makeLibrary
|
||||
import org.gotson.komga.domain.model.makeSeries
|
||||
|
|
@ -18,6 +19,7 @@ import org.junit.jupiter.api.extension.ExtendWith
|
|||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension
|
||||
import java.net.URI
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
|
||||
|
|
@ -27,7 +29,7 @@ class BookMetadataDaoTest(
|
|||
@Autowired private val bookMetadataDao: BookMetadataDao,
|
||||
@Autowired private val bookRepository: BookRepository,
|
||||
@Autowired private val seriesRepository: SeriesRepository,
|
||||
@Autowired private val libraryRepository: LibraryRepository
|
||||
@Autowired private val libraryRepository: LibraryRepository,
|
||||
) {
|
||||
private val library = makeLibrary()
|
||||
private val series = makeSeries("Series")
|
||||
|
|
@ -68,6 +70,7 @@ class BookMetadataDaoTest(
|
|||
authors = listOf(Author("author", "role")),
|
||||
tags = setOf("tag", "another"),
|
||||
isbn = "987654321",
|
||||
links = listOf(WebLink("Comicvine", URI("https://comicvine.gamespot.com/doctor-strange-30-a-gathering-of-fear/4000-18731/"))),
|
||||
bookId = book.id,
|
||||
titleLock = true,
|
||||
summaryLock = true,
|
||||
|
|
@ -98,6 +101,10 @@ class BookMetadataDaoTest(
|
|||
}
|
||||
assertThat(created.tags).containsAll(metadata.tags)
|
||||
assertThat(created.isbn).isEqualTo(metadata.isbn)
|
||||
with(created.links.first()) {
|
||||
assertThat(label).isEqualTo(metadata.links.first().label)
|
||||
assertThat(url).isEqualTo(metadata.links.first().url)
|
||||
}
|
||||
|
||||
assertThat(created.titleLock).isEqualTo(metadata.titleLock)
|
||||
assertThat(created.summaryLock).isEqualTo(metadata.summaryLock)
|
||||
|
|
@ -107,6 +114,7 @@ class BookMetadataDaoTest(
|
|||
assertThat(created.authorsLock).isEqualTo(metadata.authorsLock)
|
||||
assertThat(created.tagsLock).isEqualTo(metadata.tagsLock)
|
||||
assertThat(created.isbnLock).isEqualTo(metadata.isbnLock)
|
||||
assertThat(created.linksLock).isEqualTo(metadata.linksLock)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -115,7 +123,7 @@ class BookMetadataDaoTest(
|
|||
title = "Book",
|
||||
number = "1",
|
||||
numberSort = 1F,
|
||||
bookId = book.id
|
||||
bookId = book.id,
|
||||
)
|
||||
|
||||
bookMetadataDao.insert(metadata)
|
||||
|
|
@ -131,6 +139,7 @@ class BookMetadataDaoTest(
|
|||
assertThat(created.authors).isEmpty()
|
||||
assertThat(created.tags).isEmpty()
|
||||
assertThat(created.isbn).isBlank
|
||||
assertThat(created.links).isEmpty()
|
||||
|
||||
assertThat(created.titleLock).isFalse
|
||||
assertThat(created.summaryLock).isFalse
|
||||
|
|
@ -140,6 +149,7 @@ class BookMetadataDaoTest(
|
|||
assertThat(created.authorsLock).isFalse
|
||||
assertThat(created.tagsLock).isFalse
|
||||
assertThat(created.isbnLock).isFalse
|
||||
assertThat(created.linksLock).isFalse
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -152,7 +162,8 @@ class BookMetadataDaoTest(
|
|||
releaseDate = LocalDate.now(),
|
||||
authors = listOf(Author("author", "role")),
|
||||
tags = setOf("tag"),
|
||||
bookId = book.id
|
||||
links = listOf(WebLink("Comicvine", URI("https://comicvine.gamespot.com/doctor-strange-30-a-gathering-of-fear/4000-18731/"))),
|
||||
bookId = book.id,
|
||||
)
|
||||
bookMetadataDao.insert(metadata)
|
||||
|
||||
|
|
@ -167,6 +178,7 @@ class BookMetadataDaoTest(
|
|||
authors = listOf(Author("author2", "role2")),
|
||||
tags = setOf("another"),
|
||||
isbn = "987654321",
|
||||
links = listOf(WebLink("Bedetheque", URI("https://www.bedetheque.com/BD-AD-Grand-Riviere-Tome-1-Terre-d-election-12596.html"))),
|
||||
titleLock = true,
|
||||
summaryLock = true,
|
||||
numberLock = true,
|
||||
|
|
@ -175,6 +187,7 @@ class BookMetadataDaoTest(
|
|||
authorsLock = true,
|
||||
tagsLock = true,
|
||||
isbnLock = true,
|
||||
linksLock = true,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -201,10 +214,13 @@ class BookMetadataDaoTest(
|
|||
assertThat(modified.authorsLock).isEqualTo(updated.authorsLock)
|
||||
assertThat(modified.tagsLock).isEqualTo(updated.tagsLock)
|
||||
assertThat(modified.isbnLock).isEqualTo(updated.isbnLock)
|
||||
assertThat(modified.linksLock).isEqualTo(updated.linksLock)
|
||||
|
||||
assertThat(modified.tags).containsAll(updated.tags)
|
||||
assertThat(modified.authors.first().name).isEqualTo(updated.authors.first().name)
|
||||
assertThat(modified.authors.first().role).isEqualTo(updated.authors.first().role)
|
||||
assertThat(modified.links.first().label).isEqualTo(updated.links.first().label)
|
||||
assertThat(modified.links.first().url).isEqualTo(updated.links.first().url)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -216,7 +232,7 @@ class BookMetadataDaoTest(
|
|||
numberSort = 1F,
|
||||
releaseDate = LocalDate.now(),
|
||||
authors = listOf(Author("author", "role")),
|
||||
bookId = book.id
|
||||
bookId = book.id,
|
||||
)
|
||||
bookMetadataDao.insert(metadata)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.gotson.komga.domain.model.BookMetadataPatch
|
|||
import org.gotson.komga.domain.model.BookWithMedia
|
||||
import org.gotson.komga.domain.model.Media
|
||||
import org.gotson.komga.domain.model.SeriesMetadata
|
||||
import org.gotson.komga.domain.model.WebLink
|
||||
import org.gotson.komga.domain.model.makeBook
|
||||
import org.gotson.komga.domain.service.BookAnalyzer
|
||||
import org.gotson.komga.infrastructure.metadata.comicrack.dto.AgeRating
|
||||
|
|
@ -18,6 +19,7 @@ import org.junit.jupiter.api.Test
|
|||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import java.net.URI
|
||||
import java.time.LocalDate
|
||||
import java.util.stream.Stream
|
||||
|
||||
|
|
@ -34,7 +36,7 @@ class ComicInfoProviderTest {
|
|||
private val media = Media(
|
||||
status = Media.Status.READY,
|
||||
mediaType = "application/zip",
|
||||
files = listOf("ComicInfo.xml")
|
||||
files = listOf("ComicInfo.xml"),
|
||||
)
|
||||
|
||||
@Nested
|
||||
|
|
@ -51,6 +53,7 @@ class ComicInfoProviderTest {
|
|||
alternateSeries = "story arc"
|
||||
alternateNumber = "5"
|
||||
storyArc = "one, two, three"
|
||||
web = "https://www.comixology.com/Sandman/digital-comic/727888"
|
||||
}
|
||||
|
||||
every { mockMapper.readValue(any<ByteArray>(), ComicInfo::class.java) } returns comicInfo
|
||||
|
|
@ -71,6 +74,11 @@ class ComicInfoProviderTest {
|
|||
BookMetadataPatch.ReadListEntry("two"),
|
||||
BookMetadataPatch.ReadListEntry("three"),
|
||||
)
|
||||
|
||||
assertThat(links).hasSize(1)
|
||||
assertThat(links).containsExactlyInAnyOrder(
|
||||
WebLink("www.comixology.com", URI("https://www.comixology.com/Sandman/digital-comic/727888")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +96,7 @@ class ComicInfoProviderTest {
|
|||
with(patch!!) {
|
||||
assertThat(readLists).hasSize(1)
|
||||
assertThat(readLists).containsExactlyInAnyOrder(
|
||||
BookMetadataPatch.ReadListEntry("one", 6)
|
||||
BookMetadataPatch.ReadListEntry("one", 6),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -419,13 +427,16 @@ class ComicInfoProviderTest {
|
|||
}
|
||||
}
|
||||
|
||||
fun computeSeriesFromSeriesAndVolumeArguments() = Stream.of(
|
||||
Arguments.of("", null, null),
|
||||
Arguments.of(null, null, null),
|
||||
Arguments.of("Series", null, "Series"),
|
||||
Arguments.of("Series", 1, "Series"),
|
||||
Arguments.of("Series", 10, "Series (10)"),
|
||||
)
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun computeSeriesFromSeriesAndVolumeArguments(): Stream<Arguments> = Stream.of(
|
||||
Arguments.of("", null, null),
|
||||
Arguments.of(null, null, null),
|
||||
Arguments.of("Series", null, "Series"),
|
||||
Arguments.of("Series", 1, "Series"),
|
||||
Arguments.of("Series", 10, "Series (10)"),
|
||||
)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("computeSeriesFromSeriesAndVolumeArguments")
|
||||
|
|
|
|||
Loading…
Reference in a new issue