Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test JS code (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint i18n files (push) Has been cancelled
Pipeline: Test, Lint, Build / Check Docker configuration (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v5) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v6) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v7) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been cancelled
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been cancelled
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been cancelled
Pipeline: Test, Lint, Build / Package/Release (push) Has been cancelled
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
POEditor import / update-translations (push) Has been cancelled
152 lines
3.9 KiB
Go
152 lines
3.9 KiB
Go
//go:build wasip1
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/navidrome/navidrome/plugins/api"
|
|
"github.com/navidrome/navidrome/plugins/host/http"
|
|
)
|
|
|
|
type CoverArtArchiveAgent struct{}
|
|
|
|
var ErrNotFound = api.ErrNotFound
|
|
|
|
type caaImage struct {
|
|
Image string `json:"image"`
|
|
Front bool `json:"front"`
|
|
Types []string `json:"types"`
|
|
Thumbnails map[string]string `json:"thumbnails"`
|
|
}
|
|
|
|
var client = http.NewHttpService()
|
|
|
|
func (CoverArtArchiveAgent) GetAlbumImages(ctx context.Context, req *api.AlbumImagesRequest) (*api.AlbumImagesResponse, error) {
|
|
if req.Mbid == "" {
|
|
return nil, ErrNotFound
|
|
}
|
|
|
|
url := "https://coverartarchive.org/release/" + req.Mbid
|
|
resp, err := client.Get(ctx, &http.HttpRequest{Url: url, TimeoutMs: 5000})
|
|
if err != nil || resp.Status != 200 {
|
|
log.Printf("[CAA] Error getting album images from CoverArtArchive (status: %d): %v", resp.Status, err)
|
|
return nil, ErrNotFound
|
|
}
|
|
|
|
images, err := extractFrontImages(resp.Body)
|
|
if err != nil || len(images) == 0 {
|
|
return nil, ErrNotFound
|
|
}
|
|
return &api.AlbumImagesResponse{Images: images}, nil
|
|
}
|
|
|
|
func extractFrontImages(body []byte) ([]*api.ExternalImage, error) {
|
|
var data struct {
|
|
Images []caaImage `json:"images"`
|
|
}
|
|
if err := json.Unmarshal(body, &data); err != nil {
|
|
return nil, err
|
|
}
|
|
img := findFrontImage(data.Images)
|
|
if img == nil {
|
|
return nil, ErrNotFound
|
|
}
|
|
return buildImageList(img), nil
|
|
}
|
|
|
|
func findFrontImage(images []caaImage) *caaImage {
|
|
for i, img := range images {
|
|
if img.Front {
|
|
return &images[i]
|
|
}
|
|
}
|
|
for i, img := range images {
|
|
for _, t := range img.Types {
|
|
if t == "Front" {
|
|
return &images[i]
|
|
}
|
|
}
|
|
}
|
|
if len(images) > 0 {
|
|
return &images[0]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func buildImageList(img *caaImage) []*api.ExternalImage {
|
|
var images []*api.ExternalImage
|
|
// First, try numeric sizes only
|
|
for sizeStr, url := range img.Thumbnails {
|
|
if url == "" {
|
|
continue
|
|
}
|
|
size := 0
|
|
if _, err := fmt.Sscanf(sizeStr, "%d", &size); err == nil {
|
|
images = append(images, &api.ExternalImage{Url: url, Size: int32(size)})
|
|
}
|
|
}
|
|
// If no numeric sizes, fallback to large/small
|
|
if len(images) == 0 {
|
|
for sizeStr, url := range img.Thumbnails {
|
|
if url == "" {
|
|
continue
|
|
}
|
|
var size int
|
|
switch sizeStr {
|
|
case "large":
|
|
size = 500
|
|
case "small":
|
|
size = 250
|
|
default:
|
|
continue
|
|
}
|
|
images = append(images, &api.ExternalImage{Url: url, Size: int32(size)})
|
|
}
|
|
}
|
|
if len(images) == 0 && img.Image != "" {
|
|
images = append(images, &api.ExternalImage{Url: img.Image, Size: 0})
|
|
}
|
|
return images
|
|
}
|
|
|
|
func (CoverArtArchiveAgent) GetAlbumInfo(ctx context.Context, req *api.AlbumInfoRequest) (*api.AlbumInfoResponse, error) {
|
|
return nil, api.ErrNotImplemented
|
|
}
|
|
func (CoverArtArchiveAgent) GetArtistMBID(ctx context.Context, req *api.ArtistMBIDRequest) (*api.ArtistMBIDResponse, error) {
|
|
return nil, api.ErrNotImplemented
|
|
}
|
|
|
|
func (CoverArtArchiveAgent) GetArtistURL(ctx context.Context, req *api.ArtistURLRequest) (*api.ArtistURLResponse, error) {
|
|
return nil, api.ErrNotImplemented
|
|
}
|
|
|
|
func (CoverArtArchiveAgent) GetArtistBiography(ctx context.Context, req *api.ArtistBiographyRequest) (*api.ArtistBiographyResponse, error) {
|
|
return nil, api.ErrNotImplemented
|
|
}
|
|
|
|
func (CoverArtArchiveAgent) GetSimilarArtists(ctx context.Context, req *api.ArtistSimilarRequest) (*api.ArtistSimilarResponse, error) {
|
|
return nil, api.ErrNotImplemented
|
|
}
|
|
|
|
func (CoverArtArchiveAgent) GetArtistImages(ctx context.Context, req *api.ArtistImageRequest) (*api.ArtistImageResponse, error) {
|
|
return nil, api.ErrNotImplemented
|
|
}
|
|
|
|
func (CoverArtArchiveAgent) GetArtistTopSongs(ctx context.Context, req *api.ArtistTopSongsRequest) (*api.ArtistTopSongsResponse, error) {
|
|
return nil, api.ErrNotImplemented
|
|
}
|
|
|
|
func main() {}
|
|
|
|
func init() {
|
|
// Configure logging: No timestamps, no source file/line
|
|
log.SetFlags(0)
|
|
log.SetPrefix("[CAA] ")
|
|
|
|
api.RegisterMetadataAgent(CoverArtArchiveAgent{})
|
|
}
|