Always access artist images through Navidrome (proxy calls to external URLs)
This commit is contained in:
@@ -2,10 +2,7 @@ package agents
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/navidrome/navidrome/consts"
|
|
||||||
"github.com/navidrome/navidrome/core/artwork"
|
|
||||||
"github.com/navidrome/navidrome/model"
|
"github.com/navidrome/navidrome/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,25 +26,10 @@ func (p *localAgent) GetBiography(ctx context.Context, id, name, mbid string) (s
|
|||||||
return localBiography, nil
|
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) {
|
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
|
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() {
|
func init() {
|
||||||
Register(LocalAgentName, localsConstructor)
|
Register(LocalAgentName, localsConstructor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ type artistReader struct {
|
|||||||
cacheKey
|
cacheKey
|
||||||
a *artwork
|
a *artwork
|
||||||
artist model.Artist
|
artist model.Artist
|
||||||
files []string
|
files string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArtistReader(ctx context.Context, artwork *artwork, artID model.ArtworkID) (*artistReader, error) {
|
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,
|
artist: *ar,
|
||||||
}
|
}
|
||||||
a.cacheKey.lastUpdate = ar.ExternalInfoUpdatedAt
|
a.cacheKey.lastUpdate = ar.ExternalInfoUpdatedAt
|
||||||
|
var files []string
|
||||||
for _, al := range als {
|
for _, al := range als {
|
||||||
a.files = append(a.files, al.ImageFiles)
|
files = append(files, al.ImageFiles)
|
||||||
if a.cacheKey.lastUpdate.Before(al.UpdatedAt) {
|
if a.cacheKey.lastUpdate.Before(al.UpdatedAt) {
|
||||||
a.cacheKey.lastUpdate = al.UpdatedAt
|
a.cacheKey.lastUpdate = al.UpdatedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
a.files = strings.Join(files, string(filepath.ListSeparator))
|
||||||
a.cacheKey.artID = artID
|
a.cacheKey.artID = artID
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
@@ -49,7 +52,7 @@ func (a *artistReader) LastUpdated() time.Time {
|
|||||||
|
|
||||||
func (a *artistReader) Reader(ctx context.Context) (io.ReadCloser, string, error) {
|
func (a *artistReader) Reader(ctx context.Context) (io.ReadCloser, string, error) {
|
||||||
return selectImageReader(ctx, a.artID,
|
return selectImageReader(ctx, a.artID,
|
||||||
//fromExternalFile()
|
fromExternalFile(ctx, a.files, "artist.*"),
|
||||||
fromExternalSource(ctx, a.artist),
|
fromExternalSource(ctx, a.artist),
|
||||||
fromArtistPlaceholder(),
|
fromArtistPlaceholder(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func (api *Router) GetStarred(r *http.Request) (*responses.Subsonic, error) {
|
|||||||
|
|
||||||
response := newResponse()
|
response := newResponse()
|
||||||
response.Starred = &responses.Starred{}
|
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.Album = childrenFromAlbums(r.Context(), albums)
|
||||||
response.Starred.Song = childrenFromMediaFiles(r.Context(), mediaFiles)
|
response.Starred.Song = childrenFromMediaFiles(r.Context(), mediaFiles)
|
||||||
return response, nil
|
return response, nil
|
||||||
|
|||||||
+12
-10
@@ -28,7 +28,8 @@ func (api *Router) GetMusicFolders(r *http.Request) (*responses.Subsonic, error)
|
|||||||
return response, nil
|
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))
|
folder, err := api.ds.MediaFolder(ctx).Get(int32(mediaFolderId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(ctx, "Error retrieving MediaFolder", "id", mediaFolderId, err)
|
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))
|
res.Index = make([]responses.Index, len(indexes))
|
||||||
for i, idx := range indexes {
|
for i, idx := range indexes {
|
||||||
res.Index[i].Name = idx.ID
|
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
|
return res, nil
|
||||||
}
|
}
|
||||||
@@ -69,7 +70,7 @@ func (api *Router) GetIndexes(r *http.Request) (*responses.Subsonic, error) {
|
|||||||
musicFolderId := utils.ParamInt(r, "musicFolderId", 0)
|
musicFolderId := utils.ParamInt(r, "musicFolderId", 0)
|
||||||
ifModifiedSince := utils.ParamTime(r, "ifModifiedSince", time.Time{})
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
func (api *Router) GetArtists(r *http.Request) (*responses.Subsonic, error) {
|
||||||
musicFolderId := utils.ParamInt(r, "musicFolderId", 0)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -148,7 +149,7 @@ func (api *Router) GetArtist(r *http.Request) (*responses.Subsonic, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response := newResponse()
|
response := newResponse()
|
||||||
response.ArtistWithAlbumsID3 = api.buildArtist(ctx, artist, albums)
|
response.ArtistWithAlbumsID3 = api.buildArtist(r, artist, albums)
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +239,7 @@ func (api *Router) GetArtistInfo(r *http.Request) (*responses.Subsonic, error) {
|
|||||||
response.ArtistInfo.LastFmUrl = artist.ExternalUrl
|
response.ArtistInfo.LastFmUrl = artist.ExternalUrl
|
||||||
response.ArtistInfo.MusicBrainzID = artist.MbzArtistID
|
response.ArtistInfo.MusicBrainzID = artist.MbzArtistID
|
||||||
for _, s := range artist.SimilarArtists {
|
for _, s := range artist.SimilarArtists {
|
||||||
similar := toArtist(ctx, s)
|
similar := toArtist(r, s)
|
||||||
response.ArtistInfo.SimilarArtist = append(response.ArtistInfo.SimilarArtist, similar)
|
response.ArtistInfo.SimilarArtist = append(response.ArtistInfo.SimilarArtist, similar)
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
@@ -260,7 +261,8 @@ func (api *Router) GetArtistInfo2(r *http.Request) (*responses.Subsonic, error)
|
|||||||
similar.AlbumCount = s.AlbumCount
|
similar.AlbumCount = s.AlbumCount
|
||||||
similar.Starred = s.Starred
|
similar.Starred = s.Starred
|
||||||
similar.UserRating = s.UserRating
|
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)
|
response.ArtistInfo2.SimilarArtist = append(response.ArtistInfo2.SimilarArtist, similar)
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
@@ -342,10 +344,10 @@ func (api *Router) buildArtistDirectory(ctx context.Context, artist *model.Artis
|
|||||||
return dir, nil
|
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 := &responses.ArtistWithAlbumsID3{}
|
||||||
a.ArtistID3 = toArtistID3(ctx, *artist)
|
a.ArtistID3 = toArtistID3(r, *artist)
|
||||||
a.Album = childrenFromAlbums(ctx, albums)
|
a.Album = childrenFromAlbums(r.Context(), albums)
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/navidrome/navidrome/consts"
|
"github.com/navidrome/navidrome/consts"
|
||||||
|
"github.com/navidrome/navidrome/core/artwork"
|
||||||
"github.com/navidrome/navidrome/model"
|
"github.com/navidrome/navidrome/model"
|
||||||
"github.com/navidrome/navidrome/model/request"
|
"github.com/navidrome/navidrome/model/request"
|
||||||
|
"github.com/navidrome/navidrome/server"
|
||||||
"github.com/navidrome/navidrome/server/subsonic/responses"
|
"github.com/navidrome/navidrome/server/subsonic/responses"
|
||||||
"github.com/navidrome/navidrome/utils"
|
"github.com/navidrome/navidrome/utils"
|
||||||
)
|
)
|
||||||
@@ -72,22 +75,22 @@ func getUser(ctx context.Context) model.User {
|
|||||||
return 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))
|
as := make([]responses.Artist, len(artists))
|
||||||
for i, artist := range artists {
|
for i, artist := range artists {
|
||||||
as[i] = toArtist(ctx, artist)
|
as[i] = toArtist(r, artist)
|
||||||
}
|
}
|
||||||
return as
|
return as
|
||||||
}
|
}
|
||||||
|
|
||||||
func toArtist(_ context.Context, a model.Artist) responses.Artist {
|
func toArtist(r *http.Request, a model.Artist) responses.Artist {
|
||||||
artist := responses.Artist{
|
artist := responses.Artist{
|
||||||
Id: a.ID,
|
Id: a.ID,
|
||||||
Name: a.Name,
|
Name: a.Name,
|
||||||
AlbumCount: a.AlbumCount,
|
AlbumCount: a.AlbumCount,
|
||||||
UserRating: a.Rating,
|
UserRating: a.Rating,
|
||||||
CoverArt: a.CoverArtID().String(),
|
CoverArt: a.CoverArtID().String(),
|
||||||
ArtistImageUrl: a.ArtistImageUrl(),
|
ArtistImageUrl: artistCoverArtURL(r, a.CoverArtID(), 0),
|
||||||
}
|
}
|
||||||
if a.Starred {
|
if a.Starred {
|
||||||
artist.Starred = &a.StarredAt
|
artist.Starred = &a.StarredAt
|
||||||
@@ -95,13 +98,13 @@ func toArtist(_ context.Context, a model.Artist) responses.Artist {
|
|||||||
return 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{
|
artist := responses.ArtistID3{
|
||||||
Id: a.ID,
|
Id: a.ID,
|
||||||
Name: a.Name,
|
Name: a.Name,
|
||||||
AlbumCount: a.AlbumCount,
|
AlbumCount: a.AlbumCount,
|
||||||
CoverArt: a.CoverArtID().String(),
|
CoverArt: a.CoverArtID().String(),
|
||||||
ArtistImageUrl: a.ArtistImageUrl(),
|
ArtistImageUrl: artistCoverArtURL(r, a.CoverArtID(), 0),
|
||||||
UserRating: a.Rating,
|
UserRating: a.Rating,
|
||||||
}
|
}
|
||||||
if a.Starred {
|
if a.Starred {
|
||||||
@@ -110,6 +113,12 @@ func toArtistID3(_ context.Context, a model.Artist) responses.ArtistID3 {
|
|||||||
return artist
|
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 {
|
func toGenres(genres model.Genres) *responses.Genres {
|
||||||
response := make([]responses.Genre, len(genres))
|
response := make([]responses.Genre, len(genres))
|
||||||
for i, g := range genres {
|
for i, g := range genres {
|
||||||
|
|||||||
@@ -107,10 +107,12 @@ func (api *Router) Search2(r *http.Request) (*responses.Subsonic, error) {
|
|||||||
for i, artist := range as {
|
for i, artist := range as {
|
||||||
artist := artist
|
artist := artist
|
||||||
searchResult2.Artist[i] = responses.Artist{
|
searchResult2.Artist[i] = responses.Artist{
|
||||||
Id: artist.ID,
|
Id: artist.ID,
|
||||||
Name: artist.Name,
|
Name: artist.Name,
|
||||||
AlbumCount: artist.AlbumCount,
|
AlbumCount: artist.AlbumCount,
|
||||||
UserRating: artist.Rating,
|
UserRating: artist.Rating,
|
||||||
|
CoverArt: artist.CoverArtID().String(),
|
||||||
|
ArtistImageUrl: artistCoverArtURL(r, artist.CoverArtID(), 0),
|
||||||
}
|
}
|
||||||
if artist.Starred {
|
if artist.Starred {
|
||||||
searchResult2.Artist[i].Starred = &as[i].StarredAt
|
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 := &responses.SearchResult3{}
|
||||||
searchResult3.Artist = make([]responses.ArtistID3, len(as))
|
searchResult3.Artist = make([]responses.ArtistID3, len(as))
|
||||||
for i, artist := range as {
|
for i, artist := range as {
|
||||||
searchResult3.Artist[i] = toArtistID3(ctx, artist)
|
searchResult3.Artist[i] = toArtistID3(r, artist)
|
||||||
}
|
}
|
||||||
searchResult3.Album = childrenFromAlbums(ctx, als)
|
searchResult3.Album = childrenFromAlbums(ctx, als)
|
||||||
searchResult3.Song = childrenFromMediaFiles(ctx, mfs)
|
searchResult3.Song = childrenFromMediaFiles(ctx, mfs)
|
||||||
|
|||||||
Reference in New Issue
Block a user