diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt index ff66e3ef..df9bae19 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt @@ -1,9 +1,7 @@ package suwayomi.tachidesk.graphql.mutations -import eu.kanade.tachiyomi.source.model.SChapter import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.and -import org.jetbrains.exposed.sql.batchInsert import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction @@ -11,11 +9,9 @@ import org.jetbrains.exposed.sql.update import suwayomi.tachidesk.graphql.types.ChapterMetaType import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.manga.impl.Chapter -import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrNull +import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReadyById import suwayomi.tachidesk.manga.model.table.ChapterMetaTable import suwayomi.tachidesk.manga.model.table.ChapterTable -import suwayomi.tachidesk.manga.model.table.MangaTable -import suwayomi.tachidesk.manga.model.table.PageTable import suwayomi.tachidesk.server.JavalinSetup.future import java.time.Instant import java.util.concurrent.CompletableFuture @@ -203,43 +199,15 @@ class ChapterMutation { ): CompletableFuture { val (clientMutationId, chapterId) = input - val chapter = transaction { ChapterTable.select { ChapterTable.id eq chapterId }.first() } - val manga = transaction { MangaTable.select { MangaTable.id eq chapter[ChapterTable.manga] }.first() } - val source = getCatalogueSourceOrNull(manga[MangaTable.sourceReference])!! - return future { - source.getPageList( - SChapter.create().apply { - url = chapter[ChapterTable.url] - name = chapter[ChapterTable.name] - } - ) - }.thenApply { pageList -> - transaction { - PageTable.deleteWhere { PageTable.chapter eq chapterId } - PageTable.batchInsert(pageList) { page -> - this[PageTable.index] = page.index - this[PageTable.url] = page.url - this[PageTable.imageUrl] = page.imageUrl - this[PageTable.chapter] = chapterId - } - ChapterTable.update({ ChapterTable.id eq chapterId }) { - val pageCount = pageList.size - it[ChapterTable.pageCount] = pageCount - it[ChapterTable.lastPageRead] = chapter[ChapterTable.lastPageRead].coerceAtMost(pageCount - 1) - } - } - - val mangaId = manga[MangaTable.id].value - val chapterIndex = chapter[ChapterTable.sourceOrder] + getChapterDownloadReadyById(chapterId) + }.thenApply { chapter -> FetchChapterPagesPayload( clientMutationId = clientMutationId, - pages = List(pageList.size) { index -> - "/api/v1/manga/$mangaId/chapter/$chapterIndex/page/$index" + pages = List(chapter.pageCount) { index -> + "/api/v1/manga/${chapter.mangaId}/chapter/${chapter.index}/page/$index" }, - chapter = ChapterType( - transaction { ChapterTable.select { ChapterTable.id eq chapterId }.first() } - ) + chapter = ChapterType(chapter) ) } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/MangaController.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/MangaController.kt index f9a089c6..b984c87a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/MangaController.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/MangaController.kt @@ -8,7 +8,6 @@ package suwayomi.tachidesk.manga.controller * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import io.javalin.http.HttpCode -import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import org.kodein.di.DI import org.kodein.di.conf.global @@ -18,7 +17,7 @@ import suwayomi.tachidesk.manga.impl.Chapter import suwayomi.tachidesk.manga.impl.Library import suwayomi.tachidesk.manga.impl.Manga import suwayomi.tachidesk.manga.impl.Page -import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReady +import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReadyByIndex import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass @@ -293,7 +292,7 @@ object MangaController { } }, behaviorOf = { ctx, mangaId, chapterIndex -> - ctx.future(future { getChapterDownloadReady(chapterIndex, mangaId) }) + ctx.future(future { getChapterDownloadReadyByIndex(chapterIndex, mangaId) }) }, withResults = { json(HttpCode.OK) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/chapter/ChapterForDownload.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/chapter/ChapterForDownload.kt index b184dea1..adfcfb9b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/chapter/ChapterForDownload.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/chapter/ChapterForDownload.kt @@ -10,8 +10,10 @@ package suwayomi.tachidesk.manga.impl.chapter import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import org.jetbrains.exposed.sql.ResultRow +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.and -import org.jetbrains.exposed.sql.insert +import org.jetbrains.exposed.sql.batchInsert +import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.update @@ -27,15 +29,24 @@ import suwayomi.tachidesk.manga.model.table.PageTable import suwayomi.tachidesk.manga.model.table.toDataClass import java.io.File -suspend fun getChapterDownloadReady(chapterIndex: Int, mangaId: Int): ChapterDataClass { - val chapter = ChapterForDownload(chapterIndex, mangaId) +suspend fun getChapterDownloadReady(chapterId: Int? = null, chapterIndex: Int? = null, mangaId: Int? = null): ChapterDataClass { + val chapter = ChapterForDownload(chapterId, chapterIndex, mangaId) return chapter.asDownloadReady() } +suspend fun getChapterDownloadReadyById(chapterId: Int): ChapterDataClass { + return getChapterDownloadReady(chapterId = chapterId) +} + +suspend fun getChapterDownloadReadyByIndex(chapterIndex: Int, mangaId: Int): ChapterDataClass { + return getChapterDownloadReady(chapterIndex = chapterIndex, mangaId = mangaId) +} + private class ChapterForDownload( - private val chapterIndex: Int, - private val mangaId: Int + optChapterId: Int? = null, + optChapterIndex: Int? = null, + optMangaId: Int? = null ) { suspend fun asDownloadReady(): ChapterDataClass { if (isNotCompletelyDownloaded()) { @@ -51,11 +62,27 @@ private class ChapterForDownload( private fun asDataClass() = ChapterTable.toDataClass(chapterEntry) - var chapterEntry: ResultRow = freshChapterEntry() + var chapterEntry: ResultRow + val chapterId: Int + val chapterIndex: Int + val mangaId: Int - private fun freshChapterEntry() = transaction { + init { + chapterEntry = freshChapterEntry(optChapterId, optChapterIndex, optMangaId) + chapterId = chapterEntry[ChapterTable.id].value + chapterIndex = chapterEntry[ChapterTable.sourceOrder] + mangaId = chapterEntry[ChapterTable.manga].value + } + + private fun freshChapterEntry(optChapterId: Int? = null, optChapterIndex: Int? = null, optMangaId: Int? = null) = transaction { ChapterTable.select { - (ChapterTable.sourceOrder eq chapterIndex) and (ChapterTable.manga eq mangaId) + if (optChapterId != null) { + ChapterTable.id eq optChapterId + } else if (optChapterIndex != null && optMangaId != null) { + (ChapterTable.sourceOrder eq optChapterIndex) and (ChapterTable.manga eq optMangaId) + } else { + throw Exception("'optChapterId' or 'optChapterIndex' and 'optMangaId' have to be passed") + } }.first() } @@ -81,48 +108,31 @@ private class ChapterForDownload( } private fun updateDatabasePages(pageList: List) { - val chapterId = chapterEntry[ChapterTable.id].value - transaction { - pageList.forEach { page -> - val pageEntry = transaction { - PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) } - .firstOrNull() - } - if (pageEntry == null) { - PageTable.insert { - it[index] = page.index - it[url] = page.url - it[imageUrl] = page.imageUrl - it[chapter] = chapterId - } - } else { - PageTable.update({ (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }) { - it[url] = page.url - it[imageUrl] = page.imageUrl - } - } + PageTable.deleteWhere { PageTable.chapter eq chapterId } + PageTable.batchInsert(pageList) { page -> + this[PageTable.index] = page.index + this[PageTable.url] = page.url + this[PageTable.imageUrl] = page.imageUrl + this[PageTable.chapter] = chapterId } } updatePageCount(pageList, chapterId) // chapter was updated - chapterEntry = freshChapterEntry() + chapterEntry = freshChapterEntry(chapterId, chapterIndex, mangaId) } private fun updatePageCount( pageList: List, chapterId: Int ) { - val pageCount = pageList.count() - transaction { - val lastPageRead = ChapterTable.select { ChapterTable.id eq chapterId }.firstOrNull()?.get(ChapterTable.lastPageRead) ?: 0 - ChapterTable.update({ ChapterTable.id eq chapterId }) { + val pageCount = pageList.size it[ChapterTable.pageCount] = pageCount - it[ChapterTable.lastPageRead] = lastPageRead.coerceAtMost(pageCount - 1) + it[ChapterTable.lastPageRead] = chapterEntry[ChapterTable.lastPageRead].coerceAtMost(pageCount - 1) } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt index bc080fb8..f97c9250 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt @@ -20,7 +20,7 @@ import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.update import suwayomi.tachidesk.manga.impl.ChapterDownloadHelper -import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReady +import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReadyByIndex import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Downloading import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Error @@ -98,7 +98,7 @@ class Downloader( download.state = Downloading step(download, true) - download.chapter = getChapterDownloadReady(download.chapterIndex, download.mangaId) + download.chapter = getChapterDownloadReadyByIndex(download.chapterIndex, download.mangaId) step(download, false) ChapterDownloadHelper.download(download.mangaId, download.chapter.id, download, scope, this::step)