mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-29 20:47:50 +02:00
Refactor archive support with libarchive (#949)
* Refactor archive support with libarchive * Revert string resource changs * Only mark archive formats as supported Comic book archives should not be compressed. * Fixup * Remove epub from archive format list * Move to mihon package * Format * Cleanup
This commit is contained in:
@ -17,13 +17,12 @@ import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import logcat.LogPriority
|
||||
import mihon.core.common.extensions.toZipFile
|
||||
import mihon.core.common.archive.archiveReader
|
||||
import nl.adaptivity.xmlutil.AndroidXmlReader
|
||||
import nl.adaptivity.xmlutil.serialization.XML
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.storage.extension
|
||||
import tachiyomi.core.common.storage.nameWithoutExtension
|
||||
import tachiyomi.core.common.storage.openReadOnlyChannel
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
@ -45,7 +44,6 @@ import uy.kohesive.injekt.injectLazy
|
||||
import java.io.InputStream
|
||||
import java.nio.charset.StandardCharsets
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import com.github.junrar.Archive as JunrarArchive
|
||||
import tachiyomi.domain.source.model.Source as DomainSource
|
||||
|
||||
actual class LocalSource(
|
||||
@ -187,9 +185,7 @@ actual class LocalSource(
|
||||
|
||||
// Copy ComicInfo.xml from chapter archive to top level if found
|
||||
noXmlFile == null -> {
|
||||
val chapterArchives = mangaDirFiles
|
||||
.filter(Archive::isSupported)
|
||||
.toList()
|
||||
val chapterArchives = mangaDirFiles.filter(Archive::isSupported)
|
||||
|
||||
val copiedFile = copyComicInfoFileFromArchive(chapterArchives, mangaDir)
|
||||
if (copiedFile != null) {
|
||||
@ -209,26 +205,10 @@ actual class LocalSource(
|
||||
|
||||
private fun copyComicInfoFileFromArchive(chapterArchives: List<UniFile>, folder: UniFile): UniFile? {
|
||||
for (chapter in chapterArchives) {
|
||||
when (Format.valueOf(chapter)) {
|
||||
is Format.Zip -> {
|
||||
chapter.openReadOnlyChannel(context).toZipFile().use { zip ->
|
||||
zip.getEntry(COMIC_INFO_FILE)?.let { comicInfoFile ->
|
||||
zip.getInputStream(comicInfoFile).buffered().use { stream ->
|
||||
return copyComicInfoFile(stream, folder)
|
||||
}
|
||||
}
|
||||
}
|
||||
chapter.archiveReader(context).use { reader ->
|
||||
reader.getInputStream(COMIC_INFO_FILE)?.use { stream ->
|
||||
return copyComicInfoFile(stream, folder)
|
||||
}
|
||||
is Format.Rar -> {
|
||||
JunrarArchive(chapter.openInputStream()).use { rar ->
|
||||
rar.fileHeaders.firstOrNull { it.fileName == COMIC_INFO_FILE }?.let { comicInfoFile ->
|
||||
rar.getInputStream(comicInfoFile).buffered().use { stream ->
|
||||
return copyComicInfoFile(stream, folder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
return null
|
||||
@ -254,7 +234,7 @@ actual class LocalSource(
|
||||
override suspend fun getChapterList(manga: SManga): List<SChapter> = withIOContext {
|
||||
val chapters = fileSystem.getFilesInMangaDirectory(manga.url)
|
||||
// Only keep supported formats
|
||||
.filter { it.isDirectory || Archive.isSupported(it) }
|
||||
.filter { it.isDirectory || Archive.isSupported(it) || it.extension.equals("epub", true) }
|
||||
.map { chapterFile ->
|
||||
SChapter.create().apply {
|
||||
url = "${manga.url}/${chapterFile.name}"
|
||||
@ -270,7 +250,7 @@ actual class LocalSource(
|
||||
|
||||
val format = Format.valueOf(chapterFile)
|
||||
if (format is Format.Epub) {
|
||||
EpubFile(format.file.openReadOnlyChannel(context)).use { epub ->
|
||||
EpubFile(format.file.archiveReader(context)).use { epub ->
|
||||
epub.fillMetadata(manga, this)
|
||||
}
|
||||
}
|
||||
@ -328,31 +308,22 @@ actual class LocalSource(
|
||||
|
||||
entry?.let { coverManager.update(manga, it.openInputStream()) }
|
||||
}
|
||||
is Format.Zip -> {
|
||||
format.file.openReadOnlyChannel(context).toZipFile().use { zip ->
|
||||
val entry = zip.entries.toList()
|
||||
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
||||
.find { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
|
||||
is Format.Archive -> {
|
||||
format.file.archiveReader(context).use { reader ->
|
||||
val entry = reader.useEntries { entries ->
|
||||
entries
|
||||
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
||||
.find { it.isFile && ImageUtil.isImage(it.name) { reader.getInputStream(it.name)!! } }
|
||||
}
|
||||
|
||||
entry?.let { coverManager.update(manga, zip.getInputStream(it)) }
|
||||
}
|
||||
}
|
||||
is Format.Rar -> {
|
||||
JunrarArchive(format.file.openInputStream()).use { archive ->
|
||||
val entry = archive.fileHeaders
|
||||
.sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) }
|
||||
.find { !it.isDirectory && ImageUtil.isImage(it.fileName) { archive.getInputStream(it) } }
|
||||
|
||||
entry?.let { coverManager.update(manga, archive.getInputStream(it)) }
|
||||
entry?.let { coverManager.update(manga, reader.getInputStream(it.name)!!) }
|
||||
}
|
||||
}
|
||||
is Format.Epub -> {
|
||||
EpubFile(format.file.openReadOnlyChannel(context)).use { epub ->
|
||||
val entry = epub.getImagesFromPages()
|
||||
.firstOrNull()
|
||||
?.let { epub.getEntry(it) }
|
||||
EpubFile(format.file.archiveReader(context)).use { epub ->
|
||||
val entry = epub.getImagesFromPages().firstOrNull()
|
||||
|
||||
entry?.let { coverManager.update(manga, epub.getInputStream(it)) }
|
||||
entry?.let { coverManager.update(manga, epub.getInputStream(it)!!) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user