v5.7-patch1

This commit is contained in:
afkarxyz
2025-11-23 04:58:45 +07:00
parent d1bd7da2de
commit 5831a45839
25 changed files with 405 additions and 199 deletions
+13 -6
View File
@@ -172,7 +172,7 @@ func sanitizeFilename(name string) string {
return sanitized
}
func buildFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool) string {
func buildFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool, position int) string {
var filename string
// Build base filename based on format
@@ -186,14 +186,15 @@ func buildFilename(title, artist string, trackNumber int, format string, include
}
// Add track number prefix if enabled
if includeTrackNumber && trackNumber > 0 {
filename = fmt.Sprintf("%02d. %s", trackNumber, filename)
// Only use track number for bulk downloads (when position > 0)
if includeTrackNumber && position > 0 {
filename = fmt.Sprintf("%02d. %s", position, filename)
}
return filename + ".flac"
}
func (d *DeezerDownloader) DownloadByISRC(isrc, outputDir, filenameFormat string, includeTrackNumber bool, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) error {
func (d *DeezerDownloader) DownloadByISRC(isrc, outputDir, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) error {
fmt.Printf("Fetching track info for ISRC: %s\n", isrc)
track, err := d.GetTrackByISRC(isrc)
@@ -241,7 +242,7 @@ func (d *DeezerDownloader) DownloadByISRC(isrc, outputDir, filenameFormat string
safeTitle := sanitizeFilename(trackTitle)
// Build filename based on format settings
filename := buildFilename(safeTitle, safeArtist, track.TrackPos, filenameFormat, includeTrackNumber)
filename := buildFilename(safeTitle, safeArtist, track.TrackPos, filenameFormat, includeTrackNumber, position)
filepath := filepath.Join(outputDir, filename)
fmt.Println("Downloading FLAC file...")
@@ -263,12 +264,18 @@ func (d *DeezerDownloader) DownloadByISRC(isrc, outputDir, filenameFormat string
}
fmt.Println("Embedding metadata and cover art...")
// Only use track number for bulk downloads (when position > 0)
trackNumberToEmbed := 0
if position > 0 {
trackNumberToEmbed = position
}
metadata := Metadata{
Title: trackTitle,
Artist: artists,
Album: albumTitle,
Date: track.ReleaseDate,
TrackNumber: track.TrackPos,
TrackNumber: trackNumberToEmbed,
DiscNumber: track.DiskNumber,
ISRC: track.ISRC,
}
+43 -1
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"io"
"sync"
"time"
)
// Global progress tracker
@@ -12,12 +13,15 @@ var (
currentProgressLock sync.RWMutex
isDownloading bool
downloadingLock sync.RWMutex
currentSpeed float64
speedLock sync.RWMutex
)
// ProgressInfo represents download progress information
type ProgressInfo struct {
IsDownloading bool `json:"is_downloading"`
MBDownloaded float64 `json:"mb_downloaded"`
SpeedMBps float64 `json:"speed_mbps"`
}
// GetDownloadProgress returns current download progress
@@ -30,12 +34,24 @@ func GetDownloadProgress() ProgressInfo {
progress := currentProgress
currentProgressLock.RUnlock()
speedLock.RLock()
speed := currentSpeed
speedLock.RUnlock()
return ProgressInfo{
IsDownloading: downloading,
MBDownloaded: progress,
SpeedMBps: speed,
}
}
// SetDownloadSpeed updates the current download speed
func SetDownloadSpeed(mbps float64) {
speedLock.Lock()
currentSpeed = mbps
speedLock.Unlock()
}
// SetDownloadProgress updates the current download progress
func SetDownloadProgress(mbDownloaded float64) {
currentProgressLock.Lock()
@@ -52,6 +68,7 @@ func SetDownloading(downloading bool) {
if !downloading {
// Reset progress when download completes
SetDownloadProgress(0)
SetDownloadSpeed(0)
}
}
@@ -60,16 +77,27 @@ type ProgressWriter struct {
writer io.Writer
total int64
lastPrinted int64
startTime int64
lastTime int64
lastBytes int64
}
func NewProgressWriter(writer io.Writer) *ProgressWriter {
now := getCurrentTimeMillis()
return &ProgressWriter{
writer: writer,
total: 0,
lastPrinted: 0,
startTime: now,
lastTime: now,
lastBytes: 0,
}
}
func getCurrentTimeMillis() int64 {
return time.Now().UnixMilli()
}
func (pw *ProgressWriter) Write(p []byte) (int, error) {
n, err := pw.writer.Write(p)
pw.total += int64(n)
@@ -77,12 +105,26 @@ func (pw *ProgressWriter) Write(p []byte) (int, error) {
// Report progress every 256KB for smoother updates
if pw.total-pw.lastPrinted >= 256*1024 {
mbDownloaded := float64(pw.total) / (1024 * 1024)
fmt.Printf("\rDownloaded: %.2f MB", mbDownloaded)
// Calculate speed (MB/s)
now := getCurrentTimeMillis()
timeDiff := float64(now-pw.lastTime) / 1000.0 // seconds
bytesDiff := float64(pw.total - pw.lastBytes)
if timeDiff > 0 {
speedMBps := (bytesDiff / (1024 * 1024)) / timeDiff
SetDownloadSpeed(speedMBps)
fmt.Printf("\rDownloaded: %.2f MB (%.2f MB/s)", mbDownloaded, speedMBps)
} else {
fmt.Printf("\rDownloaded: %.2f MB", mbDownloaded)
}
// Update global progress
SetDownloadProgress(mbDownloaded)
pw.lastPrinted = pw.total
pw.lastTime = now
pw.lastBytes = pw.total
}
return n, err
+13 -6
View File
@@ -222,7 +222,7 @@ func (q *QobuzDownloader) DownloadCoverArt(coverURL, filepath string) error {
return err
}
func buildQobuzFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool) string {
func buildQobuzFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool, position int) string {
var filename string
// Build base filename based on format
@@ -236,14 +236,15 @@ func buildQobuzFilename(title, artist string, trackNumber int, format string, in
}
// Add track number prefix if enabled
if includeTrackNumber && trackNumber > 0 {
filename = fmt.Sprintf("%02d. %s", trackNumber, filename)
// Only use track number for bulk downloads (when position > 0)
if includeTrackNumber && position > 0 {
filename = fmt.Sprintf("%02d. %s", position, filename)
}
return filename + ".flac"
}
func (q *QobuzDownloader) DownloadByISRC(isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) error {
func (q *QobuzDownloader) DownloadByISRC(isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) error {
fmt.Printf("Fetching track info for ISRC: %s\n", isrc)
// Create output directory if it doesn't exist
@@ -311,7 +312,7 @@ func (q *QobuzDownloader) DownloadByISRC(isrc, outputDir, quality, filenameForma
safeTitle := sanitizeFilename(trackTitle)
// Build filename based on format settings
filename := buildQobuzFilename(safeTitle, safeArtist, track.TrackNumber, filenameFormat, includeTrackNumber)
filename := buildQobuzFilename(safeTitle, safeArtist, track.TrackNumber, filenameFormat, includeTrackNumber, position)
filepath := filepath.Join(outputDir, filename)
fmt.Printf("Downloading FLAC file to: %s\n", filepath)
@@ -339,12 +340,18 @@ func (q *QobuzDownloader) DownloadByISRC(isrc, outputDir, quality, filenameForma
releaseYear = track.ReleaseDateOriginal[:4]
}
// Only use track number for bulk downloads (when position > 0)
trackNumberToEmbed := 0
if position > 0 {
trackNumberToEmbed = position
}
metadata := Metadata{
Title: trackTitle,
Artist: artists,
Album: albumTitle,
Date: releaseYear,
TrackNumber: track.TrackNumber,
TrackNumber: trackNumberToEmbed,
DiscNumber: track.MediaNumber,
ISRC: track.ISRC,
}
+15 -8
View File
@@ -333,7 +333,7 @@ func (t *TidalDownloader) DownloadFile(url, filepath string) error {
return nil
}
func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) (string, error) {
func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) (string, error) {
if outputDir != "." {
if err := os.MkdirAll(outputDir, 0755); err != nil {
return "", fmt.Errorf("directory error: %w", err)
@@ -386,7 +386,7 @@ func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameForm
}
// Build filename based on format settings
filename := buildTidalFilename(trackTitle, artistName, trackInfo.TrackNumber, filenameFormat, includeTrackNumber)
filename := buildTidalFilename(trackTitle, artistName, trackInfo.TrackNumber, filenameFormat, includeTrackNumber, position)
outputFilename := filepath.Join(outputDir, filename)
if fileInfo, err := os.Stat(outputFilename); err == nil && fileInfo.Size() > 0 {
@@ -427,12 +427,18 @@ func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameForm
releaseYear = trackInfo.Album.ReleaseDate[:4]
}
// Only use track number for bulk downloads (when position > 0)
trackNumberToEmbed := 0
if position > 0 {
trackNumberToEmbed = position
}
metadata := Metadata{
Title: trackTitle,
Artist: artistName,
Album: albumTitle,
Date: releaseYear,
TrackNumber: trackInfo.TrackNumber,
TrackNumber: trackNumberToEmbed,
DiscNumber: trackInfo.VolumeNumber,
ISRC: trackInfo.ISRC,
}
@@ -447,7 +453,7 @@ func (t *TidalDownloader) Download(query, isrc, outputDir, quality, filenameForm
return outputFilename, nil
}
func (t *TidalDownloader) DownloadWithFallback(query, isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) (string, error) {
func (t *TidalDownloader) DownloadWithFallback(query, isrc, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName string) (string, error) {
apis, err := t.GetAvailableAPIs()
if err != nil {
return "", fmt.Errorf("no APIs available for fallback: %w", err)
@@ -459,7 +465,7 @@ func (t *TidalDownloader) DownloadWithFallback(query, isrc, outputDir, quality,
fallbackDownloader := NewTidalDownloader(apiURL)
result, err := fallbackDownloader.Download(query, isrc, outputDir, quality, filenameFormat, includeTrackNumber, spotifyTrackName, spotifyArtistName, spotifyAlbumName)
result, err := fallbackDownloader.Download(query, isrc, outputDir, quality, filenameFormat, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName)
if err == nil {
fmt.Printf("✓ Success with: %s\n", apiURL)
return result, nil
@@ -476,7 +482,7 @@ func (t *TidalDownloader) DownloadWithFallback(query, isrc, outputDir, quality,
return "", fmt.Errorf("all %d APIs failed. Last error: %v", len(apis), lastError)
}
func buildTidalFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool) string {
func buildTidalFilename(title, artist string, trackNumber int, format string, includeTrackNumber bool, position int) string {
var filename string
// Build base filename based on format
@@ -490,8 +496,9 @@ func buildTidalFilename(title, artist string, trackNumber int, format string, in
}
// Add track number prefix if enabled
if includeTrackNumber && trackNumber > 0 {
filename = fmt.Sprintf("%02d. %s", trackNumber, filename)
// Only use track number for bulk downloads (when position > 0)
if includeTrackNumber && position > 0 {
filename = fmt.Sprintf("%02d. %s", position, filename)
}
return filename + ".flac"