Files
filestash/server/model/plugin.go
Mickael d30c3120b6 feature (plugins): expand and migrate plugin - #803
* chore (dockerfile): cleanup dockerfile

* feature (plugin): extend plugin interface

* chore (docker): setup new Dockerfile

* chore (dockerfile): update dockerfile
2025-01-13 15:41:04 +11:00

116 lines
2.2 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, modules, err := InitModule(entry.Name())
if err != nil {
Log.Error("could not initialise module name=%s err=%s", entry.Name(), err.Error())
continue
}
PLUGINS[name] = modules
}
return nil
}
type zrc struct {
f io.ReadCloser
c io.Closer
}
func (this zrc) Read(p []byte) (n int, err error) {
return this.f.Read(p)
}
func (this zrc) Close() error {
this.f.Close()
this.c.Close()
return nil
}
func GetPluginFile(pluginName string, path string) (io.ReadCloser, 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
}
return zrc{f, zipReader}, 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
}