feat: load CBR files

This commit is contained in:
Antoine Aflalo
2025-06-12 09:11:11 -04:00
parent a5f88fe0e9
commit 970b9019df
6 changed files with 356 additions and 46 deletions

View File

@@ -4,65 +4,86 @@ import (
"archive/zip"
"bufio"
"bytes"
"context"
"fmt"
"io"
"io/fs"
"path/filepath"
"strings"
"github.com/araddon/dateparse"
"github.com/belphemur/CBZOptimizer/v2/internal/manga"
"github.com/belphemur/CBZOptimizer/v2/internal/utils/errs"
"io"
"path/filepath"
"strings"
"github.com/mholt/archives"
)
func LoadChapter(filePath string) (*manga.Chapter, error) {
// Open the .cbz file
r, err := zip.OpenReader(filePath)
if err != nil {
return nil, fmt.Errorf("failed to open .cbz file: %w", err)
}
defer errs.Capture(&err, r.Close, "failed to close opened .cbz file")
ctx := context.Background()
chapter := &manga.Chapter{
FilePath: filePath,
}
// Check for comment
if r.Comment != "" {
scanner := bufio.NewScanner(strings.NewReader(r.Comment))
if scanner.Scan() {
convertedTime := scanner.Text()
chapter.ConvertedTime, err = dateparse.ParseAny(convertedTime)
if err == nil {
chapter.IsConverted = true
// First, try to read the comment using zip.OpenReader for CBZ files
if strings.ToLower(filepath.Ext(filePath)) == ".cbz" {
r, err := zip.OpenReader(filePath)
if err == nil {
defer errs.Capture(&err, r.Close, "failed to close zip reader for comment")
// Check for comment
if r.Comment != "" {
scanner := bufio.NewScanner(strings.NewReader(r.Comment))
if scanner.Scan() {
convertedTime := scanner.Text()
chapter.ConvertedTime, err = dateparse.ParseAny(convertedTime)
if err == nil {
chapter.IsConverted = true
}
}
}
}
// Continue even if comment reading fails
}
for _, f := range r.File {
if f.FileInfo().IsDir() {
continue
}
err := func() error {
// Open the file inside the zip
rc, err := f.Open()
if err != nil {
return fmt.Errorf("failed to open file inside .cbz: %w", err)
}
// Open the archive using archives library for file operations
fsys, err := archives.FileSystem(ctx, filePath, nil)
if err != nil {
return nil, fmt.Errorf("failed to open archive file: %w", err)
}
defer errs.Capture(&err, rc.Close, "failed to close file inside .cbz")
// Walk through all files in the filesystem
err = fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
return func() error {
// Open the file
file, err := fsys.Open(path)
if err != nil {
return fmt.Errorf("failed to open file %s: %w", path, err)
}
defer errs.Capture(&err, file.Close, fmt.Sprintf("failed to close file %s", path))
// Determine the file extension
ext := strings.ToLower(filepath.Ext(f.Name))
ext := strings.ToLower(filepath.Ext(path))
fileName := strings.ToLower(filepath.Base(path))
if ext == ".xml" && strings.ToLower(filepath.Base(f.Name)) == "comicinfo.xml" {
if ext == ".xml" && fileName == "comicinfo.xml" {
// Read the ComicInfo.xml file content
xmlContent, err := io.ReadAll(rc)
xmlContent, err := io.ReadAll(file)
if err != nil {
return fmt.Errorf("failed to read ComicInfo.xml content: %w", err)
}
chapter.ComicInfoXml = string(xmlContent)
} else if !chapter.IsConverted && ext == ".txt" && strings.ToLower(filepath.Base(f.Name)) == "converted.txt" {
textContent, err := io.ReadAll(rc)
} else if !chapter.IsConverted && ext == ".txt" && fileName == "converted.txt" {
textContent, err := io.ReadAll(file)
if err != nil {
return fmt.Errorf("failed to read Converted.xml content: %w", err)
return fmt.Errorf("failed to read converted.txt content: %w", err)
}
scanner := bufio.NewScanner(bytes.NewReader(textContent))
if scanner.Scan() {
@@ -76,7 +97,7 @@ func LoadChapter(filePath string) (*manga.Chapter, error) {
} else {
// Read the file contents for page
buf := new(bytes.Buffer)
_, err = io.Copy(buf, rc)
_, err = io.Copy(buf, file)
if err != nil {
return fmt.Errorf("failed to read file contents: %w", err)
}
@@ -95,9 +116,10 @@ func LoadChapter(filePath string) (*manga.Chapter, error) {
}
return nil
}()
if err != nil {
return nil, err
}
})
if err != nil {
return nil, err
}
return chapter, nil