63 lines
2.0 KiB
Go
63 lines
2.0 KiB
Go
package recipes
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// CustomFilterParams is the typed config shape for genre and custom_filter sections.
|
|
type CustomFilterParams struct {
|
|
Filter json.RawMessage `json:"filter,omitempty"`
|
|
FilterType string `json:"filter_type,omitempty"` // movies|series|all
|
|
FilterLibrary []int `json:"filter_library,omitempty"` // multi-library scope
|
|
LibraryCollectionID string `json:"library_collection_id,omitempty"` // collection sections
|
|
}
|
|
|
|
type customFilterRecipe struct {
|
|
typ string
|
|
cacheTTL time.Duration
|
|
}
|
|
|
|
func (c *customFilterRecipe) Type() string { return c.typ }
|
|
func (c *customFilterRecipe) NewParams() any { return &CustomFilterParams{} }
|
|
func (c *customFilterRecipe) DefaultCacheTTL() time.Duration { return c.cacheTTL }
|
|
func (c *customFilterRecipe) Resolve(rc ResolverContext) (ResolvedItems, error) {
|
|
return delegateResolve(c.typ, rc)
|
|
}
|
|
|
|
func (c *customFilterRecipe) Validate(raw json.RawMessage) error {
|
|
if len(raw) == 0 {
|
|
return nil
|
|
}
|
|
var p CustomFilterParams
|
|
if err := json.Unmarshal(raw, &p); err != nil {
|
|
return err
|
|
}
|
|
// Filter, when present, must be a JSON object (not a scalar or array).
|
|
if len(p.Filter) > 0 {
|
|
var probe any
|
|
if err := json.Unmarshal(p.Filter, &probe); err != nil {
|
|
return err
|
|
}
|
|
if _, ok := probe.(map[string]any); !ok {
|
|
return fmt.Errorf("recipes: filter must be a JSON object, got %T", probe)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *customFilterRecipe) Definition() RecipeDefinition {
|
|
return RecipeDefinition{
|
|
Type: c.typ,
|
|
Category: CategoryCustom,
|
|
AdminOnly: true, // gated by sections.allow_profile_custom_sections at the API layer
|
|
Hidden: c.typ == "genre", // legacy alias — keep resolvable, hide from UI
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
Register(&customFilterRecipe{typ: "genre", cacheTTL: 5 * time.Minute})
|
|
Register(&customFilterRecipe{typ: "custom_filter", cacheTTL: 5 * time.Minute})
|
|
}
|