fix(scanner): extract metadata and covers for comic archives and kepub files

Comic archive formats (.cbz, .cbr, .cb7, .cbt) and .kepub files were
falling through to the default case in extractMetadata(), which only
set the title from the filename. This meant ComicInfo.xml was never
parsed and no cover images were extracted for comics without a Calibre
metadata.opf sidecar file.

The fix adds dedicated switch cases:
- .cbz/.cbr/.cb7/.cbt: calls mergeMetadata() with nil, which triggers
  existing ComicInfo.xml parsing (title, series, issue number, writer,
  publisher, genre, reading direction, etc.) and cover image extraction
  from the archive. Falls back to sidecar cover if no image is found.
- .kepub: treated the same as .epub since KEPUB is an EPUB variant,
  enabling full metadata and cover extraction.
This commit is contained in:
2026-04-22 21:18:53 -04:00
parent 65c860bb99
commit 9f778452d6
+19 -1
View File
@@ -1077,7 +1077,7 @@ func (s *MediaScanner) extractMetadata(path string) (*MediaMetadata, error) {
ext := strings.ToLower(filepath.Ext(path)) ext := strings.ToLower(filepath.Ext(path))
switch ext { switch ext {
case ".epub": case ".epub", ".kepub":
metadata := &MediaMetadata{} metadata := &MediaMetadata{}
result, err := s.extractEPUBMetadata(path) result, err := s.extractEPUBMetadata(path)
if err == nil { if err == nil {
@@ -1113,6 +1113,24 @@ func (s *MediaScanner) extractMetadata(path string) (*MediaMetadata, error) {
return metadata, nil return metadata, nil
case ".pdf": case ".pdf":
return s.extractPDFMetadata(path) return s.extractPDFMetadata(path)
case ".cbz", ".cbr", ".cb7", ".cbt":
metadata, err := s.mergeMetadata(path, nil)
if err != nil {
return &MediaMetadata{
Title: strings.TrimSuffix(filepath.Base(path), ext),
}, nil
}
if metadata.Title == "" {
metadata.Title = strings.TrimSuffix(filepath.Base(path), ext)
}
// If no cover from archive, try sidecar
if metadata.CoverPath == "" {
sidecarCover := findSidecarCover(path)
if sidecarCover != "" {
metadata.CoverPath = s.getRelativePath(sidecarCover)
}
}
return metadata, nil
default: default:
// For other formats, return basic metadata // For other formats, return basic metadata
return &MediaMetadata{ return &MediaMetadata{