mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-24 05:38:01 +03:00
feat(localanime): Allow for custom episode data (#1203)
This commit is contained in:
parent
8b1934fc36
commit
236849b6eb
4 changed files with 89 additions and 4 deletions
|
@ -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,
|
||||
)
|
|
@ -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,
|
||||
)
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
Loading…
Reference in a new issue