feat: allow for custom music folder path alias

closes #259
This commit is contained in:
sentriz
2022-11-21 20:17:55 +00:00
parent 92a73b2d61
commit 7e097c9bdf
6 changed files with 81 additions and 32 deletions

View File

@@ -9,6 +9,7 @@ import (
"log" "log"
"os" "os"
"path" "path"
"path/filepath"
"regexp" "regexp"
"strings" "strings"
"time" "time"
@@ -20,6 +21,7 @@ import (
"go.senan.xyz/gonic" "go.senan.xyz/gonic"
"go.senan.xyz/gonic/db" "go.senan.xyz/gonic/db"
"go.senan.xyz/gonic/paths"
"go.senan.xyz/gonic/server" "go.senan.xyz/gonic/server"
) )
@@ -48,7 +50,7 @@ func main() {
confHTTPLog := set.Bool("http-log", true, "http request logging (optional)") confHTTPLog := set.Bool("http-log", true, "http request logging (optional)")
confShowVersion := set.Bool("version", false, "show gonic version") confShowVersion := set.Bool("version", false, "show gonic version")
var confMusicPaths musicPaths var confMusicPaths paths.MusicPaths
set.Var(&confMusicPaths, "music-path", "path to music") set.Var(&confMusicPaths, "music-path", "path to music")
_ = set.String("config-path", "", "path to config (optional)") _ = set.String("config-path", "", "path to config (optional)")
@@ -77,8 +79,8 @@ func main() {
log.Fatalf("please provide a music directory") log.Fatalf("please provide a music directory")
} }
for _, confMusicPath := range confMusicPaths { for _, confMusicPath := range confMusicPaths {
if _, err := os.Stat(confMusicPath); os.IsNotExist(err) { if _, err := os.Stat(confMusicPath.Path); os.IsNotExist(err) {
log.Fatalf("music directory %q not found", confMusicPath) log.Fatalf("music directory %q not found", confMusicPath.Path)
} }
} }
if _, err := os.Stat(*confPodcastPath); os.IsNotExist(err) { if _, err := os.Stat(*confPodcastPath); os.IsNotExist(err) {
@@ -109,7 +111,7 @@ func main() {
defer dbc.Close() defer dbc.Close()
err = dbc.Migrate(db.MigrationContext{ err = dbc.Migrate(db.MigrationContext{
OriginalMusicPath: confMusicPaths[0], OriginalMusicPath: confMusicPaths[0].Path,
}) })
if err != nil { if err != nil {
log.Panicf("error migrating database: %v\n", err) log.Panicf("error migrating database: %v\n", err)
@@ -120,11 +122,11 @@ func main() {
server, err := server.New(server.Options{ server, err := server.New(server.Options{
DB: dbc, DB: dbc,
MusicPaths: confMusicPaths, MusicPaths: confMusicPaths,
CachePath: cacheDirAudio, CachePath: filepath.Clean(cacheDirAudio),
CoverCachePath: cacheDirCovers, CoverCachePath: cacheDirCovers,
ProxyPrefix: *confProxyPrefix, ProxyPrefix: *confProxyPrefix,
GenreSplit: *confGenreSplit, GenreSplit: *confGenreSplit,
PodcastPath: *confPodcastPath, PodcastPath: filepath.Clean(*confPodcastPath),
HTTPLog: *confHTTPLog, HTTPLog: *confHTTPLog,
JukeboxEnabled: *confJukeboxEnabled, JukeboxEnabled: *confJukeboxEnabled,
}) })
@@ -158,14 +160,3 @@ func main() {
log.Panicf("error in job: %v", err) log.Panicf("error in job: %v", err)
} }
} }
type musicPaths []string
func (m musicPaths) String() string {
return strings.Join(m, ", ")
}
func (m *musicPaths) Set(value string) error {
*m = append(*m, value)
return nil
}

61
paths/paths.go Normal file
View File

@@ -0,0 +1,61 @@
package paths
import (
"fmt"
"path/filepath"
"strings"
)
const sep = "->"
type MusicPaths []MusicPath
func (mps MusicPaths) String() string {
var strs []string
for _, path := range mps {
strs = append(strs, path.String())
}
return strings.Join(strs, ", ")
}
func (mps *MusicPaths) Set(value string) error {
alias, path, ok := strings.Cut(value, sep)
if !ok {
*mps = append(*mps, MusicPath{
Path: filepath.Clean(strings.TrimSpace(value)),
})
return nil
}
*mps = append(*mps, MusicPath{
Alias: strings.TrimSpace(alias),
Path: filepath.Clean(strings.TrimSpace(path)),
})
return nil
}
func (mps MusicPaths) Paths() []string {
var paths []string
for _, mp := range mps {
paths = append(paths, mp.Path)
}
return paths
}
type MusicPath struct {
Alias string
Path string
}
func (mp MusicPath) String() string {
if mp.Alias == "" {
return mp.Path
}
return fmt.Sprintf("%s %s %s", mp.Alias, sep, mp.Path)
}
func (mp MusicPath) DisplayAlias() string {
if mp.Alias == "" {
return filepath.Base(mp.Path)
}
return mp.Alias
}

View File

@@ -10,6 +10,7 @@ import (
"net/http" "net/http"
"go.senan.xyz/gonic/jukebox" "go.senan.xyz/gonic/jukebox"
"go.senan.xyz/gonic/paths"
"go.senan.xyz/gonic/podcasts" "go.senan.xyz/gonic/podcasts"
"go.senan.xyz/gonic/scrobble" "go.senan.xyz/gonic/scrobble"
"go.senan.xyz/gonic/server/ctrlbase" "go.senan.xyz/gonic/server/ctrlbase"
@@ -31,7 +32,7 @@ type Controller struct {
CachePath string CachePath string
CoverCachePath string CoverCachePath string
PodcastsPath string PodcastsPath string
MusicPaths []string MusicPaths paths.MusicPaths
Jukebox *jukebox.Jukebox Jukebox *jukebox.Jukebox
Scrobblers []scrobble.Scrobbler Scrobblers []scrobble.Scrobbler
Podcasts *podcasts.Podcasts Podcasts *podcasts.Podcasts

View File

@@ -19,6 +19,7 @@ import (
"go.senan.xyz/gonic/db" "go.senan.xyz/gonic/db"
"go.senan.xyz/gonic/mockfs" "go.senan.xyz/gonic/mockfs"
"go.senan.xyz/gonic/paths"
"go.senan.xyz/gonic/server/ctrlbase" "go.senan.xyz/gonic/server/ctrlbase"
"go.senan.xyz/gonic/server/ctrlsubsonic/params" "go.senan.xyz/gonic/server/ctrlsubsonic/params"
"go.senan.xyz/gonic/transcode" "go.senan.xyz/gonic/transcode"
@@ -158,9 +159,9 @@ func makec(t *testing.T, roots []string, audio bool) *Controller {
m.ScanAndClean() m.ScanAndClean()
m.ResetDates() m.ResetDates()
var absRoots []string var absRoots paths.MusicPaths
for _, root := range roots { for _, root := range roots {
absRoots = append(absRoots, filepath.Join(m.TmpDir(), root)) absRoots = append(absRoots, paths.MusicPath{Alias: "", Path: filepath.Join(m.TmpDir(), root)})
} }
base := &ctrlbase.Controller{DB: m.DB()} base := &ctrlbase.Controller{DB: m.DB()}

View File

@@ -15,6 +15,7 @@ import (
"go.senan.xyz/gonic/db" "go.senan.xyz/gonic/db"
"go.senan.xyz/gonic/multierr" "go.senan.xyz/gonic/multierr"
"go.senan.xyz/gonic/paths"
"go.senan.xyz/gonic/scanner" "go.senan.xyz/gonic/scanner"
"go.senan.xyz/gonic/server/ctrlsubsonic/params" "go.senan.xyz/gonic/server/ctrlsubsonic/params"
"go.senan.xyz/gonic/server/ctrlsubsonic/spec" "go.senan.xyz/gonic/server/ctrlsubsonic/spec"
@@ -29,7 +30,7 @@ func lowerUDecOrHash(in string) string {
return string(lower) return string(lower)
} }
func getMusicFolder(musicPaths []string, p params.Params) string { func getMusicFolder(musicPaths paths.MusicPaths, p params.Params) string {
idx, err := p.GetInt("musicFolderId") idx, err := p.GetInt("musicFolderId")
if err != nil { if err != nil {
return "" return ""
@@ -37,7 +38,7 @@ func getMusicFolder(musicPaths []string, p params.Params) string {
if idx < 0 || idx > len(musicPaths) { if idx < 0 || idx > len(musicPaths) {
return "" return ""
} }
return musicPaths[idx] return musicPaths[idx].Path
} }
func (c *Controller) ServeGetLicence(r *http.Request) *spec.Response { func (c *Controller) ServeGetLicence(r *http.Request) *spec.Response {
@@ -91,7 +92,7 @@ func (c *Controller) ServeGetMusicFolders(r *http.Request) *spec.Response {
sub.MusicFolders = &spec.MusicFolders{} sub.MusicFolders = &spec.MusicFolders{}
sub.MusicFolders.List = make([]*spec.MusicFolder, len(c.MusicPaths)) sub.MusicFolders.List = make([]*spec.MusicFolder, len(c.MusicPaths))
for i, path := range c.MusicPaths { for i, path := range c.MusicPaths {
sub.MusicFolders.List[i] = &spec.MusicFolder{ID: i, Name: filepath.Base(path)} sub.MusicFolders.List[i] = &spec.MusicFolder{ID: i, Name: path.DisplayAlias()}
} }
return sub return sub
} }

View File

@@ -5,7 +5,6 @@ import (
"log" "log"
"net/http" "net/http"
"os" "os"
"path/filepath"
"time" "time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@@ -14,6 +13,7 @@ import (
"go.senan.xyz/gonic/db" "go.senan.xyz/gonic/db"
"go.senan.xyz/gonic/jukebox" "go.senan.xyz/gonic/jukebox"
"go.senan.xyz/gonic/paths"
"go.senan.xyz/gonic/podcasts" "go.senan.xyz/gonic/podcasts"
"go.senan.xyz/gonic/scanner" "go.senan.xyz/gonic/scanner"
"go.senan.xyz/gonic/scanner/tags" "go.senan.xyz/gonic/scanner/tags"
@@ -29,7 +29,7 @@ import (
type Options struct { type Options struct {
DB *db.DB DB *db.DB
MusicPaths []string MusicPaths paths.MusicPaths
PodcastPath string PodcastPath string
CachePath string CachePath string
CoverCachePath string CoverCachePath string
@@ -48,15 +48,9 @@ type Server struct {
} }
func New(opts Options) (*Server, error) { func New(opts Options) (*Server, error) {
for i, musicPath := range opts.MusicPaths {
opts.MusicPaths[i] = filepath.Clean(musicPath)
}
opts.CachePath = filepath.Clean(opts.CachePath)
opts.PodcastPath = filepath.Clean(opts.PodcastPath)
tagger := &tags.TagReader{} tagger := &tags.TagReader{}
scanner := scanner.New(opts.MusicPaths, opts.DB, opts.GenreSplit, tagger) scanner := scanner.New(opts.MusicPaths.Paths(), opts.DB, opts.GenreSplit, tagger)
base := &ctrlbase.Controller{ base := &ctrlbase.Controller{
DB: opts.DB, DB: opts.DB,
ProxyPrefix: opts.ProxyPrefix, ProxyPrefix: opts.ProxyPrefix,