mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
feat(plugins): add metadata agent and scrobbler schemas for bootstrapping plugins
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
1733129537
commit
9481ba3662
176
plugins/schemas/README.md
Normal file
176
plugins/schemas/README.md
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
# Navidrome Plugin Schemas
|
||||||
|
|
||||||
|
This directory contains [XTP schemas](https://docs.xtp.dylibso.com/docs/concepts/xtp-schema)
|
||||||
|
that define the plugin capabilities for Navidrome. These schemas can be used to bootstrap
|
||||||
|
new plugins using the `xtp` CLI tool.
|
||||||
|
|
||||||
|
## Available Schemas
|
||||||
|
|
||||||
|
| Schema | Description |
|
||||||
|
|--------------------------------------------|-----------------------------------------------------------------|
|
||||||
|
| [metadata_agent.yaml](metadata_agent.yaml) | Metadata agent for retrieving artist/album information |
|
||||||
|
| [scrobbler.yaml](scrobbler.yaml) | Scrobbler capability for sending play data to external services |
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Install the `xtp` CLI tool. See the [XTP CLI documentation](https://docs.xtp.dylibso.com/docs/cli)
|
||||||
|
for installation instructions, or install via:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://static.dylibso.com/cli/install.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bootstrapping a Plugin
|
||||||
|
|
||||||
|
Use the `xtp plugin init` command to generate boilerplate code from a schema.
|
||||||
|
|
||||||
|
### Supported Languages
|
||||||
|
|
||||||
|
The XTP CLI supports multiple languages via bindgen templates:
|
||||||
|
- Go
|
||||||
|
- Rust
|
||||||
|
- TypeScript
|
||||||
|
- Python
|
||||||
|
- C#
|
||||||
|
- Zig
|
||||||
|
- C++
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
**Create a Go scrobbler plugin:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xtp plugin init \
|
||||||
|
--schema-file plugins/schemas/scrobbler.yaml \
|
||||||
|
--template go \
|
||||||
|
--path ./my-scrobbler \
|
||||||
|
--name my-scrobbler
|
||||||
|
```
|
||||||
|
|
||||||
|
**Create a Rust metadata agent plugin:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xtp plugin init \
|
||||||
|
--schema-file plugins/schemas/metadata_agent.yaml \
|
||||||
|
--template rust \
|
||||||
|
--path ./my-agent \
|
||||||
|
--name my-agent
|
||||||
|
```
|
||||||
|
|
||||||
|
**Create a TypeScript scrobbler plugin:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xtp plugin init \
|
||||||
|
--schema-file plugins/schemas/scrobbler.yaml \
|
||||||
|
--template typescript \
|
||||||
|
--path ./ts-scrobbler \
|
||||||
|
--name ts-scrobbler
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generated Files
|
||||||
|
|
||||||
|
After running `xtp plugin init`, you'll get a project structure with:
|
||||||
|
|
||||||
|
- `main.go` (or equivalent for your language) - Plugin implementation with stub functions
|
||||||
|
- `pdk.gen.go` - Generated types from the schema
|
||||||
|
- `xtp.toml` - Plugin configuration
|
||||||
|
- Build scripts for your language
|
||||||
|
|
||||||
|
### Implementing the Plugin
|
||||||
|
|
||||||
|
Edit the generated `main.go` file and replace the `panic()` calls with your implementation.
|
||||||
|
|
||||||
|
> **Note:** You don't need to implement all generated functions. Remove any functions that
|
||||||
|
> your plugin doesn't need. Navidrome will only call the functions that are exported by your
|
||||||
|
> plugin, and will gracefully handle missing capabilities.
|
||||||
|
|
||||||
|
#### Required: The `nd_manifest` Function
|
||||||
|
|
||||||
|
In addition to the capability functions generated from the schema, **every plugin must
|
||||||
|
implement the `nd_manifest` function**. This function returns metadata about your plugin
|
||||||
|
that Navidrome uses to identify and describe it.
|
||||||
|
|
||||||
|
**Go example:**
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/extism/go-pdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Manifest struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Author string `json:"author"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:wasmexport nd_manifest
|
||||||
|
func ndManifest() int32 {
|
||||||
|
manifest := Manifest{
|
||||||
|
Name: "My Scrobbler Plugin",
|
||||||
|
Author: "Your Name",
|
||||||
|
Version: "1.0.0",
|
||||||
|
Description: "A custom scrobbler for My Service",
|
||||||
|
}
|
||||||
|
out, err := json.Marshal(manifest)
|
||||||
|
if err != nil {
|
||||||
|
pdk.SetError(err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
pdk.Output(out)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Python example:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
import extism
|
||||||
|
|
||||||
|
@extism.plugin_fn
|
||||||
|
def nd_manifest():
|
||||||
|
import json
|
||||||
|
manifest = {
|
||||||
|
"name": "My Scrobbler Plugin",
|
||||||
|
"author": "Your Name",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A custom scrobbler for My Service"
|
||||||
|
}
|
||||||
|
extism.output_str(json.dumps(manifest))
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Implementing Capability Functions
|
||||||
|
|
||||||
|
Replace the `panic()` calls in the generated stubs with your implementation:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Example: Implement the IsAuthorized function
|
||||||
|
func NdScrobblerIsAuthorized(input AuthInput) (AuthOutput, error) {
|
||||||
|
// Your authorization logic here
|
||||||
|
authorized := checkUserAuthorization(input.UserID, input.Username)
|
||||||
|
return AuthOutput{Authorized: authorized}, nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building the Plugin
|
||||||
|
|
||||||
|
Build the plugin to WebAssembly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xtp plugin build
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a `.wasm` file that can be loaded by Navidrome.
|
||||||
|
|
||||||
|
## Schema Format
|
||||||
|
|
||||||
|
These schemas use the [XTP Schema v1-draft](https://docs.xtp.dylibso.com/docs/concepts/xtp-schema) format,
|
||||||
|
which is based on JSON Schema with extensions for defining plugin exports and imports.
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [XTP Documentation](https://docs.xtp.dylibso.com/)
|
||||||
|
- [XTP Bindgen Repository](https://github.com/dylibso/xtp-bindgen)
|
||||||
|
- [Extism Plugin Development Kit](https://extism.org/docs/concepts/pdk)
|
||||||
|
- [XTP Schema Definition](https://raw.githubusercontent.com/dylibso/xtp-bindgen/5090518dd86ba5e734dc225a33066ecc0ed2e12d/plugin/schema.json)
|
||||||
299
plugins/schemas/metadata_agent.yaml
Normal file
299
plugins/schemas/metadata_agent.yaml
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
version: v1-draft
|
||||||
|
|
||||||
|
exports:
|
||||||
|
nd_get_artist_mbid:
|
||||||
|
description: Retrieve the MusicBrainz ID for an artist
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/ArtistMBIDInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/ArtistMBIDOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_get_artist_url:
|
||||||
|
description: Retrieve the external URL for an artist
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/ArtistInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/ArtistURLOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_get_artist_biography:
|
||||||
|
description: Retrieve the biography for an artist
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/ArtistInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/ArtistBiographyOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_get_similar_artists:
|
||||||
|
description: Retrieve similar artists for a given artist
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/SimilarArtistsInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/SimilarArtistsOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_get_artist_images:
|
||||||
|
description: Retrieve images for an artist
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/ArtistInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/ArtistImagesOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_get_artist_top_songs:
|
||||||
|
description: Retrieve top songs for an artist
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/TopSongsInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/TopSongsOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_get_album_info:
|
||||||
|
description: Retrieve album information
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/AlbumInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/AlbumInfoOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_get_album_images:
|
||||||
|
description: Retrieve images for an album
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/AlbumInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/AlbumImagesOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
ArtistMBIDInput:
|
||||||
|
description: Input for GetArtistMBID
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: The internal Navidrome artist ID
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The artist name
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
|
||||||
|
ArtistMBIDOutput:
|
||||||
|
description: Output for GetArtistMBID
|
||||||
|
properties:
|
||||||
|
mbid:
|
||||||
|
type: string
|
||||||
|
description: The MusicBrainz ID for the artist
|
||||||
|
required:
|
||||||
|
- mbid
|
||||||
|
|
||||||
|
ArtistInput:
|
||||||
|
description: Common input for artist-related functions
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: The internal Navidrome artist ID
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The artist name
|
||||||
|
mbid:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: The MusicBrainz ID for the artist (if known)
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
|
||||||
|
ArtistURLOutput:
|
||||||
|
description: Output for GetArtistURL
|
||||||
|
properties:
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
description: The external URL for the artist
|
||||||
|
required:
|
||||||
|
- url
|
||||||
|
|
||||||
|
ArtistBiographyOutput:
|
||||||
|
description: Output for GetArtistBiography
|
||||||
|
properties:
|
||||||
|
biography:
|
||||||
|
type: string
|
||||||
|
description: The artist biography text
|
||||||
|
required:
|
||||||
|
- biography
|
||||||
|
|
||||||
|
SimilarArtistsInput:
|
||||||
|
description: Input for GetSimilarArtists
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: The internal Navidrome artist ID
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The artist name
|
||||||
|
mbid:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: The MusicBrainz ID for the artist (if known)
|
||||||
|
limit:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
description: Maximum number of similar artists to return
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- limit
|
||||||
|
|
||||||
|
ArtistRef:
|
||||||
|
description: Reference to an artist with name and optional MBID
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The artist name
|
||||||
|
mbid:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: The MusicBrainz ID for the artist
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
|
||||||
|
SimilarArtistsOutput:
|
||||||
|
description: Output for GetSimilarArtists
|
||||||
|
properties:
|
||||||
|
artists:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/ArtistRef"
|
||||||
|
description: List of similar artists
|
||||||
|
required:
|
||||||
|
- artists
|
||||||
|
|
||||||
|
ImageInfo:
|
||||||
|
description: Image with URL and size
|
||||||
|
properties:
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
description: The URL of the image
|
||||||
|
size:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
description: The size of the image in pixels (width or height)
|
||||||
|
required:
|
||||||
|
- url
|
||||||
|
- size
|
||||||
|
|
||||||
|
ArtistImagesOutput:
|
||||||
|
description: Output for GetArtistImages
|
||||||
|
properties:
|
||||||
|
images:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/ImageInfo"
|
||||||
|
description: List of artist images
|
||||||
|
required:
|
||||||
|
- images
|
||||||
|
|
||||||
|
TopSongsInput:
|
||||||
|
description: Input for GetArtistTopSongs
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: The internal Navidrome artist ID
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The artist name
|
||||||
|
mbid:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: The MusicBrainz ID for the artist (if known)
|
||||||
|
count:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
description: Maximum number of top songs to return
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- count
|
||||||
|
|
||||||
|
SongRef:
|
||||||
|
description: Reference to a song with name and optional MBID
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The song name
|
||||||
|
mbid:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: The MusicBrainz ID for the song
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
|
||||||
|
TopSongsOutput:
|
||||||
|
description: Output for GetArtistTopSongs
|
||||||
|
properties:
|
||||||
|
songs:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/SongRef"
|
||||||
|
description: List of top songs
|
||||||
|
required:
|
||||||
|
- songs
|
||||||
|
|
||||||
|
AlbumInput:
|
||||||
|
description: Common input for album-related functions
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The album name
|
||||||
|
artist:
|
||||||
|
type: string
|
||||||
|
description: The album artist name
|
||||||
|
mbid:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: The MusicBrainz ID for the album (if known)
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- artist
|
||||||
|
|
||||||
|
AlbumInfoOutput:
|
||||||
|
description: Output for GetAlbumInfo
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The album name
|
||||||
|
mbid:
|
||||||
|
type: string
|
||||||
|
description: The MusicBrainz ID for the album
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
description: The album description/notes
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
description: The external URL for the album
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- mbid
|
||||||
|
- description
|
||||||
|
- url
|
||||||
|
|
||||||
|
AlbumImagesOutput:
|
||||||
|
description: Output for GetAlbumImages
|
||||||
|
properties:
|
||||||
|
images:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/ImageInfo"
|
||||||
|
description: List of album images
|
||||||
|
required:
|
||||||
|
- images
|
||||||
182
plugins/schemas/scrobbler.yaml
Normal file
182
plugins/schemas/scrobbler.yaml
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
version: v1-draft
|
||||||
|
|
||||||
|
exports:
|
||||||
|
nd_scrobbler_is_authorized:
|
||||||
|
description: Check if a user is authorized to scrobble to this service
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/AuthInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/AuthOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_scrobbler_now_playing:
|
||||||
|
description: Send a now playing notification to the scrobbling service
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/NowPlayingInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/ScrobblerOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
nd_scrobbler_scrobble:
|
||||||
|
description: Submit a completed scrobble to the scrobbling service
|
||||||
|
input:
|
||||||
|
$ref: "#/components/schemas/ScrobbleInput"
|
||||||
|
contentType: application/json
|
||||||
|
output:
|
||||||
|
$ref: "#/components/schemas/ScrobblerOutput"
|
||||||
|
contentType: application/json
|
||||||
|
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
AuthInput:
|
||||||
|
description: Input for authorization check
|
||||||
|
properties:
|
||||||
|
user_id:
|
||||||
|
type: string
|
||||||
|
description: The internal Navidrome user ID
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
description: The username of the user
|
||||||
|
required:
|
||||||
|
- user_id
|
||||||
|
- username
|
||||||
|
|
||||||
|
AuthOutput:
|
||||||
|
description: Output for authorization check
|
||||||
|
properties:
|
||||||
|
authorized:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the user is authorized to scrobble
|
||||||
|
required:
|
||||||
|
- authorized
|
||||||
|
|
||||||
|
TrackInfo:
|
||||||
|
description: Track metadata for scrobbling
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: The internal Navidrome track ID
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
description: Track title
|
||||||
|
album:
|
||||||
|
type: string
|
||||||
|
description: Album name
|
||||||
|
artist:
|
||||||
|
type: string
|
||||||
|
description: Track artist
|
||||||
|
album_artist:
|
||||||
|
type: string
|
||||||
|
description: Album artist
|
||||||
|
duration:
|
||||||
|
type: number
|
||||||
|
format: float
|
||||||
|
description: Track duration in seconds
|
||||||
|
track_number:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
description: Track number on the album
|
||||||
|
disc_number:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
description: Disc number
|
||||||
|
mbz_recording_id:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: MusicBrainz recording ID
|
||||||
|
mbz_album_id:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: MusicBrainz album/release ID
|
||||||
|
mbz_artist_id:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: MusicBrainz artist ID
|
||||||
|
mbz_release_group_id:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: MusicBrainz release group ID
|
||||||
|
mbz_album_artist_id:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: MusicBrainz album artist ID
|
||||||
|
mbz_release_track_id:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: MusicBrainz release track ID
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- title
|
||||||
|
- album
|
||||||
|
- artist
|
||||||
|
- album_artist
|
||||||
|
- duration
|
||||||
|
- track_number
|
||||||
|
- disc_number
|
||||||
|
|
||||||
|
NowPlayingInput:
|
||||||
|
description: Input for now playing notification
|
||||||
|
properties:
|
||||||
|
user_id:
|
||||||
|
type: string
|
||||||
|
description: The internal Navidrome user ID
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
description: The username of the user
|
||||||
|
track:
|
||||||
|
$ref: "#/components/schemas/TrackInfo"
|
||||||
|
description: The track currently playing
|
||||||
|
position:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
description: Current playback position in seconds
|
||||||
|
required:
|
||||||
|
- user_id
|
||||||
|
- username
|
||||||
|
- track
|
||||||
|
- position
|
||||||
|
|
||||||
|
ScrobbleInput:
|
||||||
|
description: Input for submitting a scrobble
|
||||||
|
properties:
|
||||||
|
user_id:
|
||||||
|
type: string
|
||||||
|
description: The internal Navidrome user ID
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
description: The username of the user
|
||||||
|
track:
|
||||||
|
$ref: "#/components/schemas/TrackInfo"
|
||||||
|
description: The track that was played
|
||||||
|
timestamp:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: Unix timestamp when the track started playing
|
||||||
|
required:
|
||||||
|
- user_id
|
||||||
|
- username
|
||||||
|
- track
|
||||||
|
- timestamp
|
||||||
|
|
||||||
|
ScrobblerOutput:
|
||||||
|
description: Output for scrobbler operations (now_playing and scrobble)
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: Error message if the operation failed
|
||||||
|
error_type:
|
||||||
|
$ref: "#/components/schemas/ScrobblerErrorType"
|
||||||
|
nullable: true
|
||||||
|
description: Type of error for handling
|
||||||
|
|
||||||
|
ScrobblerErrorType:
|
||||||
|
type: string
|
||||||
|
description: Error type indicating how Navidrome should handle the error
|
||||||
|
enum:
|
||||||
|
- none
|
||||||
|
- not_authorized
|
||||||
|
- retry_later
|
||||||
|
- unrecoverable
|
||||||
Loading…
x
Reference in New Issue
Block a user