mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
fix(plugins): update IsAuthorized method to return boolean instead of response object
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
6fff476e93
commit
6698e94a9c
@ -192,8 +192,8 @@ Agents = "lastfm,spotify,my-plugin"
|
||||
Integrates with external scrobbling services. Export one or more of these functions:
|
||||
|
||||
| Function | Input | Output | Description |
|
||||
|------------------------------|-----------------------|----------------|-----------------------------||
|
||||
| `nd_scrobbler_is_authorized` | `{userId, username}` | `{authorized}` | Check if user is authorized |
|
||||
|------------------------------|-----------------------|----------------|-----------------------------|
|
||||
| `nd_scrobbler_is_authorized` | `{userId, username}` | `bool` | Check if user is authorized |
|
||||
| `nd_scrobbler_now_playing` | See below | (none) | Send now playing |
|
||||
| `nd_scrobbler_scrobble` | See below | (none) | Submit a scrobble |
|
||||
|
||||
@ -777,15 +777,15 @@ serde_json = "1.0"
|
||||
**Implementing capabilities with traits and macros:**
|
||||
|
||||
```rust
|
||||
use nd_pdk::scrobbler::{Scrobbler, IsAuthorizedRequest, IsAuthorizedResponse, Error};
|
||||
use nd_pdk::scrobbler::{Scrobbler, IsAuthorizedRequest, Error};
|
||||
use nd_pdk::register_scrobbler;
|
||||
|
||||
#[derive(Default)]
|
||||
struct MyPlugin;
|
||||
|
||||
impl Scrobbler for MyPlugin {
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<IsAuthorizedResponse, Error> {
|
||||
Ok(IsAuthorizedResponse { authorized: true })
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<bool, Error> {
|
||||
Ok(true)
|
||||
}
|
||||
fn now_playing(&self, req: NowPlayingRequest) -> Result<(), Error> { Ok(()) }
|
||||
fn scrobble(&self, req: ScrobbleRequest) -> Result<(), Error> { Ok(()) }
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
//
|
||||
// // Scrobbler requires all methods
|
||||
// type Scrobbler interface {
|
||||
// IsAuthorized(IsAuthorizedRequest) (*IsAuthorizedResponse, error)
|
||||
// IsAuthorized(IsAuthorizedRequest) (bool, error)
|
||||
// NowPlaying(NowPlayingRequest) error
|
||||
// Scrobble(ScrobbleRequest) error
|
||||
// }
|
||||
|
||||
@ -11,7 +11,7 @@ package capabilities
|
||||
type Scrobbler interface {
|
||||
// IsAuthorized checks if a user is authorized to scrobble to this service.
|
||||
//nd:export name=nd_scrobbler_is_authorized
|
||||
IsAuthorized(IsAuthorizedRequest) (*IsAuthorizedResponse, error)
|
||||
IsAuthorized(IsAuthorizedRequest) (bool, error)
|
||||
|
||||
// NowPlaying sends a now playing notification to the scrobbling service.
|
||||
//nd:export name=nd_scrobbler_now_playing
|
||||
@ -30,12 +30,6 @@ type IsAuthorizedRequest struct {
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// IsAuthorizedResponse is the response for authorization check.
|
||||
type IsAuthorizedResponse struct {
|
||||
// Authorized indicates whether the user is authorized to scrobble.
|
||||
Authorized bool `json:"authorized"`
|
||||
}
|
||||
|
||||
// TrackInfo contains track metadata for scrobbling.
|
||||
type TrackInfo struct {
|
||||
// ID is the internal Navidrome track ID.
|
||||
|
||||
@ -6,7 +6,7 @@ exports:
|
||||
$ref: '#/components/schemas/IsAuthorizedRequest'
|
||||
contentType: application/json
|
||||
output:
|
||||
$ref: '#/components/schemas/IsAuthorizedResponse'
|
||||
type: boolean
|
||||
contentType: application/json
|
||||
nd_scrobbler_now_playing:
|
||||
description: NowPlaying sends a now playing notification to the scrobbling service.
|
||||
@ -33,15 +33,6 @@ components:
|
||||
required:
|
||||
- userId
|
||||
- username
|
||||
IsAuthorizedResponse:
|
||||
description: IsAuthorizedResponse is the response for authorization check.
|
||||
type: object
|
||||
properties:
|
||||
authorized:
|
||||
type: boolean
|
||||
description: Authorized indicates whether the user is authorized to scrobble.
|
||||
required:
|
||||
- authorized
|
||||
NowPlayingRequest:
|
||||
description: NowPlayingRequest is the request for now playing notification.
|
||||
type: object
|
||||
@ -144,10 +135,3 @@ components:
|
||||
- duration
|
||||
- trackNumber
|
||||
- discNumber
|
||||
ScrobblerError:
|
||||
description: ScrobblerError represents an error type for scrobbling operations.
|
||||
type: string
|
||||
enum:
|
||||
- scrobbler(not_authorized)
|
||||
- scrobbler(retry_later)
|
||||
- scrobbler(unrecoverable)
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
use extism_pdk::*;
|
||||
use nd_pdk::host::{artwork, scheduler};
|
||||
use nd_pdk::scrobbler::{
|
||||
Error as ScrobblerError, IsAuthorizedRequest, IsAuthorizedResponse, NowPlayingRequest,
|
||||
Error as ScrobblerError, IsAuthorizedRequest, NowPlayingRequest,
|
||||
ScrobbleRequest, Scrobbler, SCROBBLER_ERROR_NOT_AUTHORIZED, SCROBBLER_ERROR_RETRY_LATER,
|
||||
};
|
||||
use nd_pdk::scheduler::{
|
||||
@ -104,18 +104,18 @@ fn get_image_url(track_id: &str) -> String {
|
||||
// ============================================================================
|
||||
|
||||
impl Scrobbler for DiscordPlugin {
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<IsAuthorizedResponse, ScrobblerError> {
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<bool, ScrobblerError> {
|
||||
let (_, users) = match get_config() {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
error!("Failed to get config: {:?}", e);
|
||||
return Ok(IsAuthorizedResponse { authorized: false });
|
||||
return Ok(false);
|
||||
}
|
||||
};
|
||||
|
||||
let authorized = users.contains_key(&req.username);
|
||||
info!("IsAuthorized for user {}: {}", req.username, authorized);
|
||||
Ok(IsAuthorizedResponse { authorized })
|
||||
Ok(authorized)
|
||||
}
|
||||
|
||||
fn now_playing(&self, req: NowPlayingRequest) -> Result<(), ScrobblerError> {
|
||||
|
||||
@ -93,15 +93,15 @@ func getImageURL(trackID string) string {
|
||||
// ============================================================================
|
||||
|
||||
// IsAuthorized checks if a user is authorized for Discord Rich Presence.
|
||||
func (p *discordPlugin) IsAuthorized(input scrobbler.IsAuthorizedRequest) (*scrobbler.IsAuthorizedResponse, error) {
|
||||
func (p *discordPlugin) IsAuthorized(input scrobbler.IsAuthorizedRequest) (bool, error) {
|
||||
_, users, err := getConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to check user authorization: %w", err)
|
||||
return false, fmt.Errorf("failed to check user authorization: %w", err)
|
||||
}
|
||||
|
||||
_, authorized := users[input.Username]
|
||||
pdk.Log(pdk.LogInfo, fmt.Sprintf("IsAuthorized for user %s: %v", input.Username, authorized))
|
||||
return &scrobbler.IsAuthorizedResponse{Authorized: authorized}, nil
|
||||
return authorized, nil
|
||||
}
|
||||
|
||||
// NowPlaying sends a now playing notification to Discord.
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
use extism_pdk::{config, error, http, info, warn, HttpRequest};
|
||||
use nd_pdk::scrobbler::{
|
||||
Error, IsAuthorizedRequest, IsAuthorizedResponse, NowPlayingRequest, ScrobbleRequest,
|
||||
Error, IsAuthorizedRequest, NowPlayingRequest, ScrobbleRequest,
|
||||
Scrobbler,
|
||||
};
|
||||
|
||||
@ -31,12 +31,12 @@ struct WebhookPlugin;
|
||||
|
||||
impl Scrobbler for WebhookPlugin {
|
||||
/// Checks if a user is authorized. This plugin authorizes all users.
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<IsAuthorizedResponse, Error> {
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<bool, Error> {
|
||||
info!(
|
||||
"Authorization check for user: {} ({})",
|
||||
req.username, req.user_id
|
||||
);
|
||||
Ok(IsAuthorizedResponse { authorized: true })
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Handles now playing notifications. This plugin ignores them (webhooks only on scrobble).
|
||||
|
||||
@ -34,12 +34,6 @@ type IsAuthorizedRequest struct {
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// IsAuthorizedResponse is the response for authorization check.
|
||||
type IsAuthorizedResponse struct {
|
||||
// Authorized indicates whether the user is authorized to scrobble.
|
||||
Authorized bool `json:"authorized"`
|
||||
}
|
||||
|
||||
// NowPlayingRequest is the request for now playing notification.
|
||||
type NowPlayingRequest struct {
|
||||
// UserID is the internal Navidrome user ID.
|
||||
@ -105,14 +99,14 @@ type TrackInfo struct {
|
||||
// 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) (*IsAuthorizedResponse, error)
|
||||
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) (*IsAuthorizedResponse, error)
|
||||
isAuthorizedImpl func(IsAuthorizedRequest) (bool, error)
|
||||
nowPlayingImpl func(NowPlayingRequest) error
|
||||
scrobbleImpl func(ScrobbleRequest) error
|
||||
)
|
||||
|
||||
@ -31,12 +31,6 @@ type IsAuthorizedRequest struct {
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// IsAuthorizedResponse is the response for authorization check.
|
||||
type IsAuthorizedResponse struct {
|
||||
// Authorized indicates whether the user is authorized to scrobble.
|
||||
Authorized bool `json:"authorized"`
|
||||
}
|
||||
|
||||
// NowPlayingRequest is the request for now playing notification.
|
||||
type NowPlayingRequest struct {
|
||||
// UserID is the internal Navidrome user ID.
|
||||
@ -102,7 +96,7 @@ type TrackInfo struct {
|
||||
// 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) (*IsAuthorizedResponse, error)
|
||||
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.
|
||||
|
||||
@ -34,7 +34,7 @@ The Scrobbler capability requires all methods to be implemented:
|
||||
|
||||
```rust
|
||||
use nd_pdk::scrobbler::{
|
||||
Error, IsAuthorizedRequest, IsAuthorizedResponse,
|
||||
Error, IsAuthorizedRequest,
|
||||
NowPlayingRequest, ScrobbleRequest, Scrobbler,
|
||||
};
|
||||
|
||||
@ -45,8 +45,8 @@ nd_pdk::register_scrobbler!(MyPlugin);
|
||||
struct MyPlugin;
|
||||
|
||||
impl Scrobbler for MyPlugin {
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<IsAuthorizedResponse, Error> {
|
||||
Ok(IsAuthorizedResponse { authorized: true })
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<bool, Error> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn now_playing(&self, req: NowPlayingRequest) -> Result<(), Error> {
|
||||
|
||||
@ -23,14 +23,6 @@ pub struct IsAuthorizedRequest {
|
||||
#[serde(default)]
|
||||
pub username: String,
|
||||
}
|
||||
/// IsAuthorizedResponse is the response for authorization check.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct IsAuthorizedResponse {
|
||||
/// Authorized indicates whether the user is authorized to scrobble.
|
||||
#[serde(default)]
|
||||
pub authorized: bool,
|
||||
}
|
||||
/// NowPlayingRequest is the request for now playing notification.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -142,7 +134,7 @@ impl Error {
|
||||
/// all three functions: IsAuthorized, NowPlaying, and Scrobble.
|
||||
pub trait Scrobbler {
|
||||
/// IsAuthorized - IsAuthorized checks if a user is authorized to scrobble to this service.
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<IsAuthorizedResponse, Error>;
|
||||
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<bool, Error>;
|
||||
/// NowPlaying - NowPlaying sends a now playing notification to the scrobbling service.
|
||||
fn now_playing(&self, req: NowPlayingRequest) -> Result<(), Error>;
|
||||
/// Scrobble - Scrobble submits a completed scrobble to the scrobbling service.
|
||||
@ -157,7 +149,7 @@ macro_rules! register_scrobbler {
|
||||
#[extism_pdk::plugin_fn]
|
||||
pub fn nd_scrobbler_is_authorized(
|
||||
req: extism_pdk::Json<$crate::scrobbler::IsAuthorizedRequest>
|
||||
) -> extism_pdk::FnResult<extism_pdk::Json<$crate::scrobbler::IsAuthorizedResponse>> {
|
||||
) -> extism_pdk::FnResult<extism_pdk::Json<bool>> {
|
||||
let plugin = <$plugin_type>::default();
|
||||
let result = $crate::scrobbler::Scrobbler::is_authorized(&plugin, req.into_inner())?;
|
||||
Ok(extism_pdk::Json(result))
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use nd_pdk::scrobbler::{Scrobbler, IsAuthorizedRequest, IsAuthorizedResponse, Error};
|
||||
//! use nd_pdk::scrobbler::{Scrobbler, IsAuthorizedRequest, Error};
|
||||
//! use nd_pdk::register_scrobbler;
|
||||
//!
|
||||
//! struct MyPlugin;
|
||||
@ -16,8 +16,8 @@
|
||||
//! }
|
||||
//!
|
||||
//! impl Scrobbler for MyPlugin {
|
||||
//! fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<IsAuthorizedResponse, Error> {
|
||||
//! Ok(IsAuthorizedResponse { authorized: true })
|
||||
//! fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<bool, Error> {
|
||||
//! Ok(true)
|
||||
//! }
|
||||
//! // ... implement other required methods
|
||||
//! }
|
||||
|
||||
@ -45,12 +45,12 @@ func (s *ScrobblerPlugin) IsAuthorized(ctx context.Context, userId string) bool
|
||||
Username: username,
|
||||
}
|
||||
|
||||
result, err := callPluginFunction[capabilities.IsAuthorizedRequest, *capabilities.IsAuthorizedResponse](ctx, s.plugin, FuncScrobblerIsAuthorized, input)
|
||||
if err != nil || result == nil {
|
||||
result, err := callPluginFunction[capabilities.IsAuthorizedRequest, bool](ctx, s.plugin, FuncScrobblerIsAuthorized, input)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return result.Authorized
|
||||
return result
|
||||
}
|
||||
|
||||
// NowPlaying sends a now playing notification to the scrobbler
|
||||
|
||||
6
plugins/testdata/test-scrobbler/main.go
vendored
6
plugins/testdata/test-scrobbler/main.go
vendored
@ -17,10 +17,8 @@ func init() {
|
||||
type testScrobbler struct{}
|
||||
|
||||
// IsAuthorized checks if a user is authorized.
|
||||
func (t *testScrobbler) IsAuthorized(scrobbler.IsAuthorizedRequest) (*scrobbler.IsAuthorizedResponse, error) {
|
||||
return &scrobbler.IsAuthorizedResponse{
|
||||
Authorized: checkAuthConfig(),
|
||||
}, nil
|
||||
func (t *testScrobbler) IsAuthorized(scrobbler.IsAuthorizedRequest) (bool, error) {
|
||||
return checkAuthConfig(), nil
|
||||
}
|
||||
|
||||
// NowPlaying sends a now playing notification.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user