mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
* 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>
201 lines
6.3 KiB
Go
201 lines
6.3 KiB
Go
// Code generated by ndpgen. DO NOT EDIT.
|
|
//
|
|
// This file contains export wrappers for the Scrobbler capability.
|
|
// It is intended for use in Navidrome plugins built with TinyGo.
|
|
//
|
|
//go:build wasip1
|
|
|
|
package scrobbler
|
|
|
|
import (
|
|
"github.com/navidrome/navidrome/plugins/pdk/go/pdk"
|
|
)
|
|
|
|
// 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) }
|
|
|
|
// 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"`
|
|
}
|
|
|
|
// IsAuthorizedRequest is the request for authorization check.
|
|
type IsAuthorizedRequest struct {
|
|
// Username is the username of the user.
|
|
Username string `json:"username"`
|
|
}
|
|
|
|
// 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"`
|
|
}
|
|
|
|
// 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"`
|
|
}
|
|
|
|
// Scrobbler requires all methods to be implemented.
|
|
// 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.
|
|
type Scrobbler interface {
|
|
// IsAuthorized - IsAuthorized checks if a user is authorized to scrobble to this service.
|
|
IsAuthorized(IsAuthorizedRequest) (bool, error)
|
|
// NowPlaying - NowPlaying sends a now playing notification to the scrobbling service.
|
|
NowPlaying(NowPlayingRequest) error
|
|
// Scrobble - Scrobble submits a completed scrobble to the scrobbling service.
|
|
Scrobble(ScrobbleRequest) error
|
|
} // Internal implementation holders
|
|
var (
|
|
isAuthorizedImpl func(IsAuthorizedRequest) (bool, error)
|
|
nowPlayingImpl func(NowPlayingRequest) error
|
|
scrobbleImpl func(ScrobbleRequest) error
|
|
)
|
|
|
|
// Register registers a scrobbler implementation.
|
|
// All methods are required.
|
|
func Register(impl Scrobbler) {
|
|
isAuthorizedImpl = impl.IsAuthorized
|
|
nowPlayingImpl = impl.NowPlaying
|
|
scrobbleImpl = impl.Scrobble
|
|
}
|
|
|
|
// NotImplementedCode is the standard return code for unimplemented functions.
|
|
// The host recognizes this and skips the plugin gracefully.
|
|
const NotImplementedCode int32 = -2
|
|
|
|
//go:wasmexport nd_scrobbler_is_authorized
|
|
func _NdScrobblerIsAuthorized() int32 {
|
|
if isAuthorizedImpl == nil {
|
|
// Return standard code - host will skip this plugin gracefully
|
|
return NotImplementedCode
|
|
}
|
|
|
|
var input IsAuthorizedRequest
|
|
if err := pdk.InputJSON(&input); err != nil {
|
|
pdk.SetError(err)
|
|
return -1
|
|
}
|
|
|
|
output, err := isAuthorizedImpl(input)
|
|
if err != nil {
|
|
pdk.SetError(err)
|
|
return -1
|
|
}
|
|
|
|
if err := pdk.OutputJSON(output); err != nil {
|
|
pdk.SetError(err)
|
|
return -1
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
//go:wasmexport nd_scrobbler_now_playing
|
|
func _NdScrobblerNowPlaying() int32 {
|
|
if nowPlayingImpl == nil {
|
|
// Return standard code - host will skip this plugin gracefully
|
|
return NotImplementedCode
|
|
}
|
|
|
|
var input NowPlayingRequest
|
|
if err := pdk.InputJSON(&input); err != nil {
|
|
pdk.SetError(err)
|
|
return -1
|
|
}
|
|
|
|
if err := nowPlayingImpl(input); err != nil {
|
|
pdk.SetError(err)
|
|
return -1
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
//go:wasmexport nd_scrobbler_scrobble
|
|
func _NdScrobblerScrobble() int32 {
|
|
if scrobbleImpl == nil {
|
|
// Return standard code - host will skip this plugin gracefully
|
|
return NotImplementedCode
|
|
}
|
|
|
|
var input ScrobbleRequest
|
|
if err := pdk.InputJSON(&input); err != nil {
|
|
pdk.SetError(err)
|
|
return -1
|
|
}
|
|
|
|
if err := scrobbleImpl(input); err != nil {
|
|
pdk.SetError(err)
|
|
return -1
|
|
}
|
|
|
|
return 0
|
|
}
|