Files
vibesonic/internal/subsonic/folders.go
T

99 lines
2.7 KiB
Go

package subsonic
import (
"database/sql"
"strconv"
"git.noroutes.net/NoRoutes/vibetunes/internal/database"
)
// folderMap resolves between VibeSonic's opaque music-folder IDs and the
// small sequential integers the Subsonic protocol expects for
// musicFolderId (the official XSD types it as xs:int, and some clients
// build folder-picker UIs assuming small integers). The mapping is
// derived fresh per request from folder creation order, which is stable
// as long as folders aren't deleted/recreated — acceptable for how
// rarely music folders change.
type folderMap struct {
folders []*database.MusicFolder
toInt map[string]int
toFolder map[int]*database.MusicFolder
}
func loadFolderMap(db *sql.DB) (*folderMap, error) {
folders, err := database.ListMusicFolders(db)
if err != nil {
return nil, err
}
fm := &folderMap{
folders: folders,
toInt: make(map[string]int, len(folders)),
toFolder: make(map[int]*database.MusicFolder, len(folders)),
}
for i, f := range folders {
id := i + 1
fm.toInt[f.ID] = id
fm.toFolder[id] = f
}
return fm, nil
}
func (fm *folderMap) IntID(folderID string) string {
return strconv.Itoa(fm.toInt[folderID])
}
func (fm *folderMap) ByIntID(s string) *database.MusicFolder {
n, err := strconv.Atoi(s)
if err != nil {
return nil
}
return fm.toFolder[n]
}
// Allowed returns the folders a user may see: every folder, unless the
// user has an explicit restriction list configured.
func (fm *folderMap) Allowed(db *sql.DB, user *database.User) ([]*database.MusicFolder, error) {
allowedIDs, err := database.AllowedMusicFolderIDs(db, user.ID)
if err != nil {
return nil, err
}
if len(allowedIDs) == 0 {
return fm.folders, nil
}
set := make(map[string]bool, len(allowedIDs))
for _, id := range allowedIDs {
set[id] = true
}
var out []*database.MusicFolder
for _, f := range fm.folders {
if set[f.ID] {
out = append(out, f)
}
}
return out, nil
}
// UserCanSeeFolder reports whether user is allowed to see folderID,
// given their restriction list (empty = unrestricted).
func UserCanSeeFolder(db *sql.DB, user *database.User, folderID string) (bool, error) {
allowedIDs, err := database.AllowedMusicFolderIDs(db, user.ID)
if err != nil {
return false, err
}
if len(allowedIDs) == 0 {
return true, nil
}
for _, id := range allowedIDs {
if id == folderID {
return true, nil
}
}
return false, nil
}
// UserCanSeeMediaFile reports whether user is allowed to see a song
// belonging to the given music folder (per their folder restriction).
func UserCanSeeMediaFile(db *sql.DB, user *database.User, mediaFile *database.MediaFile) (bool, error) {
return UserCanSeeFolder(db, user, mediaFile.MusicFolderID)
}