Rough regex routing working, needs .. much improvement also. Is

this better than before? I dunno
This commit is contained in:
Rob Emery 2025-01-18 17:23:44 +00:00
parent 42bae7e924
commit 4960f206b4
3 changed files with 148 additions and 106 deletions

View File

@ -21,6 +21,7 @@ import (
"github.com/navidrome/navidrome/dlna/upnpav"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
"github.com/oriser/regroup"
)
type contentDirectoryService struct {
@ -89,91 +90,143 @@ func (cds *contentDirectoryService) readContainer(o object, host string) (ret []
return ret, nil
}
pathComponents := strings.Split(o.Path, "/")
log.Debug(fmt.Sprintf("ReadContainer pathComponents %+v %d", pathComponents, len(pathComponents)))
filesRegex := regroup.MustCompile("\\/Music\\/Files[\\/]?((?P<Path>.+))?")
artistRegex := regroup.MustCompile("\\/Music\\/Artists[\\/]?(?P<Artist>[^\\/]+)?[\\/]?(?<ArtistAlbum>[^\\/]+)?[\\/]?(?<ArtistAlbumTrack>[^\\/]+)?")
albumRegex := regroup.MustCompile("\\/Music\\/Albums[\\/]?(?P<AlbumTitle>[^\\/]+)?[\\/]?(?<AlbumTrack>[^\\/]+)?")
genresRegex := regroup.MustCompile("\\/Music\\/Genres[\\/]?(?P<Genre>[^\\/]+)?[\\/]?(?P<GenreArtist>[^/]+)?[\\/]?(?P<GenreTrack>[^\\/]+)?")
recentRegex := regroup.MustCompile("\\/Music\\/Recently Added[\\/]?(?P<RecentTrack>[^\\/]+)?")
playlistRegex := regroup.MustCompile("\\/Music\\/Playlist[\\/]?(?P<Playlist>[^\\/]+)?[\\/]?(?P<PlaylistTrack>[^\\/]+)?")
//TODO: something other than this
switch len(pathComponents) {
case 2:
switch pathComponents[1] {
case "Music":
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Files"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Artists"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Albums"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Genres"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Recently Added"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Playlists"}, true, host))
if o.Path == "/Music" {
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Files"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Artists"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Albums"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Genres"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Recently Added"}, true, host))
ret = append(ret, cds.cdsObjectToUpnpavObject(object{Path: "/Music/Playlists"}, true, host))
return ret, nil
} else if _, err := filesRegex.Groups(o.Path); err == nil {
return cds.doFiles(ret, o.Path, host)
} else if matchResults, err := artistRegex.Groups(o.Path); err == nil {
log.Debug(fmt.Sprintf("Artist MATCH: %+v", matchResults))
if matchResults["ArtistAlbumTrack"] != "" {
//TODO
log.Debug("Artist Get a track ")
} else if matchResults["ArtistAlbum"] != "" {
log.Debug("Artist Get an album ")
album := matchResults["ArtistAlbum"]
albumResponse, _ := cds.ds.Album(cds.ctx).Get(album)
log.Debug(fmt.Sprintf("Album Returned: %+v for %s", albumResponse, album))
basePath := path.Join("/Music/Artists", matchResults["Artist"], matchResults["ArtistAlbum"])
return cds.doAlbum(albumResponse, basePath, ret, host)
} else if matchResults["Artist"] != "" {
log.Debug(fmt.Sprintf("Artist Get an Artist: %s", matchResults["Artist"]))
allAlbumsForThisArtist, _ := cds.ds.Album(cds.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"album_artist_id": matchResults["Artist"]}})
basePath := path.Join("/Music/Artists", matchResults["Artist"])
return cds.doAlbums(allAlbumsForThisArtist, basePath, ret, host)
} else {
indexes, err := cds.ds.Artist(cds.ctx).GetIndex()
if err != nil {
fmt.Printf("Error retrieving Indexes: %+v", err)
return nil, err
}
for letterIndex := range indexes {
for artist := range indexes[letterIndex].Artists {
artistId := indexes[letterIndex].Artists[artist].ID
child := object{
Path: path.Join(o.Path, indexes[letterIndex].Artists[artist].Name),
Id: path.Join(o.Path, artistId),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}
}
return ret, nil
}
case 3:
switch pathComponents[1] {
case "Music":
switch pathComponents[2] {
case "Files":
return cds.doFiles(ret, o.Path, host)
case "Artists":
indexes, err := cds.ds.Artist(cds.ctx).GetIndex()
if err != nil {
fmt.Printf("Error retrieving Indexes: %+v", err)
return nil, err
}
for letterIndex := range indexes {
for artist := range indexes[letterIndex].Artists {
artistId := indexes[letterIndex].Artists[artist].ID
child := object{
Path: path.Join(o.Path, indexes[letterIndex].Artists[artist].Name),
Id: path.Join(o.Path, artistId),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}
}
return ret, nil
case "Albums":
indexes, err := cds.ds.Album(cds.ctx).GetAllWithoutGenres()
if err != nil {
fmt.Printf("Error retrieving Indexes: %+v", err)
return nil, err
}
for indexItem := range indexes {
child := object{
Path: path.Join(o.Path, indexes[indexItem].Name),
Id: path.Join(o.Path, indexes[indexItem].ID),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}
return ret, nil
case "Genres":
indexes, err := cds.ds.Genre(cds.ctx).GetAll()
if err != nil {
fmt.Printf("Error retrieving Indexes: %+v", err)
return nil, err
}
for indexItem := range indexes {
child := object{
Path: path.Join(o.Path, indexes[indexItem].Name),
Id: path.Join(o.Path, indexes[indexItem].ID),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}
return ret, nil
case "Playlists":
indexes, err := cds.ds.Playlist(cds.ctx).GetAll()
if err != nil {
fmt.Printf("Error retrieving Indexes: %+v", err)
return nil, err
}
for indexItem := range indexes {
child := object{
Path: path.Join(o.Path, indexes[indexItem].Name),
Id: path.Join(o.Path, indexes[indexItem].ID),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}
return ret, nil
} else if matchResults, err := albumRegex.Groups(o.Path); err == nil {
log.Debug("Album MATCH")
if matchResults["AlbumTrack"] != "" {
log.Debug("AlbumTrack MATCH")
//TODO
} else if matchResults["AlbumTitle"] != "" {
log.Debug("AlbumTitle MATCH")
x, _ := cds.ds.Album(cds.ctx).Get(matchResults["AlbumTitle"])
basePath := "/Music/Albums"
return cds.doAlbum(x, basePath, ret, host)
} else {
log.Debug("albumRegex else MATCH")
indexes, err := cds.ds.Album(cds.ctx).GetAllWithoutGenres()
if err != nil {
fmt.Printf("Error retrieving Indexes: %+v", err)
return nil, err
}
for indexItem := range indexes {
child := object{
Path: path.Join(o.Path, indexes[indexItem].Name),
Id: path.Join(o.Path, indexes[indexItem].ID),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}
return ret, nil
}
default:
} else if matchResults, err := genresRegex.Groups(o.Path); err == nil {
log.Debug("Genre MATCH")
if _, exists := matchResults["GenreTrack"]; exists {
log.Debug("GenreTrack MATCH")
//TODO
} else if _, exists := matchResults["GenreArtist"]; exists {
log.Debug("GenreArtist MATCH")
//TODO
} else if genre, exists := matchResults["Genre"]; exists {
log.Debug("Genre only MATCH")
x, xerr := cds.ds.Album(cds.ctx).Get(genre)
log.Debug(fmt.Sprintf("Genre: %+v", x), xerr)
} else {
log.Debug("Genre else MATCH")
indexes, err := cds.ds.Genre(cds.ctx).GetAll()
if err != nil {
fmt.Printf("Error retrieving Indexes: %+v", err)
return nil, err
}
for indexItem := range indexes {
child := object{
Path: path.Join(o.Path, indexes[indexItem].Name),
Id: path.Join(o.Path, indexes[indexItem].ID),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}
return ret, nil
}
} else if matchResults, err := recentRegex.Groups(o.Path); err == nil {
log.Debug("recent MATCH")
fmt.Printf("%+v",matchResults)
} else if matchResults, err := playlistRegex.Groups(o.Path); err == nil {
log.Debug("Playlist MATCH")
if _, exists := matchResults["PlaylistTrack"]; exists {
log.Debug("PlaylistTrack MATCH")
} else if playlist, exists := matchResults["Playlist"]; exists {
log.Debug("Playlist only MATCH")
x, xerr := cds.ds.Playlist(cds.ctx).Get(playlist)
log.Debug(fmt.Sprintf("Playlist: %+v", x), xerr)
} else {
log.Debug("Playlist else MATCH")
indexes, err := cds.ds.Playlist(cds.ctx).GetAll()
if err != nil {
fmt.Printf("Error retrieving Indexes: %+v", err)
return nil, err
}
for indexItem := range indexes {
child := object{
Path: path.Join(o.Path, indexes[indexItem].Name),
Id: path.Join(o.Path, indexes[indexItem].ID),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}
return ret, nil
}
}
/*
deluan
@ -194,39 +247,19 @@ func (cds *contentDirectoryService) readContainer(o object, host string) (ret []
Today at 18:31
This is a limitation of Squirrel. It is string based. YOu have to use the name of the columns in the DB
*/
if len(pathComponents) >= 4 {
switch pathComponents[2] {
case "Files":
return cds.doFiles(ret, o.Path, host)
case "Artists":
allAlbumsForThisArtist, _ := cds.ds.Album(cds.ctx).GetAll(model.QueryOptions{Filters: squirrel.Eq{"album_artist_id": pathComponents[3]}})
return cds.doAlbums(allAlbumsForThisArtist, ret, host)
case "Albums":
x, _ := cds.ds.Album(cds.ctx).Get(pathComponents[3])
return cds.doAlbum(x, ret, host)
case "Genres":
x, xerr := cds.ds.Album(cds.ctx).Get(pathComponents[3])
log.Debug(fmt.Sprintf("Genre: %+v", x), xerr)
case "Playlists":
x, xerr := cds.ds.Playlist(cds.ctx).Get(pathComponents[3])
log.Debug(fmt.Sprintf("Playlist: %+v", x), xerr)
}
}
}
return
return
}
func (cds *contentDirectoryService) doAlbum(x *model.Album, ret []interface{}, host string) ([]interface{}, error) {
//TODO
func (cds *contentDirectoryService) doAlbum(album *model.Album, basepath string, ret []interface{}, host string) ([]interface{}, error) {
log.Debug(fmt.Sprintf("TODO: doAlbum Called with : '%+v', '%s'", album, basepath))
return ret, nil
}
func (cds *contentDirectoryService) doAlbums(albums model.Albums, ret []interface{}, host string) ([]interface{}, error) {
func (cds *contentDirectoryService) doAlbums(albums model.Albums, basepath string, ret []interface{}, host string) ([]interface{}, error) {
for _, album := range albums {
child := object {
Path: path.Join("/Music/Albums", album.Name),
Id: album.ID,
Path: path.Join(basepath, album.Name),
Id: path.Join(basepath, album.ID),
}
ret = append(ret, cds.cdsObjectToUpnpavObject(child, true, host))
}

1
go.mod
View File

@ -121,6 +121,7 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ogier/pflag v0.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/oriser/regroup v0.0.0-20240925165441-f6bb0e08289e // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.5 // indirect

8
go.sum
View File

@ -18,6 +18,8 @@ github.com/anacrolix/generics v0.0.1 h1:4WVhK6iLb3UAAAQP6I3uYlMOHcp9FqJC9j4n81Wv
github.com/anacrolix/generics v0.0.1/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
github.com/anacrolix/log v0.15.2 h1:LTSf5Wm6Q4GNWPFMBP7NPYV6UBVZzZLKckL+/Lj72Oo=
github.com/anacrolix/log v0.15.2/go.mod h1:m0poRtlr41mriZlXBQ9SOVZ8yZBkLjOkDhd5Li5pITA=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@ -207,6 +209,12 @@ github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI
github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/oriser/regroup v0.0.0-20240925165441-f6bb0e08289e h1:cL0lMYYEbfEUBghQd4ytnl8B8Ktdm+JremTyAagegZ0=
github.com/oriser/regroup v0.0.0-20240925165441-f6bb0e08289e/go.mod h1:tUOeYZJlwO7jSmM5ko1jTCiQaWQMvh58IENEfjwYzh8=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=