Browse Source

Clean up ComicInfo stuff a bit

arkon 2 years ago
parent
commit
6ada3c90ff

+ 113 - 57
app/src/main/java/eu/kanade/domain/manga/model/ComicInfo.kt

@@ -1,89 +1,145 @@
 package eu.kanade.domain.manga.model
 
+import eu.kanade.domain.chapter.model.Chapter
+import eu.kanade.tachiyomi.source.model.SManga
 import kotlinx.serialization.Serializable
 import nl.adaptivity.xmlutil.serialization.XmlElement
 import nl.adaptivity.xmlutil.serialization.XmlSerialName
 import nl.adaptivity.xmlutil.serialization.XmlValue
 
+const val COMIC_INFO_FILE = "ComicInfo.xml"
+
+/**
+ * Creates a ComicInfo instance based on the manga and chapter metadata.
+ */
+fun getComicInfo(manga: Manga, chapter: Chapter): ComicInfo {
+    return ComicInfo(
+        title = ComicInfo.Title(chapter.name),
+        series = ComicInfo.Series(manga.title),
+        web = ComicInfo.Web(manga.url),
+        summary = manga.description?.let { ComicInfo.Summary(it) },
+        writer = manga.author?.let { ComicInfo.Writer(it) },
+        penciller = manga.artist?.let { ComicInfo.Penciller(it) },
+        translator = chapter.scanlator?.let { ComicInfo.Translator(it) },
+        genre = manga.genre?.let { ComicInfo.Genre(it.joinToString()) },
+        publishingStatusTachiyomi = ComicInfo.PublishingStatusTachiyomi(
+            ComicInfoPublishingStatusMap.toComicInfoValue(manga.status),
+        ),
+        inker = null,
+        colorist = null,
+        letterer = null,
+        coverArtist = null,
+        tags = null,
+    )
+}
+
 @Serializable
 @XmlSerialName("ComicInfo", "", "")
 data class ComicInfo(
-    val title: ComicInfoTitle?,
-    val series: ComicInfoSeries?,
-    val summary: ComicInfoSummary?,
-    val writer: ComicInfoWriter?,
-    val penciller: ComicInfoPenciller?,
-    val inker: ComicInfoInker?,
-    val colorist: ComicInfoColorist?,
-    val letterer: ComicInfoLetterer?,
-    val coverArtist: ComicInfoCoverArtist?,
-    val translator: ComicInfoTranslator?,
-    val genre: ComicInfoGenre?,
-    val tags: ComicInfoTags?,
-    val web: ComicInfoWeb?,
-    val publishingStatusTachiyomi: ComicInfoPublishingStatusTachiyomi?,
+    val title: Title?,
+    val series: Series?,
+    val summary: Summary?,
+    val writer: Writer?,
+    val penciller: Penciller?,
+    val inker: Inker?,
+    val colorist: Colorist?,
+    val letterer: Letterer?,
+    val coverArtist: CoverArtist?,
+    val translator: Translator?,
+    val genre: Genre?,
+    val tags: Tags?,
+    val web: Web?,
+    val publishingStatusTachiyomi: PublishingStatusTachiyomi?,
 ) {
+    @Suppress("UNUSED")
     @XmlElement(false)
     @XmlSerialName("xmlns:xsd", "", "")
     val xmlSchema: String = "http://www.w3.org/2001/XMLSchema"
 
+    @Suppress("UNUSED")
     @XmlElement(false)
     @XmlSerialName("xmlns:xsi", "", "")
     val xmlSchemaInstance: String = "http://www.w3.org/2001/XMLSchema-instance"
-}
 
