Documentation
¶
Index ¶
- Variables
- func BuildBookContext(book *models.Book) map[string]interface{}
- func BuildFileContext(file *models.File) map[string]interface{}
- func DownloadCoverFromURL(ctx context.Context, md *mediafile.ParsedMetadata, allowedDomains []string, ...) bool
- func InjectHostAPIs(rt *Runtime, configGetter ConfigGetter) error
- func IsValidMetadataField(field string) bool
- func NewHandler(service *Service, manager *Manager, installer *Installer) *handler
- func RegisterIdentifyRoutes(g *echo.Group, service *Service, manager *Manager, ed *EnrichDeps)
- func RegisterLibraryRoutes(g *echo.Group, service *Service, manager *Manager, ...)
- func RegisterRoutesWithGroup(g *echo.Group, service *Service, manager *Manager, installer *Installer, ...)
- type AddRepositoryPayload
- type AnnotatedPluginVersion
- type ApplyOverrides
- type AvailablePlugin
- type AvailablePluginResponse
- type Capabilities
- type ConfigField
- type ConfigGetter
- type ConfigSchema
- type ConvertResult
- type EnrichDeps
- type EnrichSearchResult
- type ErrVersionIncompatible
- type FFmpegAccessCap
- type FSContext
- type FieldSettingsResponse
- type FileAccessCap
- type FileParserCap
- type HTTPAccessCap
- type IdentifierTypeCap
- type InputConverterCap
- type InstallPluginPayload
- type Installer
- func (inst *Installer) DownloadPluginImage(ctx context.Context, scope, pluginID, imageURL string) error
- func (inst *Installer) InstallPlugin(ctx context.Context, scope, pluginID, downloadURL, expectedSHA256 string) (*Manifest, error)
- func (inst *Installer) PluginDir() string
- func (inst *Installer) UninstallPlugin(scope, pluginID string) error
- func (inst *Installer) UpdatePlugin(ctx context.Context, scope, pluginID, downloadURL, expectedSHA256 string) (*Manifest, error)
- type LibraryFieldSettingsResponse
- type LibraryOrderEntry
- type LibraryPluginOrderPlugin
- type LibraryPluginOrderResponse
- type Manager
- func (m *Manager) CheckForUpdates(ctx context.Context) error
- func (m *Manager) CheckForUpdatesForRepo(ctx context.Context, scope string, manifest *RepositoryManifest) error
- func (m *Manager) DeletePluginData(scope, id string)
- func (m *Manager) GetManualRuntimes(ctx context.Context, hookType string, libraryID int) ([]*Runtime, error)
- func (m *Manager) GetOrderedRuntimes(ctx context.Context, hookType string, libraryID int) ([]*Runtime, error)
- func (m *Manager) GetOutputGenerator(formatID string) *PluginGenerator
- func (m *Manager) GetParserForType(fileType string) *Runtime
- func (m *Manager) GetRuntime(scope, id string) *Runtime
- func (m *Manager) LoadAll(ctx context.Context) error
- func (m *Manager) LoadPlugin(ctx context.Context, scope, id string) error
- func (m *Manager) RegisteredConverterExtensions() map[string]struct{}
- func (m *Manager) RegisteredFileExtensions() map[string]struct{}
- func (m *Manager) RegisteredOutputFormats() []OutputFormatInfo
- func (m *Manager) ReloadPlugin(ctx context.Context, scope, id string) error
- func (m *Manager) RunFileParser(ctx context.Context, rt *Runtime, filePath, fileType string) (*mediafile.ParsedMetadata, error)
- func (m *Manager) RunFingerprint(rt *Runtime, bookCtx, fileCtx map[string]interface{}) (string, error)
- func (m *Manager) RunInputConverter(ctx context.Context, rt *Runtime, sourcePath, targetDir string) (*ConvertResult, error)
- func (m *Manager) RunMetadataSearch(ctx context.Context, rt *Runtime, searchCtx map[string]interface{}, ...) (*SearchResponse, error)
- func (m *Manager) RunOnUninstalling(rt *Runtime)
- func (m *Manager) RunOutputGenerator(ctx context.Context, rt *Runtime, sourcePath, destPath string, ...) error
- func (m *Manager) SetEventCallback(cb PluginEventCallback)
- func (m *Manager) UnloadPlugin(scope, id string)
- type Manifest
- type MetadataEnricherCap
- type OrderEntry
- type OutputFormatInfo
- type OutputGeneratorCap
- type PluginApplyPayload
- type PluginConfigResponse
- type PluginEvent
- type PluginEventCallback
- type PluginEventType
- type PluginGenerator
- type PluginSearchError
- type PluginSearchPayload
- type PluginSearchResponse
- type PluginSearchSkipped
- type PluginVersion
- type RepositoryManifest
- type Runtime
- type SearchResponse
- type SelectOption
- type SeriesEntry
- type Service
- func (s *Service) AddRepository(ctx context.Context, repo *models.PluginRepository) error
- func (s *Service) AppendToOrder(ctx context.Context, hookType, scope, pluginID string) error
- func (s *Service) GetAllConfigRaw(ctx context.Context, scope, pluginID string) (map[string]*string, error)
- func (s *Service) GetConfig(ctx context.Context, scope, pluginID string, schema ConfigSchema, raw bool) (map[string]interface{}, error)
- func (s *Service) GetConfigRaw(ctx context.Context, scope, pluginID, key string) (*string, error)
- func (s *Service) GetEffectiveFieldSettings(ctx context.Context, libraryID int, scope, pluginID string, ...) (map[string]bool, error)
- func (s *Service) GetFieldSettings(ctx context.Context, scope, pluginID string) (map[string]bool, error)
- func (s *Service) GetLibraryFieldSettings(ctx context.Context, libraryID int, scope, pluginID string) (map[string]bool, error)
- func (s *Service) GetLibraryOrder(ctx context.Context, libraryID int, hookType string) ([]*models.LibraryPluginHookConfig, error)
- func (s *Service) GetOrder(ctx context.Context, hookType string) ([]*models.PluginHookConfig, error)
- func (s *Service) GetPlugin(ctx context.Context, scope, id string) (*models.Plugin, error)
- func (s *Service) GetRepository(ctx context.Context, scope string) (*models.PluginRepository, error)
- func (s *Service) InstallPlugin(ctx context.Context, plugin *models.Plugin) error
- func (s *Service) IsLibraryCustomized(ctx context.Context, libraryID int, hookType string) (bool, error)
- func (s *Service) ListIdentifierTypes(ctx context.Context) ([]*models.PluginIdentifierType, error)
- func (s *Service) ListPlugins(ctx context.Context) ([]*models.Plugin, error)
- func (s *Service) ListRepositories(ctx context.Context) ([]*models.PluginRepository, error)
- func (s *Service) RemoveRepository(ctx context.Context, scope string) error
- func (s *Service) ResetAllLibraryOrders(ctx context.Context, libraryID int) error
- func (s *Service) ResetLibraryFieldSettings(ctx context.Context, libraryID int, scope, pluginID string) error
- func (s *Service) ResetLibraryOrder(ctx context.Context, libraryID int, hookType string) error
- func (s *Service) RetrievePlugin(ctx context.Context, scope, id string) (*models.Plugin, error)
- func (s *Service) SetConfig(ctx context.Context, scope, pluginID, key, value string) error
- func (s *Service) SetFieldSetting(ctx context.Context, scope, pluginID, field string, enabled bool) error
- func (s *Service) SetLibraryFieldSetting(ctx context.Context, libraryID int, scope, pluginID, field string, ...) error
- func (s *Service) SetLibraryOrder(ctx context.Context, libraryID int, hookType string, ...) error
- func (s *Service) SetOrder(ctx context.Context, hookType string, entries []models.PluginHookConfig) error
- func (s *Service) UninstallPlugin(ctx context.Context, scope, id string) error
- func (s *Service) UpdateConfidenceThreshold(ctx context.Context, scope, pluginID string, threshold *float64) error
- func (s *Service) UpdatePlugin(ctx context.Context, plugin *models.Plugin) error
- func (s *Service) UpdateRepository(ctx context.Context, repo *models.PluginRepository) error
- func (s *Service) UpsertIdentifierTypes(ctx context.Context, scope, pluginID string, types []IdentifierTypeCap) error
- type SetFieldSettingsPayload
- type SetLibraryOrderPayload
- type SetOrderPayload
- type ShellAccessCap
- type SyncRepositoryResponse
- type UpdatePluginPayload
Constants ¶
This section is empty.
Variables ¶
var AllowedDownloadHosts = []string{"https://github.com/"}
AllowedDownloadHosts lists the allowed host prefixes for plugin download URLs. Tests can override this to allow test servers.
var AllowedFetchHosts = []string{"https://raw.githubusercontent.com/"}
AllowedFetchHosts lists the allowed host prefixes for repository manifest URLs. Tests can override this to allow test servers.
var SupportedManifestVersions = []int{1}
SupportedManifestVersions lists manifest versions this Shisho release supports.
var ValidMetadataFields = []string{
"title", "subtitle", "authors", "narrators",
"series", "seriesNumber", "genres", "tags",
"description", "publisher", "url",
"releaseDate", "cover", "identifiers",
"language", "abridged",
}
ValidMetadataFields lists all valid field names for enricher declarations. These map to fields in mediafile.ParsedMetadata.
Functions ¶
func BuildBookContext ¶
BuildBookContext converts a Book model to a map for plugin context.
func BuildFileContext ¶
BuildFileContext converts a File model to a map for plugin context.
func DownloadCoverFromURL ¶ added in v0.0.21
func DownloadCoverFromURL(ctx context.Context, md *mediafile.ParsedMetadata, allowedDomains []string, log logger.Logger) bool
DownloadCoverFromURL fetches a cover image from a URL and populates md.CoverData and md.CoverMimeType. Returns true if the download succeeded, false otherwise. Skips if CoverData is already set (precedence rule). The URL's domain (and any redirect domains) must be in the plugin's httpAccess.domains allowlist.
func InjectHostAPIs ¶
func InjectHostAPIs(rt *Runtime, configGetter ConfigGetter) error
InjectHostAPIs sets up the shisho.* APIs in a plugin's goja runtime. The logPrefix is derived from the runtime's scope and pluginID. The configGetter provides config values for the plugin.
func IsValidMetadataField ¶ added in v0.0.10
IsValidMetadataField returns true if the field name is a valid enricher field.
func NewHandler ¶
NewHandler creates a handler for testing and external route registration.
func RegisterIdentifyRoutes ¶ added in v0.0.21
func RegisterIdentifyRoutes(g *echo.Group, service *Service, manager *Manager, ed *EnrichDeps)
RegisterIdentifyRoutes registers plugin search/apply routes that require books:write permission. These are separate from the admin plugin management routes which require config:write.
func RegisterLibraryRoutes ¶
func RegisterLibraryRoutes(g *echo.Group, service *Service, manager *Manager, authMiddleware *auth.Middleware)
RegisterLibraryRoutes registers per-library plugin order routes on a libraries group.
func RegisterRoutesWithGroup ¶
func RegisterRoutesWithGroup(g *echo.Group, service *Service, manager *Manager, installer *Installer, db *bun.DB, ed *EnrichDeps)
RegisterRoutesWithGroup registers plugin management API routes.
Types ¶
type AddRepositoryPayload ¶ added in v0.0.47
type AddRepositoryPayload struct {
URL string `json:"url" validate:"required,url"`
Scope string `json:"scope" validate:"required"`
}
AddRepositoryPayload is the body of POST /plugins/repositories.
type AnnotatedPluginVersion ¶ added in v0.0.26
type AnnotatedPluginVersion struct {
PluginVersion `tstype:",extends"`
Compatible bool `json:"compatible"`
}
AnnotatedPluginVersion extends PluginVersion with a compatibility flag.
func AnnotateVersionCompatibility ¶ added in v0.0.26
func AnnotateVersionCompatibility(versions []PluginVersion) []AnnotatedPluginVersion
AnnotateVersionCompatibility annotates each version with whether it is compatible with the running Shisho version based on minShishoVersion.
type ApplyOverrides ¶ added in v0.0.47
type ApplyOverrides struct {
// FileName is the value to write to file.Name. Nil = no change.
// Empty string is treated as nil (treat absent or "" as no-op so
// callers don't need to special-case empty inputs).
FileName *string
// FileNameSource is the value to write to file.NameSource. Nil
// means "default to the plugin source for this apply call".
FileNameSource *string
// SeriesEntries, when non-nil, replaces the book's series associations
// with the provided list. An empty slice clears all series. Nil means
// "don't touch series" (the identify form's series checkbox was off).
SeriesEntries *[]SeriesEntry
}
ApplyOverrides carries apply-path-only signals that don't belong on mediafile.ParsedMetadata (which is part of the public plugin SDK contract). These come exclusively from the identify apply payload — plugins do not model them.
type AvailablePlugin ¶
type AvailablePlugin struct {
ID string `json:"id"`
Name string `json:"name"`
Overview string `json:"overview"`
Description string `json:"description"`
Homepage string `json:"homepage"`
ImageURL string `json:"imageUrl"`
Versions []PluginVersion `json:"versions"`
}
AvailablePlugin describes a plugin available for installation from a repository.
type AvailablePluginResponse ¶ added in v0.0.47
type AvailablePluginResponse struct {
Scope string `json:"scope"`
ID string `json:"id"`
Name string `json:"name"`
Overview string `json:"overview"`
Description string `json:"description"`
Homepage string `json:"homepage"`
ImageURL string `json:"imageUrl"`
IsOfficial bool `json:"is_official"`
Versions []AnnotatedPluginVersion `json:"versions"`
Compatible bool `json:"compatible"`
}
AvailablePluginResponse is the per-plugin shape returned by GET /plugins/available (as a bare array) and GET /plugins/available/:scope/:id. imageUrl is repository-index passthrough (camelCase exemption); is_official and compatible are server-added.
type Capabilities ¶
type Capabilities struct {
InputConverter *InputConverterCap `json:"inputConverter"`
FileParser *FileParserCap `json:"fileParser"`
OutputGenerator *OutputGeneratorCap `json:"outputGenerator"`
MetadataEnricher *MetadataEnricherCap `json:"metadataEnricher"`
IdentifierTypes []IdentifierTypeCap `json:"identifierTypes"`
HTTPAccess *HTTPAccessCap `json:"httpAccess"`
FileAccess *FileAccessCap `json:"fileAccess"`
FFmpegAccess *FFmpegAccessCap `json:"ffmpegAccess"`
ShellAccess *ShellAccessCap `json:"shellAccess"`
}
type ConfigField ¶
type ConfigField struct {
Type string `json:"type" tstype:"ConfigFieldType"`
Label string `json:"label"`
Description string `json:"description"`
Required bool `json:"required"`
Secret bool `json:"secret"`
Default interface{} `json:"default"`
Min *float64 `json:"min"`
Max *float64 `json:"max"`
Options []SelectOption `json:"options"`
}
ConfigField describes one entry of a plugin's configSchema as parsed from the manifest. Keys stay camelCase on the wire (manifest passthrough exemption, ADR 0004).
type ConfigGetter ¶
type ConfigGetter interface {
GetConfigRaw(ctx context.Context, scope, pluginID, key string) (*string, error)
GetAllConfigRaw(ctx context.Context, scope, pluginID string) (map[string]*string, error)
}
ConfigGetter provides config values for a plugin at runtime.
type ConfigSchema ¶
type ConfigSchema map[string]ConfigField
type ConvertResult ¶
ConvertResult is the result of an input converter hook.
type EnrichDeps ¶ added in v0.0.18
type EnrichDeps struct {
BookStore bookStore
RelStore relationStore
IdentStore identifierStore
PersonFinder personFinder
GenreFinder genreFinder
TagFinder tagFinder
PublisherFinder publisherFinder
SearchIndexer searchIndexer
PageExtractor pageExtractor
}
EnrichDeps holds optional dependencies for metadata persistence (apply/enrich). If nil, metadata persistence operations are unavailable.
type EnrichSearchResult ¶ added in v0.0.22
type EnrichSearchResult struct {
mediafile.ParsedMetadata `tstype:",extends"`
PluginScope string `json:"plugin_scope"`
PluginID string `json:"plugin_id"`
DisabledFields []string `json:"disabled_fields,omitempty"`
}
EnrichSearchResult wraps ParsedMetadata with server-added fields for the search HTTP response (sent to the frontend, not used by plugins).
type ErrVersionIncompatible ¶ added in v0.0.18
ErrVersionIncompatible is returned when a plugin requires a newer Shisho version. The Manager uses this to distinguish version incompatibility from other load errors and set the appropriate PluginStatusNotSupported status.
func (*ErrVersionIncompatible) Error ¶ added in v0.0.18
func (e *ErrVersionIncompatible) Error() string
type FFmpegAccessCap ¶
type FFmpegAccessCap struct {
Description string `json:"description"`
}
type FSContext ¶
type FSContext struct {
// contains filtered or unexported fields
}
FSContext tracks allowed paths and temp dir for a single hook invocation. It controls what filesystem operations a plugin can perform.
allowedPaths grants read+write on hook-provided paths (e.g. a file parser's sourcePath, an output generator's destPath). Callers pass a file path for file-only scope or a directory for subtree scope — there is no third option, because isPathWithin does prefix matching against a trailing separator.
allowedReadOnlyPaths is a strict subset of allowedPaths' semantics but only grants reads. Used by the metadata enricher to expose the enrichment target without letting the plugin overwrite the user's book file.
func NewFSContext ¶
func NewFSContext(pluginDir, dataDir string, allowedPaths []string, fileAccessCap *FileAccessCap) *FSContext
NewFSContext creates a new FSContext for a hook invocation.
func (*FSContext) SetReadOnlyAllowedPaths ¶ added in v0.0.35
SetReadOnlyAllowedPaths replaces the set of paths the plugin may read but not write. Pass a file path for file-only scope, or a directory for subtree scope (same semantics as allowedPaths).
type FieldSettingsResponse ¶ added in v0.0.47
FieldSettingsResponse is the body of GET /plugins/installed/:scope/:id/fields.
type FileAccessCap ¶
type FileParserCap ¶
type HTTPAccessCap ¶
type IdentifierTypeCap ¶
type InputConverterCap ¶
type InstallPluginPayload ¶ added in v0.0.47
type InstallPluginPayload struct {
Scope string `json:"scope" validate:"required"`
ID string `json:"id" validate:"required"`
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
DownloadURL string `json:"download_url,omitempty"`
SHA256 string `json:"sha256,omitempty"`
}
InstallPluginPayload is the body of POST /plugins/installed. Either both download_url and sha256 are provided, or neither (install from repository).
type Installer ¶
type Installer struct {
// contains filtered or unexported fields
}
Installer handles downloading and extracting plugins.
func NewInstaller ¶
NewInstaller creates a new Installer.
func (*Installer) DownloadPluginImage ¶ added in v0.0.18
func (inst *Installer) DownloadPluginImage(ctx context.Context, scope, pluginID, imageURL string) error
DownloadPluginImage downloads an image from the given URL and saves it as icon.png in the plugin's directory. Errors are non-fatal and logged by the caller.
func (*Installer) InstallPlugin ¶
func (inst *Installer) InstallPlugin(ctx context.Context, scope, pluginID, downloadURL, expectedSHA256 string) (*Manifest, error)
InstallPlugin downloads a plugin ZIP, verifies its SHA256, and extracts it. Returns the parsed manifest from the extracted plugin.
func (*Installer) UninstallPlugin ¶
UninstallPlugin removes a plugin's files from disk.
type LibraryFieldSettingsResponse ¶ added in v0.0.47
type LibraryFieldSettingsResponse struct {
Fields map[string]bool `json:"fields"`
Customized bool `json:"customized"`
}
LibraryFieldSettingsResponse is the body of GET /libraries/:id/plugins/:scope/:pluginId/fields.
type LibraryOrderEntry ¶ added in v0.0.47
type LibraryOrderEntry struct {
Scope string `json:"scope" validate:"required"`
ID string `json:"id" validate:"required"`
Mode string `json:"mode" tstype:"PluginMode"`
}
LibraryOrderEntry is one entry in SetLibraryOrderPayload. An empty mode defaults to "enabled" server-side.
type LibraryPluginOrderPlugin ¶ added in v0.0.47
type LibraryPluginOrderPlugin struct {
Scope string `json:"scope"`
ID string `json:"id"`
Name string `json:"name"`
Mode string `json:"mode" tstype:"PluginMode"`
}
LibraryPluginOrderPlugin is one entry in LibraryPluginOrderResponse, resolved to the plugin's display name.
type LibraryPluginOrderResponse ¶ added in v0.0.47
type LibraryPluginOrderResponse struct {
Customized bool `json:"customized"`
Plugins []LibraryPluginOrderPlugin `json:"plugins"`
}
LibraryPluginOrderResponse is the body of GET /libraries/:id/plugins/order/:hookType.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager holds loaded Runtime instances indexed by "scope/id". It coordinates loading at startup, unloading, and hot-reloading on install/update/enable.
func NewManager ¶
NewManager creates a new Manager.
func (*Manager) CheckForUpdates ¶
CheckForUpdates checks all installed plugins against enabled repositories for available updates. It sets or clears UpdateAvailableVersion on each plugin.
func (*Manager) CheckForUpdatesForRepo ¶ added in v0.0.34
func (m *Manager) CheckForUpdatesForRepo(ctx context.Context, scope string, manifest *RepositoryManifest) error
CheckForUpdatesForRepo re-evaluates UpdateAvailableVersion for installed plugins belonging to the given scope using an already-fetched manifest. Used by the sync-repo handler to avoid re-fetching every enabled repository when a single repo is synced. Plugins in other scopes are left untouched — they can't have changed since we only synced one repo.
func (*Manager) DeletePluginData ¶ added in v0.0.18
DeletePluginData removes the persistent data directory for a plugin. Errors are logged but not returned since this is a best-effort cleanup.
func (*Manager) GetManualRuntimes ¶ added in v0.0.26
func (m *Manager) GetManualRuntimes(ctx context.Context, hookType string, libraryID int) ([]*Runtime, error)
GetManualRuntimes returns runtimes for a hook type that are available for manual invocation. Both "enabled" and "manual_only" plugins are returned; only "disabled" are excluded. If libraryID > 0 and the library has customized the order for this hook type, uses the per-library order. Otherwise falls back to global order.
func (*Manager) GetOrderedRuntimes ¶
func (m *Manager) GetOrderedRuntimes(ctx context.Context, hookType string, libraryID int) ([]*Runtime, error)
GetOrderedRuntimes returns runtimes for a hook type in user-defined order. If libraryID > 0 and the library has customized the order for this hook type, uses the per-library order (only enabled entries). Otherwise falls back to global order. In both paths, only runtimes that are actually loaded (globally enabled) are returned.
func (*Manager) GetOutputGenerator ¶
func (m *Manager) GetOutputGenerator(formatID string) *PluginGenerator
GetOutputGenerator returns the PluginGenerator for a given format ID. Returns nil if no plugin provides that format.
func (*Manager) GetParserForType ¶
GetParserForType returns the first loaded runtime that has a fileParser for the given type.
func (*Manager) GetRuntime ¶
GetRuntime returns the runtime for a plugin (nil if not loaded).
func (*Manager) LoadAll ¶
LoadAll loads all enabled plugins from the database at startup. Errors are stored in plugins.LoadError and don't prevent other plugins from loading.
func (*Manager) LoadPlugin ¶
LoadPlugin loads a single plugin (called during install/enable).
func (*Manager) RegisteredConverterExtensions ¶
RegisteredConverterExtensions returns source extensions that have input converters.
func (*Manager) RegisteredFileExtensions ¶
RegisteredFileExtensions returns all file extensions registered by plugin fileParsers (excluding reserved built-in extensions: epub, cbz, m4b, pdf).
func (*Manager) RegisteredOutputFormats ¶
func (m *Manager) RegisteredOutputFormats() []OutputFormatInfo
RegisteredOutputFormats returns all format IDs registered by plugin output generators, along with their source type restrictions.
func (*Manager) ReloadPlugin ¶
ReloadPlugin performs a hot-reload (called during update). Acquires write lock on old runtime (waits for in-progress hooks), then swaps.
func (*Manager) RunFileParser ¶
func (m *Manager) RunFileParser(ctx context.Context, rt *Runtime, filePath, fileType string) (*mediafile.ParsedMetadata, error)
RunFileParser invokes a plugin's fileParser.parse() hook.
func (*Manager) RunFingerprint ¶
func (m *Manager) RunFingerprint(rt *Runtime, bookCtx, fileCtx map[string]interface{}) (string, error)
RunFingerprint invokes a plugin's outputGenerator.fingerprint() hook.
func (*Manager) RunInputConverter ¶
func (m *Manager) RunInputConverter(ctx context.Context, rt *Runtime, sourcePath, targetDir string) (*ConvertResult, error)
RunInputConverter invokes a plugin's inputConverter.convert() hook.
func (*Manager) RunMetadataSearch ¶ added in v0.0.18
func (m *Manager) RunMetadataSearch(ctx context.Context, rt *Runtime, searchCtx map[string]interface{}, targetFilePath string) (*SearchResponse, error)
RunMetadataSearch invokes a plugin's metadataEnricher.search() hook.
targetFilePath, if non-empty, grants the enricher read-only access to exactly that one file (the enrichment target) via FSContext's read-only allowedPaths — without it, enrichers get no filesystem access beyond the plugin's own directory unless they declare the broader fileAccess capability. Writes to the target path are NOT granted; a plugin that needs to modify files must declare fileAccess: readwrite explicitly.
func (*Manager) RunOnUninstalling ¶ added in v0.0.18
RunOnUninstalling invokes a plugin's optional onUninstalling() lifecycle hook. This is called before uninstall to give the plugin a chance to clean up. Errors in the hook do not prevent uninstall.
func (*Manager) RunOutputGenerator ¶
func (m *Manager) RunOutputGenerator(ctx context.Context, rt *Runtime, sourcePath, destPath string, bookCtx, fileCtx map[string]interface{}) error
RunOutputGenerator invokes a plugin's outputGenerator.generate() hook.
func (*Manager) SetEventCallback ¶ added in v0.0.18
func (m *Manager) SetEventCallback(cb PluginEventCallback)
SetEventCallback registers a callback for plugin lifecycle events. Only one callback is supported; subsequent calls replace the previous one.
func (*Manager) UnloadPlugin ¶
UnloadPlugin removes a plugin from memory (called during uninstall/disable).
type Manifest ¶
type Manifest struct {
ManifestVersion int `json:"manifestVersion"`
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
Overview string `json:"overview"`
Description string `json:"description"`
Homepage string `json:"homepage"`
License string `json:"license"`
MinShishoVersion string `json:"minShishoVersion"`
Capabilities Capabilities `json:"capabilities"`
ConfigSchema ConfigSchema `json:"configSchema"`
}
func ParseManifest ¶
ParseManifest parses and validates a manifest.json byte slice.
type MetadataEnricherCap ¶
type OrderEntry ¶ added in v0.0.47
type OrderEntry struct {
Scope string `json:"scope" validate:"required"`
ID string `json:"id" validate:"required"`
Mode string `json:"mode" tstype:"PluginMode"`
}
OrderEntry is one entry in SetOrderPayload. An empty mode defaults to "enabled" server-side.
type OutputFormatInfo ¶
type OutputFormatInfo struct {
ID string
Name string
SourceTypes []string
Scope string
PluginID string
}
OutputFormatInfo describes a plugin-provided output format.
type OutputGeneratorCap ¶
type PluginApplyPayload ¶ added in v0.0.47
type PluginApplyPayload struct {
BookID int `json:"book_id" validate:"required"`
FileID *int `json:"file_id"`
Fields map[string]any `json:"fields" validate:"required"`
// FileName is an optional override for file.Name. The backend treats an
// empty string as absent; only set when the user explicitly opts the
// Name field into the apply payload.
FileName *string `json:"file_name"`
// FileNameSource is the source attribution for file.Name: "plugin" when
// the saved value matches the plugin's proposal, "user" when edited.
FileNameSource *string `json:"file_name_source" tstype:"'plugin' | 'user'"`
PluginScope string `json:"plugin_scope" validate:"required"`
PluginID string `json:"plugin_id" validate:"required"`
}
PluginApplyPayload is the body of POST /plugins/apply. Fields carries the user-selected metadata as an untyped map (converted server-side by convertFieldsToMetadata / extractSeriesEntries).
type PluginConfigResponse ¶ added in v0.0.47
type PluginConfigResponse struct {
Schema ConfigSchema `json:"schema"`
Values map[string]interface{} `json:"values"`
DeclaredFields []string `json:"declaredFields"`
FieldSettings map[string]bool `json:"fieldSettings"`
ConfidenceThreshold *float64 `json:"confidence_threshold"`
}
PluginConfigResponse is the body of GET /plugins/installed/:scope/:id/config. Schema/declaredFields come from the parsed manifest (camelCase exemption); values holds the stored config with secrets masked.
type PluginEvent ¶ added in v0.0.18
type PluginEvent struct {
Type PluginEventType
Scope string
ID string
// Hooks lists the hook types this plugin provides (e.g., "fileParser", "metadataEnricher").
// Empty for uninstall/disable events.
Hooks []string
}
PluginEvent contains information about a plugin lifecycle change.
type PluginEventCallback ¶ added in v0.0.18
type PluginEventCallback func(event PluginEvent)
PluginEventCallback is the signature for event listeners.
type PluginEventType ¶ added in v0.0.18
type PluginEventType int
PluginEventType describes a plugin lifecycle event.
const ( // PluginEventInstalled fires after a plugin is installed and loaded. PluginEventInstalled PluginEventType = iota // PluginEventUninstalled fires after a plugin is uninstalled. PluginEventUninstalled // PluginEventUpdated fires after a plugin version is updated (hot-reloaded). PluginEventUpdated // PluginEventEnabled fires after a disabled plugin is re-enabled and loaded. PluginEventEnabled // PluginEventDisabled fires after an active plugin is disabled and unloaded. PluginEventDisabled // PluginEventMalfunctioned fires when a plugin fails to load. PluginEventMalfunctioned )
type PluginGenerator ¶
type PluginGenerator struct {
// contains filtered or unexported fields
}
PluginGenerator adapts a plugin's outputGenerator hook to the filegen.Generator interface.
func NewPluginGenerator ¶
func NewPluginGenerator(manager *Manager, scope, pluginID, formatID string) *PluginGenerator
NewPluginGenerator creates a new PluginGenerator.
func (*PluginGenerator) Fingerprint ¶
Fingerprint returns the plugin's fingerprint string for cache invalidation.
func (*PluginGenerator) Generate ¶
func (g *PluginGenerator) Generate(ctx context.Context, srcPath, destPath string, book *models.Book, file *models.File) error
Generate implements filegen.Generator by delegating to the plugin's outputGenerator.generate() hook.
func (*PluginGenerator) SupportedType ¶
func (g *PluginGenerator) SupportedType() string
SupportedType implements filegen.Generator.
type PluginSearchError ¶ added in v0.0.31
type PluginSearchError struct {
PluginScope string `json:"plugin_scope"`
PluginID string `json:"plugin_id"`
PluginName string `json:"plugin_name"`
Message string `json:"message"`
}
PluginSearchError reports a plugin whose search() hook failed so the frontend can surface it to the user instead of silently dropping it.
type PluginSearchPayload ¶ added in v0.0.47
type PluginSearchPayload struct {
Query string `json:"query" validate:"required"`
BookID int `json:"book_id" validate:"required"`
FileID *int `json:"file_id"`
Author string `json:"author,omitempty"`
Identifiers []mediafile.ParsedIdentifier `json:"identifiers,omitempty" tstype:"ParsedIdentifier[]"`
}
PluginSearchPayload is the body of POST /plugins/search.
type PluginSearchResponse ¶ added in v0.0.32
type PluginSearchResponse struct {
Results []EnrichSearchResult `json:"results"`
Errors []PluginSearchError `json:"errors,omitempty"`
SkippedPlugins []PluginSearchSkipped `json:"skipped_plugins,omitempty"`
TotalPlugins int `json:"total_plugins"`
}
PluginSearchResponse is the HTTP response body for POST /plugins/search. TotalPlugins is the number of candidate enricher runtimes considered for this search (after library + mode filtering but before file-type skipping), which lets the frontend distinguish "every enricher was skipped" from "some enrichers ran and returned nothing".
type PluginSearchSkipped ¶ added in v0.0.31
type PluginSearchSkipped struct {
PluginScope string `json:"plugin_scope"`
PluginID string `json:"plugin_id"`
PluginName string `json:"plugin_name"`
}
PluginSearchSkipped reports an enricher that was skipped because it does not declare support for the target file type. The frontend uses this to distinguish "no plugins handle this file type" from "plugins ran and returned nothing".
type PluginVersion ¶
type PluginVersion struct {
Version string `json:"version"`
MinShishoVersion string `json:"minShishoVersion"`
ManifestVersion int `json:"manifestVersion"`
ReleaseDate string `json:"releaseDate"`
Changelog string `json:"changelog"`
DownloadURL string `json:"downloadUrl"`
SHA256 string `json:"sha256"`
// ReleaseURL is an optional explicit URL for this version's release page
// (e.g. a GitHub release, a GitLab tag page). When present, the UI renders
// a "View release" link on the version card. When absent, no link is shown.
// Not validated — any string URL is accepted.
ReleaseURL string `json:"releaseUrl,omitempty"`
Capabilities *Capabilities `json:"capabilities,omitempty"`
}
PluginVersion describes a specific version of an available plugin.
func FilterCompatibleVersions ¶
func FilterCompatibleVersions(versions []PluginVersion) []PluginVersion
FilterCompatibleVersions returns only versions with a manifestVersion supported by this Shisho release.
func FilterVersionCompatibleVersions ¶ added in v0.0.26
func FilterVersionCompatibleVersions(versions []PluginVersion) []PluginVersion
FilterVersionCompatibleVersions returns only versions whose minShishoVersion is satisfied by the running Shisho version.
type RepositoryManifest ¶
type RepositoryManifest struct {
RepositoryVersion int `json:"repositoryVersion"`
Scope string `json:"scope"`
Name string `json:"name"`
Plugins []AvailablePlugin `json:"plugins"`
}
RepositoryManifest is the parsed JSON from a repository URL.
func FetchRepository ¶
func FetchRepository(rawURL string) (*RepositoryManifest, error)
FetchRepository downloads and parses a repository manifest from the given URL. Only HTTPS URLs to allowed hosts (raw.githubusercontent.com by default) are permitted.
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
Runtime wraps a goja VM for a single plugin. It loads manifest.json, executes main.js (which defines a `plugin` global via IIFE), and extracts hook function references.
func LoadPlugin ¶
LoadPlugin creates a new Runtime by reading manifest.json and executing main.js from the given plugin directory.
func (*Runtime) HookTypes ¶
HookTypes returns the list of hook type strings this plugin provides, sorted alphabetically for deterministic output.
func (*Runtime) LoadWarning ¶ added in v0.0.10
LoadWarning returns any non-fatal warning from plugin load. Empty string means no warning.
func (*Runtime) SetFSContext ¶
SetFSContext sets the filesystem context for the current hook invocation. Called by hook execution code before invoking hooks. Pass nil to clear.
type SearchResponse ¶ added in v0.0.18
type SearchResponse struct {
Results []mediafile.ParsedMetadata
}
SearchResponse is the result of a metadata enricher's search() hook. Results are ParsedMetadata directly — no intermediate SearchResult type.
type SelectOption ¶
type SeriesEntry ¶ added in v0.0.42
SeriesEntry represents a single series association in the multi-series apply payload. Used by the identify form which supports multiple series per book, unlike the plugin SDK which models a single series.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service provides database operations for plugin management.
func (*Service) AddRepository ¶
AddRepository inserts a new plugin repository.
func (*Service) AppendToOrder ¶
AppendToOrder appends a plugin to the end of the hook config for a hook type.
func (*Service) GetAllConfigRaw ¶
func (s *Service) GetAllConfigRaw(ctx context.Context, scope, pluginID string) (map[string]*string, error)
GetAllConfigRaw returns all raw config key-value pairs for a plugin.
func (*Service) GetConfig ¶
func (s *Service) GetConfig(ctx context.Context, scope, pluginID string, schema ConfigSchema, raw bool) (map[string]interface{}, error)
GetConfig returns the configuration values for a plugin. If raw is false, secret values are masked with "***". The schema is used to determine which fields are secrets.
func (*Service) GetConfigRaw ¶
GetConfigRaw returns the raw value for a single config key.
func (*Service) GetEffectiveFieldSettings ¶ added in v0.0.10
func (s *Service) GetEffectiveFieldSettings(ctx context.Context, libraryID int, scope, pluginID string, declaredFields []string) (map[string]bool, error)
GetEffectiveFieldSettings returns the effective field settings for a library, merging global settings with library-specific overrides. Returns a map of field name -> enabled status for the specified declared fields. Priority: library override > global setting > default (enabled).
func (*Service) GetFieldSettings ¶ added in v0.0.10
func (s *Service) GetFieldSettings(ctx context.Context, scope, pluginID string) (map[string]bool, error)
GetFieldSettings returns global field settings for a plugin. Returns a map of field name -> enabled status for fields that are explicitly disabled. Absence from the map means the field is enabled (default).
func (*Service) GetLibraryFieldSettings ¶ added in v0.0.10
func (s *Service) GetLibraryFieldSettings(ctx context.Context, libraryID int, scope, pluginID string) (map[string]bool, error)
GetLibraryFieldSettings returns per-library field overrides for a plugin. Returns a map of field name -> enabled status for fields with explicit overrides. Unlike global settings, both enabled and disabled overrides are stored.
func (*Service) GetLibraryOrder ¶
func (s *Service) GetLibraryOrder(ctx context.Context, libraryID int, hookType string) ([]*models.LibraryPluginHookConfig, error)
GetLibraryOrder returns the per-library plugin hook config for a hook type, sorted by position.
func (*Service) GetOrder ¶
func (s *Service) GetOrder(ctx context.Context, hookType string) ([]*models.PluginHookConfig, error)
GetOrder returns the plugin hook config entries for a hook type, sorted by position.
func (*Service) GetRepository ¶
func (s *Service) GetRepository(ctx context.Context, scope string) (*models.PluginRepository, error)
GetRepository returns a single plugin repository by scope.
func (*Service) InstallPlugin ¶
InstallPlugin inserts a new plugin record.
func (*Service) IsLibraryCustomized ¶
func (s *Service) IsLibraryCustomized(ctx context.Context, libraryID int, hookType string) (bool, error)
IsLibraryCustomized checks if a library has customized plugin order for a hook type.
func (*Service) ListIdentifierTypes ¶
ListIdentifierTypes returns plugin-registered identifier types, deduplicated by ID. Multiple plugins can register the same type (e.g., local and published versions); only the first by scope/plugin ordering is returned.
func (*Service) ListPlugins ¶
ListPlugins returns all installed plugins.
func (*Service) ListRepositories ¶
ListRepositories returns all plugin repositories, ordered by official first then by scope.
func (*Service) RemoveRepository ¶
RemoveRepository removes a non-official plugin repository by scope.
func (*Service) ResetAllLibraryOrders ¶
ResetAllLibraryOrders removes all per-library plugin customizations for a library.
func (*Service) ResetLibraryFieldSettings ¶ added in v0.0.10
func (s *Service) ResetLibraryFieldSettings(ctx context.Context, libraryID int, scope, pluginID string) error
ResetLibraryFieldSettings removes all per-library field overrides for a plugin.
func (*Service) ResetLibraryOrder ¶
ResetLibraryOrder removes per-library customization for a specific hook type.
func (*Service) RetrievePlugin ¶
RetrievePlugin returns a single plugin by scope and id.
func (*Service) SetFieldSetting ¶ added in v0.0.10
func (s *Service) SetFieldSetting(ctx context.Context, scope, pluginID, field string, enabled bool) error
SetFieldSetting upserts a single global field setting. If enabled=true, the row is deleted (enabled is the default). If enabled=false, the row is upserted.
func (*Service) SetLibraryFieldSetting ¶ added in v0.0.10
func (s *Service) SetLibraryFieldSetting(ctx context.Context, libraryID int, scope, pluginID, field string, enabled bool) error
SetLibraryFieldSetting upserts a per-library field override. Both enabled and disabled overrides are stored to allow library-specific overrides in either direction.
func (*Service) SetLibraryOrder ¶
func (s *Service) SetLibraryOrder(ctx context.Context, libraryID int, hookType string, entries []models.LibraryPluginHookConfig) error
SetLibraryOrder replaces all per-library plugin hook config entries for a hook type. Also creates the customization record if it doesn't exist.
func (*Service) SetOrder ¶
func (s *Service) SetOrder(ctx context.Context, hookType string, entries []models.PluginHookConfig) error
SetOrder replaces all hook config entries for a hook type in a transaction.
func (*Service) UninstallPlugin ¶
UninstallPlugin removes a plugin and its related data (configs, orders cascade via FK).
func (*Service) UpdateConfidenceThreshold ¶ added in v0.0.22
func (s *Service) UpdateConfidenceThreshold(ctx context.Context, scope, pluginID string, threshold *float64) error
UpdateConfidenceThreshold sets the per-plugin confidence threshold.
func (*Service) UpdatePlugin ¶
UpdatePlugin updates an existing plugin record.
func (*Service) UpdateRepository ¶
UpdateRepository updates an existing plugin repository.
func (*Service) UpsertIdentifierTypes ¶
func (s *Service) UpsertIdentifierTypes(ctx context.Context, scope, pluginID string, types []IdentifierTypeCap) error
UpsertIdentifierTypes replaces all identifier types for a plugin in a transaction.
type SetFieldSettingsPayload ¶ added in v0.0.47
SetFieldSettingsPayload is the body of PUT /plugins/installed/:scope/:id/fields and PUT /libraries/:id/plugins/:scope/:pluginId/fields.
type SetLibraryOrderPayload ¶ added in v0.0.47
type SetLibraryOrderPayload struct {
Plugins []LibraryOrderEntry `json:"plugins" validate:"required"`
}
SetLibraryOrderPayload is the body of PUT /libraries/:id/plugins/order/:hookType.
type SetOrderPayload ¶ added in v0.0.47
type SetOrderPayload struct {
Order []OrderEntry `json:"order" validate:"required"`
}
SetOrderPayload is the body of PUT /plugins/order/:hookType.
type ShellAccessCap ¶ added in v0.0.9
type SyncRepositoryResponse ¶ added in v0.0.47
type SyncRepositoryResponse struct {
models.PluginRepository `tstype:",extends"`
UpdateRefreshError *string `json:"update_refresh_error,omitempty"`
}
SyncRepositoryResponse is the body of POST /plugins/repositories/:scope/sync. It embeds the repository by value (so tygo emits `extends PluginRepository` and the fields stay at the top level for backwards-compat with clients reading them) and adds an optional update_refresh_error populated when the post-sync update refresh failed.
type UpdatePluginPayload ¶ added in v0.0.47
type UpdatePluginPayload struct {
Enabled *bool `json:"enabled"`
AutoUpdate *bool `json:"auto_update"`
Config map[string]string `json:"config,omitempty"`
ConfidenceThreshold *float64 `json:"confidence_threshold"`
ClearConfidenceThreshold *bool `json:"clear_confidence_threshold"`
}
UpdatePluginPayload is the body of PATCH /plugins/installed/:scope/:id.
Source Files
¶
- events.go
- generator.go
- handler.go
- handler_apply_metadata.go
- handler_convert.go
- handler_enrich.go
- handler_fields.go
- handler_image.go
- handler_install.go
- handler_list.go
- handler_manifest.go
- handler_order.go
- handler_persist_metadata.go
- handler_repositories.go
- handler_update.go
- hooks.go
- hostapi.go
- hostapi_archive.go
- hostapi_ffmpeg.go
- hostapi_fs.go
- hostapi_html.go
- hostapi_http.go
- hostapi_shell.go
- hostapi_url.go
- hostapi_xml.go
- hostapi_yaml.go
- installer.go
- manager.go
- manifest.go
- repository.go
- routes.go
- runtime.go
- service.go
- target_file.go
- types.go