Fix/recognition of already downloaded chapters (#922)

* Remove overrides of "ChapterFilesProvider::downloadImpl"

* Check final download folder for existing page on download

Downloads were changed to get downloaded to the system temp folder instead to directly into the final download folder.

This broke the check for existing pages, because now only the temp folder was checked instead of both the temp and the final download folder.

Regression introduced with 1c9a139006

* Properly check for already existing downloaded pages

The previous check was always false because the file ending of the page file is unknown and thus, missing from the created file path

* Cleanup cache download folder
This commit is contained in:
schroda
2024-04-07 04:53:49 +02:00
committed by GitHub
parent 48e19f7914
commit cdc21b067c
3 changed files with 50 additions and 34 deletions

View File

@@ -13,6 +13,8 @@ import suwayomi.tachidesk.manga.impl.Page
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
import suwayomi.tachidesk.manga.impl.util.createComicInfoFile import suwayomi.tachidesk.manga.impl.util.createComicInfoFile
import suwayomi.tachidesk.manga.impl.util.getChapterCachePath import suwayomi.tachidesk.manga.impl.util.getChapterCachePath
import suwayomi.tachidesk.manga.impl.util.getChapterDownloadPath
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import java.io.File import java.io.File
@@ -28,21 +30,40 @@ abstract class ChaptersFilesProvider(val mangaId: Int, val chapterId: Int) : Dow
return RetrieveFile1Args(::getImageImpl) return RetrieveFile1Args(::getImageImpl)
} }
/**
* Extract the existing download to the base download folder (see [getChapterDownloadPath])
*/
protected abstract fun extractExistingDownload()
protected abstract suspend fun handleSuccessfulDownload()
@OptIn(FlowPreview::class) @OptIn(FlowPreview::class)
open suspend fun downloadImpl( private suspend fun downloadImpl(
download: DownloadChapter, download: DownloadChapter,
scope: CoroutineScope, scope: CoroutineScope,
step: suspend (DownloadChapter?, Boolean) -> Unit, step: suspend (DownloadChapter?, Boolean) -> Unit,
): Boolean { ): Boolean {
val pageCount = download.chapter.pageCount extractExistingDownload()
val chapterDir = getChapterCachePath(mangaId, chapterId)
val folder = File(chapterDir)
folder.mkdirs()
val finalDownloadFolder = getChapterDownloadPath(mangaId, chapterId)
val cacheChapterDir = getChapterCachePath(mangaId, chapterId)
val downloadCacheFolder = File(cacheChapterDir)
downloadCacheFolder.mkdirs()
val pageCount = download.chapter.pageCount
for (pageNum in 0 until pageCount) { for (pageNum in 0 until pageCount) {
var pageProgressJob: Job? = null var pageProgressJob: Job? = null
val fileName = Page.getPageName(pageNum) // might have to change this to index stored in database val fileName = Page.getPageName(pageNum) // might have to change this to index stored in database
if (File(folder, fileName).exists()) continue
val pageExistsInFinalDownloadFolder = ImageResponse.findFileNameStartingWith(finalDownloadFolder, fileName) != null
val pageExistsInCacheDownloadFolder = ImageResponse.findFileNameStartingWith(cacheChapterDir, fileName) != null
val doesPageAlreadyExist = pageExistsInFinalDownloadFolder || pageExistsInCacheDownloadFolder
if (doesPageAlreadyExist) {
continue
}
try { try {
Page.getPageImage( Page.getPageImage(
mangaId = download.mangaId, mangaId = download.mangaId,
@@ -69,7 +90,7 @@ abstract class ChaptersFilesProvider(val mangaId: Int, val chapterId: Int) : Dow
} }
createComicInfoFile( createComicInfoFile(
folder.toPath(), downloadCacheFolder.toPath(),
transaction { transaction {
MangaTable.select { MangaTable.id eq mangaId }.first() MangaTable.select { MangaTable.id eq mangaId }.first()
}, },
@@ -78,6 +99,10 @@ abstract class ChaptersFilesProvider(val mangaId: Int, val chapterId: Int) : Dow
}, },
) )
handleSuccessfulDownload()
File(cacheChapterDir).deleteRecursively()
return true return true
} }

View File

@@ -1,6 +1,5 @@
package suwayomi.tachidesk.manga.impl.download.fileProvider.impl package suwayomi.tachidesk.manga.impl.download.fileProvider.impl
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
@@ -11,7 +10,6 @@ import org.kodein.di.DI
import org.kodein.di.conf.global import org.kodein.di.conf.global
import org.kodein.di.instance import org.kodein.di.instance
import suwayomi.tachidesk.manga.impl.download.fileProvider.ChaptersFilesProvider import suwayomi.tachidesk.manga.impl.download.fileProvider.ChaptersFilesProvider
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
import suwayomi.tachidesk.manga.impl.util.getChapterCachePath import suwayomi.tachidesk.manga.impl.util.getChapterCachePath
import suwayomi.tachidesk.manga.impl.util.getChapterCbzPath import suwayomi.tachidesk.manga.impl.util.getChapterCbzPath
import suwayomi.tachidesk.manga.impl.util.getMangaDownloadDir import suwayomi.tachidesk.manga.impl.util.getMangaDownloadDir
@@ -32,17 +30,21 @@ class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mang
return Pair(inputStream.buffered(), "image/$fileType") return Pair(inputStream.buffered(), "image/$fileType")
} }
override suspend fun downloadImpl( override fun extractExistingDownload() {
download: DownloadChapter, val outputFile = File(getChapterCbzPath(mangaId, chapterId))
scope: CoroutineScope, val chapterCacheFolder = File(getChapterCachePath(mangaId, chapterId))
step: suspend (DownloadChapter?, Boolean) -> Unit,
): Boolean { if (!outputFile.exists()) {
return
}
extractCbzFile(outputFile, chapterCacheFolder)
}
override suspend fun handleSuccessfulDownload() {
val mangaDownloadFolder = File(getMangaDownloadDir(mangaId)) val mangaDownloadFolder = File(getMangaDownloadDir(mangaId))
val outputFile = File(getChapterCbzPath(mangaId, chapterId)) val outputFile = File(getChapterCbzPath(mangaId, chapterId))
val chapterCacheFolder = File(getChapterCachePath(mangaId, chapterId)) val chapterCacheFolder = File(getChapterCachePath(mangaId, chapterId))
if (outputFile.exists()) handleExistingCbzFile(outputFile, chapterCacheFolder)
super.downloadImpl(download, scope, step)
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
mangaDownloadFolder.mkdirs() mangaDownloadFolder.mkdirs()
@@ -68,8 +70,6 @@ class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mang
if (chapterCacheFolder.exists() && chapterCacheFolder.isDirectory) { if (chapterCacheFolder.exists() && chapterCacheFolder.isDirectory) {
chapterCacheFolder.deleteRecursively() chapterCacheFolder.deleteRecursively()
} }
return true
} }
override fun delete(): Boolean { override fun delete(): Boolean {
@@ -83,7 +83,7 @@ class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mang
return cbzDeleted return cbzDeleted
} }
private fun handleExistingCbzFile( private fun extractCbzFile(
cbzFile: File, cbzFile: File,
chapterFolder: File, chapterFolder: File,
) { ) {

View File

@@ -1,11 +1,9 @@
package suwayomi.tachidesk.manga.impl.download.fileProvider.impl package suwayomi.tachidesk.manga.impl.download.fileProvider.impl
import kotlinx.coroutines.CoroutineScope
import org.kodein.di.DI import org.kodein.di.DI
import org.kodein.di.conf.global import org.kodein.di.conf.global
import org.kodein.di.instance import org.kodein.di.instance
import suwayomi.tachidesk.manga.impl.download.fileProvider.ChaptersFilesProvider import suwayomi.tachidesk.manga.impl.download.fileProvider.ChaptersFilesProvider
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
import suwayomi.tachidesk.manga.impl.util.getChapterCachePath import suwayomi.tachidesk.manga.impl.util.getChapterCachePath
import suwayomi.tachidesk.manga.impl.util.getChapterDownloadPath import suwayomi.tachidesk.manga.impl.util.getChapterDownloadPath
import suwayomi.tachidesk.manga.impl.util.storage.FileDeletionHelper import suwayomi.tachidesk.manga.impl.util.storage.FileDeletionHelper
@@ -29,23 +27,16 @@ class FolderProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(manga
return Pair(FileInputStream(file).buffered(), "image/$fileType") return Pair(FileInputStream(file).buffered(), "image/$fileType")
} }
override suspend fun downloadImpl( override fun extractExistingDownload() {
download: DownloadChapter, // nothing to do
scope: CoroutineScope, }
step: suspend (DownloadChapter?, Boolean) -> Unit,
): Boolean { override suspend fun handleSuccessfulDownload() {
val chapterDir = getChapterDownloadPath(mangaId, chapterId) val chapterDir = getChapterDownloadPath(mangaId, chapterId)
val folder = File(chapterDir) val folder = File(chapterDir)
val downloadSucceeded = super.downloadImpl(download, scope, step)
if (!downloadSucceeded) {
return false
}
val cacheChapterDir = getChapterCachePath(mangaId, chapterId) val cacheChapterDir = getChapterCachePath(mangaId, chapterId)
File(cacheChapterDir).copyRecursively(folder, true) File(cacheChapterDir).copyRecursively(folder, true)
return true
} }
override fun delete(): Boolean { override fun delete(): Boolean {