Add local agent, only for images

This commit is contained in:
Deluan 2022-12-30 23:52:53 -05:00 committed by Deluan Quintão
parent 387acc5f63
commit bf461473ef
15 changed files with 134 additions and 76 deletions

View File

@ -29,9 +29,11 @@ const (
DevInitialUserName = "admin"
DevInitialName = "Dev Admin"
URLPathUI = "/app"
URLPathNativeAPI = "/api"
URLPathSubsonicAPI = "/rest"
URLPathUI = "/app"
URLPathNativeAPI = "/api"
URLPathSubsonicAPI = "/rest"
URLPathPublic = "/p"
URLPathPublicImages = URLPathPublic + "/img"
// DefaultUILoginBackgroundURL uses Navidrome curated background images collection,
// available at https://unsplash.com/collections/20072696/navidrome
@ -46,13 +48,15 @@ const (
ServerReadHeaderTimeout = 3 * time.Second
ArtistInfoTimeToLive = 24 * time.Hour
ArtistInfoTimeToLive = time.Second
//ArtistInfoTimeToLive = 24 * time.Hour
I18nFolder = "i18n"
SkipScanFile = ".ndignore"
PlaceholderAlbumArt = "placeholder.png"
PlaceholderAvatar = "logo-192x192.png"
PlaceholderArtistArt = "artist-placeholder.webp"
PlaceholderAlbumArt = "placeholder.png"
PlaceholderAvatar = "logo-192x192.png"
DefaultUIVolume = 100

View File

@ -9,4 +9,4 @@ A new agent must comply with these simple implementation rules:
For an agent to be used it needs to be listed in the `Agents` config option (default is `"lastfm,spotify"`). The order dictates the priority of the agents
For a simple Agent example, look at the [placeholders](placeholders.go) agent source code.
For a simple Agent example, look at the [local_agent](local_agent.go) agent source code.

View File

@ -22,7 +22,7 @@ func New(ds model.DataStore) *Agents {
if conf.Server.Agents != "" {
order = strings.Split(conf.Server.Agents, ",")
}
order = append(order, PlaceholderAgentName)
order = append(order, LocalAgentName)
var res []Interface
for _, name := range order {
init, ok := Map[name]

View File

@ -0,0 +1,49 @@
package agents
import (
"context"
"path/filepath"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/core/artwork"
"github.com/navidrome/navidrome/model"
)
const LocalAgentName = "local"
const (
localBiography = "Biography not available"
)
type localAgent struct{}
func localsConstructor(_ model.DataStore) Interface {
return &localAgent{}
}
func (p *localAgent) AgentName() string {
return LocalAgentName
}
func (p *localAgent) GetBiography(ctx context.Context, id, name, mbid string) (string, error) {
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) artistImage(id string, size int) ArtistImage {
return ArtistImage{
filepath.Join(consts.URLPathPublicImages, artwork.Public(model.NewArtworkID(model.KindArtistArtwork, id), size)),
size,
}
}
func init() {
Register(LocalAgentName, localsConstructor)
}

View File

@ -1,43 +0,0 @@
package agents
import (
"context"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/model"
)
const PlaceholderAgentName = "placeholder"
const (
placeholderArtistImageSmallUrl = consts.URLPathUI + "/artist-placeholder.webp"
placeholderArtistImageMediumUrl = consts.URLPathUI + "/artist-placeholder.webp"
placeholderArtistImageLargeUrl = consts.URLPathUI + "/artist-placeholder.webp"
placeholderBiography = "Biography not available"
)
type placeholderAgent struct{}
func placeholdersConstructor(_ model.DataStore) Interface {
return &placeholderAgent{}
}
func (p *placeholderAgent) AgentName() string {
return PlaceholderAgentName
}
func (p *placeholderAgent) GetBiography(ctx context.Context, id, name, mbid string) (string, error) {
return placeholderBiography, nil
}
func (p *placeholderAgent) GetImages(ctx context.Context, id, name, mbid string) ([]ArtistImage, error) {
return []ArtistImage{
{placeholderArtistImageLargeUrl, 300},
{placeholderArtistImageMediumUrl, 174},
{placeholderArtistImageSmallUrl, 64},
}, nil
}
func init() {
Register(PlaceholderAgentName, placeholdersConstructor)
}

View File

@ -7,6 +7,7 @@ import (
"io"
"time"
"github.com/navidrome/navidrome/core/auth"
"github.com/navidrome/navidrome/core/ffmpeg"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
@ -73,6 +74,9 @@ func (a *artwork) getArtworkId(ctx context.Context, id string) (model.ArtworkID,
return model.ArtworkID{}, err
}
switch e := entity.(type) {
case *model.Artist:
artID = model.NewArtworkID(model.KindArtistArtwork, e.ID)
log.Trace(ctx, "ID is for an Artist", "id", id, "name", e.Name, "artist", e.Name)
case *model.Album:
artID = model.NewArtworkID(model.KindAlbumArtwork, e.ID)
log.Trace(ctx, "ID is for an Album", "id", id, "name", e.Name, "artist", e.AlbumArtist)
@ -93,6 +97,8 @@ func (a *artwork) getArtworkReader(ctx context.Context, artID model.ArtworkID, s
artReader, err = resizedFromOriginal(ctx, a, artID, size)
} else {
switch artID.Kind {
case model.KindArtistArtwork:
artReader, err = newArtistReader(ctx, a, artID)
case model.KindAlbumArtwork:
artReader, err = newAlbumArtworkReader(ctx, a, artID)
case model.KindMediaFileArtwork:
@ -105,3 +111,11 @@ func (a *artwork) getArtworkReader(ctx context.Context, artID model.ArtworkID, s
}
return artReader, err
}
func Public(artID model.ArtworkID, size int) string {
token, _ := auth.CreatePublicToken(map[string]any{
"id": artID.String(),
"size": size,
})
return token
}

View File

@ -37,7 +37,7 @@ func (a *albumArtworkReader) LastUpdated() time.Time {
func (a *albumArtworkReader) Reader(ctx context.Context) (io.ReadCloser, string, error) {
var ff = fromCoverArtPriority(ctx, a.a.ffmpeg, conf.Server.CoverArtPriority, a.album)
ff = append(ff, fromPlaceholder())
ff = append(ff, fromAlbumPlaceholder())
return selectImageReader(ctx, a.artID, ff...)
}

View File

@ -0,0 +1,35 @@
package artwork
import (
"context"
"fmt"
"io"
"time"
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/model"
)
type artistReader struct {
artID model.ArtworkID
}
func newArtistReader(_ context.Context, _ *artwork, artID model.ArtworkID) (*artistReader, error) {
a := &artistReader{
artID: artID,
}
return a, nil
}
func (a *artistReader) LastUpdated() time.Time {
return consts.ServerStart // Invalidate cached placeholder every server start
}
func (a *artistReader) Key() string {
return fmt.Sprintf("placeholder.%d.0.%d", a.LastUpdated().UnixMilli(), conf.Server.CoverJpegQuality)
}
func (a *artistReader) Reader(ctx context.Context) (io.ReadCloser, string, error) {
return selectImageReader(ctx, a.artID, fromArtistPlaceholder())
}

View File

@ -31,5 +31,5 @@ func (a *emptyIDReader) Key() string {
}
func (a *emptyIDReader) Reader(ctx context.Context) (io.ReadCloser, string, error) {
return selectImageReader(ctx, a.artID, fromPlaceholder())
return selectImageReader(ctx, a.artID, fromAlbumPlaceholder())
}

View File

@ -53,13 +53,3 @@ func (a *mediafileArtworkReader) Reader(ctx context.Context) (io.ReadCloser, str
ff = append(ff, fromAlbum(ctx, a.a, a.mediafile.AlbumCoverArtID()))
return selectImageReader(ctx, a.artID, ff...)
}
func fromAlbum(ctx context.Context, a *artwork, id model.ArtworkID) sourceFunc {
return func() (io.ReadCloser, string, error) {
r, _, err := a.Get(ctx, id.String(), 0)
if err != nil {
return nil, "", err
}
return r, id.String(), nil
}
}

View File

@ -49,7 +49,7 @@ func (a *playlistArtworkReader) Reader(ctx context.Context) (io.ReadCloser, stri
if err == nil {
ff = append(ff, a.fromGeneratedTile(ctx, pl.Tracks))
}
ff = append(ff, fromPlaceholder())
ff = append(ff, fromAlbumPlaceholder())
return selectImageReader(ctx, a.artID, ff...)
}

View File

@ -112,9 +112,26 @@ func fromFFmpegTag(ctx context.Context, ffmpeg ffmpeg.FFmpeg, path string) sourc
}
}
func fromPlaceholder() sourceFunc {
func fromAlbum(ctx context.Context, a *artwork, id model.ArtworkID) sourceFunc {
return func() (io.ReadCloser, string, error) {
r, _, err := a.Get(ctx, id.String(), 0)
if err != nil {
return nil, "", err
}
return r, id.String(), nil
}
}
func fromAlbumPlaceholder() sourceFunc {
return func() (io.ReadCloser, string, error) {
r, _ := resources.FS().Open(consts.PlaceholderAlbumArt)
return r, consts.PlaceholderAlbumArt, nil
}
}
func fromArtistPlaceholder() sourceFunc {
return func() (io.ReadCloser, string, error) {
r, _ := resources.FS().Open(consts.PlaceholderArtistArt)
return r, consts.PlaceholderArtistArt, nil
}
}

View File

@ -12,13 +12,15 @@ type Kind struct{ prefix string }
var (
KindMediaFileArtwork = Kind{"mf"}
KindArtistArtwork = Kind{"ar"}
KindAlbumArtwork = Kind{"al"}
KindPlaylistArtwork = Kind{"pl"}
)
var artworkKindList = []string{
KindAlbumArtwork.prefix,
KindMediaFileArtwork.prefix,
KindArtistArtwork.prefix,
KindAlbumArtwork.prefix,
KindPlaylistArtwork.prefix,
}

View File

Before

Width:  |  Height:  |  Size: 546 B

After

Width:  |  Height:  |  Size: 546 B

View File

@ -3,7 +3,6 @@ package public
import (
"context"
"errors"
"fmt"
"io"
"net/http"
"time"
@ -27,15 +26,6 @@ func New(artwork artwork.Artwork) *Router {
p := &Router{artwork: artwork}
p.Handler = p.routes()
t, err := auth.CreatePublicToken(map[string]any{
"id": "al-ee07551e7371500da55e23ae8520f1d8",
"size": 300,
})
if err != nil {
panic(err)
}
fmt.Println("!!!!!!!!!!!!!!!!!", t, "!!!!!!!!!!!!!!!!")
return p
}