Skip to content

Commit

Permalink
feat(kobo): update changed covers on Kobo
Browse files Browse the repository at this point in the history
  • Loading branch information
gotson committed Sep 25, 2024
1 parent 51cd7e0 commit 870afff
Show file tree
Hide file tree
Showing 10 changed files with 35 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE main.SYNC_POINT_BOOK
ADD COLUMN BOOK_THUMBNAIL_ID varchar NULL;
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ data class SyncPoint(
val fileSize: Long,
val fileHash: String,
val metadataLastModifiedDate: ZonedDateTime,
val thumbnailId: String?,
val synced: Boolean,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ interface ThumbnailBookRepository {
size: Int,
): Collection<String>

fun existsById(thumbnailId: String): Boolean

fun insert(thumbnail: ThumbnailBook)

fun update(thumbnail: ThumbnailBook)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,11 @@ class BookLifecycle(
}
}

fun getThumbnailBytesByThumbnailId(thumbnailId: String): ByteArray? =
thumbnailBookRepository.findByIdOrNull(thumbnailId)?.let {
getBytesFromThumbnailBook(it)
fun getThumbnailBytesByThumbnailId(thumbnailId: String): TypedBytes? =
thumbnailBookRepository.findByIdOrNull(thumbnailId)?.let { thumbnail ->
getBytesFromThumbnailBook(thumbnail)?.let { bytes ->
TypedBytes(bytes, thumbnail.mediaType)
}
}

private fun getBytesFromThumbnailBook(thumbnail: ThumbnailBook): ByteArray? =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class KoboDtoDao(
private val d = Tables.BOOK_METADATA
private val a = Tables.BOOK_METADATA_AUTHOR
private val sd = Tables.SERIES_METADATA
private val bt = Tables.THUMBNAIL_BOOK

override fun findBookMetadataByIds(
bookIds: Collection<String>,
Expand All @@ -46,10 +47,12 @@ class KoboDtoDao(
m.EPUB_IS_KEPUB,
m.EXTENSION_CLASS,
m.EXTENSION_VALUE_BLOB,
bt.ID,
).from(b)
.leftJoin(d).on(b.ID.eq(d.BOOK_ID))
.leftJoin(sd).on(b.SERIES_ID.eq(sd.SERIES_ID))
.leftJoin(m).on(b.ID.eq(m.BOOK_ID))
.leftJoin(bt).on(b.ID.eq(bt.BOOK_ID)).and(bt.SELECTED.isTrue)
.where(d.BOOK_ID.`in`(bookIds))
.fetch()

Expand All @@ -58,6 +61,7 @@ class KoboDtoDao(
val dr = rec.into(d)
val sr = rec.into(sd)
val mr = rec.into(m)
val btr = rec.into(bt)
val mediaExtension = mapper.deserializeMediaExtension(mr.extensionClass, mr.extensionValueBlob) as? MediaExtensionEpub

val authors =
Expand All @@ -69,7 +73,7 @@ class KoboDtoDao(
KoboBookMetadataDto(
contributorRoles = authors[dr.bookId].orEmpty().map { ContributorDto(it.name) },
contributors = authors[dr.bookId].orEmpty().map { it.name },
coverImageId = dr.bookId,
coverImageId = btr.id,
crossRevisionId = dr.bookId,
// if null or empty Kobo will not update it, force it to blank
description = dr.summary.ifEmpty { " " },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class SyncPointDao(
private val b = Tables.BOOK
private val m = Tables.MEDIA
private val d = Tables.BOOK_METADATA
private val bt = Tables.THUMBNAIL_BOOK
private val r = Tables.READ_PROGRESS
private val sd = Tables.SERIES_METADATA
private val sp = Tables.SYNC_POINT
Expand Down Expand Up @@ -76,6 +77,7 @@ class SyncPointDao(
spb.BOOK_FILE_HASH,
spb.BOOK_METADATA_LAST_MODIFIED_DATE,
spb.BOOK_READ_PROGRESS_LAST_MODIFIED_DATE,
spb.BOOK_THUMBNAIL_ID,
).select(
dsl.select(
DSL.`val`(syncPointId),
Expand All @@ -87,11 +89,13 @@ class SyncPointDao(
b.FILE_HASH,
d.LAST_MODIFIED_DATE,
r.LAST_MODIFIED_DATE,
bt.ID,
).from(b)
.join(m).on(b.ID.eq(m.BOOK_ID))
.join(d).on(b.ID.eq(d.BOOK_ID))
.join(sd).on(b.SERIES_ID.eq(sd.SERIES_ID))
.leftJoin(r).on(b.ID.eq(r.BOOK_ID)).and(r.USER_ID.eq(user.id))
.leftJoin(bt).on(b.ID.eq(bt.BOOK_ID)).and(bt.SELECTED.isTrue)
.where(conditions),
).execute()

Expand Down Expand Up @@ -236,7 +240,8 @@ class SyncPointDao(
spb.BOOK_FILE_LAST_MODIFIED.ne(spbFrom.BOOK_FILE_LAST_MODIFIED)
.or(spb.BOOK_FILE_SIZE.ne(spbFrom.BOOK_FILE_SIZE))
.or(spb.BOOK_FILE_HASH.ne(spbFrom.BOOK_FILE_HASH).and(spbFrom.BOOK_FILE_HASH.isNotNull))
.or(spb.BOOK_METADATA_LAST_MODIFIED_DATE.ne(spbFrom.BOOK_METADATA_LAST_MODIFIED_DATE)),
.or(spb.BOOK_METADATA_LAST_MODIFIED_DATE.ne(spbFrom.BOOK_METADATA_LAST_MODIFIED_DATE))
.or(spb.BOOK_THUMBNAIL_ID.ne(spbFrom.BOOK_THUMBNAIL_ID)),
)

return queryToPageBook(query, pageable)
Expand Down Expand Up @@ -266,6 +271,7 @@ class SyncPointDao(
.and(spb.BOOK_FILE_SIZE.eq(spbFrom.BOOK_FILE_SIZE))
.and(spb.BOOK_FILE_HASH.eq(spbFrom.BOOK_FILE_HASH).or(spbFrom.BOOK_FILE_HASH.isNull))
.and(spb.BOOK_METADATA_LAST_MODIFIED_DATE.eq(spbFrom.BOOK_METADATA_LAST_MODIFIED_DATE))
.and(spb.BOOK_THUMBNAIL_ID.eq(spbFrom.BOOK_THUMBNAIL_ID))
// with changed read progress
.and(
spb.BOOK_READ_PROGRESS_LAST_MODIFIED_DATE.ne(spbFrom.BOOK_READ_PROGRESS_LAST_MODIFIED_DATE)
Expand Down Expand Up @@ -477,6 +483,7 @@ class SyncPointDao(
fileSize = it.bookFileSize,
fileHash = it.bookFileHash,
metadataLastModifiedDate = it.bookMetadataLastModifiedDate.atZone(ZoneId.of("Z")),
thumbnailId = it.bookThumbnailId,
synced = it.synced,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class ThumbnailBookDao(
.and(tb.HEIGHT.lt(size))
.fetch(tb.BOOK_ID)

override fun existsById(thumbnailId: String): Boolean = dsl.fetchExists(tb, tb.ID.eq(thumbnailId))

override fun insert(thumbnail: ThumbnailBook) {
dsl.insertInto(tb)
.set(tb.ID, thumbnail.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.gotson.komga.domain.persistence.BookRepository
import org.gotson.komga.domain.persistence.MediaRepository
import org.gotson.komga.domain.persistence.ReadProgressRepository
import org.gotson.komga.domain.persistence.SyncPointRepository
import org.gotson.komga.domain.persistence.ThumbnailBookRepository
import org.gotson.komga.domain.service.BookLifecycle
import org.gotson.komga.domain.service.SyncPointLifecycle
import org.gotson.komga.infrastructure.configuration.KomgaProperties
Expand Down Expand Up @@ -169,6 +170,7 @@ class KoboController(
private val commonBookController: CommonBookController,
private val bookLifecycle: BookLifecycle,
private val bookRepository: BookRepository,
private val thumbnailBookRepository: ThumbnailBookRepository,
private val readProgressRepository: ReadProgressRepository,
private val imageConverter: ImageConverter,
private val mediaRepository: MediaRepository,
Expand Down Expand Up @@ -670,26 +672,26 @@ class KoboController(

@GetMapping(
value = [
"v1/books/{bookId}/thumbnail/{width}/{height}/{isGreyScale}/image.jpg",
"v1/books/{bookId}/thumbnail/{width}/{height}/{quality}/{isGreyScale}/image.jpg",
"v1/books/{thumbnailId}/thumbnail/{width}/{height}/{isGreyScale}/image.jpg",
"v1/books/{thumbnailId}/thumbnail/{width}/{height}/{quality}/{isGreyScale}/image.jpg",
],
produces = [MediaType.IMAGE_JPEG_VALUE],
)
fun getBookCover(
@AuthenticationPrincipal principal: KomgaPrincipal,
@PathVariable bookId: String,
@PathVariable thumbnailId: String,
@PathVariable width: String?,
@PathVariable height: String?,
@PathVariable quality: String?,
@PathVariable isGreyScale: String?,
): ResponseEntity<Any> =
if (!bookRepository.existsById(bookId) && koboProxy.isEnabled()) {
if (!thumbnailBookRepository.existsById(thumbnailId) && koboProxy.isEnabled()) {
ResponseEntity
.status(HttpStatus.TEMPORARY_REDIRECT)
.location(UriComponentsBuilder.fromHttpUrl(koboProxy.imageHostUrl).buildAndExpand(bookId, width, height).toUri())
.location(UriComponentsBuilder.fromHttpUrl(koboProxy.imageHostUrl).buildAndExpand(thumbnailId, width, height).toUri())
.build()
} else {
val poster = bookLifecycle.getThumbnailBytes(bookId) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
val poster = bookLifecycle.getThumbnailBytesByThumbnailId(thumbnailId) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
val posterBytes =
if (poster.mediaType != ImageType.JPEG.mediaType)
imageConverter.convertImage(poster.bytes, ImageType.JPEG.imageIOFormat)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ data class KoboBookMetadataDto(
val categories: List<String> = listOf(DUMMY_ID),
val contributorRoles: List<ContributorDto> = emptyList(),
val contributors: List<String> = emptyList(),
val coverImageId: String,
val coverImageId: String? = null,
val crossRevisionId: String,
val currentDisplayPrice: AmountDto = AmountDto("USD", 0),
val currentLoveDisplayPrice: AmountDto = AmountDto(totalAmount = 0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ class BookController(
): ByteArray {
contentRestrictionChecker.checkContentRestriction(principal.user, bookId)

return bookLifecycle.getThumbnailBytesByThumbnailId(thumbnailId)
return bookLifecycle.getThumbnailBytesByThumbnailId(thumbnailId)?.bytes
?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
}

Expand Down

0 comments on commit 870afff

Please sign in to comment.