package main import ( "context" "flag" "fmt" "log/slog" "os" "os/signal" "syscall" "ym-dl/internal/config" "ym-dl/internal/downloader" "ym-dl/internal/monitor" "ym-dl/internal/storage" "ym-dl/internal/yandex" ) func main() { configPath := flag.String("config", "config.yaml", "Path to config file") flag.Parse() // Load configuration cfg, err := config.Load(*configPath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to load config: %v\n", err) os.Exit(1) } // Setup logger logLevel := slog.LevelInfo if cfg.Debug { logLevel = slog.LevelDebug } logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ Level: logLevel, })) slog.SetDefault(logger) // Create Yandex client yandexClient, err := yandex.NewYandexClient(&cfg.Yandex, cfg.Debug) if err != nil { logger.Error("Failed to create Yandex client", "error", err) os.Exit(1) } // Create storage store, err := storage.NewStorage(cfg.Storage.Path, cfg.Storage.Organize) if err != nil { logger.Error("Failed to create storage", "error", err) os.Exit(1) } // Create downloader dl := downloader.NewDownloader(yandexClient, store) // Create monitor mon := monitor.NewMonitor(cfg, yandexClient, store, dl, logger) // Setup context with signal handling ctx, cancel := context.WithCancel(context.Background()) defer cancel() sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) go func() { <-sigCh logger.Info("Shutdown signal received") cancel() mon.Stop() if err := store.Close(); err != nil { logger.Error("Failed to close storage", "error", err) } }() // Start monitor if err := mon.Start(ctx); err != nil { logger.Error("Failed to start monitor", "error", err) os.Exit(1) } logger.Info("ym-dl started", "artists", len(cfg.Artists), "storage", cfg.Storage.Path) // Wait for context cancellation <-ctx.Done() mon.Stop() if err := store.Close(); err != nil { logger.Error("Failed to close storage", "error", err) } logger.Info("ym-dl stopped") }