Jorge Pardo Pardo 85e9982b43
feat(plugins): add path to Scrobbler and Lyrics plugin TrackInfo (#5339)
* feat: add Path to TrackInfo struct

* refactor: improve naming to follow the rest of the code

* test: add tests

* fix: actually check for filesystem permission

* refactor: remove library logic from specific plugins

* refactor: move hasFilesystemPermission to a Manifest method

* test(plugins): add unit tests for hasLibraryFilesystemAccess method

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor(plugins): remove hasFilesystemPerm field and use manifest for filesystem permission checks

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor(plugins): streamline library filesystem access checks in lyrics and scrobbler adapters

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
2026-04-12 10:27:58 -04:00

110 lines
4.2 KiB
Go

package capabilities
// Scrobbler provides scrobbling functionality to external services.
// This capability allows plugins to submit listening history to services like Last.fm,
// ListenBrainz, or custom scrobbling backends.
//
// All methods are required - plugins implementing this capability must provide
// all three functions: IsAuthorized, NowPlaying, and Scrobble.
//
//nd:capability name=scrobbler required=true
type Scrobbler interface {
// IsAuthorized checks if a user is authorized to scrobble to this service.
//nd:export name=nd_scrobbler_is_authorized
IsAuthorized(IsAuthorizedRequest) (bool, error)
// NowPlaying sends a now playing notification to the scrobbling service.
//nd:export name=nd_scrobbler_now_playing
NowPlaying(NowPlayingRequest) error
// Scrobble submits a completed scrobble to the scrobbling service.
//nd:export name=nd_scrobbler_scrobble
Scrobble(ScrobbleRequest) error
}
// IsAuthorizedRequest is the request for authorization check.
type IsAuthorizedRequest struct {
// Username is the username of the user.
Username string `json:"username"`
}
// ArtistRef is a reference to an artist with name and optional MBID.
type ArtistRef struct {
// ID is the internal Navidrome artist ID (if known).
ID string `json:"id,omitempty"`
// Name is the artist name.
Name string `json:"name"`
// MBID is the MusicBrainz ID for the artist.
MBID string `json:"mbid,omitempty"`
}
// TrackInfo contains track metadata.
type TrackInfo struct {
// ID is the internal Navidrome track ID.
ID string `json:"id"`
// Title is the track title.
Title string `json:"title"`
// Album is the album name.
Album string `json:"album"`
// Artist is the formatted artist name for display (e.g., "Artist1 • Artist2").
Artist string `json:"artist"`
// AlbumArtist is the formatted album artist name for display.
AlbumArtist string `json:"albumArtist"`
// Artists is the list of track artists.
Artists []ArtistRef `json:"artists"`
// AlbumArtists is the list of album artists.
AlbumArtists []ArtistRef `json:"albumArtists"`
// Duration is the track duration in seconds.
Duration float32 `json:"duration"`
// TrackNumber is the track number on the album.
TrackNumber int32 `json:"trackNumber"`
// DiscNumber is the disc number.
DiscNumber int32 `json:"discNumber"`
// MBZRecordingID is the MusicBrainz recording ID.
MBZRecordingID string `json:"mbzRecordingId,omitempty"`
// MBZAlbumID is the MusicBrainz album/release ID.
MBZAlbumID string `json:"mbzAlbumId,omitempty"`
// MBZReleaseGroupID is the MusicBrainz release group ID.
MBZReleaseGroupID string `json:"mbzReleaseGroupId,omitempty"`
// MBZReleaseTrackID is the MusicBrainz release track ID.
MBZReleaseTrackID string `json:"mbzReleaseTrackId,omitempty"`
// Path is the full path to the track file, relative to the library root.
// Only included if the plugin has library permission with filesystem access for the track's library.
Path string `json:"path,omitempty"`
}
// NowPlayingRequest is the request for now playing notification.
type NowPlayingRequest struct {
// Username is the username of the user.
Username string `json:"username"`
// Track is the track currently playing.
Track TrackInfo `json:"track"`
// Position is the current playback position in seconds.
Position int32 `json:"position"`
}
// ScrobbleRequest is the request for submitting a scrobble.
type ScrobbleRequest struct {
// Username is the username of the user.
Username string `json:"username"`
// Track is the track that was played.
Track TrackInfo `json:"track"`
// Timestamp is the Unix timestamp when the track started playing.
Timestamp int64 `json:"timestamp"`
}
// ScrobblerError represents an error type for scrobbling operations.
type ScrobblerError string
const (
// ScrobblerErrorNotAuthorized indicates the user is not authorized.
ScrobblerErrorNotAuthorized ScrobblerError = "scrobbler(not_authorized)"
// ScrobblerErrorRetryLater indicates the operation should be retried later.
ScrobblerErrorRetryLater ScrobblerError = "scrobbler(retry_later)"
// ScrobblerErrorUnrecoverable indicates an unrecoverable error.
ScrobblerErrorUnrecoverable ScrobblerError = "scrobbler(unrecoverable)"
)
// Error implements the error interface for ScrobblerError.
func (e ScrobblerError) Error() string { return string(e) }