feat: integrate zerolog for enhanced logging across multiple components

This commit is contained in:
Antoine Aflalo
2025-08-26 21:16:54 -04:00
parent 94fb60c5c6
commit 32c009ed9b
5 changed files with 316 additions and 21 deletions

View File

@@ -3,28 +3,42 @@ package cbz
import (
"archive/zip"
"fmt"
"github.com/belphemur/CBZOptimizer/v2/internal/manga"
"github.com/belphemur/CBZOptimizer/v2/internal/utils/errs"
"os"
"time"
"github.com/belphemur/CBZOptimizer/v2/internal/manga"
"github.com/belphemur/CBZOptimizer/v2/internal/utils/errs"
"github.com/rs/zerolog/log"
)
func WriteChapterToCBZ(chapter *manga.Chapter, outputFilePath string) error {
log.Debug().
Str("chapter_file", chapter.FilePath).
Str("output_path", outputFilePath).
Int("page_count", len(chapter.Pages)).
Bool("is_converted", chapter.IsConverted).
Msg("Starting CBZ file creation")
// Create a new ZIP file
log.Debug().Str("output_path", outputFilePath).Msg("Creating output CBZ file")
zipFile, err := os.Create(outputFilePath)
if err != nil {
log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to create CBZ file")
return fmt.Errorf("failed to create .cbz file: %w", err)
}
defer errs.Capture(&err, zipFile.Close, "failed to close .cbz file")
// Create a new ZIP writer
log.Debug().Str("output_path", outputFilePath).Msg("Creating ZIP writer")
zipWriter := zip.NewWriter(zipFile)
if err != nil {
log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to create ZIP writer")
return err
}
defer errs.Capture(&err, zipWriter.Close, "failed to close .cbz writer")
// Write each page to the ZIP archive
log.Debug().Str("output_path", outputFilePath).Int("pages_to_write", len(chapter.Pages)).Msg("Writing pages to CBZ archive")
for _, page := range chapter.Pages {
// Construct the file name for the page
var fileName string
@@ -36,6 +50,15 @@ func WriteChapterToCBZ(chapter *manga.Chapter, outputFilePath string) error {
fileName = fmt.Sprintf("%04d%s", page.Index, page.Extension)
}
log.Debug().
Str("output_path", outputFilePath).
Uint16("page_index", page.Index).
Bool("is_splitted", page.IsSplitted).
Uint16("split_part", page.SplitPartIndex).
Str("filename", fileName).
Int("size", len(page.Contents.Bytes())).
Msg("Writing page to CBZ archive")
// Create a new file in the ZIP archive
fileWriter, err := zipWriter.CreateHeader(&zip.FileHeader{
Name: fileName,
@@ -43,41 +66,58 @@ func WriteChapterToCBZ(chapter *manga.Chapter, outputFilePath string) error {
Modified: time.Now(),
})
if err != nil {
log.Error().Str("output_path", outputFilePath).Str("filename", fileName).Err(err).Msg("Failed to create file in CBZ archive")
return fmt.Errorf("failed to create file in .cbz: %w", err)
}
// Write the page contents to the file
_, err = fileWriter.Write(page.Contents.Bytes())
bytesWritten, err := fileWriter.Write(page.Contents.Bytes())
if err != nil {
log.Error().Str("output_path", outputFilePath).Str("filename", fileName).Err(err).Msg("Failed to write page contents")
return fmt.Errorf("failed to write page contents: %w", err)
}
log.Debug().
Str("output_path", outputFilePath).
Str("filename", fileName).
Int("bytes_written", bytesWritten).
Msg("Page written successfully")
}
// Optionally, write the ComicInfo.xml file if present
if chapter.ComicInfoXml != "" {
log.Debug().Str("output_path", outputFilePath).Int("xml_size", len(chapter.ComicInfoXml)).Msg("Writing ComicInfo.xml to CBZ archive")
comicInfoWriter, err := zipWriter.CreateHeader(&zip.FileHeader{
Name: "ComicInfo.xml",
Method: zip.Deflate,
Modified: time.Now(),
})
if err != nil {
log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to create ComicInfo.xml in CBZ archive")
return fmt.Errorf("failed to create ComicInfo.xml in .cbz: %w", err)
}
_, err = comicInfoWriter.Write([]byte(chapter.ComicInfoXml))
bytesWritten, err := comicInfoWriter.Write([]byte(chapter.ComicInfoXml))
if err != nil {
log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to write ComicInfo.xml contents")
return fmt.Errorf("failed to write ComicInfo.xml contents: %w", err)
}
log.Debug().Str("output_path", outputFilePath).Int("bytes_written", bytesWritten).Msg("ComicInfo.xml written successfully")
} else {
log.Debug().Str("output_path", outputFilePath).Msg("No ComicInfo.xml to write")
}
if chapter.IsConverted {
convertedString := fmt.Sprintf("%s\nThis chapter has been converted by CBZOptimizer.", chapter.ConvertedTime)
log.Debug().Str("output_path", outputFilePath).Str("comment", convertedString).Msg("Setting CBZ comment for converted chapter")
err = zipWriter.SetComment(convertedString)
if err != nil {
log.Error().Str("output_path", outputFilePath).Err(err).Msg("Failed to write CBZ comment")
return fmt.Errorf("failed to write comment: %w", err)
}
log.Debug().Str("output_path", outputFilePath).Msg("CBZ comment set successfully")
}
log.Debug().Str("output_path", outputFilePath).Msg("CBZ file creation completed successfully")
return nil
}

View File

@@ -15,9 +15,12 @@ import (
"github.com/belphemur/CBZOptimizer/v2/internal/manga"
"github.com/belphemur/CBZOptimizer/v2/internal/utils/errs"
"github.com/mholt/archives"
"github.com/rs/zerolog/log"
)
func LoadChapter(filePath string) (*manga.Chapter, error) {
log.Debug().Str("file_path", filePath).Msg("Starting chapter loading")
ctx := context.Background()
chapter := &manga.Chapter{
@@ -26,32 +29,45 @@ func LoadChapter(filePath string) (*manga.Chapter, error) {
// First, try to read the comment using zip.OpenReader for CBZ files
if strings.ToLower(filepath.Ext(filePath)) == ".cbz" {
log.Debug().Str("file_path", filePath).Msg("Checking CBZ comment for conversion status")
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 != "" {
log.Debug().Str("file_path", filePath).Str("comment", r.Comment).Msg("Found CBZ comment")
scanner := bufio.NewScanner(strings.NewReader(r.Comment))
if scanner.Scan() {
convertedTime := scanner.Text()
log.Debug().Str("file_path", filePath).Str("converted_time", convertedTime).Msg("Parsing conversion timestamp")
chapter.ConvertedTime, err = dateparse.ParseAny(convertedTime)
if err == nil {
chapter.IsConverted = true
log.Debug().Str("file_path", filePath).Time("converted_time", chapter.ConvertedTime).Msg("Chapter marked as previously converted")
} else {
log.Debug().Str("file_path", filePath).Err(err).Msg("Failed to parse conversion timestamp")
}
}
} else {
log.Debug().Str("file_path", filePath).Msg("No CBZ comment found")
}
} else {
log.Debug().Str("file_path", filePath).Err(err).Msg("Failed to open CBZ file for comment reading")
}
// Continue even if comment reading fails
}
// Open the archive using archives library for file operations
log.Debug().Str("file_path", filePath).Msg("Opening archive file system")
fsys, err := archives.FileSystem(ctx, filePath, nil)
if err != nil {
log.Error().Str("file_path", filePath).Err(err).Msg("Failed to open archive file system")
return nil, fmt.Errorf("failed to open archive file: %w", err)
}
// Walk through all files in the filesystem
log.Debug().Str("file_path", filePath).Msg("Starting filesystem walk")
err = fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
@@ -74,31 +90,41 @@ func LoadChapter(filePath string) (*manga.Chapter, error) {
fileName := strings.ToLower(filepath.Base(path))
if ext == ".xml" && fileName == "comicinfo.xml" {
log.Debug().Str("file_path", filePath).Str("archive_file", path).Msg("Found ComicInfo.xml")
// Read the ComicInfo.xml file content
xmlContent, err := io.ReadAll(file)
if err != nil {
log.Error().Str("file_path", filePath).Str("archive_file", path).Err(err).Msg("Failed to read ComicInfo.xml")
return fmt.Errorf("failed to read ComicInfo.xml content: %w", err)
}
chapter.ComicInfoXml = string(xmlContent)
log.Debug().Str("file_path", filePath).Int("xml_size", len(xmlContent)).Msg("ComicInfo.xml loaded")
} else if !chapter.IsConverted && ext == ".txt" && fileName == "converted.txt" {
log.Debug().Str("file_path", filePath).Str("archive_file", path).Msg("Found converted.txt")
textContent, err := io.ReadAll(file)
if err != nil {
log.Error().Str("file_path", filePath).Str("archive_file", path).Err(err).Msg("Failed to read converted.txt")
return fmt.Errorf("failed to read converted.txt content: %w", err)
}
scanner := bufio.NewScanner(bytes.NewReader(textContent))
if scanner.Scan() {
convertedTime := scanner.Text()
log.Debug().Str("file_path", filePath).Str("converted_time", convertedTime).Msg("Parsing converted.txt timestamp")
chapter.ConvertedTime, err = dateparse.ParseAny(convertedTime)
if err != nil {
log.Error().Str("file_path", filePath).Err(err).Msg("Failed to parse converted time from converted.txt")
return fmt.Errorf("failed to parse converted time: %w", err)
}
chapter.IsConverted = true
log.Debug().Str("file_path", filePath).Time("converted_time", chapter.ConvertedTime).Msg("Chapter marked as converted from converted.txt")
}
} else {
// Read the file contents for page
log.Debug().Str("file_path", filePath).Str("archive_file", path).Str("extension", ext).Msg("Processing page file")
buf := new(bytes.Buffer)
_, err = io.Copy(buf, file)
bytesCopied, err := io.Copy(buf, file)
if err != nil {
log.Error().Str("file_path", filePath).Str("archive_file", path).Err(err).Msg("Failed to read page file contents")
return fmt.Errorf("failed to read file contents: %w", err)
}
@@ -113,14 +139,28 @@ func LoadChapter(filePath string) (*manga.Chapter, error) {
// Add the page to the chapter
chapter.Pages = append(chapter.Pages, page)
log.Debug().
Str("file_path", filePath).
Str("archive_file", path).
Uint16("page_index", page.Index).
Int64("bytes_read", bytesCopied).
Msg("Page loaded successfully")
}
return nil
}()
})
if err != nil {
log.Error().Str("file_path", filePath).Err(err).Msg("Failed during filesystem walk")
return nil, err
}
log.Debug().
Str("file_path", filePath).
Int("pages_loaded", len(chapter.Pages)).
Bool("is_converted", chapter.IsConverted).
Bool("has_comic_info", chapter.ComicInfoXml != "").
Msg("Chapter loading completed successfully")
return chapter, nil
}