added cbr/rar support

archive entries are sorted using natural sort comparator
This commit is contained in:
Gauthier Roebroeck 2019-08-16 18:03:11 +08:00
parent f88279b29b
commit 08c78f6a92
6 changed files with 54 additions and 11 deletions

View file

@ -56,6 +56,8 @@ dependencies {
implementation("org.apache.tika:tika-core:1.22")
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")

View file

@ -6,6 +6,7 @@ import org.gotson.komga.domain.model.BookMetadata
import org.gotson.komga.domain.model.Status
import org.gotson.komga.domain.model.path
import org.gotson.komga.infrastructure.archive.ContentDetector
import org.gotson.komga.infrastructure.archive.RarExtractor
import org.gotson.komga.infrastructure.archive.ZipExtractor
import org.springframework.stereotype.Service
import java.io.InputStream
@ -15,11 +16,13 @@ private val logger = KotlinLogging.logger {}
@Service
class BookParser(
private val contentDetector: ContentDetector,
private val zipExtractor: ZipExtractor
private val zipExtractor: ZipExtractor,
private val rarExtractor: RarExtractor
) {
val supportedMimeTypes = listOf(
"application/zip"
val supportedMediaTypes = mapOf(
"application/zip" to zipExtractor,
"application/x-rar-compressed" to rarExtractor
)
fun parse(book: Book): BookMetadata {
@ -27,10 +30,10 @@ class BookParser(
val mediaType = contentDetector.detectMediaType(book.path())
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)
val pageNames = zipExtractor.getFilenames(book.path())
val pageNames = supportedMediaTypes.getValue(mediaType).getFilenames(book.path())
logger.info { "Book has ${pageNames.size} pages" }
return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pageNames)
@ -49,7 +52,7 @@ class BookParser(
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])
}
}

View file

@ -20,7 +20,7 @@ private val logger = KotlinLogging.logger {}
@Service
class FileSystemScanner {
val supportedExtensions = listOf("cbz", "zip")
val supportedExtensions = listOf("cbz", "zip", "cbr", "rar")
fun scanRootFolder(root: Path): List<Serie> {
logger.info { "Scanning folder: $root" }

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -6,12 +6,12 @@ import java.io.InputStream
import java.nio.file.Path
@Service
class ZipExtractor {
class ZipExtractor : ArchiveExtractor() {
fun getFilenames(path: Path) =
ZipFile(path.toFile()).fileHeaders.map { it.fileName }.toMutableList()
override fun getFilenames(path: Path) =
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 {
it.getInputStream(it.getFileHeader(entryName))
}