Создана структура документации, описывающая функциональность, установку, использование CLI, архитектуру и интеграции с TorrAPI и OpenRouter. Добавлены примеры конфигурации и метаданных, а также описание структуры выходных данных.
163 lines
4.8 KiB
Go
163 lines
4.8 KiB
Go
// Package presentation реализует порт ProcessLogger —
|
||
// детальное логирование процесса обработки аудиокниг в консоль.
|
||
package presentation
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"sync"
|
||
|
||
"github.com/fofanov/genaudiobookinfo/internal/domain"
|
||
"github.com/schollz/progressbar/v3"
|
||
)
|
||
|
||
// ConsoleLogger реализует domain.ProcessLogger для вывода логов в консоль.
|
||
type ConsoleLogger struct {
|
||
mu sync.Mutex // защита от гонок при параллельном логировании
|
||
bar *progressbar.ProgressBar
|
||
}
|
||
|
||
// NewConsoleLogger создаёт новый экземпляр логгера.
|
||
func NewConsoleLogger() *ConsoleLogger {
|
||
return &ConsoleLogger{}
|
||
}
|
||
|
||
// NewConsoleLoggerWithProgress создаёт логгер с progress bar.
|
||
func NewConsoleLoggerWithProgress(total int) *ConsoleLogger {
|
||
bar := progressbar.NewOptions(total,
|
||
progressbar.OptionSetDescription("Обработка аудиокниг"),
|
||
progressbar.OptionSetWriter(os.Stderr),
|
||
progressbar.OptionSetWidth(40),
|
||
progressbar.OptionShowCount(),
|
||
progressbar.OptionShowIts(),
|
||
progressbar.OptionSetPredictTime(true),
|
||
progressbar.OptionSetTheme(progressbar.Theme{
|
||
Saucer: "=",
|
||
SaucerHead: ">",
|
||
SaucerPadding: " ",
|
||
BarStart: "[",
|
||
BarEnd: "]",
|
||
}),
|
||
progressbar.OptionOnCompletion(func() {
|
||
fmt.Fprintln(os.Stderr)
|
||
}),
|
||
)
|
||
return &ConsoleLogger{
|
||
bar: bar,
|
||
}
|
||
}
|
||
|
||
// LogStart логирует начало обработки книги.
|
||
func (l *ConsoleLogger) LogStart(folderName string) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar == nil {
|
||
fmt.Printf("\n📁 Обработка: %s\n", folderName)
|
||
}
|
||
// С progressbar не меняем описание — с N воркерами оно мерцает
|
||
}
|
||
|
||
// LogExtraction логирует этап извлечения метаданных.
|
||
func (l *ConsoleLogger) LogExtraction() {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar == nil {
|
||
fmt.Println(" 🎵 Извлечение метаданных...")
|
||
}
|
||
}
|
||
|
||
// LogLLMValidation логирует этап валидации через LLM.
|
||
func (l *ConsoleLogger) LogLLMValidation() {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar == nil {
|
||
fmt.Println(" 🤖 Валидация через LLM...")
|
||
}
|
||
}
|
||
|
||
// LogSearch логирует этап поиска на трекерах.
|
||
func (l *ConsoleLogger) LogSearch() {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar == nil {
|
||
fmt.Println(" 🔍 Поиск на трекерах...")
|
||
}
|
||
}
|
||
|
||
// LogWrite логирует этап записи результата.
|
||
func (l *ConsoleLogger) LogWrite() {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar == nil {
|
||
fmt.Println(" 💾 Запись результата...")
|
||
}
|
||
}
|
||
|
||
// LogCoverDownload логирует этап скачивания обложки.
|
||
func (l *ConsoleLogger) LogCoverDownload() {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar == nil {
|
||
fmt.Println(" 🖼️ Скачивание обложки...")
|
||
}
|
||
}
|
||
|
||
// LogComplete логирует успешное завершение обработки книги.
|
||
func (l *ConsoleLogger) LogComplete(folderName string) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar != nil {
|
||
l.bar.Add(1)
|
||
} else {
|
||
fmt.Printf(" ✅ Завершено: %s\n", folderName)
|
||
}
|
||
}
|
||
|
||
// LogError логирует ошибку обработки.
|
||
func (l *ConsoleLogger) LogError(folderName string, err error) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar != nil {
|
||
l.bar.Add(1)
|
||
// Пишем ошибку в stderr (туда же, куда и progressbar), чтобы не ломать вывод
|
||
fmt.Fprintf(os.Stderr, "\n ❌ Ошибка [%s]: %v\n", folderName, err)
|
||
} else {
|
||
fmt.Printf(" ❌ Ошибка [%s]: %v\n", folderName, err)
|
||
}
|
||
}
|
||
|
||
// LogWarning логирует предупреждение.
|
||
func (l *ConsoleLogger) LogWarning(message string) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar != nil {
|
||
// Выводим предупреждения в stderr, чтобы они не терялись
|
||
fmt.Fprintf(os.Stderr, "\n ⚠️ %s\n", message)
|
||
} else {
|
||
fmt.Printf(" ⚠️ %s\n", message)
|
||
}
|
||
}
|
||
|
||
// LogInfo логирует информационное сообщение (штатное событие, не ошибка).
|
||
func (l *ConsoleLogger) LogInfo(message string) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar != nil {
|
||
fmt.Fprintf(os.Stderr, "\n ℹ️ %s\n", message)
|
||
} else {
|
||
fmt.Printf(" ℹ️ %s\n", message)
|
||
}
|
||
}
|
||
|
||
// Finish завершает работу progressbar (если есть).
|
||
func (l *ConsoleLogger) Finish() {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
if l.bar != nil {
|
||
l.bar.Finish()
|
||
}
|
||
}
|
||
|
||
// Проверка во время компиляции, что ConsoleLogger реализует domain.ProcessLogger
|
||
var _ domain.ProcessLogger = (*ConsoleLogger)(nil)
|