refactor: consolidate specid <-> filesystem mapping and always use abs paths (#309)
This commit is contained in:
77
server/ctrlsubsonic/specidpaths/specidpaths.go
Normal file
77
server/ctrlsubsonic/specidpaths/specidpaths.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package specidpaths
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"go.senan.xyz/gonic/db"
|
||||
"go.senan.xyz/gonic/server/ctrlsubsonic/specid"
|
||||
)
|
||||
|
||||
var ErrNotAbs = errors.New("not abs")
|
||||
var ErrNotFound = errors.New("not found")
|
||||
|
||||
type Result interface {
|
||||
SID() *specid.ID
|
||||
AbsPath() string
|
||||
}
|
||||
|
||||
// Locate maps a specid to its location on the filesystem
|
||||
func Locate(dbc *db.DB, podcastsPath string, id specid.ID) (Result, error) {
|
||||
switch id.Type {
|
||||
case specid.Track:
|
||||
var track db.Track
|
||||
if err := dbc.Preload("Album").Where("id=?", id.Value).Find(&track).Error; err == nil {
|
||||
return &track, nil
|
||||
}
|
||||
case specid.PodcastEpisode:
|
||||
var pe db.PodcastEpisode
|
||||
if err := dbc.Where("id=?", id.Value).Find(&pe).Error; err == nil {
|
||||
pe.AbsP = filepath.Join(podcastsPath, pe.Path)
|
||||
return &pe, err
|
||||
}
|
||||
}
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
// Locate maps a location on the filesystem to a specid
|
||||
func Lookup(dbc *db.DB, musicPaths []string, podcastsPath string, path string) (Result, error) {
|
||||
if !filepath.IsAbs(path) {
|
||||
return nil, ErrNotAbs
|
||||
}
|
||||
|
||||
if strings.HasPrefix(path, podcastsPath) {
|
||||
path, _ = filepath.Rel(podcastsPath, path)
|
||||
var pe db.PodcastEpisode
|
||||
if err := dbc.Where(`path=?`, path).First(&pe).Error; err == nil {
|
||||
return &pe, nil
|
||||
}
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
var musicPath string
|
||||
for _, mp := range musicPaths {
|
||||
if strings.HasPrefix(path, mp) {
|
||||
musicPath = mp
|
||||
}
|
||||
}
|
||||
if musicPath == "" {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
relPath, _ := filepath.Rel(musicPath, path)
|
||||
relDir, filename := filepath.Split(relPath)
|
||||
leftPath, rightPath := filepath.Split(filepath.Clean(relDir))
|
||||
|
||||
q := dbc.
|
||||
Where(`albums.root_dir=? AND albums.left_path=? AND albums.right_path=? AND tracks.filename=?`, musicPath, leftPath, rightPath, filename).
|
||||
Joins(`JOIN albums ON tracks.album_id=albums.id`).
|
||||
Preload("Album")
|
||||
|
||||
var track db.Track
|
||||
if err := q.First(&track).Error; err == nil {
|
||||
return &track, nil
|
||||
}
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
Reference in New Issue
Block a user