mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
docs: update README for .ndp plugin packaging and installation instructions
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
e52b757cd4
commit
4e392f7b07
@ -29,38 +29,41 @@ Navidrome supports WebAssembly (Wasm) plugins for extending functionality. Plugi
|
|||||||
|
|
||||||
### 1. Create a minimal plugin
|
### 1. Create a minimal plugin
|
||||||
|
|
||||||
|
Create `main.go`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/extism/go-pdk"
|
||||||
"encoding/json"
|
|
||||||
"github.com/extism/go-pdk"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:wasmexport nd_manifest
|
|
||||||
func ndManifest() int32 {
|
|
||||||
manifest := map[string]string{
|
|
||||||
"name": "My Plugin",
|
|
||||||
"author": "Your Name",
|
|
||||||
"version": "1.0.0",
|
|
||||||
}
|
|
||||||
out, _ := json.Marshal(manifest)
|
|
||||||
pdk.Output(out)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {}
|
func main() {}
|
||||||
|
|
||||||
|
// Implement your capability functions here
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Build with TinyGo
|
Create `manifest.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "My Plugin",
|
||||||
|
"author": "Your Name",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Build with TinyGo and package as .ndp
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tinygo build -o my-plugin.wasm -target wasip1 -buildmode=c-shared .
|
# Compile to WebAssembly
|
||||||
|
tinygo build -o plugin.wasm -target wasip1 -buildmode=c-shared .
|
||||||
|
|
||||||
|
# Package as .ndp (zip archive)
|
||||||
|
zip -j my-plugin.ndp manifest.json plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Install
|
### 3. Install
|
||||||
|
|
||||||
Copy `my-plugin.wasm` to your Navidrome plugins folder and enable plugins in your config:
|
Copy `my-plugin.ndp` to your Navidrome plugins folder and enable plugins in your config:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[Plugins]
|
[Plugins]
|
||||||
@ -74,23 +77,31 @@ Folder = "/path/to/plugins"
|
|||||||
|
|
||||||
### What is a Plugin?
|
### What is a Plugin?
|
||||||
|
|
||||||
A Navidrome plugin is a WebAssembly (`.wasm`) file that:
|
A Navidrome plugin is an `.ndp` package file (zip archive) containing:
|
||||||
|
|
||||||
1. **Exports `nd_manifest`** – Returns JSON describing the plugin
|
1. **`manifest.json`** – Plugin metadata (name, author, version, permissions)
|
||||||
2. **Exports capability functions** – Implements one or more capabilities
|
2. **`plugin.wasm`** – Compiled WebAssembly module with capability functions
|
||||||
|
|
||||||
|
### Plugin Package Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
my-plugin.ndp (zip archive)
|
||||||
|
├── manifest.json # Required: Plugin metadata
|
||||||
|
└── plugin.wasm # Required: Compiled WebAssembly module
|
||||||
|
```
|
||||||
|
|
||||||
### Plugin Naming
|
### Plugin Naming
|
||||||
|
|
||||||
Plugins are identified by their **filename** (without `.wasm` extension), not the manifest `name` field:
|
Plugins are identified by their **filename** (without `.ndp` extension), not the manifest `name` field:
|
||||||
|
|
||||||
- `my-plugin.wasm` → plugin ID is `my-plugin`
|
- `my-plugin.ndp` → plugin ID is `my-plugin`
|
||||||
- The manifest `name` is the display name shown in the UI
|
- The manifest `name` is the display name shown in the UI
|
||||||
|
|
||||||
This allows users to have multiple instances of the same plugin with different configs by renaming the files.
|
This allows users to have multiple instances of the same plugin with different configs by renaming the files.
|
||||||
|
|
||||||
### The Manifest
|
### The Manifest
|
||||||
|
|
||||||
Every plugin must export `nd_manifest` returning JSON:
|
Every plugin must include a `manifest.json` file. Example:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -110,8 +121,6 @@ Every plugin must export `nd_manifest` returning JSON:
|
|||||||
|
|
||||||
**Required fields:** `name`, `author`, `version`
|
**Required fields:** `name`, `author`, `version`
|
||||||
|
|
||||||
**Capabilities are auto-detected** from which functions your plugin exports. You don't declare them in the manifest.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Capabilities
|
## Capabilities
|
||||||
@ -572,12 +581,12 @@ Enabled = true
|
|||||||
Folder = "/path/to/plugins" # Default: DataFolder/plugins
|
Folder = "/path/to/plugins" # Default: DataFolder/plugins
|
||||||
AutoReload = true # Auto-reload on file changes (dev mode)
|
AutoReload = true # Auto-reload on file changes (dev mode)
|
||||||
LogLevel = "debug" # Plugin-specific log level
|
LogLevel = "debug" # Plugin-specific log level
|
||||||
CacheSize = "100MB" # Compilation cache size limit
|
CacheSize = "200MB" # Compilation cache size limit
|
||||||
```
|
```
|
||||||
|
|
||||||
### Plugin Configuration
|
### Plugin Configuration
|
||||||
|
|
||||||
Plugin configuration is managed through the Navidrome web UI. Navigate to the Plugins page, select a plugin, and edit its configuration as a JSON object with string key-value pairs.
|
Plugin configuration is managed through the Navidrome web UI. Navigate to the Plugins page, select a plugin, and edit its configuration as key-value pairs.
|
||||||
|
|
||||||
Access configuration values in your plugin:
|
Access configuration values in your plugin:
|
||||||
|
|
||||||
@ -607,8 +616,31 @@ Plugins can be written in any language that compiles to WebAssembly. We recommen
|
|||||||
```bash
|
```bash
|
||||||
# Install TinyGo: https://tinygo.org/getting-started/install/
|
# Install TinyGo: https://tinygo.org/getting-started/install/
|
||||||
|
|
||||||
# Build
|
# Build WebAssembly module
|
||||||
tinygo build -o my-plugin.wasm -target wasip1 -buildmode=c-shared .
|
tinygo build -o plugin.wasm -target wasip1 -buildmode=c-shared .
|
||||||
|
|
||||||
|
# Package as .ndp
|
||||||
|
zip -j my-plugin.ndp manifest.json plugin.wasm
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build WebAssembly module
|
||||||
|
cargo build --release --target wasm32-unknown-unknown
|
||||||
|
|
||||||
|
# Package as .ndp
|
||||||
|
zip -j my-plugin.ndp manifest.json target/wasm32-unknown-unknown/release/plugin.wasm
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python (with extism-py)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build WebAssembly module (requires extism-py installed)
|
||||||
|
extism-py plugin.wasm -o plugin.wasm *.py
|
||||||
|
|
||||||
|
# Package as .ndp
|
||||||
|
zip -j my-plugin.ndp manifest.json plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using XTP CLI (Scaffolding)
|
### Using XTP CLI (Scaffolding)
|
||||||
@ -625,8 +657,9 @@ xtp plugin init \
|
|||||||
--path ./my-agent \
|
--path ./my-agent \
|
||||||
--name my-agent
|
--name my-agent
|
||||||
|
|
||||||
# Build
|
# Build and package
|
||||||
cd my-agent && xtp plugin build
|
cd my-agent && xtp plugin build
|
||||||
|
zip -j my-agent.ndp manifest.json dist/plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
See [schemas/README.md](schemas/README.md) for available schemas.
|
See [schemas/README.md](schemas/README.md) for available schemas.
|
||||||
@ -671,16 +704,18 @@ Plugins run in a secure WebAssembly sandbox:
|
|||||||
|
|
||||||
## Runtime Management
|
## Runtime Management
|
||||||
|
|
||||||
### Auto-Reload (Development)
|
### Auto-Reload
|
||||||
|
|
||||||
With `AutoReload = true`, Navidrome watches the plugins folder and automatically reloads plugins when files change.
|
With `AutoReload = true`, Navidrome watches the plugins folder and automatically detects when `.ndp` files are added, modified, or removed. When a plugin file changes, the plugin is disabled and its metadata is re-read from the archive.
|
||||||
|
|
||||||
### Programmatic Control
|
If the `AutoReload` setting is disabled, Navidrome needs to be restarted to pick up plugin changes.
|
||||||
|
|
||||||
Plugins can be enabled/disabled via the Navidrome UI or API. The plugin state is persisted in the database.
|
### Enabling/Disabling Plugins
|
||||||
|
|
||||||
|
Plugins can be enabled/disabled via the Navidrome UI. The plugin state is persisted in the database.
|
||||||
|
|
||||||
### Important Notes
|
### Important Notes
|
||||||
|
|
||||||
- **In-flight requests** – When reloading, existing requests complete before the new version takes over
|
- **In-flight requests** – When reloading, existing requests complete before the new version takes over
|
||||||
- **Config changes** – Plugin configuration is read at load time; changes require a reload
|
- **Config changes** – Changes to the plugin configuration in the UI are applied immediately
|
||||||
- **Cache persistence** – The in-memory cache is cleared when a plugin is unloaded
|
- **Cache persistence** – The in-memory cache is cleared when a plugin is unloaded
|
||||||
|
|||||||
@ -23,18 +23,20 @@ This folder contains example plugins demonstrating various capabilities and lang
|
|||||||
- **Python plugins:** [extism-py](https://github.com/extism/python-pdk)
|
- **Python plugins:** [extism-py](https://github.com/extism/python-pdk)
|
||||||
- **Rust plugins:** [Rust](https://rustup.rs/) with `wasm32-unknown-unknown` target
|
- **Rust plugins:** [Rust](https://rustup.rs/) with `wasm32-unknown-unknown` target
|
||||||
|
|
||||||
### Build All (Go plugins)
|
### Build All Plugins
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make all
|
make all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This creates `.ndp` package files for each plugin.
|
||||||
|
|
||||||
### Build Individual Plugin
|
### Build Individual Plugin
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make minimal.wasm
|
make minimal.ndp
|
||||||
make wikimedia.wasm
|
make wikimedia.ndp
|
||||||
make discord-rich-presence.wasm
|
make discord-rich-presence.ndp
|
||||||
```
|
```
|
||||||
|
|
||||||
### Clean
|
### Clean
|
||||||
@ -47,15 +49,15 @@ make clean
|
|||||||
|
|
||||||
### With Extism CLI
|
### With Extism CLI
|
||||||
|
|
||||||
Test any plugin without running Navidrome:
|
Test any plugin without running Navidrome. First extract the `.wasm` file from the `.ndp` package:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install: https://extism.org/docs/install
|
# Install: https://extism.org/docs/install
|
||||||
|
|
||||||
# Test manifest
|
# Extract the wasm file from the package
|
||||||
extism call minimal.wasm nd_manifest --wasi
|
unzip -p minimal.ndp plugin.wasm > minimal.wasm
|
||||||
|
|
||||||
# Test with input
|
# Test a capability function
|
||||||
extism call minimal.wasm nd_get_artist_biography --wasi \
|
extism call minimal.wasm nd_get_artist_biography --wasi \
|
||||||
--input '{"id":"1","name":"The Beatles"}'
|
--input '{"id":"1","name":"The Beatles"}'
|
||||||
```
|
```
|
||||||
@ -63,6 +65,7 @@ extism call minimal.wasm nd_get_artist_biography --wasi \
|
|||||||
For plugins that make HTTP requests, allow the hosts:
|
For plugins that make HTTP requests, allow the hosts:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
unzip -p wikimedia.ndp plugin.wasm > wikimedia.wasm
|
||||||
extism call wikimedia.wasm nd_get_artist_biography --wasi \
|
extism call wikimedia.wasm nd_get_artist_biography --wasi \
|
||||||
--input '{"id":"1","name":"Yussef Dayes"}' \
|
--input '{"id":"1","name":"Yussef Dayes"}' \
|
||||||
--allow-host "query.wikidata.org" \
|
--allow-host "query.wikidata.org" \
|
||||||
@ -71,7 +74,7 @@ extism call wikimedia.wasm nd_get_artist_biography --wasi \
|
|||||||
|
|
||||||
### With Navidrome
|
### With Navidrome
|
||||||
|
|
||||||
1. Copy the `.wasm` file to your plugins folder
|
1. Copy the `.ndp` file to your plugins folder
|
||||||
2. Enable plugins in `navidrome.toml`:
|
2. Enable plugins in `navidrome.toml`:
|
||||||
```toml
|
```toml
|
||||||
[Plugins]
|
[Plugins]
|
||||||
@ -92,8 +95,9 @@ Copy the [minimal](minimal/) example and modify:
|
|||||||
```bash
|
```bash
|
||||||
cp -r minimal my-plugin
|
cp -r minimal my-plugin
|
||||||
cd my-plugin
|
cd my-plugin
|
||||||
# Edit main.go
|
# Edit main.go and manifest.json
|
||||||
tinygo build -o my-plugin.wasm -target wasip1 -buildmode=c-shared .
|
tinygo build -o plugin.wasm -target wasip1 -buildmode=c-shared .
|
||||||
|
zip -j my-plugin.ndp manifest.json plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
### Option 2: Bootstrap with XTP CLI
|
### Option 2: Bootstrap with XTP CLI
|
||||||
@ -108,6 +112,11 @@ xtp plugin init \
|
|||||||
--template go \
|
--template go \
|
||||||
--path ./my-plugin \
|
--path ./my-plugin \
|
||||||
--name my-plugin
|
--name my-plugin
|
||||||
|
|
||||||
|
# Then create manifest.json and package
|
||||||
|
cd my-plugin
|
||||||
|
xtp plugin build
|
||||||
|
zip -j my-plugin.ndp manifest.json dist/plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
Available schemas in [../schemas/](../schemas/):
|
Available schemas in [../schemas/](../schemas/):
|
||||||
|
|||||||
@ -23,18 +23,19 @@ A Python example plugin that fetches album cover images from the [Cover Art Arch
|
|||||||
From the `plugins/examples` directory:
|
From the `plugins/examples` directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make coverartarchive-py.wasm
|
make coverartarchive-py.ndp
|
||||||
```
|
```
|
||||||
|
|
||||||
Or directly:
|
Or directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
extism-py plugin/__init__.py -o coverartarchive-py.wasm
|
extism-py plugin/__init__.py -o plugin.wasm
|
||||||
|
zip -j coverartarchive-py.ndp manifest.json plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Copy `coverartarchive-py.wasm` to your Navidrome plugins folder
|
1. Copy `coverartarchive-py.ndp` to your Navidrome plugins folder
|
||||||
|
|
||||||
2. Enable plugins in `navidrome.toml`:
|
2. Enable plugins in `navidrome.toml`:
|
||||||
```toml
|
```toml
|
||||||
@ -50,15 +51,10 @@ extism-py plugin/__init__.py -o coverartarchive-py.wasm
|
|||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Test the manifest:
|
Extract the wasm file and test:
|
||||||
|
|
||||||
```bash
|
|
||||||
extism call coverartarchive-py.wasm nd_manifest --wasi
|
|
||||||
```
|
|
||||||
|
|
||||||
Test album image retrieval (using Portishead's "Dummy" MBID):
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
unzip -p coverartarchive-py.ndp plugin.wasm > coverartarchive-py.wasm
|
||||||
extism call coverartarchive-py.wasm nd_get_album_images --wasi \
|
extism call coverartarchive-py.wasm nd_get_album_images --wasi \
|
||||||
--input '{"name":"Dummy","artist":"Portishead","mbid":"76df3287-6cda-33eb-8e9a-044b5e15ffdd"}' \
|
--input '{"name":"Dummy","artist":"Portishead","mbid":"76df3287-6cda-33eb-8e9a-044b5e15ffdd"}' \
|
||||||
--allow-host "coverartarchive.org" --allow-host "archive.org"
|
--allow-host "coverartarchive.org" --allow-host "archive.org"
|
||||||
|
|||||||
@ -14,15 +14,11 @@ This is a WebSocket-based WASM plugin for Navidrome that displays real-time cryp
|
|||||||
|
|
||||||
Configure in the Navidrome UI (Settings → Plugins → crypto-ticker):
|
Configure in the Navidrome UI (Settings → Plugins → crypto-ticker):
|
||||||
|
|
||||||
```json
|
| Key | Description | Default |
|
||||||
{
|
|-----------|----------------------------------------------------------------------|-----------|
|
||||||
"tickers": "BTC,ETH,SOL,MATIC"
|
| `tickers` | Comma-separated list of cryptocurrency symbols (e.g., `BTC,ETH,SOL`) | `BTC,ETH` |
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `tickers` is a comma-separated list of cryptocurrency symbols
|
The plugin will append `-USD` to any symbol without a trading pair specified.
|
||||||
- The plugin will append `-USD` to any symbol without a trading pair specified
|
|
||||||
- Default: `BTC,ETH` if not configured
|
|
||||||
|
|
||||||
## How it Works
|
## How it Works
|
||||||
|
|
||||||
@ -40,19 +36,23 @@ This plugin was scaffolded using XTP CLI:
|
|||||||
xtp plugin init --schema-file ../schemas/websocket_callback.yaml --template go --path ./crypto-ticker --name crypto-ticker
|
xtp plugin init --schema-file ../schemas/websocket_callback.yaml --template go --path ./crypto-ticker --name crypto-ticker
|
||||||
```
|
```
|
||||||
|
|
||||||
To build the plugin to WASM:
|
To build the plugin and package as `.ndp`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Using TinyGo (recommended - smaller binary)
|
# Using TinyGo (recommended - smaller binary)
|
||||||
tinygo build -o crypto-ticker.wasm -target wasip1 -buildmode=c-shared .
|
tinygo build -o plugin.wasm -target wasip1 -buildmode=c-shared .
|
||||||
|
zip -j crypto-ticker.ndp manifest.json plugin.wasm
|
||||||
|
```
|
||||||
|
|
||||||
# Or using standard Go
|
Or from the `plugins/examples/` directory:
|
||||||
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o crypto-ticker.wasm .
|
|
||||||
|
```bash
|
||||||
|
make crypto-ticker.ndp
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Copy the resulting `crypto-ticker.wasm` to your Navidrome plugins folder.
|
Copy the resulting `crypto-ticker.ndp` to your Navidrome plugins folder.
|
||||||
|
|
||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
|
|||||||
@ -63,34 +63,30 @@ To work within this model the plugin stores no in-memory state. Connections are
|
|||||||
|
|
||||||
Configure in the Navidrome UI (Settings → Plugins → discord-rich-presence):
|
Configure in the Navidrome UI (Settings → Plugins → discord-rich-presence):
|
||||||
|
|
||||||
```json
|
| Key | Description | Example |
|
||||||
{
|
|------------|----------------------------------------------------------|--------------------------------|
|
||||||
"clientid": "123456789012345678",
|
| `clientid` | Your Discord application ID | `123456789012345678` |
|
||||||
"users": "alice:token123,bob:token456"
|
| `users` | Comma-separated list of `username:token` pairs | `alice:token123,bob:token456` |
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `ClientID` is your Discord application ID
|
|
||||||
- `Users` is a comma-separated list of `username:token` pairs used for authorization
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
From the `plugins/examples/` directory:
|
From the `plugins/examples/` directory:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make discord-rich-presence.wasm
|
make discord-rich-presence.ndp
|
||||||
```
|
```
|
||||||
|
|
||||||
Or manually:
|
Or manually:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd discord-rich-presence
|
cd discord-rich-presence
|
||||||
tinygo build -target wasip1 -buildmode=c-shared -o ../discord-rich-presence.wasm .
|
tinygo build -target wasip1 -buildmode=c-shared -o plugin.wasm .
|
||||||
|
zip -j discord-rich-presence.ndp manifest.json plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Place the resulting `discord-rich-presence.wasm` in your Navidrome plugins folder and enable plugins in your configuration:
|
Place the resulting `discord-rich-presence.ndp` in your Navidrome plugins folder and enable plugins in your configuration:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[Plugins]
|
[Plugins]
|
||||||
@ -101,7 +97,7 @@ Folder = "/path/to/plugins"
|
|||||||
## Files
|
## Files
|
||||||
|
|
||||||
| File | Description |
|
| File | Description |
|
||||||
|------|-------------|
|
|----------------|---------------------------------------------------------|
|
||||||
| `main.go` | Plugin entry point, manifest, scrobbler implementation |
|
| `main.go` | Plugin entry point, manifest, scrobbler implementation |
|
||||||
| `rpc.go` | Discord gateway communication and RPC logic |
|
| `rpc.go` | Discord gateway communication and RPC logic |
|
||||||
| `pdk.gen.go` | Generated types from XTP schemas (combined) |
|
| `pdk.gen.go` | Generated types from XTP schemas (combined) |
|
||||||
@ -110,7 +106,7 @@ Folder = "/path/to/plugins"
|
|||||||
## Host Services Used
|
## Host Services Used
|
||||||
|
|
||||||
| Service | Purpose |
|
| Service | Purpose |
|
||||||
|---------|---------|
|
|-----------|------------------------------------------------------------------|
|
||||||
| Cache | Store Discord sequence numbers and processed image URLs |
|
| Cache | Store Discord sequence numbers and processed image URLs |
|
||||||
| Scheduler | Schedule heartbeats (recurring) and activity clearing (one-time) |
|
| Scheduler | Schedule heartbeats (recurring) and activity clearing (one-time) |
|
||||||
| WebSocket | Maintain persistent connection to Discord gateway |
|
| WebSocket | Maintain persistent connection to Discord gateway |
|
||||||
|
|||||||
@ -23,19 +23,20 @@ rustup target add wasm32-wasip1
|
|||||||
# Build the plugin
|
# Build the plugin
|
||||||
cargo build --target wasm32-wasip1 --release
|
cargo build --target wasm32-wasip1 --release
|
||||||
|
|
||||||
# The output will be at target/wasm32-wasip1/release/library_inspector.wasm
|
# Package as .ndp
|
||||||
|
zip -j library-inspector.ndp manifest.json target/wasm32-wasip1/release/library_inspector.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
Or use the provided Makefile from the examples directory:
|
Or use the provided Makefile from the examples directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd plugins/examples
|
cd plugins/examples
|
||||||
make library-inspector.wasm
|
make library-inspector.ndp
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Copy the `.wasm` file to your Navidrome plugins folder
|
1. Copy the `.ndp` file to your Navidrome plugins folder
|
||||||
2. Enable plugins in your Navidrome configuration:
|
2. Enable plugins in your Navidrome configuration:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
@ -50,11 +51,9 @@ Folder = "/path/to/plugins"
|
|||||||
|
|
||||||
Configure the inspection interval in the Navidrome UI (Settings → Plugins → library-inspector):
|
Configure the inspection interval in the Navidrome UI (Settings → Plugins → library-inspector):
|
||||||
|
|
||||||
```json
|
| Key | Description | Default |
|
||||||
{
|
|--------|------------------------------------------|--------------|
|
||||||
"cron": "@every 5m"
|
| `cron` | Cron expression for inspection interval | `@every 1m` |
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cron Expression Examples
|
### Cron Expression Examples
|
||||||
|
|
||||||
|
|||||||
@ -8,12 +8,19 @@ This is a minimal example demonstrating how to create a Navidrome plugin using G
|
|||||||
2. Build the plugin:
|
2. Build the plugin:
|
||||||
```bash
|
```bash
|
||||||
go mod tidy
|
go mod tidy
|
||||||
tinygo build -o minimal.wasm -target wasip1 -buildmode=c-shared ./main.go
|
tinygo build -o plugin.wasm -target wasip1 -buildmode=c-shared ./main.go
|
||||||
|
zip -j minimal.ndp manifest.json plugin.wasm
|
||||||
|
```
|
||||||
|
|
||||||
|
Or using the examples Makefile:
|
||||||
|
```bash
|
||||||
|
cd plugins/examples
|
||||||
|
make minimal.ndp
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
Copy `minimal.wasm` to your Navidrome plugins folder (default: `<data-folder>/plugins/`).
|
Copy `minimal.ndp` to your Navidrome plugins folder (default: `<data-folder>/plugins/`).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@ -29,7 +36,7 @@ Agents = "lastfm,spotify,minimal"
|
|||||||
|
|
||||||
## What This Example Demonstrates
|
## What This Example Demonstrates
|
||||||
|
|
||||||
- Exporting the required `nd_manifest` function
|
- Plugin package structure (`.ndp` = zip with `manifest.json` + `plugin.wasm`)
|
||||||
- Implementing `nd_get_artist_biography` as a MetadataAgent capability
|
- Implementing `nd_get_artist_biography` as a MetadataAgent capability
|
||||||
- Basic JSON input/output handling with the Extism PDK
|
- Basic JSON input/output handling with the Extism PDK
|
||||||
|
|
||||||
|
|||||||
@ -23,18 +23,19 @@ A Python example plugin that demonstrates the **Scheduler** and **SubsonicAPI**
|
|||||||
From the `plugins/examples` directory:
|
From the `plugins/examples` directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make nowplaying-py.wasm
|
make nowplaying-py.ndp
|
||||||
```
|
```
|
||||||
|
|
||||||
Or directly:
|
Or directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
extism-py plugin/__init__.py -o nowplaying-py.wasm
|
extism-py plugin/__init__.py -o plugin.wasm
|
||||||
|
zip -j nowplaying-py.ndp manifest.json plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Copy `nowplaying-py.wasm` to your Navidrome plugins folder
|
1. Copy `nowplaying-py.ndp` to your Navidrome plugins folder
|
||||||
|
|
||||||
2. Enable plugins in `navidrome.toml`:
|
2. Enable plugins in `navidrome.toml`:
|
||||||
```toml
|
```toml
|
||||||
@ -43,19 +44,13 @@ extism-py plugin/__init__.py -o nowplaying-py.wasm
|
|||||||
Folder = "/path/to/plugins"
|
Folder = "/path/to/plugins"
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Configure the plugin in the UI (Settings → Plugins → nowplaying-py):
|
3. Configure the plugin in the UI (Settings → Plugins → nowplaying-py)
|
||||||
```json
|
|
||||||
{
|
|
||||||
"cron": "*/1 * * * *",
|
|
||||||
"user": "admin"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration Options
|
## Configuration
|
||||||
|
|
||||||
| Key | Description | Default |
|
| Key | Description | Default |
|
||||||
|--------|-------------------------------------|------------------------------|
|
|--------|-------------------------------------|---------------|
|
||||||
| `cron` | Cron expression for check frequency | `*/1 * * * *` (every minute) |
|
| `cron` | Cron expression for check frequency | `*/1 * * * *` |
|
||||||
| `user` | Navidrome user for SubsonicAPI | `admin` |
|
| `user` | Navidrome user for SubsonicAPI | `admin` |
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|||||||
@ -20,7 +20,7 @@ A Navidrome plugin written in Rust that sends HTTP webhook notifications when tr
|
|||||||
From the `plugins/examples` directory:
|
From the `plugins/examples` directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make webhook-rs.wasm
|
make webhook-rs.ndp
|
||||||
```
|
```
|
||||||
|
|
||||||
Or build directly with cargo:
|
Or build directly with cargo:
|
||||||
@ -28,28 +28,20 @@ Or build directly with cargo:
|
|||||||
```bash
|
```bash
|
||||||
cd webhook-rs
|
cd webhook-rs
|
||||||
cargo build --release
|
cargo build --release
|
||||||
cp target/wasm32-unknown-unknown/release/webhook_rs.wasm ../webhook-rs.wasm
|
zip -j webhook-rs.ndp manifest.json target/wasm32-unknown-unknown/release/webhook_rs.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Copy `webhook-rs.wasm` to your Navidrome plugins folder (configured via `Plugins.Folder` in your config).
|
Copy `webhook-rs.ndp` to your Navidrome plugins folder (configured via `Plugins.Folder` in your config).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Configure in the Navidrome UI (Settings → Plugins → webhook-rs):
|
Configure in the Navidrome UI (Settings → Plugins → webhook-rs):
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"urls": "https://example.com/webhook,https://another.example.com/notify"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration Options
|
|
||||||
|
|
||||||
| Key | Description | Example |
|
| Key | Description | Example |
|
||||||
|--------|--------------------------------------|---------------------------------------------------------|
|
|--------|--------------------------------------|-----------------------------------------------------------|
|
||||||
| `urls` | Comma-separated list of webhook URLs | `"https://example.com/hook1,https://example.com/hook2"` |
|
| `urls` | Comma-separated list of webhook URLs | `https://example.com/hook1,https://example.com/hook2` |
|
||||||
|
|
||||||
## Webhook Request Format
|
## Webhook Request Format
|
||||||
|
|
||||||
|
|||||||
@ -22,16 +22,11 @@ xtp plugin init \
|
|||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
### Using XTP CLI (recommended)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
xtp plugin build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using TinyGo
|
### Using TinyGo
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tinygo build -target wasip1 -buildmode=c-shared -o dist/plugin.wasm .
|
tinygo build -target wasip1 -buildmode=c-shared -o plugin.wasm .
|
||||||
|
zip -j wikimedia.ndp manifest.json plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using the Makefile
|
### Using the Makefile
|
||||||
@ -39,15 +34,22 @@ tinygo build -target wasip1 -buildmode=c-shared -o dist/plugin.wasm .
|
|||||||
From the `plugins/examples` directory:
|
From the `plugins/examples` directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make wikimedia.wasm
|
make wikimedia.ndp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using XTP CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xtp plugin build
|
||||||
|
zip -j wikimedia.ndp manifest.json dist/plugin.wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Copy the `.wasm` file to your Navidrome plugins folder:
|
Copy the `.ndp` file to your Navidrome plugins folder:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp dist/plugin.wasm /path/to/navidrome/plugins/wikimedia.wasm
|
cp wikimedia.ndp /path/to/navidrome/plugins/
|
||||||
```
|
```
|
||||||
|
|
||||||
Then enable plugins in your `navidrome.toml`:
|
Then enable plugins in your `navidrome.toml`:
|
||||||
@ -73,23 +75,13 @@ brew install extism/tap/extism # macOS
|
|||||||
# or see https://extism.org/docs/install for other platforms
|
# or see https://extism.org/docs/install for other platforms
|
||||||
```
|
```
|
||||||
|
|
||||||
Run these commands from the `plugins/examples` directory.
|
Extract the wasm file from the package and test:
|
||||||
|
|
||||||
### Test the manifest
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
extism call wikimedia.wasm nd_manifest --wasi
|
# Extract wasm from package
|
||||||
```
|
unzip -p wikimedia.ndp plugin.wasm > wikimedia.wasm
|
||||||
|
|
||||||
Expected output:
|
# Test artist URL lookup with MBID (The Beatles)
|
||||||
```json
|
|
||||||
{"name":"Wikimedia","author":"Navidrome","version":"1.0.0","description":"Fetches artist metadata from Wikidata, DBpedia and Wikipedia","website":"https://navidrome.org","permissions":{"http":{"reason":"Fetch metadata from Wikimedia APIs","allowedHosts":["query.wikidata.org","dbpedia.org","en.wikipedia.org"]}}}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test artist URL lookup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# With MBID (The Beatles)
|
|
||||||
extism call wikimedia.wasm nd_get_artist_url --wasi \
|
extism call wikimedia.wasm nd_get_artist_url --wasi \
|
||||||
--input '{"id":"1","name":"The Beatles","mbid":"b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d"}' \
|
--input '{"id":"1","name":"The Beatles","mbid":"b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d"}' \
|
||||||
--allow-host "query.wikidata.org"
|
--allow-host "query.wikidata.org"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user