feat(metadata): import Comicinfo.xml's GTIN element as ISBN

only valid ISBN numbers will be imported

Refs: anansi-project/comicinfo#12
This commit is contained in:
Gauthier Roebroeck 2023-03-15 14:49:57 +08:00
parent c0d6bf29e2
commit a51bf46dc8
4 changed files with 34 additions and 18 deletions

View file

@ -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<BookMetadataPatchCapability> =
@ -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

View file

@ -125,4 +125,7 @@ class ComicInfo {
@JsonProperty(value = "AgeRating", defaultValue = "Unknown")
var ageRating: AgeRating? = null
@JsonProperty(value = "GTIN")
var gtin: String? = null
}

View file

@ -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<BookAnalyzer>().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<ByteArray>(), 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<ByteArray>(), ComicInfo::class.java) } returns comicInfo
@ -236,6 +241,7 @@ class ComicInfoProviderTest {
assertThat(numberSort).isNull()
assertThat(authors).isNull()
assertThat(readLists).isEmpty()
assertThat(isbn).isNull()
}
}

View file

@ -15,26 +15,26 @@ class ComicInfoTest {
val xml = """
<?xml version="1.0"?>
<ComicInfo>
<Title>v01 - Preludes &amp; Nocturnes - 30th Anniversary Edition</Title>
<Series>Sandman</Series>
<Web>https://www.comixology.com/Sandman/digital-comic/727888</Web>
<Summary>Neil Gaiman's seminal series, THE SANDMAN, celebrates its 30th anniversary with an all-new edition of THE
SANDMAN VOL. 1: PRELUDES &amp; NOCTURNES!
<Title>v01 - Preludes &amp; Nocturnes - 30th Anniversary Edition</Title>
<Series>Sandman</Series>
<Web>https://www.comixology.com/Sandman/digital-comic/727888</Web>
<Summary>Neil Gaiman's seminal series, THE SANDMAN, celebrates its 30th anniversary with an all-new edition of THE
SANDMAN VOL. 1: PRELUDES &amp; 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 &amp; 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 &amp; 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.</Summary>
 Collects THE SANDMAN #1-8.</Summary>
<Notes>Scraped metadata from Comixology [CMXDB727888], [RELDATE:2018-10-30]</Notes>
<Translator>The translator</Translator>
<Publisher>DC</Publisher>
@ -47,7 +47,8 @@ class ComicInfoTest {
<AgeRating>Mature 17+</AgeRating>
<BlackAndWhite>No</BlackAndWhite>
<Manga>No</Manga>
<SeriesGroup>Sandman</SeriesGroup>
<SeriesGroup>Sandman</SeriesGroup>
<GTIN>ABC123</GTIN>
<ScanInformation></ScanInformation>
</ComicInfo>
""".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")
}
}