227 lines
8.4 KiB
Go
227 lines
8.4 KiB
Go
package extension
|
|
|
|
import (
|
|
"strings"
|
|
)
|
|
|
|
type Consumer interface {
|
|
InitExtensionBank(bank *UnifiedBank)
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
type Type string
|
|
|
|
type Language string
|
|
|
|
type PluginPermissionScope string
|
|
|
|
const (
|
|
TypeAnimeTorrentProvider Type = "anime-torrent-provider"
|
|
TypeMangaProvider Type = "manga-provider"
|
|
TypeOnlinestreamProvider Type = "onlinestream-provider"
|
|
TypePlugin Type = "plugin"
|
|
)
|
|
|
|
const (
|
|
LanguageJavascript Language = "javascript"
|
|
LanguageTypescript Language = "typescript"
|
|
LanguageGo Language = "go"
|
|
)
|
|
|
|
type Extension struct {
|
|
// ID is the unique identifier of the extension
|
|
// It must be unique across all extensions
|
|
// It must start with a letter and contain only alphanumeric characters
|
|
ID string `json:"id"` // e.g. "extension-example"
|
|
Name string `json:"name"` // e.g. "Extension"
|
|
Version string `json:"version"` // e.g. "1.0.0"
|
|
SemverConstraint string `json:"semverConstraint,omitempty"`
|
|
// The URI to the extension manifest file.
|
|
// This is "builtin" if the extension is built-in and "" if the extension is local.
|
|
ManifestURI string `json:"manifestURI"` // e.g. "http://cdn.something.app/extensions/extension-example/manifest.json"
|
|
// The programming language of the extension
|
|
// It is used to determine how to interpret the extension
|
|
Language Language `json:"language"` // e.g. "go"
|
|
// Type is the area of the application the extension is targeting
|
|
Type Type `json:"type"` // e.g. "anime-torrent-provider"
|
|
Description string `json:"description"` // e.g. "This extension provides torrents"
|
|
Author string `json:"author"` // e.g. "Seanime"
|
|
// Icon is the URL to the extension icon
|
|
Icon string `json:"icon"`
|
|
// Website is the URL to the extension website
|
|
Website string `json:"website"`
|
|
// ISO 639-1 language code.
|
|
// Set this to "multi" if the extension supports multiple languages.
|
|
// Defaults to "en".
|
|
Lang string `json:"lang"`
|
|
// List of permissions asked by the extension.
|
|
// The user must grant these permissions before the extension can be loaded.
|
|
Permissions []string `json:"permissions,omitempty"` // NOT IMPLEMENTED
|
|
UserConfig *UserConfig `json:"userConfig,omitempty"`
|
|
// Payload is the content of the extension.
|
|
Payload string `json:"payload"`
|
|
// PayloadURI is the URI to the extension payload.
|
|
// It can be used as an alternative to the Payload field to load the payload from a remote source.
|
|
// If the extension is in debug mode, this can be a file path to the local payload.
|
|
PayloadURI string `json:"payloadURI,omitempty"`
|
|
// Plugin is the manifest of the extension if it is a plugin.
|
|
Plugin *PluginManifest `json:"plugin,omitempty"`
|
|
|
|
// IsDevelopment is true if the extension is in development mode.
|
|
// If true, the extension code will be loaded from PayloadURI and allow you to edit the code from an editor and reload the extension without restarting the application.
|
|
IsDevelopment bool `json:"isDevelopment,omitempty"`
|
|
|
|
SavedUserConfig *SavedUserConfig `json:"-"` // Contains the saved user config for the extension
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// BaseExtension is the base interface for all extensions
|
|
// An extension is a JS file that is loaded by HTTP request
|
|
type BaseExtension interface {
|
|
GetID() string
|
|
GetName() string
|
|
GetVersion() string
|
|
GetManifestURI() string
|
|
GetLanguage() Language
|
|
GetType() Type
|
|
GetDescription() string
|
|
GetAuthor() string
|
|
GetPayload() string
|
|
GetPayloadURI() string
|
|
GetLang() string
|
|
GetIcon() string
|
|
GetWebsite() string
|
|
GetPermissions() []string
|
|
GetUserConfig() *UserConfig
|
|
GetSavedUserConfig() *SavedUserConfig
|
|
GetIsDevelopment() bool
|
|
}
|
|
|
|
type Configurable interface {
|
|
SetSavedUserConfig(config SavedUserConfig)
|
|
}
|
|
|
|
func ToExtensionData(ext BaseExtension) *Extension {
|
|
return &Extension{
|
|
ID: ext.GetID(),
|
|
Name: ext.GetName(),
|
|
Version: ext.GetVersion(),
|
|
ManifestURI: ext.GetManifestURI(),
|
|
Language: ext.GetLanguage(),
|
|
Lang: GetExtensionLang(ext.GetLang()),
|
|
Type: ext.GetType(),
|
|
Description: ext.GetDescription(),
|
|
Author: ext.GetAuthor(),
|
|
Permissions: ext.GetPermissions(),
|
|
UserConfig: ext.GetUserConfig(),
|
|
Icon: ext.GetIcon(),
|
|
Website: ext.GetWebsite(),
|
|
Payload: ext.GetPayload(),
|
|
PayloadURI: ext.GetPayloadURI(),
|
|
IsDevelopment: ext.GetIsDevelopment(),
|
|
SavedUserConfig: ext.GetSavedUserConfig(),
|
|
}
|
|
}
|
|
|
|
func GetExtensionLang(lang string) string {
|
|
if lang == "" {
|
|
return "en"
|
|
}
|
|
if lang == "all" {
|
|
return "multi"
|
|
}
|
|
return lang
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
type InvalidExtensionErrorCode string
|
|
|
|
const (
|
|
// InvalidExtensionManifestError is returned when the extension manifest is invalid
|
|
InvalidExtensionManifestError InvalidExtensionErrorCode = "invalid_manifest"
|
|
// InvalidExtensionPayloadError is returned when the extension code is invalid / obsolete
|
|
InvalidExtensionPayloadError InvalidExtensionErrorCode = "invalid_payload"
|
|
InvalidExtensionUserConfigError InvalidExtensionErrorCode = "user_config_error"
|
|
// InvalidExtensionAuthorizationError is returned when some authorization scopes have not been granted
|
|
InvalidExtensionAuthorizationError InvalidExtensionErrorCode = "invalid_authorization"
|
|
// InvalidExtensionPluginPermissionsNotGranted is returned when the plugin permissions have not been granted
|
|
InvalidExtensionPluginPermissionsNotGranted InvalidExtensionErrorCode = "plugin_permissions_not_granted"
|
|
// InvalidExtensionSemverConstraintError is returned when the semver constraint is invalid
|
|
InvalidExtensionSemverConstraintError InvalidExtensionErrorCode = "invalid_semver_constraint"
|
|
)
|
|
|
|
type InvalidExtension struct {
|
|
// Auto-generated ID
|
|
ID string `json:"id"`
|
|
Path string `json:"path"`
|
|
Extension Extension `json:"extension"`
|
|
Reason string `json:"reason"`
|
|
Code InvalidExtensionErrorCode `json:"code"`
|
|
PluginPermissionDescription string `json:"pluginPermissionDescription,omitempty"`
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
type UserConfig struct {
|
|
// The version of the extension configuration.
|
|
// This is used to determine if the configuration has changed.
|
|
Version int `json:"version"`
|
|
// Whether the extension requires user configuration.
|
|
RequiresConfig bool `json:"requiresConfig"`
|
|
// This will be used to generate the user configuration form, and the values will be passed to the extension.
|
|
Fields []ConfigField `json:"fields"`
|
|
}
|
|
|
|
type Preferences struct {
|
|
// This will be used to generate the preference form, and the values will be passed to the extension.
|
|
Fields []ConfigField `json:"fields"`
|
|
}
|
|
|
|
type SavedUserConfig struct {
|
|
// The version of the extension configuration.
|
|
Version int `json:"version"`
|
|
// The values of the user configuration fields.
|
|
Values map[string]string `json:"values"`
|
|
}
|
|
|
|
const (
|
|
ConfigFieldTypeText ConfigFieldType = "text"
|
|
ConfigFieldTypeSwitch ConfigFieldType = "switch"
|
|
ConfigFieldTypeSelect ConfigFieldType = "select"
|
|
)
|
|
|
|
type (
|
|
|
|
// ConfigField represents a field in an extension's configuration.
|
|
// The fields are defined in the manifest file.
|
|
ConfigField struct {
|
|
Type ConfigFieldType `json:"type"`
|
|
Name string `json:"name"`
|
|
Label string `json:"label"`
|
|
Options []ConfigFieldSelectOption `json:"options,omitempty"`
|
|
Default string `json:"default,omitempty"`
|
|
}
|
|
|
|
ConfigFieldType string
|
|
|
|
ConfigFieldSelectOption struct {
|
|
Value string `json:"value"`
|
|
Label string `json:"label"`
|
|
}
|
|
|
|
ConfigFieldValueValidator func(value string) error
|
|
)
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
func (p *PluginPermissionScope) String() string {
|
|
return string(*p)
|
|
}
|
|
|
|
func (p *PluginPermissionScope) Is(str string) bool {
|
|
return strings.EqualFold(string(*p), str)
|
|
}
|