feat: support for EPUB format (comics only)

closes #119
This commit is contained in:
Gauthier Roebroeck 2020-04-09 15:53:54 +08:00
parent c5d9f10e92
commit 0a06a6f799
4 changed files with 61 additions and 1 deletions

View file

@ -6,6 +6,8 @@ export function getBookFormatFromMediaType (mediaType: string): BookFormat {
return { type: 'CBZ', color: '#4CAF50' }
case 'application/pdf':
return { type: 'PDF', color: '#FF5722' }
case 'application/epub+zip':
return { type: 'EPUB', color: '#ff5ab1' }
default:
return { type: '?', color: '#000000' }
}

View file

@ -69,6 +69,7 @@ dependencies {
implementation("com.github.junrar:junrar:4.0.0")
implementation("org.apache.pdfbox:pdfbox:2.0.19")
implementation("net.grey-panther:natural-comparator:1.1")
implementation("org.jsoup:jsoup:1.13.1")
implementation("net.coobird:thumbnailator:0.4.11")
implementation("com.twelvemonkeys.imageio:imageio-jpeg:3.5")

View file

@ -24,7 +24,7 @@ class FileSystemScanner(
private val komgaProperties: KomgaProperties
) {
val supportedExtensions = listOf("cbz", "zip", "cbr", "rar", "pdf")
val supportedExtensions = listOf("cbz", "zip", "cbr", "rar", "pdf", "epub")
fun scanRootFolder(root: Path): List<Series> {
logger.info { "Scanning folder: $root" }

View file

@ -0,0 +1,57 @@
package org.gotson.komga.infrastructure.mediacontainer
import mu.KotlinLogging
import org.apache.commons.compress.archivers.zip.ZipFile
import org.gotson.komga.domain.model.MediaContainerEntry
import org.jsoup.Jsoup
import org.springframework.stereotype.Service
import java.nio.file.Path
import java.nio.file.Paths
private val logger = KotlinLogging.logger {}
@Service
class EpubExtractor(contentDetector: ContentDetector) : ZipExtractor(contentDetector) {
override fun mediaTypes(): List<String> = listOf("application/epub+zip")
override fun getEntries(path: Path): List<MediaContainerEntry> {
ZipFile(path.toFile()).use { zip ->
try {
val packagePath = zip.getEntry("META-INF/container.xml").let { entry ->
val container = zip.getInputStream(entry).use { Jsoup.parse(it, null, "") }
container.getElementsByTag("rootfile").first().attr("full-path")
}
val opf = zip.getInputStream(zip.getEntry(packagePath)).use { Jsoup.parse(it, null, "") }
val manifest = opf.select("manifest > item")
.associate { it.attr("id") to ManifestItem(it.attr("id"), it.attr("href"), it.attr("media-type")) }
val pages = opf.select("spine > itemref").map { it.attr("idref") }
.mapNotNull { manifest[it] }
.map { it.href }
val images = pages.flatMap { pagePath ->
val doc = zip.getInputStream(zip.getEntry(pagePath)).use { Jsoup.parse(it, null, "") }
doc.getElementsByTag("img")
.map { it.attr("src") }
.map { Paths.get(pagePath).parent?.resolve(it).toString() }
}
return images.map { image ->
MediaContainerEntry(image, manifest.values.first { it.href == image }.mediaType)
}
} catch (e: Exception) {
logger.error(e) { "File is not a proper Epub, treating it as a zip file" }
return super.getEntries(path)
}
}
}
private data class ManifestItem(
val id: String,
val href: String,
val mediaType: String
)
}