mirror of
https://github.com/gotson/komga.git
synced 2026-02-14 19:33:02 +01:00
feat(opds): browse by collection
This commit is contained in:
parent
ca91af7792
commit
15f9c8257e
1 changed files with 74 additions and 0 deletions
|
|
@ -7,12 +7,14 @@ import org.gotson.komga.domain.model.BookSearch
|
|||
import org.gotson.komga.domain.model.Library
|
||||
import org.gotson.komga.domain.model.Media
|
||||
import org.gotson.komga.domain.model.Series
|
||||
import org.gotson.komga.domain.model.SeriesCollection
|
||||
import org.gotson.komga.domain.model.SeriesMetadata
|
||||
import org.gotson.komga.domain.model.SeriesSearch
|
||||
import org.gotson.komga.domain.persistence.BookMetadataRepository
|
||||
import org.gotson.komga.domain.persistence.BookRepository
|
||||
import org.gotson.komga.domain.persistence.LibraryRepository
|
||||
import org.gotson.komga.domain.persistence.MediaRepository
|
||||
import org.gotson.komga.domain.persistence.SeriesCollectionRepository
|
||||
import org.gotson.komga.domain.persistence.SeriesMetadataRepository
|
||||
import org.gotson.komga.domain.persistence.SeriesRepository
|
||||
import org.gotson.komga.infrastructure.security.KomgaPrincipal
|
||||
|
|
@ -54,17 +56,20 @@ private const val ROUTE_CATALOG = "catalog"
|
|||
private const val ROUTE_SERIES_ALL = "series"
|
||||
private const val ROUTE_SERIES_LATEST = "series/latest"
|
||||
private const val ROUTE_LIBRARIES_ALL = "libraries"
|
||||
private const val ROUTE_COLLECTIONS_ALL = "collections"
|
||||
private const val ROUTE_SEARCH = "search"
|
||||
|
||||
private const val ID_SERIES_ALL = "allSeries"
|
||||
private const val ID_SERIES_LATEST = "latestSeries"
|
||||
private const val ID_LIBRARIES_ALL = "allLibraries"
|
||||
private const val ID_COLLECTIONS_ALL = "allCollections"
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = [ROUTE_BASE], produces = [MediaType.APPLICATION_ATOM_XML_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE])
|
||||
class OpdsController(
|
||||
servletContext: ServletContext,
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val collectionRepository: SeriesCollectionRepository,
|
||||
private val seriesRepository: SeriesRepository,
|
||||
private val seriesMetadataRepository: SeriesMetadataRepository,
|
||||
private val bookRepository: BookRepository,
|
||||
|
|
@ -113,6 +118,13 @@ class OpdsController(
|
|||
id = ID_LIBRARIES_ALL,
|
||||
content = "Browse by library",
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, "$routeBase$ROUTE_LIBRARIES_ALL")
|
||||
),
|
||||
OpdsEntryNavigation(
|
||||
title = "All collections",
|
||||
updated = ZonedDateTime.now(),
|
||||
id = ID_COLLECTIONS_ALL,
|
||||
content = "Browse by collection",
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, "$routeBase$ROUTE_COLLECTIONS_ALL")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -207,6 +219,29 @@ class OpdsController(
|
|||
)
|
||||
}
|
||||
|
||||
@GetMapping(ROUTE_COLLECTIONS_ALL)
|
||||
fun getCollections(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
): OpdsFeed {
|
||||
val collections =
|
||||
if (principal.user.sharedAllLibraries) {
|
||||
collectionRepository.findAll()
|
||||
} else {
|
||||
collectionRepository.findAllByLibraries(principal.user.sharedLibrariesIds, principal.user.sharedLibrariesIds)
|
||||
}
|
||||
return OpdsFeedNavigation(
|
||||
id = ID_COLLECTIONS_ALL,
|
||||
title = "All collections",
|
||||
updated = ZonedDateTime.now(),
|
||||
author = komgaAuthor,
|
||||
links = listOf(
|
||||
OpdsLinkFeedNavigation(OpdsLinkRel.SELF, "$routeBase$ROUTE_COLLECTIONS_ALL"),
|
||||
linkStart
|
||||
),
|
||||
entries = collections.map { it.toOpdsEntry() }
|
||||
)
|
||||
}
|
||||
|
||||
@GetMapping("series/{id}")
|
||||
fun getOneSeries(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
|
|
@ -268,6 +303,35 @@ class OpdsController(
|
|||
)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
@GetMapping("collections/{id}")
|
||||
fun getOneCollection(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable id: Long
|
||||
): OpdsFeed {
|
||||
return collectionRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let { collection ->
|
||||
val series = collection.seriesIds.mapNotNull { seriesRepository.findByIdOrNull(it) }
|
||||
.map { SeriesWithInfo(it, seriesMetadataRepository.findById(it.id)) }
|
||||
|
||||
val sorted =
|
||||
if (!collection.ordered) series.sortedBy { it.metadata.titleSort }
|
||||
else series
|
||||
|
||||
val entries = sorted.map { it.toOpdsEntry() }
|
||||
|
||||
OpdsFeedNavigation(
|
||||
id = collection.id.toString(),
|
||||
title = collection.name,
|
||||
updated = collection.lastModifiedDate.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
|
||||
author = komgaAuthor,
|
||||
links = listOf(
|
||||
OpdsLinkFeedNavigation(OpdsLinkRel.SELF, "${routeBase}collections/$id"),
|
||||
linkStart
|
||||
),
|
||||
entries = entries
|
||||
)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
}
|
||||
|
||||
|
||||
private fun SeriesWithInfo.toOpdsEntry(): OpdsEntryNavigation =
|
||||
OpdsEntryNavigation(
|
||||
|
|
@ -317,6 +381,16 @@ class OpdsController(
|
|||
)
|
||||
}
|
||||
|
||||
private fun SeriesCollection.toOpdsEntry(): OpdsEntryNavigation {
|
||||
return OpdsEntryNavigation(
|
||||
title = name,
|
||||
updated = lastModifiedDate.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
|
||||
id = id.toString(),
|
||||
content = "",
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, "${routeBase}collections/$id")
|
||||
)
|
||||
}
|
||||
|
||||
private fun shouldPrependBookNumbers(userAgent: String) =
|
||||
userAgent.contains("chunky", ignoreCase = true)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue