mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-21 20:27:06 +03:00
Merge branch 'master' into MR
This commit is contained in:
commit
b9d42c97d6
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 logcat.LogPriority
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import tachiyomi.core.metadata.tachiyomi.AnimeDetails
|
import tachiyomi.core.metadata.tachiyomi.AnimeDetails
|
||||||
|
import tachiyomi.core.metadata.tachiyomi.EpisodeDetails
|
||||||
import tachiyomi.core.util.lang.withIOContext
|
import tachiyomi.core.util.lang.withIOContext
|
||||||
import tachiyomi.core.util.system.logcat
|
import tachiyomi.core.util.system.logcat
|
||||||
import tachiyomi.domain.entries.anime.model.Anime
|
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 tachiyomi.source.local.io.anime.LocalAnimeSourceFileSystem
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
actual class LocalAnimeSource(
|
actual class LocalAnimeSource(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
@ -138,7 +142,7 @@ actual class LocalAnimeSource(
|
||||||
val animeDirFiles = fileSystem.getFilesInAnimeDirectory(anime.url).toList()
|
val animeDirFiles = fileSystem.getFilesInAnimeDirectory(anime.url).toList()
|
||||||
|
|
||||||
animeDirFiles
|
animeDirFiles
|
||||||
.firstOrNull { it.extension == "json" }
|
.firstOrNull { it.extension == "json" && it.nameWithoutExtension == "details" }
|
||||||
?.let { file ->
|
?.let { file ->
|
||||||
json.decodeFromStream<AnimeDetails>(file.inputStream()).run {
|
json.decodeFromStream<AnimeDetails>(file.inputStream()).run {
|
||||||
title?.let { anime.title = it }
|
title?.let { anime.title = it }
|
||||||
|
@ -155,6 +159,15 @@ actual class LocalAnimeSource(
|
||||||
|
|
||||||
// Episodes
|
// Episodes
|
||||||
override suspend fun getEpisodeList(anime: SAnime): List<SEpisode> {
|
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)
|
return fileSystem.getFilesInAnimeDirectory(anime.url)
|
||||||
// Only keep supported formats
|
// Only keep supported formats
|
||||||
.filter { it.isDirectory || ArchiveAnime.isSupported(it) }
|
.filter { it.isDirectory || ArchiveAnime.isSupported(it) }
|
||||||
|
@ -168,11 +181,21 @@ actual class LocalAnimeSource(
|
||||||
}
|
}
|
||||||
date_upload = episodeFile.lastModified()
|
date_upload = episodeFile.lastModified()
|
||||||
|
|
||||||
episode_number = EpisodeRecognition.parseEpisodeNumber(
|
val episodeNumber = EpisodeRecognition.parseEpisodeNumber(
|
||||||
anime.title,
|
anime.title,
|
||||||
this.name,
|
this.name,
|
||||||
this.episode_number,
|
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 ->
|
.sortedWith { e1, e2 ->
|
||||||
|
@ -182,6 +205,14 @@ actual class LocalAnimeSource(
|
||||||
.toList()
|
.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
|
// Filters
|
||||||
override fun getFilterList() = AnimeFilterList(AnimeOrderBy.Popular(context))
|
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.COMIC_INFO_FILE
|
||||||
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
||||||
import tachiyomi.core.metadata.comicinfo.copyFromComicInfo
|
import tachiyomi.core.metadata.comicinfo.copyFromComicInfo
|
||||||
|
import tachiyomi.core.metadata.tachiyomi.ChapterDetails
|
||||||
import tachiyomi.core.metadata.tachiyomi.MangaDetails
|
import tachiyomi.core.metadata.tachiyomi.MangaDetails
|
||||||
import tachiyomi.core.util.lang.withIOContext
|
import tachiyomi.core.util.lang.withIOContext
|
||||||
import tachiyomi.core.util.system.ImageUtil
|
import tachiyomi.core.util.system.ImageUtil
|
||||||
|
@ -39,8 +40,11 @@ import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.zip.ZipFile
|
import java.util.zip.ZipFile
|
||||||
|
import kotlin.math.abs
|
||||||
import com.github.junrar.Archive as JunrarArchive
|
import com.github.junrar.Archive as JunrarArchive
|
||||||
|
|
||||||
actual class LocalMangaSource(
|
actual class LocalMangaSource(
|
||||||
|
@ -162,7 +166,7 @@ actual class LocalMangaSource(
|
||||||
val noXmlFile = mangaDirFiles
|
val noXmlFile = mangaDirFiles
|
||||||
.firstOrNull { it.name == ".noxml" }
|
.firstOrNull { it.name == ".noxml" }
|
||||||
val legacyJsonDetailsFile = mangaDirFiles
|
val legacyJsonDetailsFile = mangaDirFiles
|
||||||
.firstOrNull { it.extension == "json" }
|
.firstOrNull { it.extension == "json" && it.nameWithoutExtension == "details" }
|
||||||
|
|
||||||
when {
|
when {
|
||||||
// Top level ComicInfo.xml
|
// Top level ComicInfo.xml
|
||||||
|
@ -256,6 +260,15 @@ actual class LocalMangaSource(
|
||||||
|
|
||||||
// Chapters
|
// Chapters
|
||||||
override suspend fun getChapterList(manga: SManga): List<SChapter> {
|
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)
|
return fileSystem.getFilesInMangaDirectory(manga.url)
|
||||||
// Only keep supported formats
|
// Only keep supported formats
|
||||||
.filter { it.isDirectory || ArchiveManga.isSupported(it) }
|
.filter { it.isDirectory || ArchiveManga.isSupported(it) }
|
||||||
|
@ -268,11 +281,13 @@ actual class LocalMangaSource(
|
||||||
chapterFile.nameWithoutExtension
|
chapterFile.nameWithoutExtension
|
||||||
}
|
}
|
||||||
date_upload = chapterFile.lastModified()
|
date_upload = chapterFile.lastModified()
|
||||||
chapter_number = ChapterRecognition.parseChapterNumber(
|
|
||||||
|
val chapterNumber = ChapterRecognition.parseChapterNumber(
|
||||||
manga.title,
|
manga.title,
|
||||||
this.name,
|
this.name,
|
||||||
this.chapter_number,
|
this.chapter_number,
|
||||||
)
|
)
|
||||||
|
chapter_number = chapterNumber
|
||||||
|
|
||||||
val format = Format.valueOf(chapterFile)
|
val format = Format.valueOf(chapterFile)
|
||||||
if (format is Format.Epub) {
|
if (format is Format.Epub) {
|
||||||
|
@ -280,6 +295,15 @@ actual class LocalMangaSource(
|
||||||
epub.fillChapterMetadata(this)
|
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 ->
|
.sortedWith { c1, c2 ->
|
||||||
|
@ -289,6 +313,14 @@ actual class LocalMangaSource(
|
||||||
.toList()
|
.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
|
// Filters
|
||||||
override fun getFilterList() = FilterList(MangaOrderBy.Popular(context))
|
override fun getFilterList() = FilterList(MangaOrderBy.Popular(context))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue