From a51bf46dc8e915d1d0ca86650b1ff0603e30905c Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Wed, 15 Mar 2023 14:49:57 +0800 Subject: [PATCH] feat(metadata): import Comicinfo.xml's GTIN element as ISBN only valid ISBN numbers will be imported Refs: anansi-project/comicinfo#12 --- .../metadata/comicrack/ComicInfoProvider.kt | 5 +++ .../metadata/comicrack/dto/ComicInfo.kt | 3 ++ .../comicrack/ComicInfoProviderTest.kt | 8 ++++- .../metadata/comicrack/dto/ComicInfoTest.kt | 36 ++++++++++--------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/ComicInfoProvider.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/ComicInfoProvider.kt index fdefa5a7..2634c6b5 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/ComicInfoProvider.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/ComicInfoProvider.kt @@ -2,6 +2,7 @@ package org.gotson.komga.infrastructure.metadata.comicrack import com.fasterxml.jackson.dataformat.xml.XmlMapper import mu.KotlinLogging +import org.apache.commons.validator.routines.ISBNValidator import org.gotson.komga.domain.model.Author import org.gotson.komga.domain.model.BookMetadataPatch import org.gotson.komga.domain.model.BookMetadataPatchCapability @@ -30,6 +31,7 @@ private const val COMIC_INFO = "ComicInfo.xml" class ComicInfoProvider( @Autowired(required = false) private val mapper: XmlMapper = XmlMapper(), private val bookAnalyzer: BookAnalyzer, + private val isbnValidator: ISBNValidator, ) : BookMetadataProvider, SeriesMetadataFromBookProvider { override fun getCapabilities(): Set = @@ -98,6 +100,8 @@ class ComicInfoProvider( val tags = comicInfo.tags?.split(',')?.mapNotNull { it.trim().lowercase().ifBlank { null } } + val isbn = comicInfo.gtin?.let { isbnValidator.validate(it) } + return BookMetadataPatch( title = comicInfo.title?.ifBlank { null }, summary = comicInfo.summary?.ifBlank { null }, @@ -108,6 +112,7 @@ class ComicInfoProvider( readLists = readLists, links = link, tags = if (!tags.isNullOrEmpty()) tags.toSet() else null, + isbn = isbn, ) } return null diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/dto/ComicInfo.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/dto/ComicInfo.kt index 26b60f63..1a1daafa 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/dto/ComicInfo.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/dto/ComicInfo.kt @@ -125,4 +125,7 @@ class ComicInfo { @JsonProperty(value = "AgeRating", defaultValue = "Unknown") var ageRating: AgeRating? = null + + @JsonProperty(value = "GTIN") + var gtin: String? = null } diff --git a/komga/src/test/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/ComicInfoProviderTest.kt b/komga/src/test/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/ComicInfoProviderTest.kt index 0b87b1e0..3b4408c9 100644 --- a/komga/src/test/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/ComicInfoProviderTest.kt +++ b/komga/src/test/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/ComicInfoProviderTest.kt @@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.metadata.comicrack import com.fasterxml.jackson.dataformat.xml.XmlMapper import io.mockk.every import io.mockk.mockk +import org.apache.commons.validator.routines.ISBNValidator import org.assertj.core.api.Assertions.assertThat import org.gotson.komga.domain.model.BookMetadataPatch import org.gotson.komga.domain.model.BookWithMedia @@ -30,8 +31,9 @@ class ComicInfoProviderTest { private val mockAnalyzer = mockk().also { every { it.getFileContent(any(), "ComicInfo.xml") } returns ByteArray(0) } + private val isbnValidator = ISBNValidator(true) - private val comicInfoProvider = ComicInfoProvider(mockMapper, mockAnalyzer) + private val comicInfoProvider = ComicInfoProvider(mockMapper, mockAnalyzer, isbnValidator) private val book = makeBook("book") private val media = Media( @@ -56,6 +58,7 @@ class ComicInfoProviderTest { storyArc = "one, two, three" web = "https://www.comixology.com/Sandman/digital-comic/727888" tags = "dark, Occult" + gtin = "9783440077894" } every { mockMapper.readValue(any(), ComicInfo::class.java) } returns comicInfo @@ -68,6 +71,7 @@ class ComicInfoProviderTest { assertThat(number).isEqualTo("010") assertThat(numberSort).isEqualTo(10F) assertThat(releaseDate).isEqualTo(LocalDate.of(2020, 2, 1)) + assertThat(isbn).isEqualTo("9783440077894") assertThat(readLists) .hasSize(4) @@ -223,6 +227,7 @@ class ComicInfoProviderTest { alternateNumber = "" storyArc = "" penciller = "" + gtin = "" } every { mockMapper.readValue(any(), ComicInfo::class.java) } returns comicInfo @@ -236,6 +241,7 @@ class ComicInfoProviderTest { assertThat(numberSort).isNull() assertThat(authors).isNull() assertThat(readLists).isEmpty() + assertThat(isbn).isNull() } } diff --git a/komga/src/test/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/dto/ComicInfoTest.kt b/komga/src/test/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/dto/ComicInfoTest.kt index bb473f63..45aba709 100644 --- a/komga/src/test/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/dto/ComicInfoTest.kt +++ b/komga/src/test/kotlin/org/gotson/komga/infrastructure/metadata/comicrack/dto/ComicInfoTest.kt @@ -15,26 +15,26 @@ class ComicInfoTest { val xml = """ - v01 - Preludes & Nocturnes - 30th Anniversary Edition - Sandman - https://www.comixology.com/Sandman/digital-comic/727888 - Neil Gaiman's seminal series, THE SANDMAN, celebrates its 30th anniversary with an all-new edition of THE - SANDMAN VOL. 1: PRELUDES & NOCTURNES! + v01 - Preludes & Nocturnes - 30th Anniversary Edition + Sandman + https://www.comixology.com/Sandman/digital-comic/727888 + Neil Gaiman's seminal series, THE SANDMAN, celebrates its 30th anniversary with an all-new edition of THE + SANDMAN VOL. 1: PRELUDES & NOCTURNES! -  New York Times best-selling author Neil Gaiman's transcendent series THE SANDMAN is often hailed as the - definitive Vertigo title and one of the finest achievements in graphic storytelling. Gaiman created an - unforgettable tale of the forces that exist beyond life and death by weaving ancient mythology, folklore and - fairy tales with his own distinct narrative vision. +  New York Times best-selling author Neil Gaiman's transcendent series THE SANDMAN is often hailed as the + definitive Vertigo title and one of the finest achievements in graphic storytelling. Gaiman created an + unforgettable tale of the forces that exist beyond life and death by weaving ancient mythology, folklore and + fairy tales with his own distinct narrative vision. -  In PRELUDES & NOCTURNES, an occultist attempting to capture Death to bargain for eternal life traps her - younger brother Dream instead. After his 70 year imprisonment and eventual escape, Dream, also known as - Morpheus, goes on a quest for his lost objects of power. On his arduous journey Morpheus encounters Lucifer, - John Constantine, and an all-powerful madman. +  In PRELUDES & NOCTURNES, an occultist attempting to capture Death to bargain for eternal life traps her + younger brother Dream instead. After his 70 year imprisonment and eventual escape, Dream, also known as + Morpheus, goes on a quest for his lost objects of power. On his arduous journey Morpheus encounters Lucifer, + John Constantine, and an all-powerful madman. -  This book also includes the story "The Sound of Her Wings," which introduces us to the pragmatic and perky goth - girl Death. +  This book also includes the story "The Sound of Her Wings," which introduces us to the pragmatic and perky goth + girl Death. -  Collects THE SANDMAN #1-8. +  Collects THE SANDMAN #1-8. Scraped metadata from Comixology [CMXDB727888], [RELDATE:2018-10-30] The translator DC @@ -47,7 +47,8 @@ class ComicInfoTest { Mature 17+ No No - Sandman + Sandman + ABC123 """.trimIndent() @@ -72,6 +73,7 @@ class ComicInfoTest { assertThat(manga).isEqualTo(Manga.NO) assertThat(seriesGroup).isEqualTo("Sandman") assertThat(translator).isEqualTo("The translator") + assertThat(gtin).isEqualTo("ABC123") } }