.clean up the code
This commit is contained in:
@@ -1,419 +0,0 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DownloadStatus string
|
||||
|
||||
const (
|
||||
StatusQueued DownloadStatus = "queued"
|
||||
StatusDownloading DownloadStatus = "downloading"
|
||||
StatusCompleted DownloadStatus = "completed"
|
||||
StatusFailed DownloadStatus = "failed"
|
||||
StatusSkipped DownloadStatus = "skipped"
|
||||
)
|
||||
|
||||
type DownloadItem struct {
|
||||
ID string `json:"id"`
|
||||
TrackName string `json:"track_name"`
|
||||
ArtistName string `json:"artist_name"`
|
||||
AlbumName string `json:"album_name"`
|
||||
SpotifyID string `json:"spotify_id"`
|
||||
Status DownloadStatus `json:"status"`
|
||||
Progress float64 `json:"progress"`
|
||||
TotalSize float64 `json:"total_size"`
|
||||
Speed float64 `json:"speed"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
ErrorMessage string `json:"error_message"`
|
||||
FilePath string `json:"file_path"`
|
||||
}
|
||||
|
||||
var (
|
||||
currentProgress float64
|
||||
currentProgressLock sync.RWMutex
|
||||
isDownloading bool
|
||||
downloadingLock sync.RWMutex
|
||||
currentSpeed float64
|
||||
speedLock sync.RWMutex
|
||||
|
||||
downloadQueue []DownloadItem
|
||||
downloadQueueLock sync.RWMutex
|
||||
currentItemID string
|
||||
currentItemLock sync.RWMutex
|
||||
totalDownloaded float64
|
||||
totalDownloadedLock sync.RWMutex
|
||||
sessionStartTime int64
|
||||
sessionStartLock sync.RWMutex
|
||||
)
|
||||
|
||||
type ProgressInfo struct {
|
||||
IsDownloading bool `json:"is_downloading"`
|
||||
MBDownloaded float64 `json:"mb_downloaded"`
|
||||
SpeedMBps float64 `json:"speed_mbps"`
|
||||
}
|
||||
|
||||
type DownloadQueueInfo struct {
|
||||
IsDownloading bool `json:"is_downloading"`
|
||||
Queue []DownloadItem `json:"queue"`
|
||||
CurrentSpeed float64 `json:"current_speed"`
|
||||
TotalDownloaded float64 `json:"total_downloaded"`
|
||||
SessionStartTime int64 `json:"session_start_time"`
|
||||
QueuedCount int `json:"queued_count"`
|
||||
CompletedCount int `json:"completed_count"`
|
||||
FailedCount int `json:"failed_count"`
|
||||
SkippedCount int `json:"skipped_count"`
|
||||
}
|
||||
|
||||
func GetDownloadProgress() ProgressInfo {
|
||||
downloadingLock.RLock()
|
||||
downloading := isDownloading
|
||||
downloadingLock.RUnlock()
|
||||
|
||||
currentProgressLock.RLock()
|
||||
progress := currentProgress
|
||||
currentProgressLock.RUnlock()
|
||||
|
||||
speedLock.RLock()
|
||||
speed := currentSpeed
|
||||
speedLock.RUnlock()
|
||||
|
||||
return ProgressInfo{
|
||||
IsDownloading: downloading,
|
||||
MBDownloaded: progress,
|
||||
SpeedMBps: speed,
|
||||
}
|
||||
}
|
||||
|
||||
func SetDownloadSpeed(mbps float64) {
|
||||
speedLock.Lock()
|
||||
currentSpeed = mbps
|
||||
speedLock.Unlock()
|
||||
}
|
||||
|
||||
func SetDownloadProgress(mbDownloaded float64) {
|
||||
currentProgressLock.Lock()
|
||||
currentProgress = mbDownloaded
|
||||
currentProgressLock.Unlock()
|
||||
}
|
||||
|
||||
func SetDownloading(downloading bool) {
|
||||
downloadingLock.Lock()
|
||||
isDownloading = downloading
|
||||
downloadingLock.Unlock()
|
||||
|
||||
if !downloading {
|
||||
|
||||
SetDownloadProgress(0)
|
||||
SetDownloadSpeed(0)
|
||||
}
|
||||
}
|
||||
|
||||
type ProgressWriter struct {
|
||||
writer io.Writer
|
||||
total int64
|
||||
lastPrinted int64
|
||||
startTime int64
|
||||
lastTime int64
|
||||
lastBytes int64
|
||||
itemID string
|
||||
}
|
||||
|
||||
func NewProgressWriter(writer io.Writer) *ProgressWriter {
|
||||
now := getCurrentTimeMillis()
|
||||
return &ProgressWriter{
|
||||
writer: writer,
|
||||
total: 0,
|
||||
lastPrinted: 0,
|
||||
startTime: now,
|
||||
lastTime: now,
|
||||
lastBytes: 0,
|
||||
itemID: "",
|
||||
}
|
||||
}
|
||||
|
||||
func NewProgressWriterWithID(writer io.Writer, itemID string) *ProgressWriter {
|
||||
pw := NewProgressWriter(writer)
|
||||
pw.itemID = itemID
|
||||
return pw
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
if pw.total-pw.lastPrinted >= 256*1024 {
|
||||
mbDownloaded := float64(pw.total) / (1024 * 1024)
|
||||
|
||||
now := getCurrentTimeMillis()
|
||||
timeDiff := float64(now-pw.lastTime) / 1000.0
|
||||
bytesDiff := float64(pw.total - pw.lastBytes)
|
||||
|
||||
var speedMBps float64
|
||||
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)
|
||||
}
|
||||
|
||||
SetDownloadProgress(mbDownloaded)
|
||||
|
||||
if pw.itemID != "" {
|
||||
UpdateItemProgress(pw.itemID, mbDownloaded, speedMBps)
|
||||
}
|
||||
|
||||
pw.lastPrinted = pw.total
|
||||
pw.lastTime = now
|
||||
pw.lastBytes = pw.total
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (pw *ProgressWriter) GetTotal() int64 {
|
||||
return pw.total
|
||||
}
|
||||
|
||||
func AddToQueue(id, trackName, artistName, albumName, spotifyID string) {
|
||||
downloadQueueLock.Lock()
|
||||
defer downloadQueueLock.Unlock()
|
||||
|
||||
item := DownloadItem{
|
||||
ID: id,
|
||||
TrackName: trackName,
|
||||
ArtistName: artistName,
|
||||
AlbumName: albumName,
|
||||
SpotifyID: spotifyID,
|
||||
Status: StatusQueued,
|
||||
Progress: 0,
|
||||
TotalSize: 0,
|
||||
Speed: 0,
|
||||
StartTime: 0,
|
||||
EndTime: 0,
|
||||
}
|
||||
|
||||
downloadQueue = append(downloadQueue, item)
|
||||
|
||||
sessionStartLock.Lock()
|
||||
if sessionStartTime == 0 {
|
||||
sessionStartTime = time.Now().Unix()
|
||||
}
|
||||
sessionStartLock.Unlock()
|
||||
}
|
||||
|
||||
func StartDownloadItem(id string) {
|
||||
downloadQueueLock.Lock()
|
||||
defer downloadQueueLock.Unlock()
|
||||
|
||||
for i := range downloadQueue {
|
||||
if downloadQueue[i].ID == id {
|
||||
downloadQueue[i].Status = StatusDownloading
|
||||
downloadQueue[i].StartTime = time.Now().Unix()
|
||||
downloadQueue[i].Progress = 0
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
currentItemLock.Lock()
|
||||
currentItemID = id
|
||||
currentItemLock.Unlock()
|
||||
}
|
||||
|
||||
func UpdateItemProgress(id string, progress, speed float64) {
|
||||
downloadQueueLock.Lock()
|
||||
defer downloadQueueLock.Unlock()
|
||||
|
||||
for i := range downloadQueue {
|
||||
if downloadQueue[i].ID == id {
|
||||
downloadQueue[i].Progress = progress
|
||||
downloadQueue[i].Speed = speed
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetCurrentItemID() string {
|
||||
currentItemLock.RLock()
|
||||
defer currentItemLock.RUnlock()
|
||||
return currentItemID
|
||||
}
|
||||
|
||||
func CompleteDownloadItem(id, filePath string, finalSize float64) {
|
||||
downloadQueueLock.Lock()
|
||||
defer downloadQueueLock.Unlock()
|
||||
|
||||
for i := range downloadQueue {
|
||||
if downloadQueue[i].ID == id {
|
||||
downloadQueue[i].Status = StatusCompleted
|
||||
downloadQueue[i].EndTime = time.Now().Unix()
|
||||
downloadQueue[i].FilePath = filePath
|
||||
downloadQueue[i].Progress = finalSize
|
||||
downloadQueue[i].TotalSize = finalSize
|
||||
|
||||
totalDownloadedLock.Lock()
|
||||
totalDownloaded += finalSize
|
||||
totalDownloadedLock.Unlock()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FailDownloadItem(id, errorMsg string) {
|
||||
downloadQueueLock.Lock()
|
||||
defer downloadQueueLock.Unlock()
|
||||
|
||||
for i := range downloadQueue {
|
||||
if downloadQueue[i].ID == id {
|
||||
downloadQueue[i].Status = StatusFailed
|
||||
downloadQueue[i].EndTime = time.Now().Unix()
|
||||
downloadQueue[i].ErrorMessage = errorMsg
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SkipDownloadItem(id, filePath string) {
|
||||
downloadQueueLock.Lock()
|
||||
defer downloadQueueLock.Unlock()
|
||||
|
||||
for i := range downloadQueue {
|
||||
if downloadQueue[i].ID == id {
|
||||
downloadQueue[i].Status = StatusSkipped
|
||||
downloadQueue[i].EndTime = time.Now().Unix()
|
||||
downloadQueue[i].FilePath = filePath
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetDownloadQueue() DownloadQueueInfo {
|
||||
|
||||
ResetSessionIfComplete()
|
||||
|
||||
downloadQueueLock.RLock()
|
||||
defer downloadQueueLock.RUnlock()
|
||||
|
||||
downloadingLock.RLock()
|
||||
downloading := isDownloading
|
||||
downloadingLock.RUnlock()
|
||||
|
||||
speedLock.RLock()
|
||||
speed := currentSpeed
|
||||
speedLock.RUnlock()
|
||||
|
||||
totalDownloadedLock.RLock()
|
||||
total := totalDownloaded
|
||||
totalDownloadedLock.RUnlock()
|
||||
|
||||
sessionStartLock.RLock()
|
||||
sessionStart := sessionStartTime
|
||||
sessionStartLock.RUnlock()
|
||||
|
||||
var queued, completed, failed, skipped int
|
||||
for _, item := range downloadQueue {
|
||||
switch item.Status {
|
||||
case StatusQueued:
|
||||
queued++
|
||||
case StatusCompleted:
|
||||
completed++
|
||||
case StatusFailed:
|
||||
failed++
|
||||
case StatusSkipped:
|
||||
skipped++
|
||||
}
|
||||
}
|
||||
|
||||
queueCopy := make([]DownloadItem, len(downloadQueue))
|
||||
copy(queueCopy, downloadQueue)
|
||||
|
||||
return DownloadQueueInfo{
|
||||
IsDownloading: downloading,
|
||||
Queue: queueCopy,
|
||||
CurrentSpeed: speed,
|
||||
TotalDownloaded: total,
|
||||
SessionStartTime: sessionStart,
|
||||
QueuedCount: queued,
|
||||
CompletedCount: completed,
|
||||
FailedCount: failed,
|
||||
SkippedCount: skipped,
|
||||
}
|
||||
}
|
||||
|
||||
func ClearDownloadQueue() {
|
||||
downloadQueueLock.Lock()
|
||||
defer downloadQueueLock.Unlock()
|
||||
|
||||
newQueue := make([]DownloadItem, 0)
|
||||
for _, item := range downloadQueue {
|
||||
if item.Status == StatusQueued || item.Status == StatusDownloading {
|
||||
newQueue = append(newQueue, item)
|
||||
}
|
||||
}
|
||||
downloadQueue = newQueue
|
||||
}
|
||||
|
||||
func ClearAllDownloads() {
|
||||
downloadQueueLock.Lock()
|
||||
downloadQueue = []DownloadItem{}
|
||||
downloadQueueLock.Unlock()
|
||||
|
||||
totalDownloadedLock.Lock()
|
||||
totalDownloaded = 0
|
||||
totalDownloadedLock.Unlock()
|
||||
|
||||
sessionStartLock.Lock()
|
||||
sessionStartTime = 0
|
||||
sessionStartLock.Unlock()
|
||||
|
||||
currentItemLock.Lock()
|
||||
currentItemID = ""
|
||||
currentItemLock.Unlock()
|
||||
|
||||
SetDownloadProgress(0)
|
||||
SetDownloadSpeed(0)
|
||||
}
|
||||
|
||||
func CancelAllQueuedItems() {
|
||||
downloadQueueLock.Lock()
|
||||
defer downloadQueueLock.Unlock()
|
||||
|
||||
for i := range downloadQueue {
|
||||
if downloadQueue[i].Status == StatusQueued {
|
||||
downloadQueue[i].Status = StatusSkipped
|
||||
downloadQueue[i].EndTime = time.Now().Unix()
|
||||
downloadQueue[i].ErrorMessage = "Cancelled"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ResetSessionIfComplete() {
|
||||
downloadQueueLock.RLock()
|
||||
hasActiveOrQueued := false
|
||||
for _, item := range downloadQueue {
|
||||
if item.Status == StatusQueued || item.Status == StatusDownloading {
|
||||
hasActiveOrQueued = true
|
||||
break
|
||||
}
|
||||
}
|
||||
downloadQueueLock.RUnlock()
|
||||
|
||||
if !hasActiveOrQueued {
|
||||
sessionStartLock.Lock()
|
||||
sessionStartTime = 0
|
||||
sessionStartLock.Unlock()
|
||||
|
||||
totalDownloadedLock.Lock()
|
||||
totalDownloaded = 0
|
||||
totalDownloadedLock.Unlock()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user