feat: library option to append ComicInfo Volume to Series title

This commit is contained in:
Gauthier Roebroeck 2023-01-12 15:59:01 +08:00
parent d2244b5e75
commit 63b3c83ce2
17 changed files with 62 additions and 15 deletions

View file

@ -246,6 +246,12 @@
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importComicInfoSeriesAppendVolume"
:label="$t('dialog.edit_library.field_import_comicinfo_series_append_volume')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importComicInfoCollection"
:label="$t('dialog.edit_library.field_import_comicinfo_collections')"
@ -379,6 +385,7 @@ export default Vue.extend({
importComicInfoSeries: true,
importComicInfoCollection: true,
importComicInfoReadList: true,
importComicInfoSeriesAppendVolume: true,
importEpubBook: true,
importEpubSeries: true,
importMylarSeries: true,
@ -416,7 +423,7 @@ export default Vue.extend({
importComicInfo: {
get: function (): number {
const val = [this.form.importComicInfoBook, this.form.importComicInfoCollection, this.form.importComicInfoReadList, this.form.importComicInfoSeries]
const val = [this.form.importComicInfoBook, this.form.importComicInfoCollection, this.form.importComicInfoReadList, this.form.importComicInfoSeries, this.form.importComicInfoSeriesAppendVolume]
const count = val.filter(Boolean).length
if (count === val.length) return 2
if (count === 0) return 0
@ -427,6 +434,7 @@ export default Vue.extend({
this.form.importComicInfoCollection = value
this.form.importComicInfoReadList = value
this.form.importComicInfoSeries = value
this.form.importComicInfoSeriesAppendVolume = value
},
},
@ -510,6 +518,7 @@ export default Vue.extend({
this.form.importComicInfoSeries = library ? library.importComicInfoSeries : true
this.form.importComicInfoCollection = library ? library.importComicInfoCollection : true
this.form.importComicInfoReadList = library ? library.importComicInfoReadList : true
this.form.importComicInfoSeriesAppendVolume = library ? library.importComicInfoSeriesAppendVolume : true
this.form.importEpubBook = library ? library.importEpubBook : true
this.form.importEpubSeries = library ? library.importEpubSeries : true
this.form.importMylarSeries = library ? library.importMylarSeries : true
@ -537,6 +546,7 @@ export default Vue.extend({
importComicInfoSeries: this.form.importComicInfoSeries,
importComicInfoCollection: this.form.importComicInfoCollection,
importComicInfoReadList: this.form.importComicInfoReadList,
importComicInfoSeriesAppendVolume: this.form.importComicInfoSeriesAppendVolume,
importEpubBook: this.form.importEpubBook,
importEpubSeries: this.form.importEpubSeries,
importMylarSeries: this.form.importMylarSeries,

View file

@ -393,6 +393,7 @@
"field_import_comicinfo_collections": "Collections",
"field_import_comicinfo_readlists": "Read lists",
"field_import_comicinfo_series": "Series metadata",
"field_import_comicinfo_series_append_volume": "Append volume to series title",
"field_import_epub_book": "Book metadata",
"field_import_epub_series": "Series metadata",
"field_import_local_artwork": "Local artwork",

View file

@ -7,6 +7,7 @@ export interface LibraryCreationDto {
importComicInfoSeries: boolean,
importComicInfoCollection: boolean,
importComicInfoReadList: boolean,
importComicInfoSeriesAppendVolume: boolean,
importEpubBook: boolean,
importEpubSeries: boolean,
importMylarSeries: boolean,
@ -30,6 +31,7 @@ export interface LibraryUpdateDto {
importComicInfoSeries: boolean,
importComicInfoCollection: boolean,
importComicInfoReadList: boolean,
importComicInfoSeriesAppendVolume: boolean,
importEpubBook: boolean,
importEpubSeries: boolean,
importMylarSeries: boolean,
@ -54,6 +56,7 @@ export interface LibraryDto {
importComicInfoSeries: boolean,
importComicInfoCollection: boolean,
importComicInfoReadList: boolean,
importComicInfoSeriesAppendVolume: boolean,
importEpubBook: boolean,
importEpubSeries: boolean,
importMylarSeries: boolean,

View file

@ -0,0 +1,2 @@
ALTER TABLE LIBRARY
add column IMPORT_COMICINFO_SERIES_APPEND_VOLUME boolean NOT NULL DEFAULT 1;

View file

@ -14,6 +14,7 @@ data class Library(
val importComicInfoSeries: Boolean = true,
val importComicInfoCollection: Boolean = true,
val importComicInfoReadList: Boolean = true,
val importComicInfoSeriesAppendVolume: Boolean = true,
val importEpubBook: Boolean = true,
val importEpubSeries: Boolean = true,
val importMylarSeries: Boolean = true,

View file

@ -53,7 +53,7 @@ class SeriesMetadataLifecycle(
else -> {
logger.debug { "Provider: ${provider.javaClass.simpleName}" }
val patches = bookRepository.findAllBySeriesId(series.id)
.mapNotNull { provider.getSeriesMetadataFromBook(BookWithMedia(it, mediaRepository.findById(it.id))) }
.mapNotNull { provider.getSeriesMetadataFromBook(BookWithMedia(it, mediaRepository.findById(it.id)), library) }
if (provider.shouldLibraryHandlePatch(library, MetadataPatchTarget.SERIES)) {
handlePatchForSeriesMetadata(patches, series)

View file

@ -65,6 +65,7 @@ class LibraryDao(
.set(l.IMPORT_COMICINFO_SERIES, library.importComicInfoSeries)
.set(l.IMPORT_COMICINFO_COLLECTION, library.importComicInfoCollection)
.set(l.IMPORT_COMICINFO_READLIST, library.importComicInfoReadList)
.set(l.IMPORT_COMICINFO_SERIES_APPEND_VOLUME, library.importComicInfoSeriesAppendVolume)
.set(l.IMPORT_EPUB_BOOK, library.importEpubBook)
.set(l.IMPORT_EPUB_SERIES, library.importEpubSeries)
.set(l.IMPORT_MYLAR_SERIES, library.importMylarSeries)
@ -92,6 +93,7 @@ class LibraryDao(
.set(l.IMPORT_COMICINFO_SERIES, library.importComicInfoSeries)
.set(l.IMPORT_COMICINFO_COLLECTION, library.importComicInfoCollection)
.set(l.IMPORT_COMICINFO_READLIST, library.importComicInfoReadList)
.set(l.IMPORT_COMICINFO_SERIES_APPEND_VOLUME, library.importComicInfoSeriesAppendVolume)
.set(l.IMPORT_EPUB_BOOK, library.importEpubBook)
.set(l.IMPORT_EPUB_SERIES, library.importEpubSeries)
.set(l.IMPORT_MYLAR_SERIES, library.importMylarSeries)
@ -122,6 +124,7 @@ class LibraryDao(
importComicInfoSeries = importComicinfoSeries,
importComicInfoCollection = importComicinfoCollection,
importComicInfoReadList = importComicinfoReadlist,
importComicInfoSeriesAppendVolume = importComicinfoSeriesAppendVolume,
importEpubBook = importEpubBook,
importEpubSeries = importEpubSeries,
importMylarSeries = importMylarSeries,

View file

@ -1,8 +1,9 @@
package org.gotson.komga.infrastructure.metadata
import org.gotson.komga.domain.model.BookWithMedia
import org.gotson.komga.domain.model.Library
import org.gotson.komga.domain.model.SeriesMetadataPatch
interface SeriesMetadataFromBookProvider : MetadataProvider {
fun getSeriesMetadataFromBook(book: BookWithMedia): SeriesMetadataPatch?
fun getSeriesMetadataFromBook(book: BookWithMedia, library: Library): SeriesMetadataPatch?
}

View file

@ -113,7 +113,7 @@ class ComicInfoProvider(
return null
}
override fun getSeriesMetadataFromBook(book: BookWithMedia): SeriesMetadataPatch? {
override fun getSeriesMetadataFromBook(book: BookWithMedia, library: Library): SeriesMetadataPatch? {
getComicInfo(book)?.let { comicInfo ->
val readingDirection = when (comicInfo.manga) {
Manga.NO -> SeriesMetadata.ReadingDirection.LEFT_TO_RIGHT
@ -122,7 +122,7 @@ class ComicInfoProvider(
}
val genres = comicInfo.genre?.split(',')?.mapNotNull { it.trim().ifBlank { null } }
val series = computeSeriesFromSeriesAndVolume(comicInfo.series, comicInfo.volume)
val series = if (library.importComicInfoSeriesAppendVolume) computeSeriesFromSeriesAndVolume(comicInfo.series, comicInfo.volume) else comicInfo.series
return SeriesMetadataPatch(
title = series,

View file

@ -84,7 +84,7 @@ class EpubMetadataProvider(
return null
}
override fun getSeriesMetadataFromBook(book: BookWithMedia): SeriesMetadataPatch? {
override fun getSeriesMetadataFromBook(book: BookWithMedia, library: Library): SeriesMetadataPatch? {
if (book.media.mediaType != MediaType.EPUB.value) return null
epubExtractor.getPackageFile(book.book.path)?.let { packageFile ->
val opf = Jsoup.parse(packageFile, "", Parser.xmlParser())

View file

@ -82,6 +82,7 @@ class LibraryController(
importComicInfoSeries = library.importComicInfoSeries,
importComicInfoCollection = library.importComicInfoCollection,
importComicInfoReadList = library.importComicInfoReadList,
importComicInfoSeriesAppendVolume = library.importComicInfoSeriesAppendVolume,
importEpubBook = library.importEpubBook,
importEpubSeries = library.importEpubSeries,
importMylarSeries = library.importMylarSeries,
@ -126,6 +127,7 @@ class LibraryController(
importComicInfoSeries = library.importComicInfoSeries,
importComicInfoCollection = library.importComicInfoCollection,
importComicInfoReadList = library.importComicInfoReadList,
importComicInfoSeriesAppendVolume = library.importComicInfoSeriesAppendVolume,
importEpubBook = library.importEpubBook,
importEpubSeries = library.importEpubSeries,
importMylarSeries = library.importMylarSeries,

View file

@ -9,6 +9,7 @@ data class LibraryCreationDto(
val importComicInfoSeries: Boolean = true,
val importComicInfoCollection: Boolean = true,
val importComicInfoReadList: Boolean = true,
val importComicInfoSeriesAppendVolume: Boolean = true,
val importEpubBook: Boolean = true,
val importEpubSeries: Boolean = true,
val importMylarSeries: Boolean = true,

View file

@ -11,6 +11,7 @@ data class LibraryDto(
val importComicInfoSeries: Boolean,
val importComicInfoCollection: Boolean,
val importComicInfoReadList: Boolean,
val importComicInfoSeriesAppendVolume: Boolean,
val importEpubBook: Boolean,
val importEpubSeries: Boolean,
val importMylarSeries: Boolean,
@ -36,6 +37,7 @@ fun Library.toDto(includeRoot: Boolean) = LibraryDto(
importComicInfoSeries = importComicInfoSeries,
importComicInfoCollection = importComicInfoCollection,
importComicInfoReadList = importComicInfoReadList,
importComicInfoSeriesAppendVolume = importComicInfoSeriesAppendVolume,
importEpubBook = importEpubBook,
importEpubSeries = importEpubSeries,
importMylarSeries = importMylarSeries,

View file

@ -9,6 +9,7 @@ data class LibraryUpdateDto(
val importComicInfoSeries: Boolean,
val importComicInfoCollection: Boolean,
val importComicInfoReadList: Boolean,
val importComicInfoSeriesAppendVolume: Boolean,
val importEpubBook: Boolean,
val importEpubSeries: Boolean,
val importMylarSeries: Boolean,

View file

@ -34,7 +34,6 @@ class LibraryDaoTest(
libraryDao.insert(library)
val created = libraryDao.findById(library.id)
assertThat(created.id).isNotEqualTo(0)
assertThat(created.createdDate).isCloseTo(now, offset)
assertThat(created.lastModifiedDate).isCloseTo(now, offset)
assertThat(created.name).isEqualTo(library.name)
@ -61,6 +60,7 @@ class LibraryDaoTest(
importComicInfoSeries = false,
importComicInfoBook = false,
importComicInfoReadList = false,
importComicInfoSeriesAppendVolume = false,
importMylarSeries = false,
importBarcodeIsbn = false,
importLocalArtwork = false,
@ -91,6 +91,7 @@ class LibraryDaoTest(
assertThat(modified.importComicInfoSeries).isEqualTo(updated.importComicInfoSeries)
assertThat(modified.importComicInfoBook).isEqualTo(updated.importComicInfoBook)
assertThat(modified.importComicInfoReadList).isEqualTo(updated.importComicInfoReadList)
assertThat(modified.importComicInfoSeriesAppendVolume).isEqualTo(updated.importComicInfoSeriesAppendVolume)
assertThat(modified.importBarcodeIsbn).isEqualTo(updated.importBarcodeIsbn)
assertThat(modified.importLocalArtwork).isEqualTo(updated.importLocalArtwork)
assertThat(modified.importMylarSeries).isEqualTo(updated.importMylarSeries)

View file

@ -10,6 +10,7 @@ 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.model.makeLibrary
import org.gotson.komga.domain.service.BookAnalyzer
import org.gotson.komga.infrastructure.metadata.comicrack.dto.AgeRating
import org.gotson.komga.infrastructure.metadata.comicrack.dto.ComicInfo
@ -329,6 +330,9 @@ class ComicInfoProviderTest {
@Nested
inner class Series {
private val library = makeLibrary()
private val libraryNoAppend = library.copy(importComicInfoSeriesAppendVolume = false)
@Test
fun `given comicInfo when getting series metadata then metadata patch is valid`() {
val comicInfo = ComicInfo().apply {
@ -344,7 +348,7 @@ class ComicInfoProviderTest {
every { mockMapper.readValue(any<ByteArray>(), ComicInfo::class.java) } returns comicInfo
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media))!!
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), library)!!
with(patch) {
assertThat(title).isEqualTo("series")
@ -370,11 +374,17 @@ class ComicInfoProviderTest {
every { mockMapper.readValue(any<ByteArray>(), ComicInfo::class.java) } returns comicInfo
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media))!!
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), library)!!
with(patch) {
assertThat(title).isEqualTo("series (2020)")
}
val patchNoAppend = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), libraryNoAppend)!!
with(patchNoAppend) {
assertThat(title).isEqualTo("series")
}
}
@Test
@ -386,11 +396,17 @@ class ComicInfoProviderTest {
every { mockMapper.readValue(any<ByteArray>(), ComicInfo::class.java) } returns comicInfo
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media))!!
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), library)!!
with(patch) {
assertThat(title).isEqualTo("series")
}
val patchNoAppend = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), libraryNoAppend)!!
with(patchNoAppend) {
assertThat(title).isEqualTo("series")
}
}
@Test
@ -401,7 +417,7 @@ class ComicInfoProviderTest {
every { mockMapper.readValue(any<ByteArray>(), ComicInfo::class.java) } returns comicInfo
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media))!!
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), library)!!
with(patch) {
assertThat(language).isNull()
@ -421,7 +437,7 @@ class ComicInfoProviderTest {
every { mockMapper.readValue(any<ByteArray>(), ComicInfo::class.java) } returns comicInfo
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media))!!
val patch = comicInfoProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), library)!!
with(patch) {
assertThat(title).isNull()

View file

@ -10,6 +10,7 @@ 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.makeBook
import org.gotson.komga.domain.model.makeLibrary
import org.gotson.komga.infrastructure.image.ImageAnalyzer
import org.gotson.komga.infrastructure.mediacontainer.ContentDetector
import org.gotson.komga.infrastructure.mediacontainer.EpubExtractor
@ -118,12 +119,14 @@ class EpubMetadataProviderTest {
@Nested
inner class Series {
private val library = makeLibrary()
@Test
fun `given epub 3 opf when getting series metadata then metadata patch is valid`() {
val opf = ClassPathResource("epub/Panik im Paradies.opf")
every { mockExtractor.getPackageFile(any()) } returns opf.file.readText()
val patch = epubMetadataProvider.getSeriesMetadataFromBook(BookWithMedia(book, media))
val patch = epubMetadataProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), library)
with(patch!!) {
assertThat(title).isEqualTo("Die drei ??? Kids")
@ -140,7 +143,7 @@ class EpubMetadataProviderTest {
val opf = ClassPathResource("epub/Die Drei 3.opf")
every { mockExtractor.getPackageFile(any()) } returns opf.file.readText()
val patch = epubMetadataProvider.getSeriesMetadataFromBook(BookWithMedia(book, media))
val patch = epubMetadataProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), library)
with(patch!!) {
assertThat(title).isEqualTo("Die drei ??? Kids")
@ -157,7 +160,7 @@ class EpubMetadataProviderTest {
val opf = ClassPathResource("epub/1979.opf")
every { mockExtractor.getPackageFile(any()) } returns opf.file.readText()
val patch = epubMetadataProvider.getSeriesMetadataFromBook(BookWithMedia(book, media))
val patch = epubMetadataProvider.getSeriesMetadataFromBook(BookWithMedia(book, media), library)
with(patch!!) {
assertThat(title).isNull()