diff --git a/index.html b/index.html index 2d293f6..f20a3ca 100644 --- a/index.html +++ b/index.html @@ -13,7 +13,7 @@

找到你想听的音乐

搜索歌曲、歌手或专辑,加入下载队列即可。

最近下载
下载队列
任务会自动处理,完成后可在本地下载目录找到文件。
-

音乐 API

用于搜索和解析音乐资源,与 Downloader Web 服务分离。

当前服务架构:Downloader Web 使用 9540,音乐 API 使用 9530。

下载

设置文件保存位置与默认音质。

WebDAV

可选的 NAS/远程音乐库同步配置。

+

音乐 API

用于搜索和解析音乐资源,与 Downloader Web 服务分离。

当前服务架构:Downloader Web 使用 9540,音乐 API 使用 9530。

下载

设置文件保存位置与默认音质。

WebDAV

可选的 NAS/远程音乐库同步配置。

“清理旧低音质”只删除数据库中已确认属于同一首歌、且音质低于当前版本的旧 WebDAV 文件,不会扫描或删除未知文件。
diff --git a/main.go b/main.go index 237411a..4ad9f81 100644 --- a/main.go +++ b/main.go @@ -59,8 +59,8 @@ type SongRequest struct { Quality string `json:"quality"` } type Config struct { - AMAPI, DownloadDir, WebDAVURL, WebDAVUser, WebDAVPass, WebDAVPath, DefaultQuality string - WorkerCount int + AMAPI, DownloadDir, WebDAVURL, WebDAVUser, WebDAVPass, WebDAVPath, DefaultQuality, WebDAVVersionPolicy string + WorkerCount int } type App struct { db *gorm.DB @@ -86,6 +86,9 @@ func main() { a := &App{db: db, cfg: Config{AMAPI: getenv("AM_API_URL", "http://127.0.0.1:9530/api"), DownloadDir: getenv("DOWNLOAD_DIR", "/downloads"), DefaultQuality: getenv("DEFAULT_QUALITY", "standard"), WorkerCount: atoi(getenv("WORKERS", "2"), 2)}, queue: make(chan uint, 100), httpClient: &http.Client{Timeout: 2 * time.Minute}} _ = os.MkdirAll(a.cfg.DownloadDir, 0755) a.loadSettings() + if a.cfg.WebDAVVersionPolicy == "" { + a.cfg.WebDAVVersionPolicy = "keep" + } a.startWorkers() r := gin.Default() r.StaticFile("/", "/app/index.html") @@ -120,6 +123,8 @@ func (a *App) loadSettings() { a.cfg.WebDAVPath = s.Value case "quality": a.cfg.DefaultQuality = s.Value + case "webdav_version_policy": + a.cfg.WebDAVVersionPolicy = s.Value } } } @@ -442,10 +447,44 @@ func (a *App) upload(t *Task) { a.fail(t, err) return } + if a.cfg.WebDAVVersionPolicy == "replace_lower" { + a.removeLowerQualityVersions(client, remote, t) + } t.Status = "done" t.Progress = 100 a.db.Save(t) } +func (a *App) removeLowerQualityVersions(client *gowebdav.Client, remote string, t *Task) { + levels := map[string]int{"standard": 1, "exhigh": 2, "sq": 3, "lossless": 4, "hires": 5, "jyeffect": 6, "sky": 7, "jymaster": 8, "atmos": 9, "atmos_plus": 10, "master": 11} + current := levels[t.ActualQuality] + if current == 0 { + current = levels[t.ResolvedQuality] + } + if current == 0 { + current = levels[t.Quality] + } + if current == 0 { + return + } + var old []Task + a.db.Where("artist = ? AND title = ? AND album = ? AND status = ? AND id <> ?", t.Artist, t.Title, t.Album, "done", t.ID).Find(&old) + for _, candidate := range old { + q := candidate.ActualQuality + if q == "" { + q = candidate.ResolvedQuality + } + if q == "" { + q = candidate.Quality + } + if levels[q] <= 0 || levels[q] >= current || candidate.RemotePath == "" || candidate.RemotePath == remote { + continue + } + if _, err := client.Stat(candidate.RemotePath); err == nil { + _ = client.Remove(candidate.RemotePath) + } + } +} + func (a *App) fail(t *Task, err error) { if t.LocalPath != "" { _ = os.Remove(t.LocalPath + ".part") @@ -456,7 +495,7 @@ func (a *App) fail(t *Task, err error) { } func (a *App) getSettings(c *gin.Context) { - c.JSON(200, gin.H{"amApi": a.cfg.AMAPI, "downloadDir": a.cfg.DownloadDir, "webdavUrl": a.cfg.WebDAVURL, "webdavUser": a.cfg.WebDAVUser, "webdavPass": a.cfg.WebDAVPass, "webdavPath": a.cfg.WebDAVPath, "quality": a.cfg.DefaultQuality}) + c.JSON(200, gin.H{"amApi": a.cfg.AMAPI, "downloadDir": a.cfg.DownloadDir, "webdavUrl": a.cfg.WebDAVURL, "webdavUser": a.cfg.WebDAVUser, "webdavPass": a.cfg.WebDAVPass, "webdavPath": a.cfg.WebDAVPath, "quality": a.cfg.DefaultQuality, "webdavVersionPolicy": a.cfg.WebDAVVersionPolicy}) } func (a *App) putSettings(c *gin.Context) { var v map[string]string @@ -468,6 +507,9 @@ func (a *App) putSettings(c *gin.Context) { a.cfg.AMAPI = x a.save("am_api", x) } + if p := v["webdavVersionPolicy"]; p != "keep" && p != "replace_lower" { + v["webdavVersionPolicy"] = "keep" + } if x := v["downloadDir"]; x != "" { a.cfg.DownloadDir = x a.save("download_dir", x) @@ -478,7 +520,10 @@ func (a *App) putSettings(c *gin.Context) { a.cfg.WebDAVPass = v["webdavPass"] a.cfg.WebDAVPath = strings.Trim(v["webdavPath"], "/") a.cfg.DefaultQuality = v["quality"] - for k, x := range map[string]string{"webdav_url": a.cfg.WebDAVURL, "webdav_user": a.cfg.WebDAVUser, "webdav_pass": a.cfg.WebDAVPass, "webdav_path": a.cfg.WebDAVPath, "quality": a.cfg.DefaultQuality} { + if p := v["webdavVersionPolicy"]; p == "keep" || p == "replace_lower" { + a.cfg.WebDAVVersionPolicy = p + } + for k, x := range map[string]string{"webdav_url": a.cfg.WebDAVURL, "webdav_user": a.cfg.WebDAVUser, "webdav_pass": a.cfg.WebDAVPass, "webdav_path": a.cfg.WebDAVPath, "quality": a.cfg.DefaultQuality, "webdav_version_policy": a.cfg.WebDAVVersionPolicy} { a.save(k, x) } c.JSON(200, gin.H{"ok": true})