diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ReadListController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ReadListController.kt index ca70646aa..573c03382 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ReadListController.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ReadListController.kt @@ -9,6 +9,7 @@ import org.gotson.komga.domain.model.DuplicateNameException import org.gotson.komga.domain.model.ROLE_ADMIN import org.gotson.komga.domain.model.ReadList import org.gotson.komga.domain.persistence.ReadListRepository +import org.gotson.komga.domain.service.BookLifecycle import org.gotson.komga.domain.service.ReadListLifecycle import org.gotson.komga.infrastructure.jooq.UnpagedSorted import org.gotson.komga.infrastructure.language.toIndexedMap @@ -17,11 +18,14 @@ import org.gotson.komga.infrastructure.swagger.PageableWithoutSortAsQueryParam import org.gotson.komga.interfaces.rest.dto.BookDto import org.gotson.komga.interfaces.rest.dto.ReadListCreationDto import org.gotson.komga.interfaces.rest.dto.ReadListDto +import org.gotson.komga.interfaces.rest.dto.ReadListProgressDto import org.gotson.komga.interfaces.rest.dto.ReadListRequestResultDto import org.gotson.komga.interfaces.rest.dto.ReadListUpdateDto +import org.gotson.komga.interfaces.rest.dto.TachiyomiReadProgressUpdateDto import org.gotson.komga.interfaces.rest.dto.restrictUrl import org.gotson.komga.interfaces.rest.dto.toDto import org.gotson.komga.interfaces.rest.persistence.BookDtoRepository +import org.gotson.komga.interfaces.rest.persistence.ReadListDtoRepository import org.springframework.data.domain.Page import org.springframework.data.domain.PageRequest import org.springframework.data.domain.Pageable @@ -54,7 +58,9 @@ private val logger = KotlinLogging.logger {} class ReadListController( private val readListRepository: ReadListRepository, private val readListLifecycle: ReadListLifecycle, - private val bookDtoRepository: BookDtoRepository + private val bookDtoRepository: BookDtoRepository, + private val readListDtoRepository: ReadListDtoRepository, + private val bookLifecycle: BookLifecycle, ) { @PageableWithoutSortAsQueryParam @@ -235,4 +241,35 @@ class ReadListController( ) ?.restrictUrl(!principal.user.roleAdmin) } ?: throw ResponseStatusException(HttpStatus.NOT_FOUND) + + @GetMapping("{id}/read-progress") + fun getReadProgress( + @PathVariable id: String, + @AuthenticationPrincipal principal: KomgaPrincipal + ): ReadListProgressDto = + readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let { readList -> + readListDtoRepository.getProgress(readList.id, principal.user.id) + } ?: throw ResponseStatusException(HttpStatus.NOT_FOUND) + + @PatchMapping("{id}/read-progress/tachiyomi") + @ResponseStatus(HttpStatus.NO_CONTENT) + fun markReadProgress( + @PathVariable id: String, + @Valid @RequestBody readProgress: TachiyomiReadProgressUpdateDto, + @AuthenticationPrincipal principal: KomgaPrincipal + ) { + readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let { readList -> + bookDtoRepository.findByReadListId( + readList.id, + principal.user.id, + principal.user.getAuthorizedLibraryIds(null), + UnpagedSorted(Sort.by(Sort.Order.asc("readList.number"))) + ).forEachIndexed { index, book -> + if (index < readProgress.lastBookRead) + bookLifecycle.markReadProgressCompleted(book.id, principal.user) + else + bookLifecycle.deleteReadProgress(book.id, principal.user) + } + } ?: throw ResponseStatusException(HttpStatus.NOT_FOUND) + } } diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/ReadListDto.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/ReadListDto.kt index a74bea91f..b90cd68c2 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/ReadListDto.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/ReadListDto.kt @@ -18,6 +18,13 @@ data class ReadListDto( val filtered: Boolean ) +data class ReadListProgressDto( + val booksCount: Int, + val booksReadCount: Int, + val booksUnreadCount: Int, + val booksInProgressCount: Int, +) + fun ReadList.toDto() = ReadListDto( id = id, diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/ReadListDtoDao.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/ReadListDtoDao.kt new file mode 100644 index 000000000..140faf099 --- /dev/null +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/dto/ReadListDtoDao.kt @@ -0,0 +1,49 @@ +package org.gotson.komga.interfaces.rest.dto + +import org.gotson.komga.infrastructure.jooq.BOOKS_IN_PROGRESS_COUNT +import org.gotson.komga.infrastructure.jooq.BOOKS_READ_COUNT +import org.gotson.komga.infrastructure.jooq.BOOKS_UNREAD_COUNT +import org.gotson.komga.infrastructure.jooq.SeriesDtoDao +import org.gotson.komga.interfaces.rest.persistence.ReadListDtoRepository +import org.gotson.komga.jooq.Tables +import org.jooq.Condition +import org.jooq.DSLContext +import org.springframework.stereotype.Component + +@Component +class ReadListDtoDao( + private val dsl: DSLContext +) : ReadListDtoRepository { + + private val rl = Tables.READLIST + private val rlb = Tables.READLIST_BOOK + private val b = Tables.BOOK + private val r = Tables.READ_PROGRESS + + override fun getProgress(readListId: String, userId: String): ReadListProgressDto { + + val booksCountRecord = dsl + .select(SeriesDtoDao.countUnread.`as`(BOOKS_UNREAD_COUNT)) + .select(SeriesDtoDao.countRead.`as`(BOOKS_READ_COUNT)) + .select(SeriesDtoDao.countInProgress.`as`(BOOKS_IN_PROGRESS_COUNT)) + .from(b) + .leftJoin(r).on(b.ID.eq(r.BOOK_ID)).and(readProgressCondition(userId)) + .leftJoin(rlb).on(b.ID.eq(rlb.BOOK_ID)) + .where(rlb.READLIST_ID.eq(readListId)) + .fetch() + .first() + + val booksUnreadCount = booksCountRecord.get(BOOKS_UNREAD_COUNT, Int::class.java) + val booksReadCount = booksCountRecord.get(BOOKS_READ_COUNT, Int::class.java) + val booksInProgressCount = booksCountRecord.get(BOOKS_IN_PROGRESS_COUNT, Int::class.java) + + return ReadListProgressDto( + booksCount = booksUnreadCount + booksReadCount + booksInProgressCount, + booksUnreadCount = booksUnreadCount, + booksInProgressCount = booksInProgressCount, + booksReadCount = booksReadCount, + ) + } + + private fun readProgressCondition(userId: String): Condition = r.USER_ID.eq(userId).or(r.USER_ID.isNull) +} diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/persistence/ReadListDtoRepository.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/persistence/ReadListDtoRepository.kt new file mode 100644 index 000000000..97806c15d --- /dev/null +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/persistence/ReadListDtoRepository.kt @@ -0,0 +1,7 @@ +package org.gotson.komga.interfaces.rest.persistence + +import org.gotson.komga.interfaces.rest.dto.ReadListProgressDto + +interface ReadListDtoRepository { + fun getProgress(readListId: String, userId: String,): ReadListProgressDto +}