diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt index 018a8306b..1e32c3729 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt @@ -374,6 +374,7 @@ class DownloadCache( when { // Ignore incomplete downloads it.name?.endsWith(Downloader.TMP_DIR_SUFFIX) == true -> null + it.name?.contains(".download.", ignoreCase = true) == true -> null // Folder of images it.isDirectory -> it.name // Archived or original document files diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index da0384082..396ddc32c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -455,9 +455,9 @@ class Downloader( document: RemoteDocument, ) { val targetName = "$chapterDirname.${document.extension}" - mangaDir.findFile(targetName)?.delete() - mangaDir.findFile("$targetName.tmp")?.delete() - val temp = mangaDir.createFile("$targetName.tmp") + val tempName = "$chapterDirname.download.${document.extension}" + mangaDir.findFile(tempName)?.delete() + val temp = mangaDir.createFile(tempName) ?: error("Failed to create temporary document file") val page = Page(0).apply { status = Page.State.DownloadImage @@ -482,6 +482,7 @@ class Downloader( throw IllegalStateException("Document download returned an empty file") } + mangaDir.findFile(targetName)?.delete() if (!temp.renameTo(targetName)) { val target = mangaDir.createFile(targetName) ?: error("Failed to create downloaded document file") diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/bookoasis/BookOasisCompat.kt b/app/src/main/java/eu/kanade/tachiyomi/source/bookoasis/BookOasisCompat.kt index 9925dd1a3..f43e1c920 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/bookoasis/BookOasisCompat.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/bookoasis/BookOasisCompat.kt @@ -21,13 +21,24 @@ internal data class BookOasisChapterRef( val format: String, ) +private fun HttpSource.bookOasisServerBase(): String { + val normalized = baseUrl.trimEnd('/') + return when { + normalized.endsWith("/app-opds-adult", ignoreCase = true) -> + normalized.dropLast("/app-opds-adult".length) + normalized.endsWith("/app-opds", ignoreCase = true) -> + normalized.dropLast("/app-opds".length) + else -> normalized + } +} + internal fun HttpSource.bookOasisDocumentDownloadRequest(ref: BookOasisChapterRef): Request { val downloadUrl = buildString { - append(baseUrl.trimEnd('/')) - append("/api/media/books/") - append(ref.bookId) - append("/download?type=") + append(bookOasisServerBase()) + append("/app-opds/download/") append(ref.dbType) + append('/') + append(ref.bookId) } return Request.Builder() @@ -43,7 +54,7 @@ internal fun Source.isBookOasisSource(): Boolean { internal fun String.toBookOasisChapterRef(): BookOasisChapterRef? { val path = substringBefore('?') - val match = Regex("""^/api/media/books/(\d+)/info$""").matchEntire(path) ?: return null + val match = Regex("""^/(?:app-opds(?:-adult)?/)?api/media/books/(\d+)/info$""").matchEntire(path) ?: return null val params = parseQueryParameters(this) val format = params["bo_format"]?.lowercase() ?: return null if (format !in DOCUMENT_FORMATS) return null diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/kavita/KavitaCompat.kt b/app/src/main/java/eu/kanade/tachiyomi/source/kavita/KavitaCompat.kt index 6306377cc..4a9c40c89 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/kavita/KavitaCompat.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/kavita/KavitaCompat.kt @@ -12,8 +12,13 @@ private const val KAVITA_PACKAGE_PREFIX = "eu.kanade.tachiyomi.extension.all.kav internal fun Source.isKavitaSource(): Boolean = this::class.java.name.startsWith(KAVITA_PACKAGE_PREFIX) +private fun HttpSource.kavitaApiBase(): String { + val normalized = baseUrl.trimEnd('/') + return if (normalized.endsWith("/api", ignoreCase = true)) normalized else "$normalized/api" +} + internal suspend fun HttpSource.detectKavitaDocumentFormat(chapterId: Int): String? { - val apiBase = baseUrl.trimEnd('/') + "/api" + val apiBase = kavitaApiBase() val request = Request.Builder() .url("$apiBase/Chapter?chapterId=$chapterId") .headers(headers) @@ -43,7 +48,7 @@ internal suspend fun HttpSource.detectKavitaDocumentFormat(chapterId: Int): Stri } internal fun HttpSource.kavitaDocumentDownloadRequest(chapterId: Int): Request { - val apiBase = baseUrl.trimEnd('/') + "/api" + val apiBase = kavitaApiBase() return Request.Builder() .url("$apiBase/Download/chapter?chapterId=$chapterId") .headers(headers)