package plugins
import (
"encoding/json"
"fmt"
"github.com/santhosh-tekuri/jsonschema/v6"
)
func ParseManifest(data []byte) (*Manifest, error) {
var m Manifest
if err := json.Unmarshal(data, &m); err != nil {
return nil, fmt.Errorf("parsing manifest JSON: %w", err)
}
if err := m.Validate(); err != nil {
return nil, fmt.Errorf("validating manifest: %w", err)
}
return &m, nil
}
func (m *Manifest) Validate() error {
if m.Permissions != nil && m.Permissions.Subsonicapi != nil {
if m.Permissions.Users == nil {
return fmt.Errorf("'subsonicapi' permission requires 'users' permission to be declared")
}
}
if m.Config != nil && m.Config.Schema != nil {
if err := validateConfigSchema(m.Config.Schema); err != nil {
return fmt.Errorf("invalid config schema: %w", err)
}
}
return nil
}
func validateConfigSchema(schema map[string]any) error {
compiler := jsonschema.NewCompiler()
if err := compiler.AddResource("schema.json", schema); err != nil {
return fmt.Errorf("invalid schema structure: %w", err)
}
if _, err := compiler.Compile("schema.json"); err != nil {
return err
}
return nil
}
func ValidateWithCapabilities(m *Manifest, capabilities []Capability) error {
if hasCapability(capabilities, CapabilityScrobbler) {
if m.Permissions == nil || m.Permissions.Users == nil {
return fmt.Errorf("scrobbler capability requires 'users' permission to be declared in manifest")
}
}
if m.Permissions != nil && m.Permissions.Scheduler != nil {
if !hasCapability(capabilities, CapabilityScheduler) {
return fmt.Errorf("'scheduler' permission requires plugin to export '%s' function", FuncSchedulerCallback)
}
}
if m.Permissions != nil && m.Permissions.Taskqueue != nil {
if !hasCapability(capabilities, CapabilityTaskWorker) {
return fmt.Errorf("'taskqueue' permission requires plugin to export '%s' function", FuncTaskWorkerCallback)
}
}
return nil
}
func (m *Manifest) HasExperimentalThreads() bool {
return m.Experimental != nil && m.Experimental.Threads != nil
}
func (m *Manifest) HasLibraryFilesystemPermission() bool {
return m.Permissions != nil &&
m.Permissions.Library != nil &&
m.Permissions.Library.Filesystem
}