59 lines
1.5 KiB
Go
59 lines
1.5 KiB
Go
package library
|
|
|
|
import (
|
|
"database/sql"
|
|
"strings"
|
|
|
|
"git.noroutes.net/NoRoutes/vibetunes/internal/database"
|
|
)
|
|
|
|
// DirEntry is one immediate child of a directory in filesystem-style
|
|
// browsing (Subsonic's getIndexes/getMusicDirectory): either a
|
|
// subdirectory (Dir=true) or a media file.
|
|
type DirEntry struct {
|
|
Name string
|
|
Dir bool
|
|
File *database.MediaFile // set when Dir is false
|
|
}
|
|
|
|
// ListDirectory returns the immediate children of subPath within a music
|
|
// folder ("" for the folder root), built from media_files.relative_path.
|
|
// This is the foundation for filesystem-style browsing, kept separate
|
|
// from the ID3/tag model in library/index.go so neither is faked in
|
|
// terms of the other.
|
|
func ListDirectory(db *sql.DB, folderID, subPath string) ([]DirEntry, error) {
|
|
files, err := database.ListMediaFilesForFolder(db, folderID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
prefix := strings.Trim(subPath, "/")
|
|
seen := make(map[string]bool)
|
|
var out []DirEntry
|
|
for _, f := range files {
|
|
if f.Missing {
|
|
continue
|
|
}
|
|
rel := f.RelativePath
|
|
if prefix != "" {
|
|
if !strings.HasPrefix(rel, prefix+"/") {
|
|
continue
|
|
}
|
|
rel = rel[len(prefix)+1:]
|
|
}
|
|
parts := strings.SplitN(rel, "/", 2)
|
|
name := parts[0]
|
|
if name == "" || seen[name] {
|
|
continue
|
|
}
|
|
if len(parts) == 2 {
|
|
seen[name] = true
|
|
out = append(out, DirEntry{Name: name, Dir: true})
|
|
continue
|
|
}
|
|
seen[name] = true
|
|
out = append(out, DirEntry{Name: name, Dir: false, File: f})
|
|
}
|
|
return out, nil
|
|
}
|