mirror of
https://github.com/gotson/komga.git
synced 2025-12-06 16:42:24 +01:00
added cbr/rar support
archive entries are sorted using natural sort comparator
This commit is contained in:
parent
f88279b29b
commit
08c78f6a92
6 changed files with 54 additions and 11 deletions
|
|
@ -56,6 +56,8 @@ dependencies {
|
||||||
|
|
||||||
implementation("org.apache.tika:tika-core:1.22")
|
implementation("org.apache.tika:tika-core:1.22")
|
||||||
implementation("net.lingala.zip4j:zip4j:2.1.2")
|
implementation("net.lingala.zip4j:zip4j:2.1.2")
|
||||||
|
implementation("com.github.junrar:junrar:4.0.0")
|
||||||
|
implementation("net.grey-panther:natural-comparator:1.1")
|
||||||
|
|
||||||
runtimeOnly("com.h2database:h2:1.4.199")
|
runtimeOnly("com.h2database:h2:1.4.199")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import org.gotson.komga.domain.model.BookMetadata
|
||||||
import org.gotson.komga.domain.model.Status
|
import org.gotson.komga.domain.model.Status
|
||||||
import org.gotson.komga.domain.model.path
|
import org.gotson.komga.domain.model.path
|
||||||
import org.gotson.komga.infrastructure.archive.ContentDetector
|
import org.gotson.komga.infrastructure.archive.ContentDetector
|
||||||
|
import org.gotson.komga.infrastructure.archive.RarExtractor
|
||||||
import org.gotson.komga.infrastructure.archive.ZipExtractor
|
import org.gotson.komga.infrastructure.archive.ZipExtractor
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
@ -15,11 +16,13 @@ private val logger = KotlinLogging.logger {}
|
||||||
@Service
|
@Service
|
||||||
class BookParser(
|
class BookParser(
|
||||||
private val contentDetector: ContentDetector,
|
private val contentDetector: ContentDetector,
|
||||||
private val zipExtractor: ZipExtractor
|
private val zipExtractor: ZipExtractor,
|
||||||
|
private val rarExtractor: RarExtractor
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val supportedMimeTypes = listOf(
|
val supportedMediaTypes = mapOf(
|
||||||
"application/zip"
|
"application/zip" to zipExtractor,
|
||||||
|
"application/x-rar-compressed" to rarExtractor
|
||||||
)
|
)
|
||||||
|
|
||||||
fun parse(book: Book): BookMetadata {
|
fun parse(book: Book): BookMetadata {
|
||||||
|
|
@ -27,10 +30,10 @@ class BookParser(
|
||||||
|
|
||||||
val mediaType = contentDetector.detectMediaType(book.path())
|
val mediaType = contentDetector.detectMediaType(book.path())
|
||||||
logger.info { "Detected media type: $mediaType" }
|
logger.info { "Detected media type: $mediaType" }
|
||||||
if (!supportedMimeTypes.contains(mediaType))
|
if (!supportedMediaTypes.keys.contains(mediaType))
|
||||||
throw UnsupportedMediaTypeException("Unsupported mime type: $mediaType. File: ${book.url}", mediaType)
|
throw UnsupportedMediaTypeException("Unsupported mime type: $mediaType. File: ${book.url}", mediaType)
|
||||||
|
|
||||||
val pageNames = zipExtractor.getFilenames(book.path())
|
val pageNames = supportedMediaTypes.getValue(mediaType).getFilenames(book.path())
|
||||||
logger.info { "Book has ${pageNames.size} pages" }
|
logger.info { "Book has ${pageNames.size} pages" }
|
||||||
|
|
||||||
return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pageNames)
|
return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pageNames)
|
||||||
|
|
@ -49,7 +52,7 @@ class BookParser(
|
||||||
throw ArrayIndexOutOfBoundsException("Page $number does not exist")
|
throw ArrayIndexOutOfBoundsException("Page $number does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
return zipExtractor.getEntryStream(book.path(), book.metadata.pages[number - 1])
|
return supportedMediaTypes.getValue(book.metadata.mediaType!!).getEntryStream(book.path(), book.metadata.pages[number - 1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ private val logger = KotlinLogging.logger {}
|
||||||
@Service
|
@Service
|
||||||
class FileSystemScanner {
|
class FileSystemScanner {
|
||||||
|
|
||||||
val supportedExtensions = listOf("cbz", "zip")
|
val supportedExtensions = listOf("cbz", "zip", "cbr", "rar")
|
||||||
|
|
||||||
fun scanRootFolder(root: Path): List<Serie> {
|
fun scanRootFolder(root: Path): List<Serie> {
|
||||||
logger.info { "Scanning folder: $root" }
|
logger.info { "Scanning folder: $root" }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.gotson.komga.infrastructure.archive
|
||||||
|
|
||||||
|
import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class ArchiveExtractor {
|
||||||
|
|
||||||
|
protected val natSortComparator: Comparator<String> = CaseInsensitiveSimpleNaturalComparator.getInstance()
|
||||||
|
|
||||||
|
abstract fun getFilenames(path: Path): List<String>
|
||||||
|
abstract fun getEntryStream(path: Path, entryName: String): InputStream
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.gotson.komga.infrastructure.archive
|
||||||
|
|
||||||
|
import com.github.junrar.Archive
|
||||||
|
import com.github.junrar.Junrar
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class RarExtractor : ArchiveExtractor() {
|
||||||
|
|
||||||
|
override fun getFilenames(path: Path): List<String> {
|
||||||
|
val contentsDescription = Junrar.getContentsDescription(path.toFile())
|
||||||
|
|
||||||
|
return contentsDescription.map { it.path }.sortedWith(natSortComparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getEntryStream(path: Path, entryName: String): InputStream {
|
||||||
|
val archive = Archive(Files.newInputStream(path))
|
||||||
|
val header = archive.fileHeaders.find { it.fileNameString == entryName }
|
||||||
|
return archive.getInputStream(header)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,12 +6,12 @@ import java.io.InputStream
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class ZipExtractor {
|
class ZipExtractor : ArchiveExtractor() {
|
||||||
|
|
||||||
fun getFilenames(path: Path) =
|
override fun getFilenames(path: Path) =
|
||||||
ZipFile(path.toFile()).fileHeaders.map { it.fileName }.toMutableList()
|
ZipFile(path.toFile()).fileHeaders.map { it.fileName }.sortedWith(natSortComparator)
|
||||||
|
|
||||||
fun getEntryStream(path: Path, entryName: String): InputStream =
|
override fun getEntryStream(path: Path, entryName: String): InputStream =
|
||||||
ZipFile(path.toFile()).let {
|
ZipFile(path.toFile()).let {
|
||||||
it.getInputStream(it.getFileHeader(entryName))
|
it.getInputStream(it.getFileHeader(entryName))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue