rclone/fs/rc/webgui/rc.go

335 lines
8 KiB
Go
Raw Normal View History

package webgui
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/rc"
)
func init() {
rc.Add(rc.Call{
Path: "pluginsctl/listTestPlugins",
AuthRequired: true,
Fn: rcListTestPlugins,
Title: "Show currently loaded test plugins",
Help: `allows listing of test plugins with the rclone.test set to true in package.json of the plugin
This takes no parameters and returns
- loadedTestPlugins: list of currently available test plugins
Eg
rclone rc pluginsctl/listTestPlugins
`,
})
}
func rcListTestPlugins(_ context.Context, _ rc.Params) (out rc.Params, err error) {
err = initPluginsOrError()
if err != nil {
return nil, err
}
return rc.Params{
"loadedTestPlugins": filterPlugins(loadedPlugins, func(json *PackageJSON) bool { return json.isTesting() }),
}, nil
}
func init() {
rc.Add(rc.Call{
Path: "pluginsctl/removeTestPlugin",
AuthRequired: true,
Fn: rcRemoveTestPlugin,
Title: "Remove a test plugin",
Help: `This allows you to remove a plugin using it's name
This takes the following parameters
- name: name of the plugin in the format ` + "`author`/`plugin_name`" + `
Eg
rclone rc pluginsctl/removeTestPlugin name=rclone/rclone-webui-react
`,
})
}
func rcRemoveTestPlugin(_ context.Context, in rc.Params) (out rc.Params, err error) {
err = initPluginsOrError()
if err != nil {
return nil, err
}
name, err := in.GetString("name")
if err != nil {
return nil, err
}
err = loadedPlugins.removePlugin(name)
if err != nil {
return nil, err
}
return nil, nil
}
func init() {
rc.Add(rc.Call{
Path: "pluginsctl/addPlugin",
AuthRequired: true,
Fn: rcAddPlugin,
Title: "Add a plugin using url",
Help: `used for adding a plugin to the webgui
This takes the following parameters
- url: http url of the github repo where the plugin is hosted (http://github.com/rclone/rclone-webui-react)
Eg
rclone rc pluginsctl/addPlugin
`,
})
}
func rcAddPlugin(_ context.Context, in rc.Params) (out rc.Params, err error) {
err = initPluginsOrError()
if err != nil {
return nil, err
}
pluginURL, err := in.GetString("url")
if err != nil {
return nil, err
}
author, repoName, repoBranch, err := getAuthorRepoBranchGithub(pluginURL)
if err != nil {
return nil, err
}
branch, err := in.GetString("branch")
if err != nil || branch == "" {
branch = repoBranch
}
version, err := in.GetString("version")
if err != nil || version == "" {
version = "latest"
}
err = CreatePathIfNotExist(PluginsPath)
if err != nil {
return nil, err
}
// fetch and package.json
// https://raw.githubusercontent.com/rclone/rclone-webui-react/master/package.json
pluginID := fmt.Sprintf("%s/%s", author, repoName)
currentPluginPath := filepath.Join(PluginsPath, pluginID)
err = CreatePathIfNotExist(currentPluginPath)
if err != nil {
return nil, err
}
packageJSONUrl := fmt.Sprintf("https://raw.githubusercontent.com/%s/%s/%s/package.json", author, repoName, branch)
packageJSONFilePath := filepath.Join(currentPluginPath, "package.json")
err = DownloadFile(packageJSONFilePath, packageJSONUrl)
if err != nil {
return nil, err
}
// register in plugins
// download release and save in plugins/<author>/repo-name/app
// https://api.github.com/repos/rclone/rclone-webui-react/releases/latest
releaseURL, tag, _, err := GetLatestReleaseURL(fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/%s", author, repoName, version))
if err != nil {
return nil, err
}
zipName := tag + ".zip"
zipPath := filepath.Join(currentPluginPath, zipName)
err = DownloadFile(zipPath, releaseURL)
if err != nil {
return nil, err
}
extractPath := filepath.Join(currentPluginPath, "app")
err = CreatePathIfNotExist(extractPath)
if err != nil {
return nil, err
}
err = os.RemoveAll(extractPath)
if err != nil {
fs.Logf(nil, "No previous downloads to remove")
}
fs.Logf(nil, "Unzipping plugin binary")
err = Unzip(zipPath, extractPath)
if err != nil {
return nil, err
}
err = loadedPlugins.addPlugin(pluginID, packageJSONFilePath)
if err != nil {
return nil, err
}
return nil, nil
}
func init() {
rc.Add(rc.Call{
Path: "pluginsctl/listPlugins",
AuthRequired: true,
Fn: rcGetPlugins,
Title: "Get the list of currently loaded plugins",
Help: `This allows you to get the currently enabled plugins and their details.
This takes no parameters and returns
- loadedPlugins: list of current production plugins
- testPlugins: list of temporarily loaded development plugins, usually running on a different server.
Eg
rclone rc pluginsctl/listPlugins
`,
})
}
func rcGetPlugins(_ context.Context, _ rc.Params) (out rc.Params, err error) {
err = initPluginsOrError()
if err != nil {
return nil, err
}
err = loadedPlugins.readFromFile()
if err != nil {
return nil, err
}
return rc.Params{
"loadedPlugins": filterPlugins(loadedPlugins, func(packageJSON *PackageJSON) bool { return !packageJSON.isTesting() }),
"loadedTestPlugins": filterPlugins(loadedPlugins, func(packageJSON *PackageJSON) bool { return packageJSON.isTesting() }),
}, nil
}
func init() {
rc.Add(rc.Call{
Path: "pluginsctl/removePlugin",
AuthRequired: true,
Fn: rcRemovePlugin,
Title: "Remove a loaded plugin",
Help: `This allows you to remove a plugin using it's name
This takes parameters
- name: name of the plugin in the format ` + "`author`/`plugin_name`" + `
Eg
rclone rc pluginsctl/removePlugin name=rclone/video-plugin
`,
})
}
func rcRemovePlugin(_ context.Context, in rc.Params) (out rc.Params, err error) {
err = initPluginsOrError()
if err != nil {
return nil, err
}
name, err := in.GetString("name")
if err != nil {
return nil, err
}
err = loadedPlugins.removePlugin(name)
if err != nil {
return nil, err
}
return nil, nil
}
func init() {
rc.Add(rc.Call{
Path: "pluginsctl/getPluginsForType",
AuthRequired: true,
Fn: rcGetPluginsForType,
Title: "Get plugins with type criteria",
Help: `This shows all possible plugins by a mime type
This takes the following parameters
- type: supported mime type by a loaded plugin e.g. (video/mp4, audio/mp3)
- pluginType: filter plugins based on their type e.g. (DASHBOARD, FILE_HANDLER, TERMINAL)
and returns
- loadedPlugins: list of current production plugins
- testPlugins: list of temporarily loaded development plugins, usually running on a different server.
Eg
rclone rc pluginsctl/getPluginsForType type=video/mp4
`,
})
}
func rcGetPluginsForType(_ context.Context, in rc.Params) (out rc.Params, err error) {
err = initPluginsOrError()
if err != nil {
return nil, err
}
handlesType, err := in.GetString("type")
if err != nil {
handlesType = ""
}
pluginType, err := in.GetString("pluginType")
if err != nil {
pluginType = ""
}
var loadedPluginsResult map[string]PackageJSON
var loadedTestPluginsResult map[string]PackageJSON
if pluginType == "" || pluginType == "FileHandler" {
loadedPluginsResult = filterPlugins(loadedPlugins, func(packageJSON *PackageJSON) bool {
for i := range packageJSON.Rclone.HandlesType {
if packageJSON.Rclone.HandlesType[i] == handlesType && !packageJSON.Rclone.Test {
return true
}
}
return false
})
loadedTestPluginsResult = filterPlugins(loadedPlugins, func(packageJSON *PackageJSON) bool {
for i := range packageJSON.Rclone.HandlesType {
if packageJSON.Rclone.HandlesType[i] == handlesType && packageJSON.Rclone.Test {
return true
}
}
return false
})
} else {
loadedPluginsResult = filterPlugins(loadedPlugins, func(packageJSON *PackageJSON) bool {
return packageJSON.Rclone.PluginType == pluginType && !packageJSON.isTesting()
})
loadedTestPluginsResult = filterPlugins(loadedPlugins, func(packageJSON *PackageJSON) bool {
return packageJSON.Rclone.PluginType == pluginType && packageJSON.isTesting()
})
}
return rc.Params{
"loadedPlugins": loadedPluginsResult,
"loadedTestPlugins": loadedTestPluginsResult,
}, nil
}