From 77a99a735b723c25015b1306bbfd250c40afdaaf Mon Sep 17 00:00:00 2001 From: Deluan <deluan@navidrome.org> Date: Sat, 31 Dec 2022 17:29:58 -0500 Subject: [PATCH] Always access artist images through Navidrome (proxy calls to external URLs) --- core/agents/local_agent.go | 18 ------------------ core/artwork/reader_artist.go | 9 ++++++--- server/subsonic/album_lists.go | 2 +- server/subsonic/browsing.go | 22 ++++++++++++---------- server/subsonic/helpers.go | 21 +++++++++++++++------ server/subsonic/searching.go | 12 +++++++----- 6 files changed, 41 insertions(+), 43 deletions(-) diff --git a/core/agents/local_agent.go b/core/agents/local_agent.go index e2ae4cb7d..9c25b1227 100644 --- a/core/agents/local_agent.go +++ b/core/agents/local_agent.go @@ -2,10 +2,7 @@ package agents import ( "context" - "path/filepath" - "github.com/navidrome/navidrome/consts" - "github.com/navidrome/navidrome/core/artwork" "github.com/navidrome/navidrome/model" ) @@ -29,25 +26,10 @@ func (p *localAgent) GetBiography(ctx context.Context, id, name, mbid string) (s return localBiography, nil } -func (p *localAgent) GetImages(_ context.Context, id, name, mbid string) ([]ArtistImage, error) { - return []ArtistImage{ - p.artistImage(id, 300), - p.artistImage(id, 174), - p.artistImage(id, 64), - }, nil -} - func (p *localAgent) GetTopSongs(ctx context.Context, id, artistName, mbid string, count int) ([]Song, error) { return nil, nil // TODO return 5-stars and liked songs sorted by playCount } -func (p *localAgent) artistImage(id string, size int) ArtistImage { - return ArtistImage{ - filepath.Join(consts.URLPathPublicImages, artwork.PublicLink(model.NewArtworkID(model.KindArtistArtwork, id), size)), - size, - } -} - func init() { Register(LocalAgentName, localsConstructor) } diff --git a/core/artwork/reader_artist.go b/core/artwork/reader_artist.go index da54b77ea..e2ad1d57c 100644 --- a/core/artwork/reader_artist.go +++ b/core/artwork/reader_artist.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/http" + "path/filepath" "strings" "time" @@ -16,7 +17,7 @@ type artistReader struct { cacheKey a *artwork artist model.Artist - files []string + files string } func newArtistReader(ctx context.Context, artwork *artwork, artID model.ArtworkID) (*artistReader, error) { @@ -33,12 +34,14 @@ func newArtistReader(ctx context.Context, artwork *artwork, artID model.ArtworkI artist: *ar, } a.cacheKey.lastUpdate = ar.ExternalInfoUpdatedAt + var files []string for _, al := range als { - a.files = append(a.files, al.ImageFiles) + files = append(files, al.ImageFiles) if a.cacheKey.lastUpdate.Before(al.UpdatedAt) { a.cacheKey.lastUpdate = al.UpdatedAt } } + a.files = strings.Join(files, string(filepath.ListSeparator)) a.cacheKey.artID = artID return a, nil } @@ -49,7 +52,7 @@ func (a *artistReader) LastUpdated() time.Time { func (a *artistReader) Reader(ctx context.Context) (io.ReadCloser, string, error) { return selectImageReader(ctx, a.artID, - //fromExternalFile() + fromExternalFile(ctx, a.files, "artist.*"), fromExternalSource(ctx, a.artist), fromArtistPlaceholder(), ) diff --git a/server/subsonic/album_lists.go b/server/subsonic/album_lists.go index b0c32afb0..4944f8d53 100644 --- a/server/subsonic/album_lists.go +++ b/server/subsonic/album_lists.go @@ -124,7 +124,7 @@ func (api *Router) GetStarred(r *http.Request) (*responses.Subsonic, error) { response := newResponse() response.Starred = &responses.Starred{} - response.Starred.Artist = toArtists(ctx, artists) + response.Starred.Artist = toArtists(r, artists) response.Starred.Album = childrenFromAlbums(r.Context(), albums) response.Starred.Song = childrenFromMediaFiles(r.Context(), mediaFiles) return response, nil diff --git a/server/subsonic/browsing.go b/server/subsonic/browsing.go index 044a535b2..9b023e98b 100644 --- a/server/subsonic/browsing.go +++ b/server/subsonic/browsing.go @@ -28,7 +28,8 @@ func (api *Router) GetMusicFolders(r *http.Request) (*responses.Subsonic, error) return response, nil } -func (api *Router) getArtistIndex(ctx context.Context, mediaFolderId int, ifModifiedSince time.Time) (*responses.Indexes, error) { +func (api *Router) getArtistIndex(r *http.Request, mediaFolderId int, ifModifiedSince time.Time) (*responses.Indexes, error) { + ctx := r.Context() folder, err := api.ds.MediaFolder(ctx).Get(int32(mediaFolderId)) if err != nil { log.Error(ctx, "Error retrieving MediaFolder", "id", mediaFolderId, err) @@ -60,7 +61,7 @@ func (api *Router) getArtistIndex(ctx context.Context, mediaFolderId int, ifModi res.Index = make([]responses.Index, len(indexes)) for i, idx := range indexes { res.Index[i].Name = idx.ID - res.Index[i].Artists = toArtists(ctx, idx.Artists) + res.Index[i].Artists = toArtists(r, idx.Artists) } return res, nil } @@ -69,7 +70,7 @@ func (api *Router) GetIndexes(r *http.Request) (*responses.Subsonic, error) { musicFolderId := utils.ParamInt(r, "musicFolderId", 0) ifModifiedSince := utils.ParamTime(r, "ifModifiedSince", time.Time{}) - res, err := api.getArtistIndex(r.Context(), musicFolderId, ifModifiedSince) + res, err := api.getArtistIndex(r, musicFolderId, ifModifiedSince) if err != nil { return nil, err } @@ -81,7 +82,7 @@ func (api *Router) GetIndexes(r *http.Request) (*responses.Subsonic, error) { func (api *Router) GetArtists(r *http.Request) (*responses.Subsonic, error) { musicFolderId := utils.ParamInt(r, "musicFolderId", 0) - res, err := api.getArtistIndex(r.Context(), musicFolderId, time.Time{}) + res, err := api.getArtistIndex(r, musicFolderId, time.Time{}) if err != nil { return nil, err } @@ -148,7 +149,7 @@ func (api *Router) GetArtist(r *http.Request) (*responses.Subsonic, error) { } response := newResponse() - response.ArtistWithAlbumsID3 = api.buildArtist(ctx, artist, albums) + response.ArtistWithAlbumsID3 = api.buildArtist(r, artist, albums) return response, nil } @@ -238,7 +239,7 @@ func (api *Router) GetArtistInfo(r *http.Request) (*responses.Subsonic, error) { response.ArtistInfo.LastFmUrl = artist.ExternalUrl response.ArtistInfo.MusicBrainzID = artist.MbzArtistID for _, s := range artist.SimilarArtists { - similar := toArtist(ctx, s) + similar := toArtist(r, s) response.ArtistInfo.SimilarArtist = append(response.ArtistInfo.SimilarArtist, similar) } return response, nil @@ -260,7 +261,8 @@ func (api *Router) GetArtistInfo2(r *http.Request) (*responses.Subsonic, error) similar.AlbumCount = s.AlbumCount similar.Starred = s.Starred similar.UserRating = s.UserRating - similar.ArtistImageUrl = server.AbsoluteURL(r, s.ArtistImageUrl) + similar.CoverArt = s.CoverArt + similar.ArtistImageUrl = s.ArtistImageUrl response.ArtistInfo2.SimilarArtist = append(response.ArtistInfo2.SimilarArtist, similar) } return response, nil @@ -342,10 +344,10 @@ func (api *Router) buildArtistDirectory(ctx context.Context, artist *model.Artis return dir, nil } -func (api *Router) buildArtist(ctx context.Context, artist *model.Artist, albums model.Albums) *responses.ArtistWithAlbumsID3 { +func (api *Router) buildArtist(r *http.Request, artist *model.Artist, albums model.Albums) *responses.ArtistWithAlbumsID3 { a := &responses.ArtistWithAlbumsID3{} - a.ArtistID3 = toArtistID3(ctx, *artist) - a.Album = childrenFromAlbums(ctx, albums) + a.ArtistID3 = toArtistID3(r, *artist) + a.Album = childrenFromAlbums(r.Context(), albums) return a } diff --git a/server/subsonic/helpers.go b/server/subsonic/helpers.go index 4ea5447df..f77cd05fa 100644 --- a/server/subsonic/helpers.go +++ b/server/subsonic/helpers.go @@ -5,11 +5,14 @@ import ( "fmt" "mime" "net/http" + "path/filepath" "strings" "github.com/navidrome/navidrome/consts" + "github.com/navidrome/navidrome/core/artwork" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/model/request" + "github.com/navidrome/navidrome/server" "github.com/navidrome/navidrome/server/subsonic/responses" "github.com/navidrome/navidrome/utils" ) @@ -72,22 +75,22 @@ func getUser(ctx context.Context) model.User { return model.User{} } -func toArtists(ctx context.Context, artists model.Artists) []responses.Artist { +func toArtists(r *http.Request, artists model.Artists) []responses.Artist { as := make([]responses.Artist, len(artists)) for i, artist := range artists { - as[i] = toArtist(ctx, artist) + as[i] = toArtist(r, artist) } return as } -func toArtist(_ context.Context, a model.Artist) responses.Artist { +func toArtist(r *http.Request, a model.Artist) responses.Artist { artist := responses.Artist{ Id: a.ID, Name: a.Name, AlbumCount: a.AlbumCount, UserRating: a.Rating, CoverArt: a.CoverArtID().String(), - ArtistImageUrl: a.ArtistImageUrl(), + ArtistImageUrl: artistCoverArtURL(r, a.CoverArtID(), 0), } if a.Starred { artist.Starred = &a.StarredAt @@ -95,13 +98,13 @@ func toArtist(_ context.Context, a model.Artist) responses.Artist { return artist } -func toArtistID3(_ context.Context, a model.Artist) responses.ArtistID3 { +func toArtistID3(r *http.Request, a model.Artist) responses.ArtistID3 { artist := responses.ArtistID3{ Id: a.ID, Name: a.Name, AlbumCount: a.AlbumCount, CoverArt: a.CoverArtID().String(), - ArtistImageUrl: a.ArtistImageUrl(), + ArtistImageUrl: artistCoverArtURL(r, a.CoverArtID(), 0), UserRating: a.Rating, } if a.Starred { @@ -110,6 +113,12 @@ func toArtistID3(_ context.Context, a model.Artist) responses.ArtistID3 { return artist } +func artistCoverArtURL(r *http.Request, artID model.ArtworkID, size int) string { + link := artwork.PublicLink(artID, size) + url := filepath.Join(consts.URLPathPublicImages, link) + return server.AbsoluteURL(r, url) +} + func toGenres(genres model.Genres) *responses.Genres { response := make([]responses.Genre, len(genres)) for i, g := range genres { diff --git a/server/subsonic/searching.go b/server/subsonic/searching.go index f1d8c37d5..90759240b 100644 --- a/server/subsonic/searching.go +++ b/server/subsonic/searching.go @@ -107,10 +107,12 @@ func (api *Router) Search2(r *http.Request) (*responses.Subsonic, error) { for i, artist := range as { artist := artist searchResult2.Artist[i] = responses.Artist{ - Id: artist.ID, - Name: artist.Name, - AlbumCount: artist.AlbumCount, - UserRating: artist.Rating, + Id: artist.ID, + Name: artist.Name, + AlbumCount: artist.AlbumCount, + UserRating: artist.Rating, + CoverArt: artist.CoverArtID().String(), + ArtistImageUrl: artistCoverArtURL(r, artist.CoverArtID(), 0), } if artist.Starred { searchResult2.Artist[i].Starred = &as[i].StarredAt @@ -134,7 +136,7 @@ func (api *Router) Search3(r *http.Request) (*responses.Subsonic, error) { searchResult3 := &responses.SearchResult3{} searchResult3.Artist = make([]responses.ArtistID3, len(as)) for i, artist := range as { - searchResult3.Artist[i] = toArtistID3(ctx, artist) + searchResult3.Artist[i] = toArtistID3(r, artist) } searchResult3.Album = childrenFromAlbums(ctx, als) searchResult3.Song = childrenFromMediaFiles(ctx, mfs)