|
|
|
@ -1,5 +1,6 @@
|
|
|
|
package org.koitharu.kotatsu.core.parser
|
|
|
|
package org.koitharu.kotatsu.core.parser
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint
|
|
|
|
import android.content.Context
|
|
|
|
import android.content.Context
|
|
|
|
import android.net.Uri
|
|
|
|
import android.net.Uri
|
|
|
|
import androidx.core.net.toFile
|
|
|
|
import androidx.core.net.toFile
|
|
|
|
@ -41,21 +42,31 @@ class LocalMangaRepository : MangaRepository, KoinComponent {
|
|
|
|
|
|
|
|
|
|
|
|
@Suppress("BlockingMethodInNonBlockingContext")
|
|
|
|
@Suppress("BlockingMethodInNonBlockingContext")
|
|
|
|
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
|
|
|
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
|
|
|
val file = Uri.parse(chapter.url).toFile()
|
|
|
|
val uri = Uri.parse(chapter.url)
|
|
|
|
|
|
|
|
val file = uri.toFile()
|
|
|
|
val zip = ZipFile(file)
|
|
|
|
val zip = ZipFile(file)
|
|
|
|
val pattern = zip.getEntry(MangaZip.INDEX_ENTRY)?.let(zip::readText)?.let(::MangaIndex)
|
|
|
|
val index = zip.getEntry(MangaZip.INDEX_ENTRY)?.let(zip::readText)?.let(::MangaIndex)
|
|
|
|
?.getChapterNamesPattern(chapter)
|
|
|
|
var entries = zip.entries().asSequence()
|
|
|
|
val entries = if (pattern != null) {
|
|
|
|
entries = if (index != null) {
|
|
|
|
zip.entries().asSequence()
|
|
|
|
val pattern = index.getChapterNamesPattern(chapter)
|
|
|
|
.filter { x -> !x.isDirectory && x.name.substringBefore('.').matches(pattern) }
|
|
|
|
entries.filter { x -> !x.isDirectory && x.name.substringBefore('.').matches(pattern) }
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
zip.entries().asSequence().filter { x -> !x.isDirectory }
|
|
|
|
val parent = uri.fragment.orEmpty()
|
|
|
|
}.toList().sortedWith(compareBy(AlphanumComparator()) { x -> x.name })
|
|
|
|
entries.filter { x ->
|
|
|
|
return entries.map { x ->
|
|
|
|
!x.isDirectory && x.name.substringBeforeLast(
|
|
|
|
val uri = zipUri(file, x.name)
|
|
|
|
File.separatorChar,
|
|
|
|
|
|
|
|
""
|
|
|
|
|
|
|
|
) == parent
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return entries
|
|
|
|
|
|
|
|
.toList()
|
|
|
|
|
|
|
|
.sortedWith(compareBy(AlphanumComparator()) { x -> x.name })
|
|
|
|
|
|
|
|
.map { x ->
|
|
|
|
|
|
|
|
val entryUri = zipUri(file, x.name)
|
|
|
|
MangaPage(
|
|
|
|
MangaPage(
|
|
|
|
id = uri.longHashCode(),
|
|
|
|
id = entryUri.longHashCode(),
|
|
|
|
url = uri,
|
|
|
|
url = entryUri,
|
|
|
|
source = MangaSource.LOCAL
|
|
|
|
source = MangaSource.LOCAL
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -67,43 +78,50 @@ class LocalMangaRepository : MangaRepository, KoinComponent {
|
|
|
|
return file.delete()
|
|
|
|
return file.delete()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@SuppressLint("DefaultLocale")
|
|
|
|
fun getFromFile(file: File): Manga {
|
|
|
|
fun getFromFile(file: File): Manga {
|
|
|
|
val zip = ZipFile(file)
|
|
|
|
val zip = ZipFile(file)
|
|
|
|
val fileUri = file.toUri().toString()
|
|
|
|
val fileUri = file.toUri().toString()
|
|
|
|
val entry = zip.getEntry(MangaZip.INDEX_ENTRY)
|
|
|
|
val entry = zip.getEntry(MangaZip.INDEX_ENTRY)
|
|
|
|
val index = entry?.let(zip::readText)?.let(::MangaIndex)
|
|
|
|
val index = entry?.let(zip::readText)?.let(::MangaIndex)
|
|
|
|
return index?.let {
|
|
|
|
val info = index?.getMangaInfo()
|
|
|
|
it.getMangaInfo()?.let { x ->
|
|
|
|
if (index != null && info != null) {
|
|
|
|
x.copy(
|
|
|
|
return info.copy(
|
|
|
|
source = MangaSource.LOCAL,
|
|
|
|
source = MangaSource.LOCAL,
|
|
|
|
url = fileUri,
|
|
|
|
url = fileUri,
|
|
|
|
coverUrl = zipUri(
|
|
|
|
coverUrl = zipUri(
|
|
|
|
file,
|
|
|
|
file,
|
|
|
|
entryName = it.getCoverEntry()
|
|
|
|
entryName = index.getCoverEntry()
|
|
|
|
?: findFirstEntry(zip.entries())?.name.orEmpty()
|
|
|
|
?: findFirstEntry(zip.entries())?.name.orEmpty()
|
|
|
|
),
|
|
|
|
),
|
|
|
|
chapters = x.chapters?.map { c -> c.copy(url = fileUri) }
|
|
|
|
chapters = info.chapters?.map { c -> c.copy(url = fileUri) }
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} ?: run {
|
|
|
|
// fallback
|
|
|
|
val title = file.nameWithoutExtension.replace("_", " ").capitalize()
|
|
|
|
val title = file.nameWithoutExtension.replace("_", " ").capitalize()
|
|
|
|
Manga(
|
|
|
|
val chapters = HashSet<String>()
|
|
|
|
|
|
|
|
for (x in zip.entries()) {
|
|
|
|
|
|
|
|
if (!x.isDirectory) {
|
|
|
|
|
|
|
|
chapters += x.name.substringBeforeLast(File.separatorChar, "")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
val uriBuilder = file.toUri().buildUpon()
|
|
|
|
|
|
|
|
return Manga(
|
|
|
|
id = file.absolutePath.longHashCode(),
|
|
|
|
id = file.absolutePath.longHashCode(),
|
|
|
|
title = title,
|
|
|
|
title = title,
|
|
|
|
url = fileUri,
|
|
|
|
url = fileUri,
|
|
|
|
source = MangaSource.LOCAL,
|
|
|
|
source = MangaSource.LOCAL,
|
|
|
|
coverUrl = zipUri(file, findFirstEntry(zip.entries())?.name.orEmpty()),
|
|
|
|
coverUrl = zipUri(file, findFirstEntry(zip.entries())?.name.orEmpty()),
|
|
|
|
chapters = listOf(
|
|
|
|
chapters = chapters.sortedWith(AlphanumComparator()).mapIndexed { i, s ->
|
|
|
|
MangaChapter(
|
|
|
|
MangaChapter(
|
|
|
|
id = file.absolutePath.longHashCode(),
|
|
|
|
id = "$i$s".longHashCode(),
|
|
|
|
url = fileUri,
|
|
|
|
name = if (s.isEmpty()) title else s,
|
|
|
|
number = 1,
|
|
|
|
number = i + 1,
|
|
|
|
source = MangaSource.LOCAL,
|
|
|
|
source = MangaSource.LOCAL,
|
|
|
|
name = title
|
|
|
|
url = uriBuilder.fragment(s).build().toString()
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fun getRemoteManga(localManga: Manga): Manga? {
|
|
|
|
fun getRemoteManga(localManga: Manga): Manga? {
|
|
|
|
|