mirror of
https://github.com/gotson/komga.git
synced 2026-01-03 22:36:07 +01:00
style: reformat for dangling comma
This commit is contained in:
parent
10efc291a0
commit
7bd5454dc2
155 changed files with 639 additions and 636 deletions
|
|
@ -21,7 +21,7 @@ class V20200810154730__thumbnails_part_2 : BaseJavaMigration() {
|
|||
|
||||
jdbcTemplate.batchUpdate(
|
||||
"INSERT INTO THUMBNAIL_BOOK(ID, THUMBNAIL, SELECTED, TYPE, BOOK_ID) values (?, ?, 1, 'GENERATED', ?)",
|
||||
parameters
|
||||
parameters,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class V20200820150923__metadata_fields_part_2 : BaseJavaMigration() {
|
|||
val bookMetadata = jdbcTemplate.queryForList(
|
||||
"""select m.AGE_RATING, m.AGE_RATING_LOCK, m.PUBLISHER, m.PUBLISHER_LOCK, m.READING_DIRECTION, m.READING_DIRECTION_LOCK, b.SERIES_ID, m.NUMBER_SORT
|
||||
from BOOK_METADATA m
|
||||
left join BOOK B on B.ID = m.BOOK_ID"""
|
||||
left join BOOK B on B.ID = m.BOOK_ID""",
|
||||
)
|
||||
|
||||
if (bookMetadata.isNotEmpty()) {
|
||||
|
|
@ -41,7 +41,7 @@ left join BOOK B on B.ID = m.BOOK_ID"""
|
|||
|
||||
jdbcTemplate.batchUpdate(
|
||||
"UPDATE SERIES_METADATA SET AGE_RATING = ?, AGE_RATING_LOCK = ?, PUBLISHER = ?, PUBLISHER_LOCK = ?, READING_DIRECTION = ?, READING_DIRECTION_LOCK = ? WHERE SERIES_ID = ?",
|
||||
parameters
|
||||
parameters,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class V20210624165023__missing_series_metadata : BaseJavaMigration() {
|
|||
val jdbcTemplate = JdbcTemplate(SingleConnectionDataSource(context.connection, true))
|
||||
|
||||
val seriesWithoutMetada = jdbcTemplate.queryForList(
|
||||
"""select s.ID, s.NAME from SERIES s where s.ID not in (select sm.SERIES_ID from SERIES_METADATA sm)"""
|
||||
"""select s.ID, s.NAME from SERIES s where s.ID not in (select sm.SERIES_ID from SERIES_METADATA sm)""",
|
||||
)
|
||||
|
||||
if (seriesWithoutMetada.isNotEmpty()) {
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ class TaskReceiver(
|
|||
bookRepository.findAllIds(
|
||||
BookSearch(
|
||||
libraryIds = listOf(library.id),
|
||||
mediaStatus = listOf(Media.Status.UNKNOWN, Media.Status.OUTDATED)
|
||||
mediaStatus = listOf(Media.Status.UNKNOWN, Media.Status.OUTDATED),
|
||||
),
|
||||
Sort.by(Sort.Order.asc("seriesId"), Sort.Order.asc("number"))
|
||||
Sort.by(Sort.Order.asc("seriesId"), Sort.Order.asc("number")),
|
||||
).forEach {
|
||||
submitTask(Task.AnalyzeBook(it))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package org.gotson.komga.domain.model
|
|||
|
||||
class Author(
|
||||
name: String,
|
||||
role: String
|
||||
role: String,
|
||||
) {
|
||||
val name = name.trim()
|
||||
val role = role.trim().lowercase()
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ data class BookMetadataPatch(
|
|||
val isbn: String? = null,
|
||||
val links: List<WebLink>? = null,
|
||||
|
||||
val readLists: List<ReadListEntry> = emptyList()
|
||||
val readLists: List<ReadListEntry> = emptyList(),
|
||||
) {
|
||||
data class ReadListEntry(
|
||||
val name: String,
|
||||
val number: Int? = null
|
||||
val number: Int? = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ package org.gotson.komga.domain.model
|
|||
data class BookPage(
|
||||
val fileName: String,
|
||||
val mediaType: String,
|
||||
val dimension: Dimension? = null
|
||||
val dimension: Dimension? = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ package org.gotson.komga.domain.model
|
|||
class BookPageContent(
|
||||
val number: Int,
|
||||
val content: ByteArray,
|
||||
val mediaType: String
|
||||
val mediaType: String,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@ package org.gotson.komga.domain.model
|
|||
|
||||
data class Dimension(
|
||||
val width: Int,
|
||||
val height: Int
|
||||
val height: Int,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ open class CodedException : Exception {
|
|||
this.code = code
|
||||
}
|
||||
}
|
||||
|
||||
fun Exception.withCode(code: String) = CodedException(this, code)
|
||||
|
||||
class MediaNotReadyException : Exception()
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ data class MediaContainerEntry(
|
|||
val name: String,
|
||||
val mediaType: String? = null,
|
||||
val comment: String? = null,
|
||||
val dimension: Dimension? = null
|
||||
val dimension: Dimension? = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,5 +19,5 @@ data class ReadList(
|
|||
/**
|
||||
* Indicates that the bookIds have been filtered and is not exhaustive.
|
||||
*/
|
||||
val filtered: Boolean = false
|
||||
val filtered: Boolean = false,
|
||||
) : Auditable(), Serializable
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@ data class SeriesCollection(
|
|||
/**
|
||||
* Indicates that the seriesIds have been filtered and is not exhaustive.
|
||||
*/
|
||||
val filtered: Boolean = false
|
||||
val filtered: Boolean = false,
|
||||
) : Auditable(), Serializable
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class SeriesMetadata(
|
|||
totalBookCountLock: Boolean = this.totalBookCountLock,
|
||||
seriesId: String = this.seriesId,
|
||||
createdDate: LocalDateTime = this.createdDate,
|
||||
lastModifiedDate: LocalDateTime = this.lastModifiedDate
|
||||
lastModifiedDate: LocalDateTime = this.lastModifiedDate,
|
||||
) =
|
||||
SeriesMetadata(
|
||||
status = status,
|
||||
|
|
@ -92,7 +92,7 @@ class SeriesMetadata(
|
|||
totalBookCountLock = totalBookCountLock,
|
||||
seriesId = seriesId,
|
||||
createdDate = createdDate,
|
||||
lastModifiedDate = lastModifiedDate
|
||||
lastModifiedDate = lastModifiedDate,
|
||||
)
|
||||
|
||||
enum class Status {
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@ data class SeriesMetadataPatch(
|
|||
val genres: Set<String>?,
|
||||
val totalBookCount: Int?,
|
||||
|
||||
val collections: List<String>
|
||||
val collections: List<String>,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ private val logger = KotlinLogging.logger {}
|
|||
class BookAnalyzer(
|
||||
private val contentDetector: ContentDetector,
|
||||
extractors: List<MediaContainerExtractor>,
|
||||
private val imageConverter: ImageConverter
|
||||
private val imageConverter: ImageConverter,
|
||||
) {
|
||||
|
||||
val supportedMediaTypes = extractors
|
||||
|
|
@ -54,7 +54,7 @@ class BookAnalyzer(
|
|||
}.let { (images, others) ->
|
||||
Pair(
|
||||
images.map { BookPage(it.name, it.mediaType!!, it.dimension) },
|
||||
others
|
||||
others,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -106,13 +106,13 @@ class BookAnalyzer(
|
|||
return ThumbnailBook(
|
||||
thumbnail = thumbnail,
|
||||
type = ThumbnailBook.Type.GENERATED,
|
||||
bookId = book.book.id
|
||||
bookId = book.book.id,
|
||||
)
|
||||
}
|
||||
|
||||
@Throws(
|
||||
MediaNotReadyException::class,
|
||||
IndexOutOfBoundsException::class
|
||||
IndexOutOfBoundsException::class,
|
||||
)
|
||||
fun getPageContent(book: BookWithMedia, number: Int): ByteArray {
|
||||
logger.info { "Get page #$number for book: $book" }
|
||||
|
|
@ -131,7 +131,7 @@ class BookAnalyzer(
|
|||
}
|
||||
|
||||
@Throws(
|
||||
MediaNotReadyException::class
|
||||
MediaNotReadyException::class,
|
||||
)
|
||||
fun getFileContent(book: BookWithMedia, fileName: String): ByteArray {
|
||||
logger.info { "Get file $fileName for book: $book" }
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class BookConverter(
|
|||
?.copy(
|
||||
id = book.id,
|
||||
seriesId = book.seriesId,
|
||||
libraryId = book.libraryId
|
||||
libraryId = book.libraryId,
|
||||
)
|
||||
?: throw IllegalStateException("Newly converted book could not be scanned: $destinationFilename")
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ class BookConverter(
|
|||
?.copy(
|
||||
id = book.id,
|
||||
seriesId = book.seriesId,
|
||||
libraryId = book.libraryId
|
||||
libraryId = book.libraryId,
|
||||
)
|
||||
?: throw IllegalStateException("Repaired book could not be scanned: $destinationFilename")
|
||||
|
||||
|
|
|
|||
|
|
@ -68,12 +68,12 @@ class BookImporter(
|
|||
|
||||
val destFile = series.path.resolve(
|
||||
if (destinationName != null) Paths.get("$destinationName.${sourceFile.extension}").name
|
||||
else sourceFile.name
|
||||
else sourceFile.name,
|
||||
)
|
||||
val sidecars = fileSystemScanner.scanBookSidecars(sourceFile).associateWith {
|
||||
series.path.resolve(
|
||||
if (destinationName != null) it.url.toURI().toPath().name.replace(sourceFile.nameWithoutExtension, destinationName, true)
|
||||
else it.url.toURI().toPath().name
|
||||
else it.url.toURI().toPath().name,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ class BookImporter(
|
|||
it.copy(
|
||||
bookId = importedBook.id,
|
||||
status = Media.Status.OUTDATED,
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -178,8 +178,8 @@ class BookImporter(
|
|||
.forEach { rl ->
|
||||
readListRepository.update(
|
||||
rl.copy(
|
||||
bookIds = rl.bookIds.values.map { if (it == bookToUpgrade.id) importedBook.id else it }.toIndexedMap()
|
||||
)
|
||||
bookIds = rl.bookIds.values.map { if (it == bookToUpgrade.id) importedBook.id else it }.toIndexedMap(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -201,7 +201,7 @@ class BookImporter(
|
|||
val destSidecar = sourceSidecar.copy(
|
||||
url = destPath.toUri().toURL(),
|
||||
parentUrl = destPath.parent.toUri().toURL(),
|
||||
lastModifiedTime = destPath.readAttributes<BasicFileAttributes>().getUpdatedTime()
|
||||
lastModifiedTime = destPath.readAttributes<BasicFileAttributes>().getUpdatedTime(),
|
||||
)
|
||||
sidecarRepository.save(importedBook.libraryId, destSidecar)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ class BookLifecycle(
|
|||
@Throws(
|
||||
ImageConversionException::class,
|
||||
MediaNotReadyException::class,
|
||||
IndexOutOfBoundsException::class
|
||||
IndexOutOfBoundsException::class,
|
||||
)
|
||||
fun getBookPage(book: Book, number: Int, convertTo: ImageType? = null, resizeTo: Int? = null): BookPageContent {
|
||||
val media = mediaRepository.findById(book.id)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class BookMetadataLifecycle(
|
|||
|
||||
private fun handlePatchForReadLists(
|
||||
patch: BookMetadataPatch?,
|
||||
book: Book
|
||||
book: Book,
|
||||
) {
|
||||
patch?.readLists?.forEach { readList ->
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ class BookMetadataLifecycle(
|
|||
}
|
||||
map[key] = book.id
|
||||
readListLifecycle.updateReadList(
|
||||
existing.copy(bookIds = map)
|
||||
existing.copy(bookIds = map),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -101,8 +101,8 @@ class BookMetadataLifecycle(
|
|||
readListLifecycle.addReadList(
|
||||
ReadList(
|
||||
name = readList.name,
|
||||
bookIds = mapOf((readList.number ?: 0) to book.id).toSortedMap()
|
||||
)
|
||||
bookIds = mapOf((readList.number ?: 0) to book.id).toSortedMap(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ class BookMetadataLifecycle(
|
|||
|
||||
private fun handlePatchForBookMetadata(
|
||||
patch: BookMetadataPatch?,
|
||||
book: Book
|
||||
book: Book,
|
||||
) {
|
||||
patch?.let { bPatch ->
|
||||
bookMetadataRepository.findById(book.id).let {
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class FileSystemScanner(
|
|||
pathToSeries[dir] = Series(
|
||||
name = dir.name.ifBlank { dir.pathString },
|
||||
url = dir.toUri().toURL(),
|
||||
fileLastModified = attrs.getUpdatedTime()
|
||||
fileLastModified = attrs.getUpdatedTime(),
|
||||
)
|
||||
|
||||
return FileVisitResult.CONTINUE
|
||||
|
|
@ -159,7 +159,7 @@ class FileSystemScanner(
|
|||
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}.also {
|
||||
val countOfBooks = scannedSeries.values.sumOf { it.size }
|
||||
|
|
@ -192,7 +192,7 @@ class FileSystemScanner(
|
|||
name = path.nameWithoutExtension,
|
||||
url = path.toUri().toURL(),
|
||||
fileLastModified = attrs.getUpdatedTime(),
|
||||
fileSize = attrs.size()
|
||||
fileSize = attrs.size(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -264,8 +264,8 @@ class LibraryContentLifecycle(
|
|||
deleted.copy(
|
||||
seriesId = newSeries.id,
|
||||
title = if (deleted.titleLock) deleted.title else newlyAdded.title,
|
||||
titleSort = if (deleted.titleSortLock) deleted.titleSort else newlyAdded.titleSort
|
||||
)
|
||||
titleSort = if (deleted.titleSortLock) deleted.titleSort else newlyAdded.titleSort,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -274,8 +274,8 @@ class LibraryContentLifecycle(
|
|||
.forEach { col ->
|
||||
collectionRepository.update(
|
||||
col.copy(
|
||||
seriesIds = col.seriesIds.map { if (it == match.first.id) newSeries.id else it }
|
||||
)
|
||||
seriesIds = col.seriesIds.map { if (it == match.first.id) newSeries.id else it },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ class LibraryContentLifecycle(
|
|||
deleted.copy(
|
||||
bookId = bookToAdd.id,
|
||||
title = if (deleted.titleLock) deleted.title else newlyAdded.title,
|
||||
)
|
||||
),
|
||||
)
|
||||
if (!deleted.titleLock) taskReceiver.refreshBookMetadata(bookToAdd.id, setOf(BookMetadataPatchCapability.TITLE))
|
||||
}
|
||||
|
|
@ -349,8 +349,8 @@ class LibraryContentLifecycle(
|
|||
.forEach { rl ->
|
||||
readListRepository.update(
|
||||
rl.copy(
|
||||
bookIds = rl.bookIds.values.map { if (it == match.id) bookToAdd.id else it }.toIndexedMap()
|
||||
)
|
||||
bookIds = rl.bookIds.values.map { if (it == match.id) bookToAdd.id else it }.toIndexedMap(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class LibraryLifecycle(
|
|||
FileNotFoundException::class,
|
||||
DirectoryNotFoundException::class,
|
||||
DuplicateNameException::class,
|
||||
PathContainedInPath::class
|
||||
PathContainedInPath::class,
|
||||
)
|
||||
fun addLibrary(library: Library): Library {
|
||||
logger.info { "Adding new library: ${library.name} with root folder: ${library.root}" }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class LocalArtworkLifecycle(
|
|||
private val libraryRepository: LibraryRepository,
|
||||
private val bookLifecycle: BookLifecycle,
|
||||
private val seriesLifecycle: SeriesLifecycle,
|
||||
private val localArtworkProvider: LocalArtworkProvider
|
||||
private val localArtworkProvider: LocalArtworkProvider,
|
||||
) {
|
||||
|
||||
fun refreshLocalArtwork(book: Book) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class ReadListLifecycle(
|
|||
) {
|
||||
|
||||
@Throws(
|
||||
DuplicateNameException::class
|
||||
DuplicateNameException::class,
|
||||
)
|
||||
fun addReadList(readList: ReadList): ReadList {
|
||||
logger.info { "Adding new read list: $readList" }
|
||||
|
|
|
|||
|
|
@ -55,13 +55,13 @@ class ReadListMatcher(
|
|||
return if (bookIds.isNotEmpty())
|
||||
ReadListRequestResult(
|
||||
readList = ReadList(name = request.name, bookIds = bookIds.toIndexedMap()),
|
||||
unmatchedBooks = unmatchedBooks
|
||||
unmatchedBooks = unmatchedBooks,
|
||||
)
|
||||
else {
|
||||
ReadListRequestResult(
|
||||
readList = null,
|
||||
unmatchedBooks = unmatchedBooks,
|
||||
errorCode = "ERR_1010"
|
||||
errorCode = "ERR_1010",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class SeriesCollectionLifecycle(
|
|||
) {
|
||||
|
||||
@Throws(
|
||||
DuplicateNameException::class
|
||||
DuplicateNameException::class,
|
||||
)
|
||||
fun addCollection(collection: SeriesCollection): SeriesCollection {
|
||||
logger.info { "Adding new collection: $collection" }
|
||||
|
|
|
|||
|
|
@ -81,20 +81,20 @@ class SeriesLifecycle(
|
|||
.trim()
|
||||
.stripAccents()
|
||||
.replace(whitespacePattern, " ")
|
||||
}
|
||||
},
|
||||
)
|
||||
.map { book -> book to metadatas.first { it.bookId == book.id } }
|
||||
logger.debug { "Sorted books: $sorted" }
|
||||
|
||||
bookRepository.update(
|
||||
sorted.mapIndexed { index, (book, _) -> book.copy(number = index + 1) }
|
||||
sorted.mapIndexed { index, (book, _) -> book.copy(number = index + 1) },
|
||||
)
|
||||
|
||||
val oldToNew = sorted.mapIndexedNotNull { index, (_, metadata) ->
|
||||
if (metadata.numberLock && metadata.numberSortLock) null
|
||||
else metadata to metadata.copy(
|
||||
number = if (!metadata.numberLock) (index + 1).toString() else metadata.number,
|
||||
numberSort = if (!metadata.numberSortLock) (index + 1).toFloat() else metadata.numberSort
|
||||
numberSort = if (!metadata.numberSortLock) (index + 1).toFloat() else metadata.numberSort,
|
||||
)
|
||||
}
|
||||
bookMetadataRepository.update(oldToNew.map { it.second })
|
||||
|
|
@ -131,7 +131,7 @@ class SeriesLifecycle(
|
|||
title = it.name,
|
||||
number = it.number.toString(),
|
||||
numberSort = it.number.toFloat(),
|
||||
bookId = it.id
|
||||
bookId = it.id,
|
||||
)
|
||||
}.let { bookMetadataRepository.insert(it) }
|
||||
}
|
||||
|
|
@ -147,12 +147,12 @@ class SeriesLifecycle(
|
|||
SeriesMetadata(
|
||||
title = series.name,
|
||||
titleSort = StringUtils.stripAccents(series.name),
|
||||
seriesId = series.id
|
||||
)
|
||||
seriesId = series.id,
|
||||
),
|
||||
)
|
||||
|
||||
bookMetadataAggregationRepository.insert(
|
||||
BookMetadataAggregation(seriesId = series.id)
|
||||
BookMetadataAggregation(seriesId = series.id),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class SeriesMetadataLifecycle(
|
|||
|
||||
private fun handlePatchForCollections(
|
||||
patches: List<SeriesMetadataPatch>,
|
||||
series: Series
|
||||
series: Series,
|
||||
) {
|
||||
patches.flatMap { it.collections }.distinct().forEach { collection ->
|
||||
collectionRepository.findByNameOrNull(collection).let { existing ->
|
||||
|
|
@ -101,7 +101,7 @@ class SeriesMetadataLifecycle(
|
|||
else {
|
||||
logger.debug { "Adding series '${series.name}' to existing collection '${existing.name}'" }
|
||||
collectionLifecycle.updateCollection(
|
||||
existing.copy(seriesIds = existing.seriesIds + series.id)
|
||||
existing.copy(seriesIds = existing.seriesIds + series.id),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -109,8 +109,8 @@ class SeriesMetadataLifecycle(
|
|||
collectionLifecycle.addCollection(
|
||||
SeriesCollection(
|
||||
name = collection,
|
||||
seriesIds = listOf(series.id)
|
||||
)
|
||||
seriesIds = listOf(series.id),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -119,7 +119,7 @@ class SeriesMetadataLifecycle(
|
|||
|
||||
private fun handlePatchForSeriesMetadata(
|
||||
patches: List<SeriesMetadataPatch>,
|
||||
series: Series
|
||||
series: Series,
|
||||
) {
|
||||
val aggregatedPatch = SeriesMetadataPatch(
|
||||
title = patches.mostFrequent { it.title },
|
||||
|
|
@ -132,7 +132,7 @@ class SeriesMetadataLifecycle(
|
|||
ageRating = patches.mapNotNull { it.ageRating }.maxOrNull(),
|
||||
publisher = patches.mostFrequent { it.publisher },
|
||||
totalBookCount = patches.mapNotNull { it.totalBookCount }.maxOrNull(),
|
||||
collections = emptyList()
|
||||
collections = emptyList(),
|
||||
)
|
||||
|
||||
handlePatchForSeriesMetadata(aggregatedPatch, series)
|
||||
|
|
@ -140,7 +140,7 @@ class SeriesMetadataLifecycle(
|
|||
|
||||
private fun handlePatchForSeriesMetadata(
|
||||
patch: SeriesMetadataPatch,
|
||||
series: Series
|
||||
series: Series,
|
||||
) {
|
||||
seriesMetadataRepository.findById(series.id).let {
|
||||
logger.debug { "Apply metadata for series: $series" }
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class TransientBookLifecycle(
|
|||
|
||||
@Throws(
|
||||
MediaNotReadyException::class,
|
||||
IndexOutOfBoundsException::class
|
||||
IndexOutOfBoundsException::class,
|
||||
)
|
||||
fun getBookPage(transientBook: BookWithMedia, number: Int): BookPageContent {
|
||||
val pageContent = bookAnalyzer.getPageContent(transientBook, number)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import javax.sql.DataSource
|
|||
|
||||
@Configuration
|
||||
class DataSourcesConfiguration(
|
||||
private val komgaProperties: KomgaProperties
|
||||
private val komgaProperties: KomgaProperties,
|
||||
) {
|
||||
|
||||
@Bean("sqliteDataSource")
|
||||
|
|
@ -29,7 +29,7 @@ class DataSourcesConfiguration(
|
|||
dataSource = sqliteUdfDataSource
|
||||
poolName = "SqliteUdfPool"
|
||||
maximumPoolSize = 1
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class SqliteUdfDataSource : SimpleDriverDataSource() {
|
|||
|
||||
result(if (regexp.containsMatchIn(text)) 1 else 0)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ class SqliteUdfDataSource : SimpleDriverDataSource() {
|
|||
null -> error("Argument must not be null")
|
||||
else -> result(text.stripAccents())
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ class SqliteUdfDataSource : SimpleDriverDataSource() {
|
|||
}
|
||||
|
||||
override fun xCompare(str1: String, str2: String): Int = collator.compare(str1, str2)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class MosaicGenerator {
|
|||
0 to 0,
|
||||
106 to 0,
|
||||
0 to 150,
|
||||
106 to 150
|
||||
106 to 150,
|
||||
).forEachIndexed { index, (x, y) ->
|
||||
thumbs.getOrNull(index)?.let { drawImage(it, x, y, null) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,18 +40,18 @@ class ArtemisConfig : ArtemisConfigurationCustomizer {
|
|||
QUEUE_TASKS,
|
||||
AddressSettings().apply {
|
||||
defaultConsumerWindowSize = 0
|
||||
}
|
||||
},
|
||||
)
|
||||
it.addQueueConfiguration(
|
||||
QueueConfiguration(QUEUE_TASKS)
|
||||
.setAddress(QUEUE_TASKS)
|
||||
.setLastValueKey(QUEUE_UNIQUE_ID)
|
||||
.setRoutingType(RoutingType.ANYCAST)
|
||||
.setRoutingType(RoutingType.ANYCAST),
|
||||
)
|
||||
it.addQueueConfiguration(
|
||||
QueueConfiguration(QUEUE_SSE)
|
||||
.setAddress(QUEUE_SSE)
|
||||
.setRoutingType(RoutingType.MULTICAST)
|
||||
.setRoutingType(RoutingType.MULTICAST),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import java.time.LocalDateTime
|
|||
|
||||
@Component
|
||||
class AuthenticationActivityDao(
|
||||
private val dsl: DSLContext
|
||||
private val dsl: DSLContext,
|
||||
) : AuthenticationActivityRepository {
|
||||
|
||||
private val aa = Tables.AUTHENTICATION_ACTIVITY
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class BookDao(
|
|||
items,
|
||||
if (pageable.isPaged) PageRequest.of(pageable.pageNumber, pageable.pageSize, pageSort)
|
||||
else PageRequest.of(0, maxOf(count.toInt(), 20), pageSort),
|
||||
count
|
||||
count,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +246,7 @@ class BookDao(
|
|||
b.LIBRARY_ID,
|
||||
b.SERIES_ID,
|
||||
b.DELETED_DATE,
|
||||
).values(null as String?, null, null, null, null, null, null, null, null, null)
|
||||
).values(null as String?, null, null, null, null, null, null, null, null, null),
|
||||
).also { step ->
|
||||
chunk.forEach {
|
||||
step.bind(
|
||||
|
|
@ -337,6 +337,6 @@ class BookDao(
|
|||
deletedDate = deletedDate,
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
number = number
|
||||
number = number,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class BookMetadataAggregationDao(
|
|||
.leftJoin(a).on(d.SERIES_ID.eq(a.SERIES_ID))
|
||||
.where(d.SERIES_ID.`in`(seriesIds))
|
||||
.fetchGroups(
|
||||
{ it.into(d) }, { it.into(a) }
|
||||
{ it.into(d) }, { it.into(a) },
|
||||
).map { (dr, ar) ->
|
||||
dr.toDomain(ar.filterNot { it.name == null }.map { it.toDomain() }, findTags(dr.seriesId))
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ class BookMetadataAggregationDao(
|
|||
metadata.authors.chunked(batchSize).forEach { chunk ->
|
||||
dsl.batch(
|
||||
dsl.insertInto(a, a.SERIES_ID, a.NAME, a.ROLE)
|
||||
.values(null as String?, null, null)
|
||||
.values(null as String?, null, null),
|
||||
).also { step ->
|
||||
chunk.forEach {
|
||||
step.bind(metadata.seriesId, it.name, it.role)
|
||||
|
|
@ -102,7 +102,7 @@ class BookMetadataAggregationDao(
|
|||
metadata.tags.chunked(batchSize).forEach { chunk ->
|
||||
dsl.batch(
|
||||
dsl.insertInto(t, t.SERIES_ID, t.TAG)
|
||||
.values(null as String?, null)
|
||||
.values(null as String?, null),
|
||||
).also { step ->
|
||||
chunk.forEach {
|
||||
step.bind(metadata.seriesId, it)
|
||||
|
|
@ -141,12 +141,12 @@ class BookMetadataAggregationDao(
|
|||
seriesId = seriesId,
|
||||
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone()
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
)
|
||||
|
||||
private fun BookMetadataAggregationAuthorRecord.toDomain() =
|
||||
Author(
|
||||
name = name,
|
||||
role = role
|
||||
role = role,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class KomgaUserDao(
|
||||
private val dsl: DSLContext
|
||||
private val dsl: DSLContext,
|
||||
) : KomgaUserRepository {
|
||||
|
||||
private val u = Tables.USER
|
||||
|
|
@ -51,7 +51,7 @@ class KomgaUserDao(
|
|||
sharedAllLibraries = ur.sharedAllLibraries,
|
||||
id = ur.id,
|
||||
createdDate = ur.createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = ur.lastModifiedDate.toCurrentTimeZone()
|
||||
lastModifiedDate = ur.lastModifiedDate.toCurrentTimeZone(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ class KomgaUserDao(
|
|||
override fun existsByEmailIgnoreCase(email: String): Boolean =
|
||||
dsl.fetchExists(
|
||||
dsl.selectFrom(u)
|
||||
.where(u.EMAIL.equalIgnoreCase(email))
|
||||
.where(u.EMAIL.equalIgnoreCase(email)),
|
||||
)
|
||||
|
||||
override fun findByEmailIgnoreCaseOrNull(email: String): KomgaUser? =
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class LibraryDao(
|
||||
private val dsl: DSLContext
|
||||
private val dsl: DSLContext,
|
||||
) : LibraryRepository {
|
||||
|
||||
private val l = Tables.LIBRARY
|
||||
|
|
@ -130,6 +130,6 @@ class LibraryDao(
|
|||
unavailableDate = unavailableDate,
|
||||
id = id,
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone()
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class MediaDao(
|
|||
.groupBy(*groupFields)
|
||||
.orderBy(p.NUMBER.asc())
|
||||
.fetchGroups(
|
||||
{ it.into(m) }, { it.into(p) }
|
||||
{ it.into(m) }, { it.into(p) },
|
||||
).map { (mr, pr) ->
|
||||
val files = dsl.selectFrom(f)
|
||||
.where(f.BOOK_ID.eq(bookId))
|
||||
|
|
@ -77,8 +77,8 @@ class MediaDao(
|
|||
m.STATUS,
|
||||
m.MEDIA_TYPE,
|
||||
m.COMMENT,
|
||||
m.PAGE_COUNT
|
||||
).values(null as String?, null, null, null, null)
|
||||
m.PAGE_COUNT,
|
||||
).values(null as String?, null, null, null, null),
|
||||
).also { step ->
|
||||
chunk.forEach {
|
||||
step.bind(
|
||||
|
|
@ -86,7 +86,7 @@ class MediaDao(
|
|||
it.status,
|
||||
it.mediaType,
|
||||
it.comment,
|
||||
it.pages.size
|
||||
it.pages.size,
|
||||
)
|
||||
}
|
||||
}.execute()
|
||||
|
|
@ -108,8 +108,8 @@ class MediaDao(
|
|||
p.MEDIA_TYPE,
|
||||
p.NUMBER,
|
||||
p.WIDTH,
|
||||
p.HEIGHT
|
||||
).values(null as String?, null, null, null, null, null)
|
||||
p.HEIGHT,
|
||||
).values(null as String?, null, null, null, null, null),
|
||||
).also { step ->
|
||||
chunk.forEach { media ->
|
||||
media.pages.forEachIndexed { index, page ->
|
||||
|
|
@ -119,7 +119,7 @@ class MediaDao(
|
|||
page.mediaType,
|
||||
index,
|
||||
page.dimension?.width,
|
||||
page.dimension?.height
|
||||
page.dimension?.height,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -135,14 +135,14 @@ class MediaDao(
|
|||
dsl.insertInto(
|
||||
f,
|
||||
f.BOOK_ID,
|
||||
f.FILE_NAME
|
||||
).values(null as String?, null)
|
||||
f.FILE_NAME,
|
||||
).values(null as String?, null),
|
||||
).also { step ->
|
||||
chunk.forEach { media ->
|
||||
media.files.forEach {
|
||||
step.bind(
|
||||
media.bookId,
|
||||
it
|
||||
it,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -201,13 +201,13 @@ class MediaDao(
|
|||
comment = comment,
|
||||
bookId = bookId,
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone()
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
)
|
||||
|
||||
private fun MediaPageRecord.toDomain() =
|
||||
BookPage(
|
||||
fileName = fileName,
|
||||
mediaType = mediaType,
|
||||
dimension = if (width != null && height != null) Dimension(width, height) else null
|
||||
dimension = if (width != null && height != null) Dimension(width, height) else null,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class ReadListDao(
|
|||
items,
|
||||
if (pageable.isPaged) PageRequest.of(pageable.pageNumber, pageable.pageSize, pageSort)
|
||||
else PageRequest.of(0, maxOf(count.toInt(), 20), pageSort),
|
||||
count
|
||||
count,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ class ReadListDao(
|
|||
items,
|
||||
if (pageable.isPaged) PageRequest.of(pageable.pageNumber, pageable.pageSize, pageSort)
|
||||
else PageRequest.of(0, maxOf(count, 20), pageSort),
|
||||
count.toLong()
|
||||
count.toLong(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -139,8 +139,8 @@ class ReadListDao(
|
|||
dsl.select(rl.ID)
|
||||
.from(rl)
|
||||
.leftJoin(rlb).on(rl.ID.eq(rlb.READLIST_ID))
|
||||
.where(rlb.READLIST_ID.isNull)
|
||||
)
|
||||
.where(rlb.READLIST_ID.isNull),
|
||||
),
|
||||
).fetchInto(rl)
|
||||
.map { it.toDomain(sortedMapOf()) }
|
||||
|
||||
|
|
@ -244,7 +244,7 @@ class ReadListDao(
|
|||
override fun existsByName(name: String): Boolean =
|
||||
dsl.fetchExists(
|
||||
dsl.selectFrom(rl)
|
||||
.where(rl.NAME.equalIgnoreCase(name))
|
||||
.where(rl.NAME.equalIgnoreCase(name)),
|
||||
)
|
||||
|
||||
private fun ReadlistRecord.toDomain(bookIds: SortedMap<Int, String>) =
|
||||
|
|
@ -255,6 +255,6 @@ class ReadListDao(
|
|||
id = id,
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
filtered = bookCount != bookIds.size
|
||||
filtered = bookCount != bookIds.size,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ class ReadProgressDao(
|
|||
.innerJoin(r).on(b.ID.eq(r.BOOK_ID))
|
||||
.where(b.SERIES_ID.`in`(seriesIdsQuery))
|
||||
.apply { userId?.let { and(r.USER_ID.eq(it)) } }
|
||||
.groupBy(b.SERIES_ID, r.USER_ID)
|
||||
.groupBy(b.SERIES_ID, r.USER_ID),
|
||||
).execute()
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +172,6 @@ class ReadProgressDao(
|
|||
completed = completed,
|
||||
readDate = readDate.toCurrentTimeZone(),
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone()
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import java.math.BigDecimal
|
|||
|
||||
@Component
|
||||
class ReadProgressDtoDao(
|
||||
private val dsl: DSLContext
|
||||
private val dsl: DSLContext,
|
||||
) : ReadProgressDtoRepository {
|
||||
|
||||
private val rlb = Tables.READLIST_BOOK
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import java.time.LocalDate
|
|||
|
||||
@Component
|
||||
class ReferentialDao(
|
||||
private val dsl: DSLContext
|
||||
private val dsl: DSLContext,
|
||||
) : ReferentialRepository {
|
||||
|
||||
private val a = Tables.BOOK_METADATA_AUTHOR
|
||||
|
|
@ -151,7 +151,7 @@ class ReferentialDao(
|
|||
items,
|
||||
if (pageable.isPaged) PageRequest.of(pageable.pageNumber, pageable.pageSize, pageSort)
|
||||
else PageRequest.of(0, maxOf(count, 20), pageSort),
|
||||
count.toLong()
|
||||
count.toLong(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ class ReferentialDao(
|
|||
.union(
|
||||
select(st.TAG.`as`("tag"))
|
||||
.from(st)
|
||||
.apply { filterOnLibraryIds?.let { leftJoin(s).on(st.SERIES_ID.eq(s.ID)).where(s.LIBRARY_ID.`in`(it)) } }
|
||||
.apply { filterOnLibraryIds?.let { leftJoin(s).on(st.SERIES_ID.eq(s.ID)).where(s.LIBRARY_ID.`in`(it)) } },
|
||||
)
|
||||
.fetchSet(0, String::class.java)
|
||||
.sortedBy { it.stripAccents().lowercase() }
|
||||
|
|
@ -231,7 +231,7 @@ class ReferentialDao(
|
|||
.from(st)
|
||||
.leftJoin(s).on(st.SERIES_ID.eq(s.ID))
|
||||
.where(s.LIBRARY_ID.eq(libraryId))
|
||||
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
|
||||
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } },
|
||||
)
|
||||
.fetchSet(0, String::class.java)
|
||||
.sortedBy { it.stripAccents().lowercase() }
|
||||
|
|
@ -250,7 +250,7 @@ class ReferentialDao(
|
|||
.leftJoin(cs).on(st.SERIES_ID.eq(cs.SERIES_ID))
|
||||
.leftJoin(s).on(st.SERIES_ID.eq(s.ID))
|
||||
.where(cs.COLLECTION_ID.eq(collectionId))
|
||||
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
|
||||
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } },
|
||||
)
|
||||
.fetchSet(0, String::class.java)
|
||||
.sortedBy { it.stripAccents().lowercase() }
|
||||
|
|
@ -377,7 +377,7 @@ class ReferentialDao(
|
|||
items,
|
||||
if (pageable.isPaged) PageRequest.of(pageable.pageNumber, pageable.pageSize, pageSort)
|
||||
else PageRequest.of(0, maxOf(count, 20), pageSort),
|
||||
count.toLong()
|
||||
count.toLong(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -466,12 +466,12 @@ class ReferentialDao(
|
|||
private fun BookMetadataAuthorRecord.toDomain(): Author =
|
||||
Author(
|
||||
name = name,
|
||||
role = role
|
||||
role = role,
|
||||
)
|
||||
|
||||
private fun BookMetadataAggregationAuthorRecord.toDomain(): Author =
|
||||
Author(
|
||||
name = name,
|
||||
role = role
|
||||
role = role,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class SeriesCollectionDao(
|
|||
items,
|
||||
if (pageable.isPaged) PageRequest.of(pageable.pageNumber, pageable.pageSize, pageSort)
|
||||
else PageRequest.of(0, maxOf(count.toInt(), 20), pageSort),
|
||||
count
|
||||
count,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ class SeriesCollectionDao(
|
|||
items,
|
||||
if (pageable.isPaged) PageRequest.of(pageable.pageNumber, pageable.pageSize, pageSort)
|
||||
else PageRequest.of(0, maxOf(count, 20), pageSort),
|
||||
count.toLong()
|
||||
count.toLong(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -138,8 +138,8 @@ class SeriesCollectionDao(
|
|||
dsl.select(c.ID)
|
||||
.from(c)
|
||||
.leftJoin(cs).on(c.ID.eq(cs.COLLECTION_ID))
|
||||
.where(cs.COLLECTION_ID.isNull)
|
||||
)
|
||||
.where(cs.COLLECTION_ID.isNull),
|
||||
),
|
||||
).fetchInto(c)
|
||||
.map { it.toDomain(emptyList()) }
|
||||
|
||||
|
|
@ -244,7 +244,7 @@ class SeriesCollectionDao(
|
|||
override fun existsByName(name: String): Boolean =
|
||||
dsl.fetchExists(
|
||||
dsl.selectFrom(c)
|
||||
.where(c.NAME.equalIgnoreCase(name))
|
||||
.where(c.NAME.equalIgnoreCase(name)),
|
||||
)
|
||||
|
||||
private fun CollectionRecord.toDomain(seriesIds: List<String>) =
|
||||
|
|
@ -255,6 +255,6 @@ class SeriesCollectionDao(
|
|||
id = id,
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
filtered = seriesCount != seriesIds.size
|
||||
filtered = seriesCount != seriesIds.size,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,6 @@ class SeriesDao(
|
|||
bookCount = bookCount,
|
||||
deletedDate = deletedDate,
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone()
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ class SeriesMetadataDao(
|
|||
metadata.genres.chunked(batchSize).forEach { chunk ->
|
||||
dsl.batch(
|
||||
dsl.insertInto(g, g.SERIES_ID, g.GENRE)
|
||||
.values(null as String?, null)
|
||||
.values(null as String?, null),
|
||||
).also { step ->
|
||||
chunk.forEach {
|
||||
step.bind(metadata.seriesId, it)
|
||||
|
|
@ -137,7 +137,7 @@ class SeriesMetadataDao(
|
|||
metadata.tags.chunked(batchSize).forEach { chunk ->
|
||||
dsl.batch(
|
||||
dsl.insertInto(st, st.SERIES_ID, st.TAG)
|
||||
.values(null as String?, null)
|
||||
.values(null as String?, null),
|
||||
).also { step ->
|
||||
chunk.forEach {
|
||||
step.bind(metadata.seriesId, it)
|
||||
|
|
@ -196,6 +196,6 @@ class SeriesMetadataDao(
|
|||
seriesId = seriesId,
|
||||
|
||||
createdDate = createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone()
|
||||
lastModifiedDate = lastModifiedDate.toCurrentTimeZone(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,6 @@ class ThumbnailBookDao(
|
|||
id = id,
|
||||
bookId = bookId,
|
||||
createdDate = createdDate,
|
||||
lastModifiedDate = lastModifiedDate
|
||||
lastModifiedDate = lastModifiedDate,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.springframework.transaction.annotation.Transactional
|
|||
|
||||
@Component
|
||||
class ThumbnailReadListDao(
|
||||
private val dsl: DSLContext
|
||||
private val dsl: DSLContext,
|
||||
) : ThumbnailReadListRepository {
|
||||
private val tr = Tables.THUMBNAIL_READLIST
|
||||
|
||||
|
|
@ -90,6 +90,6 @@ class ThumbnailReadListDao(
|
|||
id = id,
|
||||
readListId = readlistId,
|
||||
createdDate = createdDate,
|
||||
lastModifiedDate = lastModifiedDate
|
||||
lastModifiedDate = lastModifiedDate,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.springframework.transaction.annotation.Transactional
|
|||
|
||||
@Component
|
||||
class ThumbnailSeriesCollectionDao(
|
||||
private val dsl: DSLContext
|
||||
private val dsl: DSLContext,
|
||||
) : ThumbnailSeriesCollectionRepository {
|
||||
private val tc = Tables.THUMBNAIL_COLLECTION
|
||||
|
||||
|
|
@ -90,6 +90,6 @@ class ThumbnailSeriesCollectionDao(
|
|||
id = id,
|
||||
collectionId = collectionId,
|
||||
createdDate = createdDate,
|
||||
lastModifiedDate = lastModifiedDate
|
||||
lastModifiedDate = lastModifiedDate,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,6 @@ class ThumbnailSeriesDao(
|
|||
id = id,
|
||||
seriesId = seriesId,
|
||||
createdDate = createdDate,
|
||||
lastModifiedDate = lastModifiedDate
|
||||
lastModifiedDate = lastModifiedDate,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import org.springframework.data.domain.Pageable
|
|||
import org.springframework.data.domain.Sort
|
||||
|
||||
class UnpagedSorted(
|
||||
private val sort: Sort
|
||||
private val sort: Sort,
|
||||
) : Pageable {
|
||||
|
||||
override fun getPageNumber(): Int {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ fun DSLContext.insertTempStrings(batchSize: Int, collection: Collection<String>)
|
|||
if (collection.isNotEmpty()) {
|
||||
collection.chunked(batchSize).forEach { chunk ->
|
||||
this.batch(
|
||||
this.insertInto(Tables.TEMP_STRING_LIST, Tables.TEMP_STRING_LIST.STRING).values(null as String?)
|
||||
this.insertInto(Tables.TEMP_STRING_LIST, Tables.TEMP_STRING_LIST.STRING).values(null as String?),
|
||||
).also { step ->
|
||||
chunk.forEach {
|
||||
step.bind(it)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ private val logger = KotlinLogging.logger {}
|
|||
|
||||
@Service
|
||||
class ContentDetector(
|
||||
private val tika: TikaConfig
|
||||
private val tika: TikaConfig,
|
||||
) {
|
||||
|
||||
fun detectMediaType(path: Path): String {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ private val logger = KotlinLogging.logger {}
|
|||
class EpubExtractor(
|
||||
private val zipExtractor: ZipExtractor,
|
||||
private val contentDetector: ContentDetector,
|
||||
private val imageAnalyzer: ImageAnalyzer
|
||||
private val imageAnalyzer: ImageAnalyzer,
|
||||
) : MediaContainerExtractor {
|
||||
|
||||
override fun mediaTypes(): List<String> = listOf("application/epub+zip")
|
||||
|
|
@ -94,6 +94,6 @@ class EpubExtractor(
|
|||
private data class ManifestItem(
|
||||
val id: String,
|
||||
val href: String,
|
||||
val mediaType: String
|
||||
val mediaType: String,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ private val logger = KotlinLogging.logger {}
|
|||
|
||||
@Service
|
||||
class PdfExtractor(
|
||||
private val imageAnalyzer: ImageAnalyzer
|
||||
private val imageAnalyzer: ImageAnalyzer,
|
||||
) : MediaContainerExtractor {
|
||||
|
||||
private val mediaType = "image/jpeg"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ private val logger = KotlinLogging.logger {}
|
|||
@Service
|
||||
class RarExtractor(
|
||||
private val contentDetector: ContentDetector,
|
||||
private val imageAnalyzer: ImageAnalyzer
|
||||
private val imageAnalyzer: ImageAnalyzer,
|
||||
) : MediaContainerExtractor {
|
||||
|
||||
private val natSortComparator: Comparator<String> = CaseInsensitiveSimpleNaturalComparator.getInstance()
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ private val logger = KotlinLogging.logger {}
|
|||
@Service
|
||||
class ZipExtractor(
|
||||
private val contentDetector: ContentDetector,
|
||||
private val imageAnalyzer: ImageAnalyzer
|
||||
private val imageAnalyzer: ImageAnalyzer,
|
||||
) : MediaContainerExtractor {
|
||||
|
||||
private val cache = Caffeine.newBuilder()
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ private const val PAGES_FIRST = 3
|
|||
@Service
|
||||
class IsbnBarcodeProvider(
|
||||
private val bookAnalyzer: BookAnalyzer,
|
||||
private val validator: ISBNValidator
|
||||
private val validator: ISBNValidator,
|
||||
) : BookMetadataProvider {
|
||||
|
||||
private val hints = mapOf(
|
||||
DecodeHintType.POSSIBLE_FORMATS to EnumSet.of(BarcodeFormat.EAN_13),
|
||||
DecodeHintType.TRY_HARDER to true
|
||||
DecodeHintType.TRY_HARDER to true,
|
||||
)
|
||||
|
||||
override fun getCapabilities(): Set<BookMetadataPatchCapability> =
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ private val logger = KotlinLogging.logger {}
|
|||
|
||||
@Service
|
||||
class LocalArtworkProvider(
|
||||
private val contentDetector: ContentDetector
|
||||
private val contentDetector: ContentDetector,
|
||||
) : SidecarSeriesConsumer, SidecarBookConsumer {
|
||||
|
||||
val supportedExtensions = listOf("png", "jpeg", "jpg", "tbn")
|
||||
|
|
@ -45,7 +45,7 @@ class LocalArtworkProvider(
|
|||
url = path.toUri().toURL(),
|
||||
type = ThumbnailBook.Type.SIDECAR,
|
||||
bookId = book.id,
|
||||
selected = index == 0
|
||||
selected = index == 0,
|
||||
)
|
||||
}.toList()
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ class LocalArtworkProvider(
|
|||
url = path.toUri().toURL(),
|
||||
seriesId = series.id,
|
||||
selected = index == 0,
|
||||
type = ThumbnailSeries.Type.SIDECAR
|
||||
type = ThumbnailSeries.Type.SIDECAR,
|
||||
)
|
||||
}.toList()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,5 +41,5 @@ data class MylarMetadata(
|
|||
@field:JsonProperty("publication_run")
|
||||
val publicationRun: String,
|
||||
|
||||
val status: Status
|
||||
val status: Status,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
|||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
data class Series(
|
||||
val metadata: MylarMetadata
|
||||
val metadata: MylarMetadata,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class CorsConfiguration {
|
|||
allowCredentials = true
|
||||
addExposedHeader(HttpHeaders.CONTENT_DISPOSITION)
|
||||
addExposedHeader(sessionHeaderName)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class LoginListener(
|
|||
ip = event.getIp(),
|
||||
userAgent = event.getUserAgent(),
|
||||
success = true,
|
||||
source = source
|
||||
source = source,
|
||||
)
|
||||
|
||||
logger.info { activity }
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class SecurityConfiguration(
|
|||
it.mvcMatchers(
|
||||
"/api/**",
|
||||
"/opds/**",
|
||||
"/sse/**"
|
||||
"/sse/**",
|
||||
).hasRole(ROLE_USER)
|
||||
}
|
||||
.headers {
|
||||
|
|
@ -102,7 +102,7 @@ class SecurityConfiguration(
|
|||
setTokenValiditySeconds(komgaProperties.rememberMe.validity.seconds.toInt())
|
||||
setAlwaysRemember(true)
|
||||
setAuthenticationDetailsSource(userAgentWebAuthenticationDetailsSource)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -125,7 +125,7 @@ class SecurityConfiguration(
|
|||
"/android-chrome-512x512.png",
|
||||
"/manifest.json",
|
||||
"/",
|
||||
"/index.html"
|
||||
"/index.html",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class GithubOAuth2UserService : DefaultOAuth2UserService() {
|
|||
RequestEntity<Any>(
|
||||
HttpHeaders().apply { setBearerAuth(userRequest.accessToken.tokenValue) },
|
||||
HttpMethod.GET,
|
||||
UriComponentsBuilder.fromUriString("${userRequest.clientRegistration.providerDetails.userInfoEndpoint.uri}/emails").build().toUri()
|
||||
UriComponentsBuilder.fromUriString("${userRequest.clientRegistration.providerDetails.userInfoEndpoint.uri}/emails").build().toUri(),
|
||||
),
|
||||
parameterizedResponseType,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import io.swagger.v3.oas.annotations.media.Schema
|
|||
@Parameters(
|
||||
Parameter(
|
||||
description = "Author criteria in the format: name,role. Multiple author criteria are supported.",
|
||||
`in` = ParameterIn.QUERY, name = "author", array = ArraySchema(schema = Schema(type = "string"))
|
||||
)
|
||||
`in` = ParameterIn.QUERY, name = "author", array = ArraySchema(schema = Schema(type = "string")),
|
||||
),
|
||||
)
|
||||
annotation class AuthorsAsQueryParam
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import io.swagger.v3.oas.annotations.media.Schema
|
|||
description = "Zero-based page index (0..N)",
|
||||
`in` = ParameterIn.QUERY,
|
||||
name = "page",
|
||||
schema = Schema(type = "integer")
|
||||
schema = Schema(type = "integer"),
|
||||
)
|
||||
annotation class PageAsQueryParam
|
||||
|
||||
|
|
@ -21,14 +21,14 @@ annotation class PageAsQueryParam
|
|||
description = "Zero-based page index (0..N)",
|
||||
`in` = ParameterIn.QUERY,
|
||||
name = "page",
|
||||
schema = Schema(type = "integer")
|
||||
schema = Schema(type = "integer"),
|
||||
),
|
||||
Parameter(
|
||||
description = "The size of the page to be returned",
|
||||
`in` = ParameterIn.QUERY,
|
||||
name = "size",
|
||||
schema = Schema(type = "integer")
|
||||
)
|
||||
schema = Schema(type = "integer"),
|
||||
),
|
||||
)
|
||||
annotation class PageableWithoutSortAsQueryParam
|
||||
|
||||
|
|
@ -38,17 +38,17 @@ annotation class PageableWithoutSortAsQueryParam
|
|||
description = "Zero-based page index (0..N)",
|
||||
`in` = ParameterIn.QUERY,
|
||||
name = "page",
|
||||
schema = Schema(type = "integer")
|
||||
schema = Schema(type = "integer"),
|
||||
),
|
||||
Parameter(
|
||||
description = "The size of the page to be returned",
|
||||
`in` = ParameterIn.QUERY,
|
||||
name = "size",
|
||||
schema = Schema(type = "integer")
|
||||
schema = Schema(type = "integer"),
|
||||
),
|
||||
Parameter(
|
||||
description = "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
|
||||
`in` = ParameterIn.QUERY, name = "sort", array = ArraySchema(schema = Schema(type = "string"))
|
||||
)
|
||||
`in` = ParameterIn.QUERY, name = "sort", array = ArraySchema(schema = Schema(type = "string")),
|
||||
),
|
||||
)
|
||||
annotation class PageableAsQueryParam
|
||||
|
|
|
|||
|
|
@ -24,20 +24,20 @@ class SwaggerConfiguration {
|
|||
Komga offers 2 APIs: REST and OPDS.
|
||||
|
||||
Both APIs are secured using HTTP Basic Authentication.
|
||||
""".trimIndent()
|
||||
""".trimIndent(),
|
||||
)
|
||||
.license(License().name("MIT").url("https://github.com/gotson/komga/blob/master/LICENSE"))
|
||||
.license(License().name("MIT").url("https://github.com/gotson/komga/blob/master/LICENSE")),
|
||||
)
|
||||
.externalDocs(
|
||||
ExternalDocumentation()
|
||||
.description("Komga documentation")
|
||||
.url("https://komga.org")
|
||||
.url("https://komga.org"),
|
||||
)
|
||||
.components(
|
||||
Components()
|
||||
.addSecuritySchemes(
|
||||
"basicAuth",
|
||||
SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")
|
||||
)
|
||||
SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import kotlin.reflect.KClass
|
|||
annotation class BCP47(
|
||||
val message: String = "Must be a valid BCP 47 language tag",
|
||||
val groups: Array<KClass<out Any>> = [],
|
||||
val payload: Array<KClass<out Any>> = []
|
||||
val payload: Array<KClass<out Any>> = [],
|
||||
)
|
||||
|
||||
class BCP47Validator : ConstraintValidator<BCP47, String> {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import kotlin.reflect.KClass
|
|||
annotation class Blank(
|
||||
val message: String = "Must be blank",
|
||||
val groups: Array<KClass<out Any>> = [],
|
||||
val payload: Array<KClass<out Any>> = []
|
||||
val payload: Array<KClass<out Any>> = [],
|
||||
)
|
||||
|
||||
class BlankValidator : ConstraintValidator<Blank, String> {
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ import kotlin.reflect.KClass
|
|||
annotation class NullOrBlankOrBCP47(
|
||||
val message: String = "Must be null or blank or valid BCP 47 language tag",
|
||||
val groups: Array<KClass<out Any>> = [],
|
||||
val payload: Array<KClass<out Any>> = []
|
||||
val payload: Array<KClass<out Any>> = [],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ import kotlin.reflect.KClass
|
|||
annotation class NullOrBlankOrISBN(
|
||||
val message: String = "Must be null or blank or valid ISBN-13",
|
||||
val groups: Array<KClass<out Any>> = [],
|
||||
val payload: Array<KClass<out Any>> = []
|
||||
val payload: Array<KClass<out Any>> = [],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ import kotlin.reflect.KClass
|
|||
annotation class NullOrNotBlank(
|
||||
val message: String = "Must be null or not blank",
|
||||
val groups: Array<KClass<out Any>> = [],
|
||||
val payload: Array<KClass<out Any>> = []
|
||||
val payload: Array<KClass<out Any>> = [],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ import kotlin.reflect.KClass
|
|||
annotation class NullOrNotEmpty(
|
||||
val message: String = "Must be null or not empty",
|
||||
val groups: Array<KClass<out Any>> = [],
|
||||
val payload: Array<KClass<out Any>> = []
|
||||
val payload: Array<KClass<out Any>> = [],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class AuthorsHandlerMethodArgumentResolver : HandlerMethodArgumentResolver {
|
|||
parameter: MethodParameter,
|
||||
mavContainer: ModelAndViewContainer?,
|
||||
webRequest: NativeWebRequest,
|
||||
binderFactory: WebDataBinderFactory?
|
||||
binderFactory: WebDataBinderFactory?,
|
||||
): Any? {
|
||||
val param = webRequest.getParameterValues("author") ?: return null
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class BracketParamsFilterConfiguration {
|
|||
FilterRegistrationBean(BracketParamsFilter())
|
||||
.also {
|
||||
it.addUrlPatterns(
|
||||
"/api/*"
|
||||
"/api/*",
|
||||
)
|
||||
it.setName("queryParamsFilter")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ package org.gotson.komga.infrastructure.web
|
|||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||
annotation class DelimitedPair(
|
||||
val parameterName: String
|
||||
val parameterName: String,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class DelimitedPairHandlerMethodArgumentResolver : HandlerMethodArgumentResolver
|
|||
parameter: MethodParameter,
|
||||
mavContainer: ModelAndViewContainer?,
|
||||
webRequest: NativeWebRequest,
|
||||
binderFactory: WebDataBinderFactory?
|
||||
binderFactory: WebDataBinderFactory?,
|
||||
): Pair<String, String>? {
|
||||
val paramName = parameter.getParameterAnnotation(DelimitedPair::class.java)?.parameterName ?: return null
|
||||
val param = webRequest.getParameterValues(paramName) ?: return null
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class EtagFilterConfiguration {
|
|||
.also {
|
||||
it.addUrlPatterns(
|
||||
"/api/*",
|
||||
"/opds/*"
|
||||
"/opds/*",
|
||||
)
|
||||
it.setName("etagFilter")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class WebMvcConfiguration : WebMvcConfigurer {
|
|||
"/apple-touch-icon-180x180.png",
|
||||
"/android-chrome-192x192.png",
|
||||
"/android-chrome-512x512.png",
|
||||
"/manifest.json"
|
||||
"/manifest.json",
|
||||
)
|
||||
.addResourceLocations(
|
||||
"classpath:public/index.html",
|
||||
|
|
@ -50,7 +50,7 @@ class WebMvcConfiguration : WebMvcConfigurer {
|
|||
"classpath:public/apple-touch-icon-180x180.png",
|
||||
"classpath:public/android-chrome-192x192.png",
|
||||
"classpath:public/android-chrome-512x512.png",
|
||||
"classpath:public/manifest.json"
|
||||
"classpath:public/manifest.json",
|
||||
)
|
||||
.setCacheControl(CacheControl.noStore())
|
||||
|
||||
|
|
@ -59,13 +59,13 @@ class WebMvcConfiguration : WebMvcConfigurer {
|
|||
"/css/**",
|
||||
"/fonts/**",
|
||||
"/img/**",
|
||||
"/js/**"
|
||||
"/js/**",
|
||||
)
|
||||
.addResourceLocations(
|
||||
"classpath:public/css/",
|
||||
"classpath:public/fonts/",
|
||||
"classpath:public/img/",
|
||||
"classpath:public/js/"
|
||||
"classpath:public/js/",
|
||||
)
|
||||
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic())
|
||||
}
|
||||
|
|
@ -75,9 +75,9 @@ class WebMvcConfiguration : WebMvcConfigurer {
|
|||
WebContentInterceptor().apply {
|
||||
addCacheMapping(
|
||||
cachePrivate,
|
||||
"/api/**", "/opds/**"
|
||||
"/api/**", "/opds/**",
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ class OpdsController(
|
|||
private val seriesDtoRepository: SeriesDtoRepository,
|
||||
private val bookDtoRepository: BookDtoRepository,
|
||||
private val mediaRepository: MediaRepository,
|
||||
private val referentialRepository: ReferentialRepository
|
||||
private val referentialRepository: ReferentialRepository,
|
||||
) {
|
||||
|
||||
private val routeBase = "${servletContext.contextPath}$ROUTE_BASE"
|
||||
|
|
@ -121,12 +121,12 @@ class OpdsController(
|
|||
return listOfNotNull(
|
||||
if (!page.isFirst) OpdsLinkFeedNavigation(
|
||||
OpdsLinkRel.PREVIOUS,
|
||||
pageBuilder.expand(mapOf("page" to page.pageable.previousOrFirst().pageNumber)).toUriString()
|
||||
pageBuilder.expand(mapOf("page" to page.pageable.previousOrFirst().pageNumber)).toUriString(),
|
||||
)
|
||||
else null,
|
||||
if (!page.isLast) OpdsLinkFeedNavigation(
|
||||
OpdsLinkRel.NEXT,
|
||||
pageBuilder.expand(mapOf("page" to page.pageable.next().pageNumber)).toUriString()
|
||||
pageBuilder.expand(mapOf("page" to page.pageable.next().pageNumber)).toUriString(),
|
||||
)
|
||||
else null,
|
||||
)
|
||||
|
|
@ -206,8 +206,8 @@ class OpdsController(
|
|||
id = ID_PUBLISHERS_ALL,
|
||||
content = "Browse by publishers",
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, uriBuilder(ROUTE_PUBLISHERS_ALL).toUriString()),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@GetMapping(ROUTE_SEARCH)
|
||||
|
|
@ -404,7 +404,7 @@ class OpdsController(
|
|||
OpdsLinkFeedNavigation(OpdsLinkRel.SELF, uriBuilder(ROUTE_LIBRARIES_ALL).toUriString()),
|
||||
linkStart,
|
||||
),
|
||||
entries = libraries.map { it.toOpdsEntry() }
|
||||
entries = libraries.map { it.toOpdsEntry() },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -434,7 +434,7 @@ class OpdsController(
|
|||
linkStart,
|
||||
*linkPage(uriBuilder, collections).toTypedArray(),
|
||||
),
|
||||
entries = collections.content.map { it.toOpdsEntry() }
|
||||
entries = collections.content.map { it.toOpdsEntry() },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +464,7 @@ class OpdsController(
|
|||
linkStart,
|
||||
*linkPage(uriBuilder, readLists).toTypedArray(),
|
||||
),
|
||||
entries = readLists.content.map { it.toOpdsEntry() }
|
||||
entries = readLists.content.map { it.toOpdsEntry() },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -496,7 +496,7 @@ class OpdsController(
|
|||
content = "",
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, uriBuilder(ROUTE_SERIES_ALL).queryParam("publisher", publisher).toUriString()),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -569,7 +569,7 @@ class OpdsController(
|
|||
linkStart,
|
||||
*linkPage(uriBuilder, entries).toTypedArray(),
|
||||
),
|
||||
entries = entries.content
|
||||
entries = entries.content,
|
||||
)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
|
|
@ -609,7 +609,7 @@ class OpdsController(
|
|||
linkStart,
|
||||
*linkPage(uriBuilder, entries).toTypedArray(),
|
||||
),
|
||||
entries = entries.content
|
||||
entries = entries.content,
|
||||
)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
|
|
@ -653,7 +653,7 @@ class OpdsController(
|
|||
linkStart,
|
||||
*linkPage(uriBuilder, booksPage).toTypedArray(),
|
||||
),
|
||||
entries = entries.content
|
||||
entries = entries.content,
|
||||
)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
|
|
@ -694,7 +694,7 @@ class OpdsController(
|
|||
OpdsLinkImage(media.pages[0].mediaType, uriBuilder("books/$id/pages/1").toUriString()),
|
||||
OpdsLinkFileAcquisition(media.mediaType, uriBuilder("books/$id/file/${sanitize(FilenameUtils.getName(url))}").toUriString()),
|
||||
opdsLinkPageStreaming,
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -704,7 +704,7 @@ class OpdsController(
|
|||
updated = lastModifiedDate.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
|
||||
id = id,
|
||||
content = "",
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, uriBuilder("libraries/$id").toUriString())
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, uriBuilder("libraries/$id").toUriString()),
|
||||
)
|
||||
|
||||
private fun SeriesCollection.toOpdsEntry(): OpdsEntryNavigation =
|
||||
|
|
@ -713,7 +713,7 @@ class OpdsController(
|
|||
updated = lastModifiedDate.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
|
||||
id = id,
|
||||
content = "",
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, uriBuilder("collections/$id").toUriString())
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, uriBuilder("collections/$id").toUriString()),
|
||||
)
|
||||
|
||||
private fun ReadList.toOpdsEntry(): OpdsEntryNavigation =
|
||||
|
|
@ -722,7 +722,7 @@ class OpdsController(
|
|||
updated = lastModifiedDate.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
|
||||
id = id,
|
||||
content = "",
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, uriBuilder("readlists/$id").toUriString())
|
||||
link = OpdsLinkFeedNavigation(OpdsLinkRel.SUBSECTION, uriBuilder("readlists/$id").toUriString()),
|
||||
)
|
||||
|
||||
private fun shouldPrependBookNumbers(userAgent: String) =
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@ data class OpdsAuthor(
|
|||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JacksonXmlProperty(namespace = ATOM)
|
||||
val uri: URI? = null
|
||||
val uri: URI? = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ abstract class OpdsEntry(
|
|||
@get:JacksonXmlProperty(namespace = ATOM)
|
||||
val id: String,
|
||||
|
||||
content: String
|
||||
content: String,
|
||||
) {
|
||||
@get:JacksonXmlProperty(namespace = ATOM)
|
||||
val content: String = content.replace("\n", "<br/>")
|
||||
|
|
@ -29,7 +29,7 @@ class OpdsEntryNavigation(
|
|||
content: String,
|
||||
|
||||
@JacksonXmlProperty(namespace = ATOM)
|
||||
val link: OpdsLink
|
||||
val link: OpdsLink,
|
||||
) : OpdsEntry(title, updated, id, content)
|
||||
|
||||
class OpdsEntryAcquisition(
|
||||
|
|
@ -44,5 +44,5 @@ class OpdsEntryAcquisition(
|
|||
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
@JacksonXmlProperty(localName = "link", namespace = ATOM)
|
||||
val links: List<OpdsLink>
|
||||
val links: List<OpdsLink>,
|
||||
) : OpdsEntry(title, updated, id, content)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ abstract class OpdsFeed(
|
|||
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
@JacksonXmlProperty(localName = "entry", namespace = ATOM)
|
||||
val entries: List<OpdsEntry>
|
||||
val entries: List<OpdsEntry>,
|
||||
)
|
||||
|
||||
@JsonSerialize(`as` = OpdsFeed::class)
|
||||
|
|
@ -36,7 +36,7 @@ class OpdsFeedNavigation(
|
|||
updated: ZonedDateTime,
|
||||
author: OpdsAuthor,
|
||||
links: List<OpdsLink>,
|
||||
entries: List<OpdsEntryNavigation>
|
||||
entries: List<OpdsEntryNavigation>,
|
||||
) : OpdsFeed(id, title, updated, author, links, entries)
|
||||
|
||||
@JsonSerialize(`as` = OpdsFeed::class)
|
||||
|
|
@ -46,5 +46,5 @@ class OpdsFeedAcquisition(
|
|||
updated: ZonedDateTime,
|
||||
author: OpdsAuthor,
|
||||
links: List<OpdsLink>,
|
||||
entries: List<OpdsEntryAcquisition>
|
||||
entries: List<OpdsEntryAcquisition>,
|
||||
) : OpdsFeed(id, title, updated, author, links, entries)
|
||||
|
|
|
|||
|
|
@ -11,49 +11,49 @@ open class OpdsLink(
|
|||
val rel: String,
|
||||
|
||||
@get:JacksonXmlProperty(isAttribute = true)
|
||||
val href: String
|
||||
val href: String,
|
||||
)
|
||||
|
||||
@JsonSerialize(`as` = OpdsLink::class)
|
||||
class OpdsLinkFeedNavigation(rel: String, href: String) : OpdsLink(
|
||||
type = "application/atom+xml;profile=opds-catalog;kind=navigation",
|
||||
rel = rel,
|
||||
href = href
|
||||
href = href,
|
||||
)
|
||||
|
||||
@JsonSerialize(`as` = OpdsLink::class)
|
||||
class OpdsLinkFeedAcquisition(rel: String, href: String) : OpdsLink(
|
||||
type = "application/atom+xml;profile=opds-catalog;kind=acquisition",
|
||||
rel = rel,
|
||||
href = href
|
||||
href = href,
|
||||
)
|
||||
|
||||
@JsonSerialize(`as` = OpdsLink::class)
|
||||
class OpdsLinkImage(mediaType: String, href: String) : OpdsLink(
|
||||
type = mediaType,
|
||||
rel = "http://opds-spec.org/image",
|
||||
href = href
|
||||
href = href,
|
||||
)
|
||||
|
||||
@JsonSerialize(`as` = OpdsLink::class)
|
||||
class OpdsLinkImageThumbnail(mediaType: String, href: String) : OpdsLink(
|
||||
type = mediaType,
|
||||
rel = "http://opds-spec.org/image/thumbnail",
|
||||
href = href
|
||||
href = href,
|
||||
)
|
||||
|
||||
@JsonSerialize(`as` = OpdsLink::class)
|
||||
class OpdsLinkFileAcquisition(mediaType: String?, href: String) : OpdsLink(
|
||||
type = mediaType ?: "application/octet-stream",
|
||||
rel = "http://opds-spec.org/acquisition",
|
||||
href = href
|
||||
href = href,
|
||||
)
|
||||
|
||||
@JsonSerialize(`as` = OpdsLink::class)
|
||||
class OpdsLinkSearch(href: String) : OpdsLink(
|
||||
type = "application/opensearchdescription+xml",
|
||||
rel = "search",
|
||||
href = href
|
||||
href = href,
|
||||
)
|
||||
|
||||
class OpdsLinkPageStreaming(
|
||||
|
|
@ -68,7 +68,7 @@ class OpdsLinkPageStreaming(
|
|||
) : OpdsLink(
|
||||
type = mediaType,
|
||||
rel = "http://vaemendis.net/opds-pse/stream",
|
||||
href = href
|
||||
href = href,
|
||||
)
|
||||
|
||||
class OpdsLinkRel {
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ class OpenSearchDescription(
|
|||
val outputEncoding: String = "UTF-8",
|
||||
|
||||
@JacksonXmlProperty(localName = "Url", namespace = OPENSEARCH)
|
||||
val url: OpenSearchUrl
|
||||
val url: OpenSearchUrl,
|
||||
) {
|
||||
class OpenSearchUrl(
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
val template: String
|
||||
val template: String,
|
||||
) {
|
||||
@JacksonXmlProperty(isAttribute = true)
|
||||
val type = "application/atom+xml;profile=opds-catalog;kind=acquisition"
|
||||
|
|
|
|||
|
|
@ -28,14 +28,14 @@ interface BookDtoRepository {
|
|||
readListId: String,
|
||||
bookId: String,
|
||||
userId: String,
|
||||
filterOnLibraryIds: Collection<String>?
|
||||
filterOnLibraryIds: Collection<String>?,
|
||||
): BookDto?
|
||||
|
||||
fun findNextInReadListOrNull(
|
||||
readListId: String,
|
||||
bookId: String,
|
||||
userId: String,
|
||||
filterOnLibraryIds: Collection<String>?
|
||||
filterOnLibraryIds: Collection<String>?,
|
||||
): BookDto?
|
||||
|
||||
fun findAllOnDeck(userId: String, filterOnLibraryIds: Collection<String>?, pageable: Pageable): Page<BookDto>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import org.gotson.komga.interfaces.api.rest.dto.TachiyomiReadProgressDto
|
|||
import org.gotson.komga.interfaces.api.rest.dto.TachiyomiReadProgressV2Dto
|
||||
|
||||
interface ReadProgressDtoRepository {
|
||||
fun findProgressBySeries(seriesId: String, userId: String,): TachiyomiReadProgressDto
|
||||
fun findProgressV2BySeries(seriesId: String, userId: String,): TachiyomiReadProgressV2Dto
|
||||
fun findProgressByReadList(readListId: String, userId: String,): TachiyomiReadProgressDto
|
||||
fun findProgressBySeries(seriesId: String, userId: String): TachiyomiReadProgressDto
|
||||
fun findProgressV2BySeries(seriesId: String, userId: String): TachiyomiReadProgressV2Dto
|
||||
fun findProgressByReadList(readListId: String, userId: String): TachiyomiReadProgressDto
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import javax.validation.constraints.NotBlank
|
|||
@RequestMapping("api/v1/claim", produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||
@Validated
|
||||
class ClaimController(
|
||||
private val userDetailsLifecycle: KomgaUserLifecycle
|
||||
private val userDetailsLifecycle: KomgaUserLifecycle,
|
||||
) {
|
||||
|
||||
@GetMapping
|
||||
|
|
@ -29,7 +29,7 @@ class ClaimController(
|
|||
@PostMapping
|
||||
fun claimAdmin(
|
||||
@Email(regexp = ".+@.+\\..+") @RequestHeader("X-Komga-Email") email: String,
|
||||
@NotBlank @RequestHeader("X-Komga-Password") password: String
|
||||
@NotBlank @RequestHeader("X-Komga-Password") password: String,
|
||||
): UserDto {
|
||||
if (userDetailsLifecycle.countUsers() > 0)
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "This server has already been claimed")
|
||||
|
|
@ -38,12 +38,12 @@ class ClaimController(
|
|||
KomgaUser(
|
||||
email = email,
|
||||
password = password,
|
||||
roleAdmin = true
|
||||
)
|
||||
roleAdmin = true,
|
||||
),
|
||||
).toDto()
|
||||
}
|
||||
|
||||
data class ClaimStatus(
|
||||
val isClaimed: Boolean
|
||||
val isClaimed: Boolean,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,28 +14,28 @@ class ErrorHandlingControllerAdvice {
|
|||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ResponseBody
|
||||
fun onConstraintValidationException(
|
||||
e: ConstraintViolationException
|
||||
e: ConstraintViolationException,
|
||||
): ValidationErrorResponse =
|
||||
ValidationErrorResponse(
|
||||
e.constraintViolations.map { Violation(it.propertyPath.toString(), it.message) }
|
||||
e.constraintViolations.map { Violation(it.propertyPath.toString(), it.message) },
|
||||
)
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException::class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ResponseBody
|
||||
fun onMethodArgumentNotValidException(
|
||||
e: MethodArgumentNotValidException
|
||||
e: MethodArgumentNotValidException,
|
||||
): ValidationErrorResponse =
|
||||
ValidationErrorResponse(
|
||||
e.bindingResult.fieldErrors.map { Violation(it.field, it.defaultMessage) }
|
||||
e.bindingResult.fieldErrors.map { Violation(it.field, it.defaultMessage) },
|
||||
)
|
||||
}
|
||||
|
||||
data class ValidationErrorResponse(
|
||||
val violations: List<Violation> = emptyList()
|
||||
val violations: List<Violation> = emptyList(),
|
||||
)
|
||||
|
||||
data class Violation(
|
||||
val fieldName: String? = null,
|
||||
val message: String? = null
|
||||
val message: String? = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ class FileSystemController {
|
|||
|
||||
@PostMapping
|
||||
fun getDirectoryListing(
|
||||
@RequestBody(required = false) request: DirectoryRequestDto = DirectoryRequestDto()
|
||||
@RequestBody(required = false) request: DirectoryRequestDto = DirectoryRequestDto(),
|
||||
): DirectoryListingDto =
|
||||
if (request.path.isEmpty()) {
|
||||
DirectoryListingDto(
|
||||
directories = fs.rootDirectories.map { it.toDto() }
|
||||
directories = fs.rootDirectories.map { it.toDto() },
|
||||
)
|
||||
} else {
|
||||
val p = fs.getPath(request.path)
|
||||
|
|
@ -42,7 +42,7 @@ class FileSystemController {
|
|||
.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.toString() })
|
||||
.map { it.toDto() }
|
||||
.toList()
|
||||
}
|
||||
},
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Path does not exist")
|
||||
|
|
@ -51,24 +51,24 @@ class FileSystemController {
|
|||
}
|
||||
|
||||
data class DirectoryRequestDto(
|
||||
val path: String = ""
|
||||
val path: String = "",
|
||||
)
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
data class DirectoryListingDto(
|
||||
val parent: String? = null,
|
||||
val directories: List<PathDto>
|
||||
val directories: List<PathDto>,
|
||||
)
|
||||
|
||||
data class PathDto(
|
||||
val type: String,
|
||||
val name: String,
|
||||
val path: String
|
||||
val path: String,
|
||||
)
|
||||
|
||||
fun Path.toDto(): PathDto =
|
||||
PathDto(
|
||||
type = if (Files.isDirectory(this)) "directory" else "file",
|
||||
name = (fileName ?: this).toString(),
|
||||
path = toString()
|
||||
path = toString(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class LibraryController(
|
|||
|
||||
@GetMapping
|
||||
fun getAll(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
): List<LibraryDto> =
|
||||
if (principal.user.sharedAllLibraries) {
|
||||
libraryRepository.findAll()
|
||||
|
|
@ -59,7 +59,7 @@ class LibraryController(
|
|||
@GetMapping("{libraryId}")
|
||||
fun getOne(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable libraryId: String
|
||||
@PathVariable libraryId: String,
|
||||
): LibraryDto =
|
||||
libraryRepository.findByIdOrNull(libraryId)?.let {
|
||||
if (!principal.user.canAccessLibrary(it)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -70,7 +70,7 @@ class LibraryController(
|
|||
@PreAuthorize("hasRole('$ROLE_ADMIN')")
|
||||
fun addOne(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@Valid @RequestBody library: LibraryCreationDto
|
||||
@Valid @RequestBody library: LibraryCreationDto,
|
||||
): LibraryDto =
|
||||
try {
|
||||
libraryLifecycle.addLibrary(
|
||||
|
|
@ -92,14 +92,15 @@ class LibraryController(
|
|||
convertToCbz = library.convertToCbz,
|
||||
emptyTrashAfterScan = library.emptyTrashAfterScan,
|
||||
seriesCover = library.seriesCover.toDomain(),
|
||||
)
|
||||
),
|
||||
).toDto(includeRoot = principal.user.roleAdmin)
|
||||
} catch (e: Exception) {
|
||||
when (e) {
|
||||
is FileNotFoundException,
|
||||
is DirectoryNotFoundException,
|
||||
is DuplicateNameException,
|
||||
is PathContainedInPath ->
|
||||
is PathContainedInPath,
|
||||
->
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, e.message)
|
||||
else -> throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
|
|
@ -110,7 +111,7 @@ class LibraryController(
|
|||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun updateOne(
|
||||
@PathVariable libraryId: String,
|
||||
@Valid @RequestBody library: LibraryUpdateDto
|
||||
@Valid @RequestBody library: LibraryUpdateDto,
|
||||
) {
|
||||
libraryRepository.findByIdOrNull(libraryId)?.let {
|
||||
val toUpdate = Library(
|
||||
|
|
@ -140,7 +141,8 @@ class LibraryController(
|
|||
is FileNotFoundException,
|
||||
is DirectoryNotFoundException,
|
||||
is DuplicateNameException,
|
||||
is PathContainedInPath ->
|
||||
is PathContainedInPath,
|
||||
->
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, e.message)
|
||||
else -> throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class ReadListController(
|
|||
@RequestParam(name = "search", required = false) searchTerm: String?,
|
||||
@RequestParam(name = "library_id", required = false) libraryIds: List<String>?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<ReadListDto> {
|
||||
val sort = when {
|
||||
!searchTerm.isNullOrBlank() -> Sort.by("relevance")
|
||||
|
|
@ -107,31 +107,31 @@ class ReadListController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
return when {
|
||||
principal.user.sharedAllLibraries && libraryIds == null -> readListRepository.findAll(
|
||||
searchTerm,
|
||||
pageable = pageRequest
|
||||
pageable = pageRequest,
|
||||
)
|
||||
principal.user.sharedAllLibraries && libraryIds != null -> readListRepository.findAllByLibraryIds(
|
||||
libraryIds,
|
||||
null,
|
||||
searchTerm,
|
||||
pageable = pageRequest
|
||||
pageable = pageRequest,
|
||||
)
|
||||
!principal.user.sharedAllLibraries && libraryIds != null -> readListRepository.findAllByLibraryIds(
|
||||
libraryIds,
|
||||
principal.user.sharedLibrariesIds,
|
||||
searchTerm,
|
||||
pageable = pageRequest
|
||||
pageable = pageRequest,
|
||||
)
|
||||
else -> readListRepository.findAllByLibraryIds(
|
||||
principal.user.sharedLibrariesIds,
|
||||
principal.user.sharedLibrariesIds,
|
||||
searchTerm,
|
||||
pageable = pageRequest
|
||||
pageable = pageRequest,
|
||||
)
|
||||
}.map { it.toDto() }
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ class ReadListController(
|
|||
@GetMapping("{id}")
|
||||
fun getOne(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable id: String
|
||||
@PathVariable id: String,
|
||||
): ReadListDto =
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))
|
||||
?.toDto()
|
||||
|
|
@ -149,7 +149,7 @@ class ReadListController(
|
|||
@GetMapping(value = ["{id}/thumbnail"], produces = [MediaType.IMAGE_JPEG_VALUE])
|
||||
fun getReadListThumbnail(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable id: String
|
||||
@PathVariable id: String,
|
||||
): ResponseEntity<ByteArray> {
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let {
|
||||
return ResponseEntity.ok()
|
||||
|
|
@ -163,7 +163,7 @@ class ReadListController(
|
|||
fun getReadListThumbnailById(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable(name = "id") id: String,
|
||||
@PathVariable(name = "thumbnailId") thumbnailId: String
|
||||
@PathVariable(name = "thumbnailId") thumbnailId: String,
|
||||
): ByteArray {
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let {
|
||||
return readListLifecycle.getThumbnailBytes(thumbnailId)
|
||||
|
|
@ -200,7 +200,7 @@ class ReadListController(
|
|||
readListId = readList.id,
|
||||
thumbnail = file.bytes,
|
||||
type = ThumbnailReadList.Type.USER_UPLOADED,
|
||||
selected = selected
|
||||
selected = selected,
|
||||
),
|
||||
)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
|
@ -239,15 +239,15 @@ class ReadListController(
|
|||
@PostMapping
|
||||
@PreAuthorize("hasRole('$ROLE_ADMIN')")
|
||||
fun addOne(
|
||||
@Valid @RequestBody readList: ReadListCreationDto
|
||||
@Valid @RequestBody readList: ReadListCreationDto,
|
||||
): ReadListDto =
|
||||
try {
|
||||
readListLifecycle.addReadList(
|
||||
ReadList(
|
||||
name = readList.name,
|
||||
summary = readList.summary,
|
||||
bookIds = readList.bookIds.toIndexedMap()
|
||||
)
|
||||
bookIds = readList.bookIds.toIndexedMap(),
|
||||
),
|
||||
).toDto()
|
||||
} catch (e: DuplicateNameException) {
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, e.message)
|
||||
|
|
@ -265,13 +265,13 @@ class ReadListController(
|
|||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun updateOne(
|
||||
@PathVariable id: String,
|
||||
@Valid @RequestBody readList: ReadListUpdateDto
|
||||
@Valid @RequestBody readList: ReadListUpdateDto,
|
||||
) {
|
||||
readListRepository.findByIdOrNull(id)?.let { existing ->
|
||||
val updated = existing.copy(
|
||||
name = readList.name ?: existing.name,
|
||||
summary = readList.summary ?: existing.summary,
|
||||
bookIds = readList.bookIds?.toIndexedMap() ?: existing.bookIds
|
||||
bookIds = readList.bookIds?.toIndexedMap() ?: existing.bookIds,
|
||||
)
|
||||
try {
|
||||
readListLifecycle.updateReadList(updated)
|
||||
|
|
@ -285,7 +285,7 @@ class ReadListController(
|
|||
@PreAuthorize("hasRole('$ROLE_ADMIN')")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun deleteOne(
|
||||
@PathVariable id: String
|
||||
@PathVariable id: String,
|
||||
) {
|
||||
readListRepository.findByIdOrNull(id)?.let {
|
||||
readListLifecycle.deleteReadList(it)
|
||||
|
|
@ -305,7 +305,7 @@ class ReadListController(
|
|||
@RequestParam(name = "deleted", required = false) deleted: Boolean?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) @Authors authors: List<Author>?,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<BookDto> =
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let { readList ->
|
||||
val sort = Sort.by(Sort.Order.asc("readList.number"))
|
||||
|
|
@ -315,7 +315,7 @@ class ReadListController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
val bookSearch = BookSearchWithReadProgress(
|
||||
|
|
@ -332,7 +332,7 @@ class ReadListController(
|
|||
principal.user.id,
|
||||
principal.user.getAuthorizedLibraryIds(null),
|
||||
bookSearch,
|
||||
pageRequest
|
||||
pageRequest,
|
||||
)
|
||||
.map { it.restrictUrl(!principal.user.roleAdmin) }
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
|
@ -341,14 +341,14 @@ class ReadListController(
|
|||
fun getBookSiblingPrevious(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable id: String,
|
||||
@PathVariable bookId: String
|
||||
@PathVariable bookId: String,
|
||||
): BookDto =
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let {
|
||||
bookDtoRepository.findPreviousInReadListOrNull(
|
||||
id,
|
||||
bookId,
|
||||
principal.user.id,
|
||||
principal.user.getAuthorizedLibraryIds(null)
|
||||
principal.user.getAuthorizedLibraryIds(null),
|
||||
)
|
||||
?.restrictUrl(!principal.user.roleAdmin)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
|
@ -357,14 +357,14 @@ class ReadListController(
|
|||
fun getBookSiblingNext(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable id: String,
|
||||
@PathVariable bookId: String
|
||||
@PathVariable bookId: String,
|
||||
): BookDto =
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let {
|
||||
bookDtoRepository.findNextInReadListOrNull(
|
||||
id,
|
||||
bookId,
|
||||
principal.user.id,
|
||||
principal.user.getAuthorizedLibraryIds(null)
|
||||
principal.user.getAuthorizedLibraryIds(null),
|
||||
)
|
||||
?.restrictUrl(!principal.user.roleAdmin)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
|
@ -372,7 +372,7 @@ class ReadListController(
|
|||
@GetMapping("{id}/read-progress/tachiyomi")
|
||||
fun getReadProgress(
|
||||
@PathVariable id: String,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
): TachiyomiReadProgressDto =
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let { readList ->
|
||||
readProgressDtoRepository.findProgressByReadList(readList.id, principal.user.id)
|
||||
|
|
@ -383,7 +383,7 @@ class ReadListController(
|
|||
fun markReadProgressTachiyomi(
|
||||
@PathVariable id: String,
|
||||
@Valid @RequestBody readProgress: TachiyomiReadProgressUpdateDto,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
) {
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let { readList ->
|
||||
bookDtoRepository.findAllByReadListId(
|
||||
|
|
@ -391,7 +391,7 @@ class ReadListController(
|
|||
principal.user.id,
|
||||
principal.user.getAuthorizedLibraryIds(null),
|
||||
BookSearchWithReadProgress(),
|
||||
UnpagedSorted(Sort.by(Sort.Order.asc("readList.number")))
|
||||
UnpagedSorted(Sort.by(Sort.Order.asc("readList.number"))),
|
||||
).filterIndexed { index, _ -> index < readProgress.lastBookRead }
|
||||
.forEach { book ->
|
||||
if (book.readProgress?.completed != true)
|
||||
|
|
@ -404,7 +404,7 @@ class ReadListController(
|
|||
@PreAuthorize("hasRole('$ROLE_FILE_DOWNLOAD')")
|
||||
fun getReadListFile(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable id: String
|
||||
@PathVariable id: String,
|
||||
): ResponseEntity<StreamingResponseBody> {
|
||||
readListRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let { readList ->
|
||||
|
||||
|
|
@ -439,7 +439,7 @@ class ReadListController(
|
|||
contentDisposition = ContentDisposition.builder("attachment")
|
||||
.filename(readList.name + ".zip")
|
||||
.build()
|
||||
}
|
||||
},
|
||||
)
|
||||
.contentType(MediaType.parseMediaType("application/zip"))
|
||||
.body(streamingResponse)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import org.springframework.web.bind.annotation.RestController
|
|||
@RestController
|
||||
@RequestMapping("api", produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||
class ReferentialController(
|
||||
private val referentialRepository: ReferentialRepository
|
||||
private val referentialRepository: ReferentialRepository,
|
||||
) {
|
||||
|
||||
@GetMapping("v1/authors")
|
||||
|
|
@ -70,7 +70,7 @@ class ReferentialController(
|
|||
@GetMapping("v1/authors/names")
|
||||
fun getAuthorsNames(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "search", defaultValue = "") search: String
|
||||
@RequestParam(name = "search", defaultValue = "") search: String,
|
||||
): List<String> =
|
||||
referentialRepository.findAllAuthorsNamesByName(search, principal.user.getAuthorizedLibraryIds(null))
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ class ReferentialController(
|
|||
fun getGenres(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryId: String?,
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?,
|
||||
): Set<String> =
|
||||
when {
|
||||
libraryId != null -> referentialRepository.findAllGenresByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
|
||||
|
|
@ -96,7 +96,7 @@ class ReferentialController(
|
|||
fun getTags(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryId: String?,
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?,
|
||||
): Set<String> =
|
||||
when {
|
||||
libraryId != null -> referentialRepository.findAllSeriesAndBookTagsByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
|
||||
|
|
@ -120,7 +120,7 @@ class ReferentialController(
|
|||
fun getSeriesTags(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryId: String?,
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?,
|
||||
): Set<String> =
|
||||
when {
|
||||
libraryId != null -> referentialRepository.findAllSeriesTagsByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
|
||||
|
|
@ -132,7 +132,7 @@ class ReferentialController(
|
|||
fun getLanguages(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryId: String?,
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?,
|
||||
): Set<String> =
|
||||
when {
|
||||
libraryId != null -> referentialRepository.findAllLanguagesByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
|
||||
|
|
@ -144,7 +144,7 @@ class ReferentialController(
|
|||
fun getPublishers(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryId: String?,
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?,
|
||||
): Set<String> =
|
||||
when {
|
||||
libraryId != null -> referentialRepository.findAllPublishersByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
|
||||
|
|
@ -156,7 +156,7 @@ class ReferentialController(
|
|||
fun getAgeRatings(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryId: String?,
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?,
|
||||
): Set<String> =
|
||||
when {
|
||||
libraryId != null -> referentialRepository.findAllAgeRatingsByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
|
||||
|
|
@ -168,7 +168,7 @@ class ReferentialController(
|
|||
fun getSeriesReleaseDates(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryId: String?,
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?
|
||||
@RequestParam(name = "collection_id", required = false) collectionId: String?,
|
||||
): Set<String> =
|
||||
when {
|
||||
libraryId != null -> referentialRepository.findAllSeriesReleaseDatesByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class SeriesCollectionController(
|
|||
@RequestParam(name = "search", required = false) searchTerm: String?,
|
||||
@RequestParam(name = "library_id", required = false) libraryIds: List<String>?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<CollectionDto> {
|
||||
val sort = when {
|
||||
!searchTerm.isNullOrBlank() -> Sort.by("relevance")
|
||||
|
|
@ -87,7 +87,7 @@ class SeriesCollectionController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
return when {
|
||||
|
|
@ -101,7 +101,7 @@ class SeriesCollectionController(
|
|||
@GetMapping("{id}")
|
||||
fun getOne(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable id: String
|
||||
@PathVariable id: String,
|
||||
): CollectionDto =
|
||||
collectionRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))
|
||||
?.toDto()
|
||||
|
|
@ -111,7 +111,7 @@ class SeriesCollectionController(
|
|||
@GetMapping(value = ["{id}/thumbnail"], produces = [MediaType.IMAGE_JPEG_VALUE])
|
||||
fun getCollectionThumbnail(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable id: String
|
||||
@PathVariable id: String,
|
||||
): ResponseEntity<ByteArray> {
|
||||
collectionRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let {
|
||||
return ResponseEntity.ok()
|
||||
|
|
@ -125,7 +125,7 @@ class SeriesCollectionController(
|
|||
fun getCollectionThumbnailById(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable(name = "id") id: String,
|
||||
@PathVariable(name = "thumbnailId") thumbnailId: String
|
||||
@PathVariable(name = "thumbnailId") thumbnailId: String,
|
||||
): ByteArray {
|
||||
collectionRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let {
|
||||
return collectionLifecycle.getThumbnailBytes(thumbnailId)
|
||||
|
|
@ -162,7 +162,7 @@ class SeriesCollectionController(
|
|||
collectionId = collection.id,
|
||||
thumbnail = file.bytes,
|
||||
type = ThumbnailSeriesCollection.Type.USER_UPLOADED,
|
||||
selected = selected
|
||||
selected = selected,
|
||||
),
|
||||
)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
|
@ -201,15 +201,15 @@ class SeriesCollectionController(
|
|||
@PostMapping
|
||||
@PreAuthorize("hasRole('$ROLE_ADMIN')")
|
||||
fun addOne(
|
||||
@Valid @RequestBody collection: CollectionCreationDto
|
||||
@Valid @RequestBody collection: CollectionCreationDto,
|
||||
): CollectionDto =
|
||||
try {
|
||||
collectionLifecycle.addCollection(
|
||||
SeriesCollection(
|
||||
name = collection.name,
|
||||
ordered = collection.ordered,
|
||||
seriesIds = collection.seriesIds
|
||||
)
|
||||
seriesIds = collection.seriesIds,
|
||||
),
|
||||
).toDto()
|
||||
} catch (e: DuplicateNameException) {
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, e.message)
|
||||
|
|
@ -220,13 +220,13 @@ class SeriesCollectionController(
|
|||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun updateOne(
|
||||
@PathVariable id: String,
|
||||
@Valid @RequestBody collection: CollectionUpdateDto
|
||||
@Valid @RequestBody collection: CollectionUpdateDto,
|
||||
) {
|
||||
collectionRepository.findByIdOrNull(id)?.let { existing ->
|
||||
val updated = existing.copy(
|
||||
name = collection.name ?: existing.name,
|
||||
ordered = collection.ordered ?: existing.ordered,
|
||||
seriesIds = collection.seriesIds ?: existing.seriesIds
|
||||
seriesIds = collection.seriesIds ?: existing.seriesIds,
|
||||
)
|
||||
try {
|
||||
collectionLifecycle.updateCollection(updated)
|
||||
|
|
@ -240,7 +240,7 @@ class SeriesCollectionController(
|
|||
@PreAuthorize("hasRole('$ROLE_ADMIN')")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun deleteOne(
|
||||
@PathVariable id: String
|
||||
@PathVariable id: String,
|
||||
) {
|
||||
collectionRepository.findByIdOrNull(id)?.let {
|
||||
collectionLifecycle.deleteCollection(it)
|
||||
|
|
@ -266,7 +266,7 @@ class SeriesCollectionController(
|
|||
@RequestParam(name = "complete", required = false) complete: Boolean?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) @Authors authors: List<Author>?,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<SeriesDto> =
|
||||
collectionRepository.findByIdOrNull(id, principal.user.getAuthorizedLibraryIds(null))?.let { collection ->
|
||||
val sort =
|
||||
|
|
@ -278,7 +278,7 @@ class SeriesCollectionController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
val seriesSearch = SeriesSearchWithReadProgress(
|
||||
|
|
@ -293,7 +293,7 @@ class SeriesCollectionController(
|
|||
tags = tags,
|
||||
ageRatings = ageRatings?.map { it.toIntOrNull() },
|
||||
releaseYears = release_years,
|
||||
authors = authors
|
||||
authors = authors,
|
||||
)
|
||||
|
||||
seriesDtoRepository.findAllByCollectionId(collection.id, seriesSearch, principal.user.id, pageRequest)
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@ class SeriesController(
|
|||
@Parameters(
|
||||
Parameter(
|
||||
description = "Search by regex criteria, in the form: regex,field. Supported fields are TITLE and TITLE_SORT.",
|
||||
`in` = ParameterIn.QUERY, name = "search_regex", schema = Schema(type = "string")
|
||||
)
|
||||
`in` = ParameterIn.QUERY, name = "search_regex", schema = Schema(type = "string"),
|
||||
),
|
||||
)
|
||||
@GetMapping("v1/series")
|
||||
fun getAllSeries(
|
||||
|
|
@ -134,7 +134,7 @@ class SeriesController(
|
|||
@RequestParam(name = "complete", required = false) complete: Boolean?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) @Authors authors: List<Author>?,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<SeriesDto> {
|
||||
val sort =
|
||||
when {
|
||||
|
|
@ -148,7 +148,7 @@ class SeriesController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
val seriesSearch = SeriesSearchWithReadProgress(
|
||||
|
|
@ -172,7 +172,7 @@ class SeriesController(
|
|||
tags = tags,
|
||||
ageRatings = ageRatings?.map { it.toIntOrNull() },
|
||||
releaseYears = release_years,
|
||||
authors = authors
|
||||
authors = authors,
|
||||
)
|
||||
|
||||
return seriesDtoRepository.findAll(seriesSearch, principal.user.id, pageRequest)
|
||||
|
|
@ -183,8 +183,8 @@ class SeriesController(
|
|||
@Parameters(
|
||||
Parameter(
|
||||
description = "Search by regex criteria, in the form: regex,field. Supported fields are TITLE and TITLE_SORT.",
|
||||
`in` = ParameterIn.QUERY, name = "search_regex", schema = Schema(type = "string")
|
||||
)
|
||||
`in` = ParameterIn.QUERY, name = "search_regex", schema = Schema(type = "string"),
|
||||
),
|
||||
)
|
||||
@GetMapping("v1/series/alphabetical-groups")
|
||||
fun getAlphabeticalGroups(
|
||||
|
|
@ -204,7 +204,7 @@ class SeriesController(
|
|||
@RequestParam(name = "deleted", required = false) deleted: Boolean?,
|
||||
@RequestParam(name = "complete", required = false) complete: Boolean?,
|
||||
@Parameter(hidden = true) @Authors authors: List<Author>?,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): List<GroupCountDto> {
|
||||
val seriesSearch = SeriesSearchWithReadProgress(
|
||||
libraryIds = principal.user.getAuthorizedLibraryIds(libraryIds),
|
||||
|
|
@ -227,7 +227,7 @@ class SeriesController(
|
|||
tags = tags,
|
||||
ageRatings = ageRatings?.map { it.toIntOrNull() },
|
||||
releaseYears = release_years,
|
||||
authors = authors
|
||||
authors = authors,
|
||||
)
|
||||
|
||||
return seriesDtoRepository.countByFirstCharacter(seriesSearch, principal.user.id)
|
||||
|
|
@ -241,7 +241,7 @@ class SeriesController(
|
|||
@RequestParam(name = "library_id", required = false) libraryIds: List<String>?,
|
||||
@RequestParam(name = "deleted", required = false) deleted: Boolean?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<SeriesDto> {
|
||||
val sort = Sort.by(Sort.Order.desc("lastModified"))
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ class SeriesController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
return seriesDtoRepository.findAll(
|
||||
|
|
@ -259,7 +259,7 @@ class SeriesController(
|
|||
deleted = deleted,
|
||||
),
|
||||
principal.user.id,
|
||||
pageRequest
|
||||
pageRequest,
|
||||
).map { it.restrictUrl(!principal.user.roleAdmin) }
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ class SeriesController(
|
|||
@RequestParam(name = "library_id", required = false) libraryIds: List<String>?,
|
||||
@RequestParam(name = "deleted", required = false) deleted: Boolean?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<SeriesDto> {
|
||||
val sort = Sort.by(Sort.Order.desc("created"))
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ class SeriesController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
return seriesDtoRepository.findAll(
|
||||
|
|
@ -289,7 +289,7 @@ class SeriesController(
|
|||
deleted = deleted,
|
||||
),
|
||||
principal.user.id,
|
||||
pageRequest
|
||||
pageRequest,
|
||||
).map { it.restrictUrl(!principal.user.roleAdmin) }
|
||||
}
|
||||
|
||||
|
|
@ -301,7 +301,7 @@ class SeriesController(
|
|||
@RequestParam(name = "library_id", required = false) libraryIds: List<String>?,
|
||||
@RequestParam(name = "deleted", required = false) deleted: Boolean?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<SeriesDto> {
|
||||
val sort = Sort.by(Sort.Order.desc("lastModified"))
|
||||
|
||||
|
|
@ -310,7 +310,7 @@ class SeriesController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
return seriesDtoRepository.findAllRecentlyUpdated(
|
||||
|
|
@ -319,14 +319,14 @@ class SeriesController(
|
|||
deleted = deleted,
|
||||
),
|
||||
principal.user.id,
|
||||
pageRequest
|
||||
pageRequest,
|
||||
).map { it.restrictUrl(!principal.user.roleAdmin) }
|
||||
}
|
||||
|
||||
@GetMapping("v1/series/{seriesId}")
|
||||
fun getOneSeries(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable(name = "seriesId") id: String
|
||||
@PathVariable(name = "seriesId") id: String,
|
||||
): SeriesDto =
|
||||
seriesDtoRepository.findByIdOrNull(id, principal.user.id)?.let {
|
||||
if (!principal.user.canAccessLibrary(it.libraryId)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -352,7 +352,7 @@ class SeriesController(
|
|||
fun getSeriesThumbnailById(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable(name = "seriesId") seriesId: String,
|
||||
@PathVariable(name = "thumbnailId") thumbnailId: String
|
||||
@PathVariable(name = "thumbnailId") thumbnailId: String,
|
||||
): ByteArray {
|
||||
seriesRepository.getLibraryId(seriesId)?.let {
|
||||
if (!principal.user.canAccessLibrary(it)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -365,7 +365,7 @@ class SeriesController(
|
|||
@GetMapping(value = ["v1/series/{seriesId}/thumbnails"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||
fun getSeriesThumbnails(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable(name = "seriesId") seriesId: String
|
||||
@PathVariable(name = "seriesId") seriesId: String,
|
||||
): Collection<SeriesThumbnailDto> {
|
||||
seriesRepository.getLibraryId(seriesId)?.let {
|
||||
if (!principal.user.canAccessLibrary(it)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -391,9 +391,9 @@ class SeriesController(
|
|||
ThumbnailSeries(
|
||||
seriesId = series.id,
|
||||
thumbnail = file.bytes,
|
||||
type = ThumbnailSeries.Type.USER_UPLOADED
|
||||
type = ThumbnailSeries.Type.USER_UPLOADED,
|
||||
),
|
||||
if (selected) MarkSelectedPreference.YES else MarkSelectedPreference.NO
|
||||
if (selected) MarkSelectedPreference.YES else MarkSelectedPreference.NO,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +440,7 @@ class SeriesController(
|
|||
@RequestParam(name = "deleted", required = false) deleted: Boolean?,
|
||||
@RequestParam(name = "unpaged", required = false) unpaged: Boolean = false,
|
||||
@Parameter(hidden = true) @Authors authors: List<Author>?,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
@Parameter(hidden = true) page: Pageable,
|
||||
): Page<BookDto> {
|
||||
seriesRepository.getLibraryId(seriesId)?.let {
|
||||
if (!principal.user.canAccessLibrary(it)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -454,7 +454,7 @@ class SeriesController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
return bookDtoRepository.findAll(
|
||||
|
|
@ -467,14 +467,14 @@ class SeriesController(
|
|||
authors = authors,
|
||||
),
|
||||
principal.user.id,
|
||||
pageRequest
|
||||
pageRequest,
|
||||
).map { it.restrictUrl(!principal.user.roleAdmin) }
|
||||
}
|
||||
|
||||
@GetMapping("v1/series/{seriesId}/collections")
|
||||
fun getAllCollectionsBySeries(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable(name = "seriesId") seriesId: String
|
||||
@PathVariable(name = "seriesId") seriesId: String,
|
||||
): List<CollectionDto> {
|
||||
seriesRepository.getLibraryId(seriesId)?.let {
|
||||
if (!principal.user.canAccessLibrary(it)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -511,7 +511,7 @@ class SeriesController(
|
|||
@PathVariable seriesId: String,
|
||||
@Parameter(description = "Metadata fields to update. Set a field to null to unset the metadata. You can omit fields you don't want to update.")
|
||||
@Valid @RequestBody newMetadata: SeriesMetadataUpdateDto,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
) =
|
||||
seriesMetadataRepository.findByIdOrNull(seriesId)?.let { existing ->
|
||||
val updated = with(newMetadata) {
|
||||
|
|
@ -554,7 +554,7 @@ class SeriesController(
|
|||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun markAsRead(
|
||||
@PathVariable seriesId: String,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
) {
|
||||
seriesRepository.getLibraryId(seriesId)?.let {
|
||||
if (!principal.user.canAccessLibrary(it)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -568,7 +568,7 @@ class SeriesController(
|
|||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun markAsUnread(
|
||||
@PathVariable seriesId: String,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
) {
|
||||
seriesRepository.getLibraryId(seriesId)?.let {
|
||||
if (!principal.user.canAccessLibrary(it)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -647,7 +647,7 @@ class SeriesController(
|
|||
@PreAuthorize("hasRole('$ROLE_FILE_DOWNLOAD')")
|
||||
fun getSeriesFile(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@PathVariable seriesId: String
|
||||
@PathVariable seriesId: String,
|
||||
): ResponseEntity<StreamingResponseBody> {
|
||||
seriesRepository.getLibraryId(seriesId)?.let {
|
||||
if (!principal.user.canAccessLibrary(it)) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
|
|
@ -682,7 +682,7 @@ class SeriesController(
|
|||
contentDisposition = ContentDisposition.builder("attachment")
|
||||
.filename(seriesMetadataRepository.findById(seriesId).title + ".zip")
|
||||
.build()
|
||||
}
|
||||
},
|
||||
)
|
||||
.contentType(MediaType.parseMediaType("application/zip"))
|
||||
.body(streamingResponse)
|
||||
|
|
@ -692,7 +692,7 @@ class SeriesController(
|
|||
@PreAuthorize("hasRole('$ROLE_ADMIN')")
|
||||
@ResponseStatus(HttpStatus.ACCEPTED)
|
||||
fun deleteSeries(
|
||||
@PathVariable seriesId: String
|
||||
@PathVariable seriesId: String,
|
||||
) {
|
||||
taskReceiver.deleteSeries(
|
||||
seriesId = seriesId,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class TransientBooksController(
|
|||
|
||||
@PostMapping
|
||||
fun scanForTransientBooks(
|
||||
@RequestBody request: ScanRequestDto
|
||||
@RequestBody request: ScanRequestDto,
|
||||
): List<TransientBookDto> =
|
||||
try {
|
||||
transientBookLifecycle.scanAndPersist(request.path)
|
||||
|
|
@ -56,7 +56,7 @@ class TransientBooksController(
|
|||
|
||||
@GetMapping(
|
||||
value = ["{id}/pages/{pageNumber}"],
|
||||
produces = [MediaType.ALL_VALUE]
|
||||
produces = [MediaType.ALL_VALUE],
|
||||
)
|
||||
fun getSourcePage(
|
||||
@PathVariable id: String,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class UserController(
|
|||
private val userRepository: KomgaUserRepository,
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val authenticationActivityRepository: AuthenticationActivityRepository,
|
||||
env: Environment
|
||||
env: Environment,
|
||||
) {
|
||||
|
||||
private val demo = env.activeProfiles.contains("demo")
|
||||
|
|
@ -66,7 +66,7 @@ class UserController(
|
|||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
fun updateMyPassword(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@Valid @RequestBody newPasswordDto: PasswordUpdateDto
|
||||
@Valid @RequestBody newPasswordDto: PasswordUpdateDto,
|
||||
) {
|
||||
if (demo) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
userRepository.findByEmailIgnoreCaseOrNull(principal.username)?.let { user ->
|
||||
|
|
@ -94,7 +94,7 @@ class UserController(
|
|||
@PreAuthorize("hasRole('$ROLE_ADMIN') and #principal.user.id != #id")
|
||||
fun delete(
|
||||
@PathVariable id: String,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
) {
|
||||
userRepository.findByIdOrNull(id)?.let {
|
||||
userLifecycle.deleteUser(it)
|
||||
|
|
@ -107,13 +107,13 @@ class UserController(
|
|||
fun updateUserRoles(
|
||||
@PathVariable id: String,
|
||||
@Valid @RequestBody patch: RolesUpdateDto,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
) {
|
||||
userRepository.findByIdOrNull(id)?.let { user ->
|
||||
val updatedUser = user.copy(
|
||||
roleAdmin = patch.roles.contains(ROLE_ADMIN),
|
||||
roleFileDownload = patch.roles.contains(ROLE_FILE_DOWNLOAD),
|
||||
rolePageStreaming = patch.roles.contains(ROLE_PAGE_STREAMING)
|
||||
rolePageStreaming = patch.roles.contains(ROLE_PAGE_STREAMING),
|
||||
)
|
||||
userRepository.update(updatedUser)
|
||||
logger.info { "Updated user roles: $updatedUser" }
|
||||
|
|
@ -126,7 +126,7 @@ class UserController(
|
|||
fun updatePassword(
|
||||
@PathVariable id: String,
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@Valid @RequestBody newPasswordDto: PasswordUpdateDto
|
||||
@Valid @RequestBody newPasswordDto: PasswordUpdateDto,
|
||||
) {
|
||||
if (demo) throw ResponseStatusException(HttpStatus.FORBIDDEN)
|
||||
userRepository.findByIdOrNull(id)?.let { user ->
|
||||
|
|
@ -139,7 +139,7 @@ class UserController(
|
|||
@PreAuthorize("hasRole('$ROLE_ADMIN')")
|
||||
fun updateSharesLibraries(
|
||||
@PathVariable id: String,
|
||||
@Valid @RequestBody sharedLibrariesUpdateDto: SharedLibrariesUpdateDto
|
||||
@Valid @RequestBody sharedLibrariesUpdateDto: SharedLibrariesUpdateDto,
|
||||
) {
|
||||
userRepository.findByIdOrNull(id)?.let { user ->
|
||||
val updatedUser = user.copy(
|
||||
|
|
@ -147,7 +147,7 @@ class UserController(
|
|||
sharedLibrariesIds = if (sharedLibrariesUpdateDto.all) emptySet()
|
||||
else libraryRepository.findAllByIds(sharedLibrariesUpdateDto.libraryIds)
|
||||
.map { it.id }
|
||||
.toSet()
|
||||
.toSet(),
|
||||
)
|
||||
userRepository.update(updatedUser)
|
||||
logger.info { "Updated user shared libraries: $updatedUser" }
|
||||
|
|
@ -171,7 +171,7 @@ class UserController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
return authenticationActivityRepository.findAllByUser(principal.user, pageRequest).map { it.toDto() }
|
||||
|
|
@ -193,7 +193,7 @@ class UserController(
|
|||
else PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
sort
|
||||
sort,
|
||||
)
|
||||
|
||||
return authenticationActivityRepository.findAll(pageRequest).map { it.toDto() }
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import org.gotson.komga.domain.model.Author
|
|||
|
||||
data class AuthorDto(
|
||||
val name: String,
|
||||
val role: String
|
||||
val role: String,
|
||||
)
|
||||
|
||||
fun Author.toDto() = AuthorDto(name, role)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue