Documentation
¶
Index ¶
- Variables
- func BuildBookContext(book *models.Book) map[string]interface{}
- func BuildFileContext(file *models.File) map[string]interface{}
- func InjectHostAPIs(rt *Runtime, configGetter ConfigGetter) error
- func NewHandler(service *Service, manager *Manager, installer *Installer) *handler
- func RegisterLibraryRoutes(g *echo.Group, service *Service, authMiddleware *auth.Middleware)
- func RegisterRoutesWithGroup(g *echo.Group, service *Service, manager *Manager, installer *Installer)
- type AvailablePlugin
- type Capabilities
- type ConfigField
- type ConfigGetter
- type ConfigSchema
- type ConvertResult
- type EnrichmentResult
- type FFmpegAccessCap
- type FSContext
- type FileAccessCap
- type FileParserCap
- type HTTPAccessCap
- type IdentifierTypeCap
- type InputConverterCap
- type Installer
- 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 Manager
- func (m *Manager) CheckForUpdates(ctx context.Context) 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) RunMetadataEnricher(ctx context.Context, rt *Runtime, enrichCtx map[string]interface{}) (*EnrichmentResult, error)
- func (m *Manager) RunOutputGenerator(ctx context.Context, rt *Runtime, sourcePath, destPath string, ...) error
- func (m *Manager) UnloadPlugin(scope, id string)
- type Manifest
- type MetadataEnricherCap
- type OutputFormatInfo
- type OutputGeneratorCap
- type PluginGenerator
- type PluginVersion
- type RepositoryManifest
- type Runtime
- type SelectOption
- 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) GetLibraryOrder(ctx context.Context, libraryID int, hookType string) ([]*models.LibraryPlugin, error)
- func (s *Service) GetOrder(ctx context.Context, hookType string) ([]*models.PluginOrder, 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) 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) SetLibraryOrder(ctx context.Context, libraryID int, hookType string, ...) error
- func (s *Service) SetOrder(ctx context.Context, hookType string, entries []models.PluginOrder) error
- func (s *Service) UninstallPlugin(ctx context.Context, scope, id string) 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
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.
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 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 NewHandler ¶
NewHandler creates a handler for testing and external route registration.
func RegisterLibraryRoutes ¶
func RegisterLibraryRoutes(g *echo.Group, service *Service, authMiddleware *auth.Middleware)
RegisterLibraryRoutes registers per-library plugin order routes on a libraries group.
Types ¶
type AvailablePlugin ¶
type AvailablePlugin struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Author string `json:"author"`
Homepage string `json:"homepage"`
Versions []PluginVersion `json:"versions"`
}
AvailablePlugin describes a plugin available for installation from a repository.
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"`
}
type ConfigField ¶
type ConfigField struct {
Type string `json:"type"` // string, boolean, number, select, textarea
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"`
}
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 EnrichmentResult ¶
type EnrichmentResult struct {
Modified bool
Metadata *mediafile.ParsedMetadata // nil if Modified is false
}
EnrichmentResult is the result of a metadata enricher hook.
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.
func NewFSContext ¶
func NewFSContext(pluginDir string, allowedPaths []string, fileAccessCap *FileAccessCap) *FSContext
NewFSContext creates a new FSContext for a hook invocation.
type FileAccessCap ¶
type FileParserCap ¶
type HTTPAccessCap ¶
type IdentifierTypeCap ¶
type InputConverterCap ¶
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) 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 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) 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).
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) RunMetadataEnricher ¶
func (m *Manager) RunMetadataEnricher(ctx context.Context, rt *Runtime, enrichCtx map[string]interface{}) (*EnrichmentResult, error)
RunMetadataEnricher invokes a plugin's metadataEnricher.enrich() hook.
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) 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"`
Description string `json:"description"`
Author string `json:"author"`
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 OutputFormatInfo ¶
type OutputFormatInfo struct {
ID string
Name string
SourceTypes []string
Scope string
PluginID string
}
OutputFormatInfo describes a plugin-provided output format.
type OutputGeneratorCap ¶
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 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"`
}
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.
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) SetFSContext ¶
SetFSContext sets the filesystem context for the current hook invocation. Called by hook execution code before invoking hooks. Pass nil to clear.
type SelectOption ¶
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 order 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) GetLibraryOrder ¶
func (s *Service) GetLibraryOrder(ctx context.Context, libraryID int, hookType string) ([]*models.LibraryPlugin, error)
GetLibraryOrder returns the per-library plugin order for a hook type, sorted by position.
func (*Service) GetOrder ¶
GetOrder returns the plugin order 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 all plugin-registered identifier types.
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) 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) SetLibraryOrder ¶
func (s *Service) SetLibraryOrder(ctx context.Context, libraryID int, hookType string, entries []models.LibraryPlugin) error
SetLibraryOrder replaces all per-library plugin order 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.PluginOrder) error
SetOrder replaces all order 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) 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.