mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-06 12:24:33 -05:00
* OPDS: Offer CBZ in older mimetype * OPDS: Include length when offering CBZ download * Disable compression on CBZ endpoint Zipping a zip * CBZ download match content type of OPDS * Move compression disable * Introduce setting for configuring CBZ mimetype * Document new option [no-ci] * Update server/src/main/kotlin/suwayomi/tachidesk/opds/impl/OpdsEntryBuilder.kt Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com> --------- Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>
111 lines
4.2 KiB
Kotlin
111 lines
4.2 KiB
Kotlin
package suwayomi.tachidesk.manga.impl
|
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import org.jetbrains.exposed.sql.transactions.transaction
|
|
import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReady
|
|
import suwayomi.tachidesk.manga.impl.download.fileProvider.ChaptersFilesProvider
|
|
import suwayomi.tachidesk.manga.impl.download.fileProvider.impl.ArchiveProvider
|
|
import suwayomi.tachidesk.manga.impl.download.fileProvider.impl.FolderProvider
|
|
import suwayomi.tachidesk.manga.impl.download.model.DownloadQueueItem
|
|
import suwayomi.tachidesk.manga.impl.util.getChapterCbzPath
|
|
import suwayomi.tachidesk.manga.impl.util.getChapterDownloadPath
|
|
import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass
|
|
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
|
import suwayomi.tachidesk.manga.model.table.MangaTable
|
|
import suwayomi.tachidesk.manga.model.table.toDataClass
|
|
import suwayomi.tachidesk.server.serverConfig
|
|
import java.io.File
|
|
import java.io.InputStream
|
|
|
|
object ChapterDownloadHelper {
|
|
fun getImage(
|
|
mangaId: Int,
|
|
chapterId: Int,
|
|
index: Int,
|
|
): Pair<InputStream, String> = provider(mangaId, chapterId).getImage().execute(index)
|
|
|
|
fun getImageCount(
|
|
mangaId: Int,
|
|
chapterId: Int,
|
|
): Int = provider(mangaId, chapterId).getImageCount()
|
|
|
|
fun delete(
|
|
mangaId: Int,
|
|
chapterId: Int,
|
|
): Boolean = provider(mangaId, chapterId).delete()
|
|
|
|
/**
|
|
* This function should never be called without calling [getChapterDownloadReady] beforehand.
|
|
*/
|
|
suspend fun download(
|
|
mangaId: Int,
|
|
chapterId: Int,
|
|
download: DownloadQueueItem,
|
|
scope: CoroutineScope,
|
|
step: suspend (DownloadQueueItem?, Boolean) -> Unit,
|
|
): Boolean = provider(mangaId, chapterId).download().execute(download, scope, step)
|
|
|
|
// return the appropriate provider based on how the download was saved. For the logic is simple but will evolve when new types of downloads are available
|
|
private fun provider(
|
|
mangaId: Int,
|
|
chapterId: Int,
|
|
): ChaptersFilesProvider<*> {
|
|
val chapterFolder = File(getChapterDownloadPath(mangaId, chapterId))
|
|
val cbzFile = File(getChapterCbzPath(mangaId, chapterId))
|
|
if (cbzFile.exists()) return ArchiveProvider(mangaId, chapterId)
|
|
if (!chapterFolder.exists() && serverConfig.downloadAsCbz.value) return ArchiveProvider(mangaId, chapterId)
|
|
return FolderProvider(mangaId, chapterId)
|
|
}
|
|
|
|
fun getArchiveStreamWithSize(
|
|
mangaId: Int,
|
|
chapterId: Int,
|
|
): Pair<InputStream, Long> = provider(mangaId, chapterId).getAsArchiveStream()
|
|
|
|
private fun getChapterWithCbzFileName(chapterId: Int): Pair<ChapterDataClass, String> =
|
|
transaction {
|
|
val row =
|
|
(ChapterTable innerJoin MangaTable)
|
|
.select(ChapterTable.columns + MangaTable.columns)
|
|
.where { ChapterTable.id eq chapterId }
|
|
.firstOrNull() ?: throw IllegalArgumentException("ChapterId $chapterId not found")
|
|
val chapter = ChapterTable.toDataClass(row)
|
|
val mangaTitle = row[MangaTable.title]
|
|
|
|
val scanlatorPart = chapter.scanlator?.let { "[$it] " } ?: ""
|
|
val fileName = "$mangaTitle - $scanlatorPart${chapter.name}.cbz"
|
|
|
|
Pair(chapter, fileName)
|
|
}
|
|
|
|
fun getCbzForDownload(
|
|
chapterId: Int,
|
|
markAsRead: Boolean?,
|
|
): Triple<InputStream, String, Long> {
|
|
val (chapterData, fileName) = getChapterWithCbzFileName(chapterId)
|
|
|
|
val cbzFile = provider(chapterData.mangaId, chapterData.id).getAsArchiveStream()
|
|
|
|
if (markAsRead == true) {
|
|
Chapter.modifyChapter(
|
|
chapterData.mangaId,
|
|
chapterData.index,
|
|
isRead = true,
|
|
isBookmarked = null,
|
|
markPrevRead = null,
|
|
lastPageRead = null,
|
|
)
|
|
}
|
|
|
|
return Triple(cbzFile.first, fileName, cbzFile.second)
|
|
}
|
|
|
|
fun getCbzMetadataForDownload(chapterId: Int): Pair<String, Long> { // fileName, fileSize
|
|
val (chapterData, fileName) = getChapterWithCbzFileName(chapterId)
|
|
|
|
val fileSize = provider(chapterData.mangaId, chapterData.id).getArchiveSize()
|
|
|
|
return Pair(fileName, fileSize)
|
|
}
|
|
}
|