diff --git a/src/all/kavita/build.gradle b/src/all/kavita/build.gradle index 613a6804..b9296fad 100644 --- a/src/all/kavita/build.gradle +++ b/src/all/kavita/build.gradle @@ -2,7 +2,7 @@ ext { kmkVersionCode = 1 extName = 'Kavita' extClass = '.KavitaFactory' - extVersionCode = 32 + extVersionCode = 33 isNsfw = false } diff --git a/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/Kavita.kt b/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/Kavita.kt index 6d01b70a..a9cb9237 100644 --- a/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/Kavita.kt +++ b/src/all/kavita/src/eu/kanade/tachiyomi/extension/all/kavita/Kavita.kt @@ -81,6 +81,7 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy import java.io.IOException +import java.net.URLEncoder import java.security.MessageDigest import java.util.Calendar import java.util.Locale @@ -1774,6 +1775,9 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou params += "pages=$pageCount" } params += "extractPdf=${shouldExtractPdf(chapter, forceExtractPdf)}" + if (isEpubChapter(chapter)) { + params += "epub=true" + } if (chapter.fileCount > 1) { params += "split=${chapter.fileCount}" } @@ -1797,6 +1801,16 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou file.format == MangaFormat.Pdf.format || file.extension.equals("pdf", ignoreCase = true) } + private fun isEpubChapter(chapter: ChapterDto): Boolean = + chapter.files.orEmpty().any { file -> + file.format == MangaFormat.Epub.format || file.extension.equals("epub", ignoreCase = true) + } + + private fun isEpubFromChapterUrl(chapter: SChapter): Boolean = + chapter.url.substringAfter("epub=", "") + .substringBefore("&") + .equals("true", ignoreCase = true) + private fun isPdfSeries(seriesId: Int?): Boolean = seriesId?.let { id -> series.find { it.id == id }?.format == MangaFormat.Pdf.format || @@ -1830,6 +1844,22 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou return Page(index = index, url = imageUrl, imageUrl = imageUrl) } + private fun readerEpubPage(chapterId: Any, pageCount: Int, title: String? = null): Page { + val params = mutableListOf( + "apiUrl=${apiUrl.urlEncode()}", + "apiKey=${apiKey.urlEncode()}", + "chapterId=${chapterId.toString().urlEncode()}", + "pages=${pageCount.coerceAtLeast(1)}", + ) + if (!title.isNullOrBlank()) { + params += "title=${title.urlEncode()}" + } + val url = "kavita-epub://reader?${params.joinToString("&")}" + return Page(index = 0, url = url, imageUrl = null) + } + + private fun String.urlEncode(): String = URLEncoder.encode(this, Charsets.UTF_8.name()) + override suspend fun getPageList(chapter: SChapter): List = withContext(Dispatchers.IO) { // Check if this is a reading list item (has readingListId in URL) if (chapter.url.contains("readingListId=")) { @@ -1877,6 +1907,9 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou } // Generate pages with consistent URL format + if (isEpubChapter(chapterDetails)) { + return@withContext listOf(readerEpubPage(chapterDetails.id, chapterDetails.pages, chapterDetails.titleName ?: chapterDetails.title)) + } val extractPdf = shouldExtractPdf(chapterDetails, isPdfSeries(seriesId)) return@withContext (0 until chapterDetails.pages).map { i -> readerPage(i, chapterDetails.id, extractPdf = extractPdf) } } catch (e: Exception) { @@ -1913,6 +1946,9 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou .runningFold(0) { acc, chapter -> acc + chapter.pages } .zip(volume.chapters.sortedBy { it.number.toFloatOrNull() ?: 0f }) .flatMap { (startIndex, chapter) -> + if (isEpubChapter(chapter)) { + return@withContext listOf(readerEpubPage(chapter.id, chapter.pages, chapter.titleName ?: chapter.title)) + } val extractPdf = shouldExtractPdf(chapter, isPdfSeries(volume.seriesId)) (0 until chapter.pages).map { i -> readerPage(startIndex + i, chapter.id, i, extractPdf) @@ -1930,6 +1966,9 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou val extractPdf = extractPdfFromChapterUrl(chapter) pageCountFromChapterUrl(chapter)?.let { pageCount -> + if (isEpubFromChapterUrl(chapter)) { + return@withContext listOf(readerEpubPage(chapterId, pageCount, chapter.name)) + } return@withContext (0 until pageCount).map { i -> readerPage(i, chapterId, extractPdf = extractPdf) } } @@ -1952,6 +1991,9 @@ class Kavita(private val suffix: String = "") : ConfigurableSource, UnmeteredSou } val fetchedExtractPdf = extractPdf || shouldExtractPdf(chapterDetails) + if (isEpubChapter(chapterDetails)) { + return@withContext listOf(readerEpubPage(chapterId, chapterDetails.pages, chapterDetails.titleName ?: chapterDetails.title)) + } return@withContext (0 until chapterDetails.pages).map { i -> readerPage(i, chapterId, extractPdf = fetchedExtractPdf) } } } catch (e: Exception) {