Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always return "ArchiveProvider" in case "downloadAsCbz" is enabled #671

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package suwayomi.tachidesk.manga.impl.download.fileProvider

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.sample
import suwayomi.tachidesk.manga.impl.Page
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
import suwayomi.tachidesk.manga.impl.util.getChapterCachePath
import java.io.File
import java.io.InputStream

/*
Expand All @@ -14,11 +23,46 @@ abstract class ChaptersFilesProvider(val mangaId: Int, val chapterId: Int) : Dow
return RetrieveFile1Args(::getImageImpl)
}

abstract suspend fun downloadImpl(
@OptIn(FlowPreview::class)
open suspend fun downloadImpl(
download: DownloadChapter,
scope: CoroutineScope,
step: suspend (DownloadChapter?, Boolean) -> Unit
): Boolean
): Boolean {
val pageCount = download.chapter.pageCount
val chapterDir = getChapterCachePath(mangaId, chapterId)
val folder = File(chapterDir)
folder.mkdirs()

for (pageNum in 0 until pageCount) {
var pageProgressJob: Job? = null
val fileName = Page.getPageName(pageNum) // might have to change this to index stored in database
if (File(folder, fileName).exists()) continue
try {
Page.getPageImage(
mangaId = download.mangaId,
chapterIndex = download.chapterIndex,
index = pageNum
) { flow ->
pageProgressJob = flow
.sample(100)
.distinctUntilChanged()
.onEach {
download.progress = (pageNum.toFloat() + (it.toFloat() * 0.01f)) / pageCount
step(null, false) // don't throw on canceled download here since we can't do anything
}
.launchIn(scope)
}
} finally {
// always cancel the page progress job even if it throws an exception to avoid memory leaks
pageProgressJob?.cancel()
}
// TODO: retry on error with 2,4,8 seconds of wait
download.progress = ((pageNum + 1).toFloat()) / pageCount
step(download, false)
}
return true
}

override fun download(): FileDownload3Args<DownloadChapter, CoroutineScope, suspend (DownloadChapter?, Boolean) -> Unit> {
return FileDownload3Args(::downloadImpl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream
import org.apache.commons.compress.archivers.zip.ZipFile
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.getChapterCbzPath
import suwayomi.tachidesk.manga.impl.util.getChapterDownloadPath
import java.io.File
import java.io.InputStream

Expand All @@ -29,20 +29,19 @@ class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mang
scope: CoroutineScope,
step: suspend (DownloadChapter?, Boolean) -> Unit
): Boolean {
val chapterDir = getChapterDownloadPath(mangaId, chapterId)
val outputFile = File(getChapterCbzPath(mangaId, chapterId))
val chapterFolder = File(chapterDir)
if (outputFile.exists()) handleExistingCbzFile(outputFile, chapterFolder)
val chapterCacheFolder = File(getChapterCachePath(mangaId, chapterId))
if (outputFile.exists()) handleExistingCbzFile(outputFile, chapterCacheFolder)

FolderProvider(mangaId, chapterId).download().execute(download, scope, step)
super.downloadImpl(download, scope, step)

withContext(Dispatchers.IO) {
outputFile.createNewFile()
}

ZipArchiveOutputStream(outputFile.outputStream()).use { zipOut ->
if (chapterFolder.isDirectory) {
chapterFolder.listFiles()?.sortedBy { it.name }?.forEach {
if (chapterCacheFolder.isDirectory) {
chapterCacheFolder.listFiles()?.sortedBy { it.name }?.forEach {
val entry = ZipArchiveEntry(it.name)
try {
zipOut.putArchiveEntry(entry)
Expand All @@ -56,8 +55,8 @@ class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mang
}
}

if (chapterFolder.exists() && chapterFolder.isDirectory) {
chapterFolder.deleteRecursively()
if (chapterCacheFolder.exists() && chapterCacheFolder.isDirectory) {
chapterCacheFolder.deleteRecursively()
}

return true
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
package suwayomi.tachidesk.manga.impl.download.fileProvider.impl

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.sample
import suwayomi.tachidesk.manga.impl.Page
import suwayomi.tachidesk.manga.impl.Page.getPageName
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.getChapterDownloadPath
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
Expand All @@ -30,47 +22,28 @@ class FolderProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(manga
return Pair(FileInputStream(file).buffered(), "image/$fileType")
}

@OptIn(FlowPreview::class)
override suspend fun downloadImpl(
download: DownloadChapter,
scope: CoroutineScope,
step: suspend (DownloadChapter?, Boolean) -> Unit
): Boolean {
val pageCount = download.chapter.pageCount
val chapterDir = getChapterDownloadPath(mangaId, chapterId)
val folder = File(chapterDir)
folder.mkdirs()

for (pageNum in 0 until pageCount) {
var pageProgressJob: Job? = null
val fileName = getPageName(pageNum) // might have to change this to index stored in database
if (isExistingFile(folder, fileName)) continue
try {
Page.getPageImage(
mangaId = download.mangaId,
chapterIndex = download.chapterIndex,
index = pageNum
) { flow ->
pageProgressJob = flow
.sample(100)
.distinctUntilChanged()
.onEach {
download.progress = (pageNum.toFloat() + (it.toFloat() * 0.01f)) / pageCount
step(null, false) // don't throw on canceled download here since we can't do anything
}
.launchIn(scope)
}.first.use { image ->
val filePath = "$chapterDir/$fileName"
ImageResponse.saveImage(filePath, image)
}
} finally {
// always cancel the page progress job even if it throws an exception to avoid memory leaks
pageProgressJob?.cancel()
}
// TODO: retry on error with 2,4,8 seconds of wait
download.progress = ((pageNum + 1).toFloat()) / pageCount
step(download, false)
val alreadyDownloaded = folder.exists()
if (alreadyDownloaded) {
return true
}

val downloadSucceeded = super.downloadImpl(download, scope, step)
if (!downloadSucceeded) {
return false
}

folder.mkdirs()
val cacheChapterDir = getChapterCachePath(mangaId, chapterId)
File(cacheChapterDir).renameTo(folder)

return true
}

Expand Down
Loading