mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
feat(LocalSource): Use ComicInfo
This commit is contained in:
parent
efd25f8445
commit
6bf37b36c3
4 changed files with 77 additions and 28 deletions
|
@ -28,6 +28,7 @@ fun SManga.toComicInfo() = ComicInfo(
|
|||
),
|
||||
categories = null,
|
||||
source = null,
|
||||
language = null,
|
||||
)
|
||||
|
||||
fun SManga.copyFromComicInfo(comicInfo: ComicInfo) {
|
||||
|
@ -82,6 +83,7 @@ data class ComicInfo(
|
|||
val publishingStatus: PublishingStatusTachiyomi?,
|
||||
val categories: CategoriesTachiyomi?,
|
||||
val source: SourceMihon?,
|
||||
val language: LanguageJ2K?,
|
||||
) {
|
||||
@XmlElement(false)
|
||||
@XmlSerialName("xmlns:xsd", "", "")
|
||||
|
@ -160,6 +162,10 @@ data class ComicInfo(
|
|||
@Serializable
|
||||
@XmlSerialName("SourceMihon", "http://www.w3.org/2001/XMLSchema", "mh")
|
||||
data class SourceMihon(val value: String = "")
|
||||
|
||||
@Serializable
|
||||
@XmlSerialName("LanguageJ2K", "http://www.w3.org/2001/XMLSchema", "j2k")
|
||||
data class LanguageJ2K(val value: String = "")
|
||||
}
|
||||
|
||||
enum class ComicInfoPublishingStatus(
|
||||
|
|
|
@ -19,6 +19,9 @@ import eu.kanade.tachiyomi.source.SourceManager
|
|||
import eu.kanade.tachiyomi.util.chapter.ChapterFilter
|
||||
import eu.kanade.tachiyomi.util.manga.MangaShortcutManager
|
||||
import kotlinx.serialization.json.Json
|
||||
import nl.adaptivity.xmlutil.XmlDeclMode
|
||||
import nl.adaptivity.xmlutil.core.XmlVersion
|
||||
import nl.adaptivity.xmlutil.serialization.XML
|
||||
import uy.kohesive.injekt.api.InjektModule
|
||||
import uy.kohesive.injekt.api.InjektRegistrar
|
||||
import uy.kohesive.injekt.api.addSingleton
|
||||
|
@ -55,6 +58,17 @@ class AppModule(val app: Application) : InjektModule {
|
|||
explicitNulls = false
|
||||
}
|
||||
}
|
||||
addSingletonFactory {
|
||||
XML {
|
||||
defaultPolicy {
|
||||
ignoreUnknownChildren()
|
||||
}
|
||||
autoPolymorphic = true
|
||||
xmlDeclMode = XmlDeclMode.Charset
|
||||
indent = 2
|
||||
xmlVersion = XmlVersion.XML10
|
||||
}
|
||||
}
|
||||
|
||||
addSingletonFactory { ChapterFilter() }
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ import android.content.Context
|
|||
import androidx.core.net.toFile
|
||||
import com.github.junrar.Archive
|
||||
import com.hippo.unifile.UniFile
|
||||
import dev.yokai.core.metadata.COMIC_INFO_FILE
|
||||
import dev.yokai.core.metadata.ComicInfo
|
||||
import dev.yokai.core.metadata.copyFromComicInfo
|
||||
import dev.yokai.core.metadata.toComicInfo
|
||||
import dev.yokai.domain.storage.StorageManager
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
|
@ -22,13 +26,15 @@ import eu.kanade.tachiyomi.util.system.toZipFile
|
|||
import eu.kanade.tachiyomi.util.system.writeText
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import nl.adaptivity.xmlutil.AndroidXmlReader
|
||||
import nl.adaptivity.xmlutil.serialization.XML
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSource {
|
||||
|
@ -44,11 +50,13 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
return langMap.getOrPut(manga.url) {
|
||||
val localDetails = getBaseDirectory().findFile(manga.url)?.listFiles().orEmpty()
|
||||
.filter { !it.isDirectory }
|
||||
.firstOrNull { it.extension.equals("json", ignoreCase = true) }
|
||||
.firstOrNull { it.name == COMIC_INFO_FILE }
|
||||
|
||||
return if (localDetails != null) {
|
||||
val obj = Json.decodeFromStream<MangaJson>(localDetails.openInputStream())
|
||||
obj.lang ?: "other"
|
||||
val obj = AndroidXmlReader(localDetails.openInputStream(), StandardCharsets.UTF_8.name()).use {
|
||||
XML.decodeFromReader<ComicInfo>(it)
|
||||
}
|
||||
obj.language?.value ?: "other"
|
||||
} else {
|
||||
"other"
|
||||
}
|
||||
|
@ -88,6 +96,7 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
}
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
private val xml: XML by injectLazy()
|
||||
|
||||
override val id = ID
|
||||
override val name = context.getString(R.string.local_source)
|
||||
|
@ -182,15 +191,43 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
override suspend fun getLatestUpdates(page: Int) = getSearchManga(page, "", latestFilters)
|
||||
|
||||
override suspend fun getMangaDetails(manga: SManga): SManga {
|
||||
val localDetails = getBaseDirectory().findFile(manga.url)?.listFiles().orEmpty()
|
||||
.filter { !it.isDirectory }
|
||||
.firstOrNull { it.extension.equals("json", ignoreCase = true) }
|
||||
try {
|
||||
val localMangaDir = getBaseDirectory().findFile(manga.url) ?: throw Exception("${manga.url} is not a valid directory")
|
||||
val localMangaFiles = localMangaDir.listFiles().orEmpty().filter { !it.isDirectory }
|
||||
val comicInfoFile = localMangaFiles.firstOrNull { it.name.orEmpty() == COMIC_INFO_FILE }
|
||||
val legacyJsonFile = localMangaFiles.firstOrNull { it.extension.orEmpty().equals("json", true) }
|
||||
|
||||
return if (localDetails != null) {
|
||||
val obj = json.decodeFromStream<MangaJson>(localDetails.openInputStream())
|
||||
if (comicInfoFile != null)
|
||||
return SManga.create().apply { setMangaDetailsFromComicInfoFile(comicInfoFile.openInputStream(), this) }
|
||||
|
||||
// TODO: Remove after awhile
|
||||
if (legacyJsonFile != null) {
|
||||
val rt = SManga.create().apply { setMangaDetailsFromLegacyJsonFile(legacyJsonFile.openInputStream(), this) }
|
||||
val comicInfo = rt.toComicInfo()
|
||||
localMangaDir.createFile(COMIC_INFO_FILE)
|
||||
?.writeText(xml.encodeToString(ComicInfo.serializer(), comicInfo)) { legacyJsonFile.delete() }
|
||||
return rt
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
|
||||
return manga
|
||||
}
|
||||
|
||||
private fun setMangaDetailsFromComicInfoFile(stream: InputStream, manga: SManga) {
|
||||
val comicInfo = AndroidXmlReader(stream, StandardCharsets.UTF_8.name()).use {
|
||||
xml.decodeFromReader<ComicInfo>(it)
|
||||
}
|
||||
|
||||
manga.copyFromComicInfo(comicInfo)
|
||||
}
|
||||
|
||||
private fun setMangaDetailsFromLegacyJsonFile(stream: InputStream, manga: SManga) {
|
||||
val obj = json.decodeFromStream<MangaJson>(stream)
|
||||
|
||||
obj.lang?.let { langMap[manga.url] = it }
|
||||
SManga.create().apply {
|
||||
manga.apply {
|
||||
title = obj.title ?: manga.title
|
||||
author = obj.author ?: manga.author
|
||||
artist = obj.artist ?: manga.artist
|
||||
|
@ -198,9 +235,6 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
genre = obj.genre?.joinToString(", ") ?: manga.genre
|
||||
status = obj.status ?: manga.status
|
||||
}
|
||||
} else {
|
||||
manga
|
||||
}
|
||||
}
|
||||
|
||||
fun updateMangaInfo(manga: SManga, lang: String?) {
|
||||
|
@ -208,14 +242,8 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
if (!directory.exists()) return
|
||||
|
||||
lang?.let { langMap[manga.url] = it }
|
||||
val json = Json { prettyPrint = true }
|
||||
val existingFileName = directory.listFiles()?.find { it.extension.equals("json", ignoreCase = true) }?.name
|
||||
val file = directory.createFile(existingFileName ?: "info.json")!!
|
||||
file.writeText(json.encodeToString(manga.toJson(lang)))
|
||||
}
|
||||
|
||||
private fun SManga.toJson(lang: String?): MangaJson {
|
||||
return MangaJson(title, author, artist, description, genre?.split(", ")?.toTypedArray(), status, lang)
|
||||
val file = directory.createFile(COMIC_INFO_FILE)!!
|
||||
file.writeText(xml.encodeToString(ComicInfo.serializer(), manga.toComicInfo()))
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
|
@ -41,9 +41,10 @@ fun UniFile.toTempFile(context: Context): File {
|
|||
return tempFile
|
||||
}
|
||||
|
||||
fun UniFile.writeText(string: String) {
|
||||
fun UniFile.writeText(string: String, onComplete: () -> Unit = {}) {
|
||||
this.openOutputStream().use {
|
||||
it.write(string.toByteArray())
|
||||
onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue