Generate ComicInfo.xml on download

This commit is contained in:
FooIbar committed 2024-01-27 13:43:08 +08:00
1 parent 41f8168c28
commit d6a58d5d34
4 files changed
+155 -6

No files matched your search

@@ -372,7 +372,7 @@ object EhEngine {
}
}.fetchUsingAsText(String::parseAs)
suspend fun fillGalleryListByApi(galleryInfoList: List<GalleryInfo>, referer: String) =
suspend fun fillGalleryListByApi(galleryInfoList: List<GalleryInfo>, referer: String? = null) =
galleryInfoList.chunked(MAX_REQUEST_SIZE).chunked(MAX_SEQUENTIAL_REQUESTS).forEachIndexed { index, chunk ->
if (index != 0) {
delay(REQUEST_INTERVAL)
@@ -0,0 +1,122 @@
package com.hippo.ehviewer.spider
import com.hippo.ehviewer.client.EhTagDatabase
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.unifile.UniFile
import com.hippo.unifile.openOutputStream
import java.io.OutputStreamWriter
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import nl.adaptivity.xmlutil.XmlDeclMode
import nl.adaptivity.xmlutil.core.XmlVersion
import nl.adaptivity.xmlutil.newGenericWriter
import nl.adaptivity.xmlutil.serialization.XML
import nl.adaptivity.xmlutil.serialization.XmlElement
import nl.adaptivity.xmlutil.xmlStreaming
const val COMIC_INFO_FILE = "ComicInfo.xml"
private val xml = XML {
recommended {
ignoreUnknownChildren()
}
xmlDeclMode = XmlDeclMode.Charset
xmlVersion = XmlVersion.XML10
}
fun GalleryInfo.getComicInfo(): ComicInfo {
val artists = mutableListOf<String>()
val groups = mutableListOf<String>()
val characters = mutableListOf<String>()
val parodies = mutableListOf<String>()
val tags = mutableListOf<String>()
simpleTags?.forEach {
val (namespace, tag) = it.split(':', limit = 2)
when (namespace) {
"artist", "cosplayer" -> artists.add(tag)
"group" -> groups.add(tag)
"character" -> characters.add(tag)
"parody" -> if (tag != "original") parodies.add(tag)
"language", "reclass" -> Unit
else -> tags.add("${EhTagDatabase.namespaceToPrefix(namespace)}:$tag")
}
}
return ComicInfo(
series = title,
alternateSeries = titleJpn.takeUnless { it.isNullOrBlank() },
writer = groups.takeUnless { it.isEmpty() }?.joinToString(),
penciller = artists.takeUnless { it.isEmpty() }?.joinToString(),
genre = tags.takeUnless { it.isEmpty() }?.joinToString(),
web = EhUrl.getGalleryDetailUrl(gid, token),
pageCount = pages,
languageISO = simpleLanguage?.lowercase(),
characters = characters.takeUnless { it.isEmpty() }?.joinToString(),
teams = parodies.takeUnless { it.isEmpty() }?.joinToString(),
communityRating = "%.1f".format(rating),
)
}
fun ComicInfo.write(file: UniFile) {
file.openOutputStream().use {
it.channel.truncate(0)
OutputStreamWriter(it, Charsets.UTF_8).use { writer ->
xmlStreaming.newGenericWriter(writer).use { xmlWriter ->
xml.encodeToWriter(xmlWriter, ComicInfo.serializer(), this)
}
}
}
}
@Serializable
data class ComicInfo(
@XmlElement
@SerialName("Series")
val series: String?,
@XmlElement
@SerialName("AlternateSeries")
val alternateSeries: String?,
@XmlElement
@SerialName("Writer")
val writer: String?,
@XmlElement
@SerialName("Penciller")
val penciller: String?,
@XmlElement
@SerialName("Genre")
val genre: String?,
@XmlElement
@SerialName("Web")
val web: String?,
@XmlElement
@SerialName("PageCount")
val pageCount: Int,
@XmlElement
@SerialName("LanguageISO")
val languageISO: String?,
@XmlElement
@SerialName("Characters")
val characters: String?,
@XmlElement
@SerialName("Teams")
val teams: String?,
@XmlElement
@SerialName("CommunityRating")
val communityRating: String?,
) {
@SerialName("xmlns:xsi")
val xmlSchemaInstance: String = "http://www.w3.org/2001/XMLSchema-instance"
@SerialName("xsi:noNamespaceSchemaLocation")
val xmlSchemaLocation: String = "https://raw.githubusercontent.com/anansi-project/comicinfo/main/schema/v2.0/ComicInfo.xsd"
}
@@ -41,6 +41,7 @@ import com.hippo.ehviewer.image.Image
import com.hippo.ehviewer.util.ExceptionUtils
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
import java.util.concurrent.atomic.AtomicInteger
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@@ -431,6 +432,21 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
mSpiderInfo.saveToCache()
}
private suspend fun writeComicInfo() {
mSpiderDen.downloadDir?.run {
createFile(COMIC_INFO_FILE)?.also {
runCatching {
withNonCancellableContext {
EhEngine.fillGalleryListByApi(listOf(galleryInfo))
}
galleryInfo.getComicInfo().write(it)
}.onFailure {
it.printStackTrace()
}
}
}
}
private fun isStateDone(state: Int): Boolean {
return state == STATE_FINISHED || state == STATE_FAILED
}
@@ -493,7 +509,13 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
val gid = galleryInfo.gid
return (sQueenMap[gid] ?: SpiderQueen(galleryInfo).also { sQueenMap[gid] = it }).apply {
setMode(mode)
launchIO { updateMode() }
launchIO {
// Will create download dir if not exists
updateMode()
if (mode == MODE_DOWNLOAD) {
writeComicInfo()
}
}
}
}
+9 -4
View File
@@ -30,6 +30,7 @@ ktor = "3.0.0-beta-1"
okhttp3 = "5.0.0-alpha.12"
okio = "3.7.0"
splitties = "3.0.0"
xmlutil = "0.86.3"
[libraries]
aboutlibraries-core = { module = "com.mikepenz:aboutlibraries-core", version.ref = "aboutlibraries" }
@@ -92,9 +93,6 @@ jsoup = "org.jsoup:jsoup:1.17.2"
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
kotlinx-serialization-cbor = { module = "org.jetbrains.kotlinx:kotlinx-serialization-cbor", version.ref = "kotlinx-serialization" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
kotlinx-serialization-json-okio = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-okio", version.ref = "kotlinx-serialization" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
@@ -110,6 +108,13 @@ r8 = { module = "com.android.tools:r8", version.ref = "android-tools-r8" }
reorderable = "sh.calvin.reorderable:reorderable:1.2.0"
serialization-cbor = { module = "org.jetbrains.kotlinx:kotlinx-serialization-cbor", version.ref = "kotlinx-serialization" }
serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
serialization-json-okio = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-okio", version.ref = "kotlinx-serialization" }
serialization-xml-core = { module = "io.github.pdvrieze.xmlutil:core-android", version.ref = "xmlutil" }
serialization-xml = { module = "io.github.pdvrieze.xmlutil:serialization-android", version.ref = "xmlutil" }
splitties-appctx = { module = "com.louiscad.splitties:splitties-appctx", version.ref = "splitties" }
splitties-arch-room = { module = "com.louiscad.splitties:splitties-arch-room", version.ref = "splitties" }
splitties-preferences = { module = "com.louiscad.splitties:splitties-preferences", version.ref = "splitties" }
@@ -120,7 +125,7 @@ androidx-navigation = ["androidx-navigation-compose", "androidx-navigation-ui"]
coil = ["coil-compose", "coil-gif", "coil-network"]
compose = ["compose-foundation", "compose-material-icons-extended", "compose-material3", "compose-material3-windowsizeclass", "compose-ui-util"]
cronet = ["cronet-api", "cronet-gms"]
kotlinx-serialization = ["kotlinx-serialization-cbor", "kotlinx-serialization-json", "kotlinx-serialization-json-okio"]
kotlinx-serialization = ["serialization-cbor", "serialization-json", "serialization-json-okio", "serialization-xml-core", "serialization-xml"]
ktor = ["ktor-client-okhttp"]
okhttp = ["okhttp-android"]
splitties = ["splitties-appctx", "splitties-arch-room", "splitties-preferences", "splitties-systemservices"]