package downloader import ( "fmt" "math/rand" "os" "time" "github.com/briandowns/spinner" "github.com/mathismqn/godeez/internal/deezer" "github.com/mathismqn/godeez/internal/logger" ) type downloadResult struct { skipped bool path string warnings []string err error } type downloadStats struct { downloaded int skipped int failed int warnings int } type progressTracker struct { logger *logger.Logger stats downloadStats totalSongs int resourceType string } func newProgressTracker(logger *logger.Logger, totalSongs int, resourceType string) *progressTracker { return &progressTracker{ logger: logger, totalSongs: totalSongs, resourceType: resourceType, } } func (pt *progressTracker) startDownload(index int, song *deezer.Song) *spinner.Spinner { trackProgress := fmt.Sprintf("[%d/%d]", index+1, pt.totalSongs) sp := spinner.New(spinner.CharSets[14], 100*time.Millisecond) sp.Writer = os.Stdout sp.Prefix = trackProgress + " " sp.Suffix = fmt.Sprintf(" Downloading: %s - %s", song.Artist, song.GetTitle()) sp.Start() return sp } func (pt *progressTracker) handleResult(index int, song *deezer.Song, result downloadResult) { trackProgress := fmt.Sprintf("[%d/%d]", index+1, pt.totalSongs) songTitle := song.GetTitle() if result.skipped { pt.stats.skipped++ fmt.Printf("%s ↷ Skipped: %s - %s\n Already exists at: %s\n", trackProgress, song.Artist, songTitle, result.path) return } if result.err != nil { pt.stats.failed++ pt.logger.Errorf("Failed to download %s - %s: %v\n", song.Artist, songTitle, result.err) fmt.Printf("%s āœ– Failed: %s - %s:\n Error: %v\n", trackProgress, song.Artist, songTitle, result.err) return } pt.stats.downloaded++ if len(result.warnings) > 0 { pt.stats.warnings++ } pt.logger.Infof("Downloaded %s - %s\n", song.Artist, songTitle) symbol := "āœ”" if len(result.warnings) > 0 { symbol = "⚠" } fmt.Printf("%s %s Downloaded: %s - %s\n", trackProgress, symbol, song.Artist, songTitle) for _, w := range result.warnings { pt.logger.Warnf("Warning: %s\n", w) fmt.Printf(" Warning: %s\n", w) } } func (pt *progressTracker) printSummary(resourceTitle, resourceID, outputDir string, elapsed time.Duration) { if pt.stats.downloaded > 0 || pt.stats.failed > 0 { pt.logger.Infof("Resource %s (%s): %d downloaded, %d skipped, %d failed\n", resourceTitle, resourceID, pt.stats.downloaded, pt.stats.skipped, pt.stats.failed) } if pt.resourceType != "track" { warningsLine := "" if pt.stats.warnings > 0 { warningsLine = fmt.Sprintf("\nWarnings: %d", pt.stats.warnings) } fmt.Printf(` ================== [ Summary ] ================== Downloaded: %d Skipped: %d Failed: %d%s Elapsed time: %s Files saved to: %s ================================================= `, pt.stats.downloaded, pt.stats.skipped, pt.stats.failed, warningsLine, elapsed.Round(time.Second), outputDir, ) if pt.stats.downloaded > 0 { pt.showSupportMessage() } } } func (pt *progressTracker) showSupportMessage() { if rand.Float64() < 0.1 { fmt.Printf("\nšŸ’– Enjoying GoDeez? Give us a ⭐ on GitHub: https://github.com/mathismqn/godeez\n") } }