Add batch chapter update endpoint (#442)

This commit is contained in:
Valter Martinek
2022-11-09 18:13:29 +01:00
committed by GitHub
parent 2f3f47c745
commit 39490ce7ba
3 changed files with 75 additions and 6 deletions
@@ -66,6 +66,7 @@ object MangaAPI {
patch("{mangaId}/meta", MangaController.meta)
get("{mangaId}/chapters", MangaController.chapterList)
post("{mangaId}/chapter/batch", MangaController.chapterBatch)
get("{mangaId}/chapter/{chapterIndex}", MangaController.chapterRetrieve)
patch("{mangaId}/chapter/{chapterIndex}", MangaController.chapterModify)
delete("{mangaId}/chapter/{chapterIndex}", MangaController.chapterDelete)
@@ -8,6 +8,11 @@ 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
import org.kodein.di.instance
import suwayomi.tachidesk.manga.impl.CategoryManga
import suwayomi.tachidesk.manga.impl.Chapter
import suwayomi.tachidesk.manga.impl.Library
@@ -26,6 +31,8 @@ import suwayomi.tachidesk.server.util.withOperation
import kotlin.time.Duration.Companion.days
object MangaController {
private val json by DI.global.instance<Json>()
/** get manga info */
val retrieve = handler(
pathParam<Int>("mangaId"),
@@ -211,6 +218,25 @@ object MangaController {
}
)
/** batch edit chapters */
val chapterBatch = handler(
pathParam<Int>("mangaId"),
documentWith = {
withOperation {
summary("Chapters update multiple")
description("Update multiple chapters. For batch marking as read, or bookmarking")
}
body<Chapter.ChapterBatchEditInput>()
},
behaviorOf = { ctx, mangaId ->
val input = json.decodeFromString<Chapter.ChapterBatchEditInput>(ctx.body())
Chapter.modifyChapters(input, mangaId)
},
withResults = {
httpCode(HttpCode.OK)
}
)
/** used to display a chapter, get a chapter in order to show its pages */
val chapterRetrieve = handler(
pathParam<Int>("mangaId"),
@@ -10,16 +10,12 @@ package suwayomi.tachidesk.manga.impl
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.chapter.ChapterRecognition
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SortOrder.ASC
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.manga.impl.Manga.getManga
import suwayomi.tachidesk.manga.impl.util.getChapterDir
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
@@ -198,6 +194,52 @@ object Chapter {
}
}
@Serializable
data class ChapterChange(
val isRead: Boolean? = null,
val isBookmarked: Boolean? = null,
val lastPageRead: Int? = null // this probably won't be very useful, but for completion's sake
)
@Serializable
data class ChapterBatchEditInput(
val chapterIds: List<Int>? = null,
val chapterIndexes: List<Int>? = null,
val change: ChapterChange?
)
fun modifyChapters(input: ChapterBatchEditInput, mangaId: Int) {
// Make sure change is defined
if (input.change == null) return
val (isRead, isBookmarked, lastPageRead) = input.change
if (isRead == null && isBookmarked == null) return
// Make sure some filter is defined
val condition = when {
input.chapterIds != null ->
Op.build { (ChapterTable.manga eq mangaId) and (ChapterTable.id inList input.chapterIds) }
input.chapterIndexes != null ->
Op.build { (ChapterTable.manga eq mangaId) and (ChapterTable.sourceOrder inList input.chapterIndexes) }
else -> null
} ?: return
transaction {
val now = Instant.now().epochSecond
ChapterTable.update({ condition }) { update ->
isRead?.also {
update[ChapterTable.isRead] = it
}
isBookmarked?.also {
update[ChapterTable.isBookmarked] = it
}
lastPageRead?.also {
update[ChapterTable.lastPageRead] = it
update[ChapterTable.lastReadAt] = now
}
}
}
}
fun getChaptersMetaMaps(chapterIds: List<EntityID<Int>>): Map<EntityID<Int>, Map<String, String>> {
return transaction {
ChapterMetaTable.select { ChapterMetaTable.ref inList chapterIds }