mirror of
https://github.com/Belphemur/CBZOptimizer.git
synced 2025-10-14 04:28:51 +02:00
171 lines
5.7 KiB
Go
171 lines
5.7 KiB
Go
package utils
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/belphemur/CBZOptimizer/v2/internal/cbz"
|
|
"github.com/belphemur/CBZOptimizer/v2/pkg/converter"
|
|
errors2 "github.com/belphemur/CBZOptimizer/v2/pkg/converter/errors"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type OptimizeOptions struct {
|
|
ChapterConverter converter.Converter
|
|
Path string
|
|
Quality uint8
|
|
Override bool
|
|
Split bool
|
|
Timeout time.Duration
|
|
}
|
|
|
|
// Optimize optimizes a CBZ/CBR file using the specified converter.
|
|
func Optimize(options *OptimizeOptions) error {
|
|
log.Info().Str("file", options.Path).Msg("Processing file")
|
|
log.Debug().
|
|
Str("file", options.Path).
|
|
Uint8("quality", options.Quality).
|
|
Bool("override", options.Override).
|
|
Bool("split", options.Split).
|
|
Msg("Optimization parameters")
|
|
|
|
// Load the chapter
|
|
log.Debug().Str("file", options.Path).Msg("Loading chapter")
|
|
chapter, err := cbz.LoadChapter(options.Path)
|
|
if err != nil {
|
|
log.Error().Str("file", options.Path).Err(err).Msg("Failed to load chapter")
|
|
return fmt.Errorf("failed to load chapter: %v", err)
|
|
}
|
|
log.Debug().
|
|
Str("file", options.Path).
|
|
Int("pages", len(chapter.Pages)).
|
|
Bool("converted", chapter.IsConverted).
|
|
Msg("Chapter loaded successfully")
|
|
|
|
if chapter.IsConverted {
|
|
log.Info().Str("file", options.Path).Msg("Chapter already converted")
|
|
return nil
|
|
}
|
|
|
|
// Convert the chapter
|
|
log.Debug().
|
|
Str("file", chapter.FilePath).
|
|
Int("pages", len(chapter.Pages)).
|
|
Uint8("quality", options.Quality).
|
|
Bool("split", options.Split).
|
|
Msg("Starting chapter conversion")
|
|
|
|
var ctx context.Context
|
|
if options.Timeout > 0 {
|
|
var cancel context.CancelFunc
|
|
ctx, cancel = context.WithTimeout(context.Background(), options.Timeout)
|
|
defer cancel()
|
|
log.Debug().Str("file", chapter.FilePath).Dur("timeout", options.Timeout).Msg("Applying timeout to chapter conversion")
|
|
} else {
|
|
ctx = context.Background()
|
|
}
|
|
|
|
convertedChapter, err := options.ChapterConverter.ConvertChapter(ctx, chapter, options.Quality, options.Split, func(msg string, current uint32, total uint32) {
|
|
if current%10 == 0 || current == total {
|
|
log.Info().Str("file", chapter.FilePath).Uint32("current", current).Uint32("total", total).Msg("Converting")
|
|
} else {
|
|
log.Debug().Str("file", chapter.FilePath).Uint32("current", current).Uint32("total", total).Msg("Converting page")
|
|
}
|
|
})
|
|
if err != nil {
|
|
var pageIgnoredError *errors2.PageIgnoredError
|
|
if errors.As(err, &pageIgnoredError) {
|
|
log.Debug().Str("file", chapter.FilePath).Err(err).Msg("Page conversion error (non-fatal)")
|
|
} else {
|
|
log.Error().Str("file", chapter.FilePath).Err(err).Msg("Chapter conversion failed")
|
|
return fmt.Errorf("failed to convert chapter: %v", err)
|
|
}
|
|
}
|
|
if convertedChapter == nil {
|
|
log.Error().Str("file", chapter.FilePath).Msg("Conversion returned nil chapter")
|
|
return fmt.Errorf("failed to convert chapter")
|
|
}
|
|
|
|
log.Debug().
|
|
Str("file", chapter.FilePath).
|
|
Int("original_pages", len(chapter.Pages)).
|
|
Int("converted_pages", len(convertedChapter.Pages)).
|
|
Msg("Chapter conversion completed")
|
|
|
|
convertedChapter.SetConverted()
|
|
|
|
// Determine output path and handle CBR override logic
|
|
log.Debug().
|
|
Str("input_path", options.Path).
|
|
Bool("override", options.Override).
|
|
Msg("Determining output path")
|
|
|
|
outputPath := options.Path
|
|
originalPath := options.Path
|
|
isCbrOverride := false
|
|
|
|
if options.Override {
|
|
// For override mode, check if it's a CBR file that needs to be converted to CBZ
|
|
pathLower := strings.ToLower(options.Path)
|
|
if strings.HasSuffix(pathLower, ".cbr") {
|
|
// Convert CBR to CBZ: change extension and mark for deletion
|
|
outputPath = strings.TrimSuffix(options.Path, filepath.Ext(options.Path)) + ".cbz"
|
|
isCbrOverride = true
|
|
log.Debug().
|
|
Str("original_path", originalPath).
|
|
Str("output_path", outputPath).
|
|
Msg("CBR to CBZ conversion: will delete original after conversion")
|
|
} else {
|
|
log.Debug().
|
|
Str("original_path", originalPath).
|
|
Str("output_path", outputPath).
|
|
Msg("CBZ override mode: will overwrite original file")
|
|
}
|
|
} else {
|
|
// Handle both .cbz and .cbr files - strip the extension and add _converted.cbz
|
|
pathLower := strings.ToLower(options.Path)
|
|
if strings.HasSuffix(pathLower, ".cbz") {
|
|
outputPath = strings.TrimSuffix(options.Path, ".cbz") + "_converted.cbz"
|
|
} else if strings.HasSuffix(pathLower, ".cbr") {
|
|
outputPath = strings.TrimSuffix(options.Path, ".cbr") + "_converted.cbz"
|
|
} else {
|
|
// Fallback for other extensions - just add _converted.cbz
|
|
outputPath = options.Path + "_converted.cbz"
|
|
}
|
|
log.Debug().
|
|
Str("original_path", originalPath).
|
|
Str("output_path", outputPath).
|
|
Msg("Non-override mode: creating converted file alongside original")
|
|
}
|
|
|
|
// Write the converted chapter to CBZ file
|
|
log.Debug().Str("output_path", outputPath).Msg("Writing converted chapter to CBZ file")
|
|
err = cbz.WriteChapterToCBZ(convertedChapter, outputPath)
|
|
if err != nil {
|
|
log.Error().Str("output_path", outputPath).Err(err).Msg("Failed to write converted chapter")
|
|
return fmt.Errorf("failed to write converted chapter: %v", err)
|
|
}
|
|
log.Debug().Str("output_path", outputPath).Msg("Successfully wrote converted chapter")
|
|
|
|
// If we're overriding a CBR file, delete the original CBR after successful write
|
|
if isCbrOverride {
|
|
log.Debug().Str("file", originalPath).Msg("Attempting to delete original CBR file")
|
|
err = os.Remove(originalPath)
|
|
if err != nil {
|
|
// Log the error but don't fail the operation since conversion succeeded
|
|
log.Warn().Str("file", originalPath).Err(err).Msg("Failed to delete original CBR file")
|
|
} else {
|
|
log.Info().Str("file", originalPath).Msg("Deleted original CBR file")
|
|
}
|
|
}
|
|
|
|
log.Info().Str("output", outputPath).Msg("Converted file written")
|
|
return nil
|
|
|
|
}
|