-@Serializable
-@XmlSerialName("Title", "", "")
-data class ComicInfoTitle(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Title", "", "")
+    data class Title(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Series", "", "")
-data class ComicInfoSeries(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Series", "", "")
+    data class Series(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Summary", "", "")
-data class ComicInfoSummary(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Summary", "", "")
+    data class Summary(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Writer", "", "")
-data class ComicInfoWriter(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Writer", "", "")
+    data class Writer(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Penciller", "", "")
-data class ComicInfoPenciller(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Penciller", "", "")
+    data class Penciller(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Inker", "", "")
-data class ComicInfoInker(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Inker", "", "")
+    data class Inker(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Colorist", "", "")
-data class ComicInfoColorist(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Colorist", "", "")
+    data class Colorist(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Letterer", "", "")
-data class ComicInfoLetterer(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Letterer", "", "")
+    data class Letterer(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("CoverArtist", "", "")
-data class ComicInfoCoverArtist(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("CoverArtist", "", "")
+    data class CoverArtist(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Translator", "", "")
-data class ComicInfoTranslator(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Translator", "", "")
+    data class Translator(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Genre", "", "")
-data class ComicInfoGenre(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Genre", "", "")
+    data class Genre(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Tags", "", "")
-data class ComicInfoTags(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Tags", "", "")
+    data class Tags(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("Web", "", "")
-data class ComicInfoWeb(@XmlValue(true) val value: String = "")
+    @Serializable
+    @XmlSerialName("Web", "", "")
+    data class Web(@XmlValue(true) val value: String = "")
 
-@Serializable
-@XmlSerialName("PublishingStatusTachiyomi", "http://www.w3.org/2001/XMLSchema", "ty")
-data class ComicInfoPublishingStatusTachiyomi(@XmlValue(true) val value: String = "")
+    // The spec doesn't have a good field for this
+    @Serializable
+    @XmlSerialName("PublishingStatusTachiyomi", "http://www.w3.org/2001/XMLSchema", "ty")
+    data class PublishingStatusTachiyomi(@XmlValue(true) val value: String = "")
+}
+
+enum class ComicInfoPublishingStatusMap(
+    val comicInfoValue: String,
+    val sMangaModelValue: Int,
+) {
+    ONGOING("Ongoing", SManga.ONGOING),
+    COMPLETED("Completed", SManga.COMPLETED),
+    LICENSED("Licensed", SManga.LICENSED),
+    PUBLISHING_FINISHED("Publishing finished", SManga.PUBLISHING_FINISHED),
+    CANCELLED("Cancelled", SManga.CANCELLED),
+    ON_HIATUS("On hiatus", SManga.ON_HIATUS),
+    ;
+
+    companion object {
+        fun toComicInfoValue(value: Long): String {
+            return values().firstOrNull { it.sMangaModelValue == value.toInt() }?.comicInfoValue
+                ?: "Unknown"
+        }
+
+        fun toSMangaValue(value: String?): Int {
+            return values().firstOrNull { it.comicInfoValue == value }?.sMangaModelValue
+                ?: SManga.UNKNOWN
+        }
+    }
+}

+ 10 - 55
app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt

@@ -6,21 +6,14 @@ import com.jakewharton.rxrelay.PublishRelay
 import eu.kanade.domain.chapter.model.Chapter
 import eu.kanade.domain.chapter.model.toDbChapter
 import eu.kanade.domain.download.service.DownloadPreferences
+import eu.kanade.domain.manga.model.COMIC_INFO_FILE
 import eu.kanade.domain.manga.model.ComicInfo
-import eu.kanade.domain.manga.model.ComicInfoGenre
-import eu.kanade.domain.manga.model.ComicInfoPenciller
-import eu.kanade.domain.manga.model.ComicInfoPublishingStatusTachiyomi
-import eu.kanade.domain.manga.model.ComicInfoSeries
-import eu.kanade.domain.manga.model.ComicInfoSummary
-import eu.kanade.domain.manga.model.ComicInfoTitle
-import eu.kanade.domain.manga.model.ComicInfoTranslator
-import eu.kanade.domain.manga.model.ComicInfoWeb
-import eu.kanade.domain.manga.model.ComicInfoWriter
 import eu.kanade.domain.manga.model.Manga
+import eu.kanade.domain.manga.model.getComicInfo
 import eu.kanade.domain.track.interactor.GetTracks
-import eu.kanade.domain.track.model.Track
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.cache.ChapterCache
+import eu.kanade.tachiyomi.data.database.models.toDomainChapter
 import eu.kanade.tachiyomi.data.download.model.Download
 import eu.kanade.tachiyomi.data.download.model.DownloadQueue
 import eu.kanade.tachiyomi.data.library.LibraryUpdateNotifier
@@ -28,8 +21,6 @@ import eu.kanade.tachiyomi.data.notification.NotificationHandler
 import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.source.UnmeteredSource
 import eu.kanade.tachiyomi.source.model.Page
-import eu.kanade.tachiyomi.source.model.SChapter
-import eu.kanade.tachiyomi.source.model.SManga
 import eu.kanade.tachiyomi.source.online.HttpSource
 import eu.kanade.tachiyomi.source.online.fetchAllImageUrlsFromPageList
 import eu.kanade.tachiyomi.util.lang.RetryWithDelay
@@ -42,7 +33,6 @@ import eu.kanade.tachiyomi.util.storage.saveTo
 import eu.kanade.tachiyomi.util.system.ImageUtil
 import eu.kanade.tachiyomi.util.system.logcat
 import kotlinx.coroutines.async
-import kotlinx.coroutines.runBlocking
 import logcat.LogPriority
 import nl.adaptivity.xmlutil.serialization.XML
 import okhttp3.Response
@@ -537,8 +527,6 @@ class Downloader(
         // Ensure that the chapter folder has all the images.
         val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") || (it.name!!.contains("__") && !it.name!!.contains("__001.jpg")) }
 
-        createComicInfoFile(tmpDir, download.manga, download.chapter)
-
         download.status = if (downloadedImages.size == download.pages!!.size) {
             // Only rename the directory if it's downloaded.
             if (downloadPreferences.saveChaptersAsCBZ().get()) {
@@ -549,8 +537,7 @@ class Downloader(
             cache.addChapter(dirname, mangaDir, download.manga)
 
             DiskUtil.createNoMediaFile(tmpDir, context)
-
-            createComicInfoFile(mangaDir, download.manga, download.chapter)
+            createComicInfoFile(mangaDir, download.manga, download.chapter.toDomainChapter()!!)
 
             Download.State.DOWNLOADED
         } else {
@@ -602,47 +589,15 @@ class Downloader(
     private fun createComicInfoFile(
         dir: UniFile,
         manga: Manga,
-        chapter: SChapter,
+        chapter: Chapter,
     ) {
-        File("${dir.filePath}/ComicInfo.xml").outputStream().also {
+        File("${dir.filePath}/$COMIC_INFO_FILE").outputStream().also {
             // Force overwrite old file
             (it as? FileOutputStream)?.channel?.truncate(0)
-        }.use { it.write(getComicInfo(manga, chapter)) }
-    }
-
-    /**
-     * returns a ByteArray containing the Manga Metadata of the chapter to download in ComicInfo.xml format
-     *
-     * @param manga the manga of the chapter to download.
-     * @param chapter the name of the chapter to download
-     */
-    private fun getComicInfo(manga: Manga, chapter: SChapter): ByteArray {
-        val track: Track? = runBlocking { getTracks.await(manga.id).firstOrNull() }
-        val comicInfo = ComicInfo(
-            title = ComicInfoTitle(chapter.name),
-            series = ComicInfoSeries(manga.title),
-            summary = manga.description?.let { ComicInfoSummary(it) },
-            writer = manga.author?.let { ComicInfoWriter(it) },
-            penciller = manga.artist?.let { ComicInfoPenciller(it) },
-            translator = chapter.scanlator?.let { ComicInfoTranslator(it) },
-            genre = manga.genre?.let { ComicInfoGenre(it.joinToString()) },
-            web = track?.remoteUrl?.let { ComicInfoWeb(it) },
-            publishingStatusTachiyomi = when (manga.status) {
-                SManga.ONGOING.toLong() -> ComicInfoPublishingStatusTachiyomi("Ongoing")
-                SManga.COMPLETED.toLong() -> ComicInfoPublishingStatusTachiyomi("Completed")
-                SManga.LICENSED.toLong() -> ComicInfoPublishingStatusTachiyomi("Licensed")
-                SManga.PUBLISHING_FINISHED.toLong() -> ComicInfoPublishingStatusTachiyomi("Publishing finished")
-                SManga.CANCELLED.toLong() -> ComicInfoPublishingStatusTachiyomi("Cancelled")
-                SManga.ON_HIATUS.toLong() -> ComicInfoPublishingStatusTachiyomi("On hiatus")
-                else -> ComicInfoPublishingStatusTachiyomi("Unknown")
-            },
-            inker = null,
-            colorist = null,
-            letterer = null,
-            coverArtist = null,
-            tags = null,
-        )
-        return xml.encodeToString(ComicInfo.serializer(), comicInfo).toByteArray()
+        }.use {
+            val comicInfo = getComicInfo(manga, chapter)
+            it.write(xml.encodeToString(ComicInfo.serializer(), comicInfo).toByteArray())
+        }
     }
 
     /**

+ 3 - 10
app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt

@@ -3,7 +3,9 @@ package eu.kanade.tachiyomi.source
 import android.content.Context
 import com.github.junrar.Archive
 import com.hippo.unifile.UniFile
+import eu.kanade.domain.manga.model.COMIC_INFO_FILE
 import eu.kanade.domain.manga.model.ComicInfo
+import eu.kanade.domain.manga.model.ComicInfoPublishingStatusMap
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.source.model.Filter
 import eu.kanade.tachiyomi.source.model.FilterList
@@ -270,15 +272,7 @@ class LocalSource(
             .takeIf { it.isNotEmpty() }
             ?.let { manga.artist = it }
 
-        manga.status = when (comicInfo.publishingStatusTachiyomi?.value) {
-            "Ongoing" -> SManga.ONGOING
-            "Completed" -> SManga.COMPLETED
-            "Licensed" -> SManga.LICENSED
-            "Publishing finished" -> SManga.PUBLISHING_FINISHED
-            "Cancelled" -> SManga.CANCELLED
-            "On hiatus" -> SManga.ON_HIATUS
-            else -> SManga.UNKNOWN
-        }
+        manga.status = ComicInfoPublishingStatusMap.toSMangaValue(comicInfo.publishingStatusTachiyomi?.value)
     }
 
     @Serializable
@@ -492,4 +486,3 @@ class LocalSource(
 }
 
 private val SUPPORTED_ARCHIVE_TYPES = listOf("zip", "cbz", "rar", "cbr", "epub")
-private val COMIC_INFO_FILE = "ComicInfo.xml"