mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
feat: Use ComicInfo for chapters
This commit is contained in:
parent
f28ed2cfb3
commit
b87cbc87d6
3 changed files with 100 additions and 48 deletions
|
@ -1,5 +1,7 @@
|
|||
package dev.yokai.core.metadata
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import kotlinx.serialization.Serializable
|
||||
import nl.adaptivity.xmlutil.serialization.XmlElement
|
||||
|
@ -9,6 +11,42 @@ import nl.adaptivity.xmlutil.serialization.XmlValue
|
|||
const val COMIC_INFO_EDITS_FILE = "ComicInfoEdits.xml"
|
||||
const val COMIC_INFO_FILE = "ComicInfo.xml"
|
||||
|
||||
fun getComicInfo(
|
||||
manga: Manga,
|
||||
chapter: Chapter,
|
||||
urls: List<String>,
|
||||
categories: List<String>?,
|
||||
sourceName: String,
|
||||
lang: String?,
|
||||
) = ComicInfo(
|
||||
title = ComicInfo.Title(chapter.name),
|
||||
series = ComicInfo.Series(manga.title),
|
||||
number = chapter.chapter_number.takeIf { it >= 0 }?.let {
|
||||
if (it.rem(1) == 0.0f) {
|
||||
ComicInfo.Number(it.toInt().toString())
|
||||
} else {
|
||||
ComicInfo.Number(it.toString())
|
||||
}
|
||||
},
|
||||
summary = manga.description?.let { ComicInfo.Summary(it) },
|
||||
writer = manga.author?.let { ComicInfo.Writer(it) },
|
||||
penciller = manga.artist?.let { ComicInfo.Penciller(it) },
|
||||
inker = null,
|
||||
colorist = null,
|
||||
letterer = null,
|
||||
coverArtist = null,
|
||||
translator = chapter.scanlator?.let { ComicInfo.Translator(it) },
|
||||
genre = manga.genre?.let { ComicInfo.Genre(it) },
|
||||
tags = null,
|
||||
web = ComicInfo.Web(urls.joinToString(" ")),
|
||||
publishingStatus = ComicInfo.PublishingStatusTachiyomi(
|
||||
ComicInfoPublishingStatus.toComicInfoValue(manga.status.toLong())
|
||||
),
|
||||
categories = categories?.let { ComicInfo.CategoriesTachiyomi(it.joinToString()) },
|
||||
source = ComicInfo.SourceMihon(sourceName),
|
||||
language = lang?.let { ComicInfo.LanguageJ2K(it) },
|
||||
)
|
||||
|
||||
fun SManga.toComicInfo(lang: String? = null) = ComicInfo(
|
||||
title = null,
|
||||
series = ComicInfo.Series(title),
|
||||
|
|
|
@ -5,9 +5,13 @@ import android.os.Handler
|
|||
import android.os.Looper
|
||||
import com.hippo.unifile.UniFile
|
||||
import com.jakewharton.rxrelay.PublishRelay
|
||||
import dev.yokai.core.metadata.COMIC_INFO_FILE
|
||||
import dev.yokai.core.metadata.ComicInfo
|
||||
import dev.yokai.core.metadata.getComicInfo
|
||||
import dev.yokai.domain.download.DownloadPreferences
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
|
@ -27,6 +31,7 @@ import eu.kanade.tachiyomi.util.system.launchIO
|
|||
import eu.kanade.tachiyomi.util.system.launchNow
|
||||
import eu.kanade.tachiyomi.util.system.withIOContext
|
||||
import eu.kanade.tachiyomi.util.system.withUIContext
|
||||
import eu.kanade.tachiyomi.util.system.writeText
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
|
@ -38,6 +43,7 @@ import kotlinx.coroutines.flow.flow
|
|||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.retryWhen
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import nl.adaptivity.xmlutil.serialization.XML
|
||||
import okhttp3.Response
|
||||
import rx.Observable
|
||||
import rx.Subscription
|
||||
|
@ -74,6 +80,8 @@ class Downloader(
|
|||
private val preferences: PreferencesHelper by injectLazy()
|
||||
private val downloadPreferences: DownloadPreferences by injectLazy()
|
||||
private val chapterCache: ChapterCache by injectLazy()
|
||||
private val xml: XML by injectLazy()
|
||||
private val db: DatabaseHelper by injectLazy()
|
||||
|
||||
/**
|
||||
* Store for persisting downloads across restarts.
|
||||
|
@ -443,16 +451,8 @@ class Downloader(
|
|||
}
|
||||
|
||||
// When the page is ready, set page path, progress (just in case) and status
|
||||
val success = splitTallImageIfNeeded(page, tmpDir)
|
||||
/*
|
||||
if (!success) {
|
||||
notifier.onError(
|
||||
context.getString(R.string.download_notifier_split_failed),
|
||||
chapName,
|
||||
download.manga.title,
|
||||
)
|
||||
}
|
||||
*/
|
||||
splitTallImageIfNeeded(page, tmpDir)
|
||||
|
||||
page.uri = file.uri
|
||||
page.progress = 100
|
||||
page.status = Page.State.READY
|
||||
|
@ -596,14 +596,12 @@ class Downloader(
|
|||
}
|
||||
|
||||
download.status = if (downloadedImagesCount == downloadPageCount) {
|
||||
// TODO: Uncomment when #8537 is resolved
|
||||
// val chapterUrl = download.source.getChapterUrl(download.chapter)
|
||||
// createComicInfoFile(
|
||||
// tmpDir,
|
||||
// download.manga,
|
||||
// download.chapter.toDomainChapter()!!,
|
||||
// chapterUrl,
|
||||
// )
|
||||
createComicInfoFile(
|
||||
tmpDir,
|
||||
download.manga,
|
||||
download.chapter,
|
||||
download.source,
|
||||
)
|
||||
|
||||
// Only rename the directory if it's downloaded
|
||||
if (preferences.saveChaptersAsCBZ().get()) {
|
||||
|
@ -655,28 +653,37 @@ class Downloader(
|
|||
tmpDir.delete()
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Creates a ComicInfo.xml file inside the given directory.
|
||||
// *
|
||||
// * @param dir the directory in which the ComicInfo file will be generated.
|
||||
// * @param manga the manga.
|
||||
// * @param chapter the chapter.
|
||||
// * @param chapterUrl the resolved URL for the chapter.
|
||||
// */
|
||||
// private fun createComicInfoFile(
|
||||
// dir: UniFile,
|
||||
// manga: Manga,
|
||||
// chapter: Chapter,
|
||||
// chapterUrl: String,
|
||||
// ) {
|
||||
// val comicInfo = getComicInfo(manga, chapter, chapterUrl)
|
||||
// val comicInfoString = xml.encodeToString(ComicInfo.serializer(), comicInfo)
|
||||
// // Remove the old file
|
||||
// dir.findFile(COMIC_INFO_FILE)?.delete()
|
||||
// dir.createFile(COMIC_INFO_FILE).openOutputStream().use {
|
||||
// it.write(comicInfoString.toByteArray())
|
||||
// }
|
||||
// }
|
||||
/**
|
||||
* Creates a ComicInfo.xml file inside the given directory.
|
||||
*
|
||||
* @param dir the directory in which the ComicInfo file will be generated.
|
||||
* @param manga the manga.
|
||||
* @param chapter the chapter.
|
||||
* @param chapterUrl the resolved URL for the chapter.
|
||||
*/
|
||||
private fun createComicInfoFile(
|
||||
dir: UniFile,
|
||||
manga: Manga,
|
||||
chapter: Chapter,
|
||||
source: HttpSource,
|
||||
) {
|
||||
val categories =
|
||||
db.getCategoriesForManga(manga).executeAsBlocking().map { it.name.trim() }.takeUnless { it.isEmpty() }
|
||||
val urls = source.getChapterUrl(manga, chapter)?.let { listOf(it) } ?: listOf()
|
||||
|
||||
val comicInfo = getComicInfo(
|
||||
manga,
|
||||
chapter,
|
||||
urls,
|
||||
categories,
|
||||
source.name,
|
||||
source.lang,
|
||||
)
|
||||
|
||||
// Remove the old file
|
||||
dir.findFile(COMIC_INFO_FILE)?.delete()
|
||||
dir.createFile(COMIC_INFO_FILE)?.writeText(xml.encodeToString(ComicInfo.serializer(), comicInfo))
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes a download. This method is called in the main thread.
|
||||
|
|
|
@ -33,6 +33,8 @@ import kotlinx.serialization.json.decodeFromStream
|
|||
import nl.adaptivity.xmlutil.AndroidXmlReader
|
||||
import nl.adaptivity.xmlutil.serialization.XML
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
|
@ -48,6 +50,12 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
private val LATEST_THRESHOLD = TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS)
|
||||
private val langMap = hashMapOf<String, String>()
|
||||
|
||||
fun decodeComicInfo(stream: InputStream, xml: XML = Injekt.get()): ComicInfo {
|
||||
return AndroidXmlReader(stream, StandardCharsets.UTF_8.name()).use { reader ->
|
||||
xml.decodeFromReader<ComicInfo>(reader)
|
||||
}
|
||||
}
|
||||
|
||||
fun getMangaLang(manga: SManga): String {
|
||||
return langMap.getOrPut(manga.url) {
|
||||
val localDetails = getBaseDirectory().findFile(manga.url)?.listFiles().orEmpty()
|
||||
|
@ -55,10 +63,7 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
.firstOrNull { it.name == COMIC_INFO_FILE }
|
||||
|
||||
return if (localDetails != null) {
|
||||
val obj = AndroidXmlReader(localDetails.openInputStream(), StandardCharsets.UTF_8.name()).use {
|
||||
XML.decodeFromReader<ComicInfo>(it)
|
||||
}
|
||||
obj.language?.value ?: "other"
|
||||
decodeComicInfo(localDetails.openInputStream()).language?.value ?: "other"
|
||||
} else {
|
||||
"other"
|
||||
}
|
||||
|
@ -218,9 +223,7 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
}
|
||||
|
||||
private fun setMangaDetailsFromComicInfoFile(stream: InputStream, manga: SManga) {
|
||||
val comicInfo = AndroidXmlReader(stream, StandardCharsets.UTF_8.name()).use {
|
||||
xml.decodeFromReader<ComicInfo>(it)
|
||||
}
|
||||
val comicInfo = decodeComicInfo(stream, xml)
|
||||
|
||||
comicInfo.language?.let { langMap[manga.url] = it.value }
|
||||
manga.copyFromComicInfo(comicInfo)
|
||||
|
@ -279,10 +282,14 @@ class LocalSource(private val context: Context) : CatalogueSource, UnmeteredSour
|
|||
val chapters = getBaseDirectory().findFile(manga.url)?.listFiles().orEmpty()
|
||||
.filter { it.isDirectory || isSupportedFile(it.extension.orEmpty()) }
|
||||
.map { chapterFile ->
|
||||
val chapterComicInfo = chapterFile.findFile(COMIC_INFO_FILE)?.let {
|
||||
decodeComicInfo(it.openInputStream(), xml)
|
||||
}
|
||||
|
||||
SChapter.create().apply {
|
||||
url = "${manga.url}/${chapterFile.name}"
|
||||
name = if (chapterFile.isDirectory) {
|
||||
chapterFile.name.orEmpty()
|
||||
chapterComicInfo?.title?.value ?: chapterFile.name.orEmpty()
|
||||
} else {
|
||||
chapterFile.nameWithoutExtension.orEmpty()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue