Files
filestash/server/model/plugin.go
2025-09-15 13:54:11 +10:00

129 lines
2.7 KiB
Go

package model
import (
"archive/zip"
"encoding/json"
"io"
"os"
"strings"
. "github.com/mickael-kerjean/filestash/server/common"
)
var PLUGINS = map[string]PluginImpl{}
type PluginImpl struct {
Author string `json:"author"`
Version string `json:"version"`
Modules []map[string]string `json:"modules"`
}
func PluginDiscovery() error {
f, err := os.Open(GetAbsolutePath(PLUGIN_PATH))
if err != nil {
return err
}
entries, err := f.ReadDir(0)
if err != nil {
return err
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
fname := entry.Name()
if strings.HasSuffix(fname, ".zip") == false {
continue
}
name, impl, err := InitModule(entry.Name())
if err != nil {
Log.Error("could not initialise module name=%s err=%s", entry.Name(), err.Error())
continue
}
for i := 0; i < len(impl.Modules); i++ {
switch impl.Modules[i]["type"] {
case "css":
b, err := GetPluginFile(name, impl.Modules[i]["entrypoint"])
if err != nil {
return err
}
Hooks.Register.CSS(string(b))
case "patch":
b, err := GetPluginFile(name, impl.Modules[i]["entrypoint"])
if err != nil {
return err
}
Hooks.Register.StaticPatch(b)
case "favicon":
b, err := GetPluginFile(name, impl.Modules[i]["entrypoint"])
if err != nil {
return err
}
Hooks.Register.Favicon(b)
}
}
PLUGINS[name] = impl
}
return nil
}
func GetPluginFile(pluginName string, path string) ([]byte, error) {
zipReader, err := zip.OpenReader(JoinPath(
GetAbsolutePath(PLUGIN_PATH),
pluginName+".zip",
))
if err != nil {
return nil, err
}
for _, zipFile := range zipReader.File {
if zipFile.Name != path {
continue
}
f, err := zipFile.Open()
if err != nil {
zipReader.Close()
return nil, err
}
data, err := io.ReadAll(f)
f.Close()
zipReader.Close()
if err != nil {
return nil, err
}
return data, nil
}
zipReader.Close()
return nil, ErrNotFound
}
func InitModule(plgName string) (string, PluginImpl, error) {
var plgImpl = PluginImpl{}
r, err := zip.OpenReader(JoinPath(GetAbsolutePath(PLUGIN_PATH), plgName))
plgName = strings.TrimSuffix(plgName, ".zip")
if err != nil {
return plgName, plgImpl, err
}
defer r.Close()
var manifestFile io.ReadCloser
for _, f := range r.File {
if f.Name != "manifest.json" {
continue
}
rc, err := f.Open()
if err != nil {
return plgName, plgImpl, err
}
manifestFile = rc
break
}
if manifestFile == nil {
return plgName, plgImpl, ErrNotFound
}
defer manifestFile.Close()
if err = json.NewDecoder(manifestFile).Decode(&plgImpl); err != nil {
return plgName, plgImpl, err
}
return plgName, plgImpl, nil
}