feat(localanime): Allow for custom episode data (#1203)

This commit is contained in:
Secozzi 2023-11-11 11:18:45 +00:00 committed by GitHub
parent 8b1934fc36
commit 236849b6eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 4 deletions

View file

@ -0,0 +1,11 @@
package tachiyomi.core.metadata.tachiyomi
import kotlinx.serialization.Serializable
@Serializable
class ChapterDetails(
val chapter_number: Float,
val name: String? = null,
val date_upload: String? = null,
val scanlator: String? = null,
)

View file

@ -0,0 +1,11 @@
package tachiyomi.core.metadata.tachiyomi
import kotlinx.serialization.Serializable
@Serializable
class EpisodeDetails(
val episode_number: Float,
val name: String? = null,
val date_upload: String? = null,
val scanlator: String? = null,
)

View file

@ -17,6 +17,7 @@ import kotlinx.serialization.json.decodeFromStream
import logcat.LogPriority
import rx.Observable
import tachiyomi.core.metadata.tachiyomi.AnimeDetails
import tachiyomi.core.metadata.tachiyomi.EpisodeDetails
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.entries.anime.model.Anime
@ -28,7 +29,10 @@ import tachiyomi.source.local.io.ArchiveAnime
import tachiyomi.source.local.io.anime.LocalAnimeSourceFileSystem
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import kotlin.math.abs
actual class LocalAnimeSource(
private val context: Context,
@ -138,7 +142,7 @@ actual class LocalAnimeSource(
val animeDirFiles = fileSystem.getFilesInAnimeDirectory(anime.url).toList()
animeDirFiles
.firstOrNull { it.extension == "json" }
.firstOrNull { it.extension == "json" && it.nameWithoutExtension == "details" }
?.let { file ->
json.decodeFromStream<AnimeDetails>(file.inputStream()).run {
title?.let { anime.title = it }
@ -155,6 +159,15 @@ actual class LocalAnimeSource(
// Episodes
override suspend fun getEpisodeList(anime: SAnime): List<SEpisode> {
val episodesData = fileSystem.getFilesInAnimeDirectory(anime.url)
.firstOrNull {
it.extension == "json" && it.nameWithoutExtension == "episodes"
}?.let { file ->
runCatching {
json.decodeFromStream<List<EpisodeDetails>>(file.inputStream())
}.getOrNull()
}
return fileSystem.getFilesInAnimeDirectory(anime.url)
// Only keep supported formats
.filter { it.isDirectory || ArchiveAnime.isSupported(it) }
@ -168,11 +181,21 @@ actual class LocalAnimeSource(
}
date_upload = episodeFile.lastModified()
episode_number = EpisodeRecognition.parseEpisodeNumber(
val episodeNumber = EpisodeRecognition.parseEpisodeNumber(
anime.title,
this.name,
this.episode_number,
)
episode_number = episodeNumber
// Overwrite data from episodes.json file
episodesData?.also { dataList ->
dataList.firstOrNull { it.episode_number.equalsTo(episodeNumber) }?.also { data ->
data.name?.also { name = it }
data.date_upload?.also { date_upload = parseDate(it) }
scanlator = data.scanlator
}
}
}
}
.sortedWith { e1, e2 ->
@ -182,6 +205,14 @@ actual class LocalAnimeSource(
.toList()
}
private fun parseDate(isoDate: String): Long {
return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault()).parse(isoDate)?.time ?: 0L
}
private fun Float.equalsTo(other: Float): Boolean {
return abs(this - other) < 0.0001
}
// Filters
override fun getFilterList() = AnimeFilterList(AnimeOrderBy.Popular(context))

View file

@ -20,6 +20,7 @@ import rx.Observable
import tachiyomi.core.metadata.comicinfo.COMIC_INFO_FILE
import tachiyomi.core.metadata.comicinfo.ComicInfo
import tachiyomi.core.metadata.comicinfo.copyFromComicInfo
import tachiyomi.core.metadata.tachiyomi.ChapterDetails
import tachiyomi.core.metadata.tachiyomi.MangaDetails
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.ImageUtil
@ -39,8 +40,11 @@ import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.nio.charset.StandardCharsets
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import java.util.zip.ZipFile
import kotlin.math.abs
import com.github.junrar.Archive as JunrarArchive
actual class LocalMangaSource(
@ -162,7 +166,7 @@ actual class LocalMangaSource(
val noXmlFile = mangaDirFiles
.firstOrNull { it.name == ".noxml" }
val legacyJsonDetailsFile = mangaDirFiles
.firstOrNull { it.extension == "json" }
.firstOrNull { it.extension == "json" && it.nameWithoutExtension == "details" }
when {
// Top level ComicInfo.xml
@ -256,6 +260,15 @@ actual class LocalMangaSource(
// Chapters
override suspend fun getChapterList(manga: SManga): List<SChapter> {
val chaptersData = fileSystem.getFilesInMangaDirectory(manga.url)
.firstOrNull {
it.extension == "json" && it.nameWithoutExtension == "chapters"
}?.let { file ->
runCatching {
json.decodeFromStream<List<ChapterDetails>>(file.inputStream())
}.getOrNull()
}
return fileSystem.getFilesInMangaDirectory(manga.url)
// Only keep supported formats
.filter { it.isDirectory || ArchiveManga.isSupported(it) }
@ -268,11 +281,13 @@ actual class LocalMangaSource(
chapterFile.nameWithoutExtension
}
date_upload = chapterFile.lastModified()
chapter_number = ChapterRecognition.parseChapterNumber(
val chapterNumber = ChapterRecognition.parseChapterNumber(
manga.title,
this.name,
this.chapter_number,
)
chapter_number = chapterNumber
val format = Format.valueOf(chapterFile)
if (format is Format.Epub) {
@ -280,6 +295,15 @@ actual class LocalMangaSource(
epub.fillChapterMetadata(this)
}
}
// Overwrite data from chapters.json file
chaptersData?.also { dataList ->
dataList.firstOrNull { it.chapter_number.equalsTo(chapterNumber) }?.also { data ->
data.name?.also { name = it }
data.date_upload?.also { date_upload = parseDate(it) }
scanlator = data.scanlator
}
}
}
}
.sortedWith { c1, c2 ->
@ -289,6 +313,14 @@ actual class LocalMangaSource(
.toList()
}
private fun parseDate(isoDate: String): Long {
return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault()).parse(isoDate)?.time ?: 0L
}
private fun Float.equalsTo(other: Float): Boolean {
return abs(this - other) < 0.0001
}
// Filters
override fun getFilterList() = FilterList(MangaOrderBy.Popular(context))