- 在插件管理器中引入 DynamicPlugin 结构体,支持动态加载和管理插件,提升插件的灵活性和可扩展性。 - 更新插件接口,添加插件名称、版本、描述、作者、类型和启用状态的获取和设置方法,增强插件信息的管理能力。 - 修改现有插件实现,确保兼容新的动态插件结构,提升插件的统一性和可维护性。 - 更新示例程序,展示如何使用新的动态插件功能,提升用户体验。 此更新提升了插件系统的灵活性和可扩展性,便于开发者更好地管理和使用插件功能。
267 lines
6.3 KiB
Go
267 lines
6.3 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"encoding/base64"
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
|
||
"github.com/darkit/goproxy/examples/plugin"
|
||
)
|
||
|
||
// StoragePlugin 存储插件
|
||
// 提供简单的文件存储功能
|
||
type StoragePlugin struct {
|
||
plugin.Plugin // 嵌入接口,确保类型检查
|
||
name string // 插件名称
|
||
version string // 插件版本
|
||
description string // 插件描述
|
||
author string // 插件作者
|
||
pluginType plugin.PluginType // 插件类型
|
||
enabled bool // 是否启用
|
||
storageDir string // 存储目录
|
||
config map[string]interface{} // 配置
|
||
mu sync.RWMutex // 读写锁
|
||
}
|
||
|
||
// Plugin 导出的插件变量
|
||
// 注意:变量名必须是Plugin,大小写敏感
|
||
var Plugin = &StoragePlugin{
|
||
name: "StoragePlugin",
|
||
version: "1.0.0",
|
||
description: "简单的文件存储插件",
|
||
author: "开发者",
|
||
pluginType: plugin.PluginTypeStorage, // 设置插件类型为存储插件
|
||
enabled: true,
|
||
}
|
||
|
||
// Name 返回插件名称
|
||
func (p *StoragePlugin) Name() string {
|
||
return p.name
|
||
}
|
||
|
||
// Version 返回插件版本
|
||
func (p *StoragePlugin) Version() string {
|
||
return p.version
|
||
}
|
||
|
||
// Description 返回插件描述
|
||
func (p *StoragePlugin) Description() string {
|
||
return p.description
|
||
}
|
||
|
||
// Author 返回插件作者
|
||
func (p *StoragePlugin) Author() string {
|
||
return p.author
|
||
}
|
||
|
||
// Type 返回插件类型
|
||
func (p *StoragePlugin) Type() plugin.PluginType {
|
||
return p.pluginType
|
||
}
|
||
|
||
// IsEnabled 返回插件是否启用
|
||
func (p *StoragePlugin) IsEnabled() bool {
|
||
return p.enabled
|
||
}
|
||
|
||
// SetEnabled 设置插件启用状态
|
||
func (p *StoragePlugin) SetEnabled(enabled bool) {
|
||
p.enabled = enabled
|
||
}
|
||
|
||
// GetOperationInfo 获取操作的参数信息
|
||
func (p *StoragePlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
|
||
return map[string]interface{}{}, nil
|
||
}
|
||
|
||
// GetAllOperations 获取所有操作及其参数信息
|
||
func (p *StoragePlugin) GetAllOperations() map[string]map[string]interface{} {
|
||
return map[string]map[string]interface{}{}
|
||
}
|
||
|
||
// Init 初始化插件
|
||
func (p *StoragePlugin) Init(ctx context.Context, config map[string]interface{}) error {
|
||
p.config = config
|
||
|
||
// 获取存储目录路径
|
||
storageDir, ok := config["storage_dir"].(string)
|
||
if !ok {
|
||
// 使用默认路径
|
||
storageDir = "storage"
|
||
}
|
||
|
||
// 确保存储目录存在
|
||
if err := os.MkdirAll(storageDir, 0o755); err != nil {
|
||
return fmt.Errorf("创建存储目录失败: %v", err)
|
||
}
|
||
|
||
p.storageDir = storageDir
|
||
fmt.Println("存储插件初始化完成,存储目录:", storageDir)
|
||
|
||
return nil
|
||
}
|
||
|
||
// Start 启动插件
|
||
func (p *StoragePlugin) Start(ctx context.Context) error {
|
||
if p.storageDir == "" {
|
||
return fmt.Errorf("插件未初始化")
|
||
}
|
||
|
||
fmt.Println("存储插件已启动")
|
||
return nil
|
||
}
|
||
|
||
// Stop 停止插件
|
||
func (p *StoragePlugin) Stop(ctx context.Context) error {
|
||
fmt.Println("存储插件已停止")
|
||
return nil
|
||
}
|
||
|
||
// Execute 执行插件功能
|
||
func (p *StoragePlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||
switch action {
|
||
case "saveFile":
|
||
// 需要参数: filename, data
|
||
filename, ok := params["filename"].(string)
|
||
if !ok {
|
||
return nil, fmt.Errorf("缺少必需参数: filename")
|
||
}
|
||
|
||
// 处理两种数据格式:字符串或Base64编码的二进制数据
|
||
var data []byte
|
||
if dataStr, ok := params["data"].(string); ok {
|
||
// 检查是否为Base64编码
|
||
if base64Str, ok := params["isBase64"].(bool); ok && base64Str {
|
||
var err error
|
||
data, err = base64.StdEncoding.DecodeString(dataStr)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("Base64解码失败: %v", err)
|
||
}
|
||
} else {
|
||
data = []byte(dataStr)
|
||
}
|
||
} else {
|
||
return nil, fmt.Errorf("缺少必需参数: data")
|
||
}
|
||
|
||
err := p.SaveFile(filename, data)
|
||
return err == nil, err
|
||
|
||
case "loadFile":
|
||
// 需要参数: filename, returnBase64
|
||
filename, ok := params["filename"].(string)
|
||
if !ok {
|
||
return nil, fmt.Errorf("缺少必需参数: filename")
|
||
}
|
||
|
||
returnBase64, _ := params["returnBase64"].(bool)
|
||
|
||
data, err := p.LoadFile(filename)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
if returnBase64 {
|
||
return base64.StdEncoding.EncodeToString(data), nil
|
||
}
|
||
return string(data), nil
|
||
|
||
case "deleteFile":
|
||
// 需要参数: filename
|
||
filename, ok := params["filename"].(string)
|
||
if !ok {
|
||
return nil, fmt.Errorf("缺少必需参数: filename")
|
||
}
|
||
|
||
err := p.DeleteFile(filename)
|
||
return err == nil, err
|
||
|
||
case "listFiles":
|
||
// 不需要参数
|
||
files, err := p.ListFiles()
|
||
return files, err
|
||
|
||
case "getStorageInfo":
|
||
// 不需要参数
|
||
info := map[string]interface{}{
|
||
"storageDir": p.storageDir,
|
||
"config": p.config,
|
||
}
|
||
return info, nil
|
||
|
||
default:
|
||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||
}
|
||
}
|
||
|
||
// SaveFile 保存文件
|
||
func (p *StoragePlugin) SaveFile(filename string, data []byte) error {
|
||
p.mu.Lock()
|
||
defer p.mu.Unlock()
|
||
|
||
if p.storageDir == "" {
|
||
return fmt.Errorf("插件未初始化")
|
||
}
|
||
|
||
filePath := filepath.Join(p.storageDir, filename)
|
||
return os.WriteFile(filePath, data, 0o644)
|
||
}
|
||
|
||
// LoadFile 加载文件
|
||
func (p *StoragePlugin) LoadFile(filename string) ([]byte, error) {
|
||
p.mu.RLock()
|
||
defer p.mu.RUnlock()
|
||
|
||
if p.storageDir == "" {
|
||
return nil, fmt.Errorf("插件未初始化")
|
||
}
|
||
|
||
filePath := filepath.Join(p.storageDir, filename)
|
||
return os.ReadFile(filePath)
|
||
}
|
||
|
||
// DeleteFile 删除文件
|
||
func (p *StoragePlugin) DeleteFile(filename string) error {
|
||
p.mu.Lock()
|
||
defer p.mu.Unlock()
|
||
|
||
if p.storageDir == "" {
|
||
return fmt.Errorf("插件未初始化")
|
||
}
|
||
|
||
filePath := filepath.Join(p.storageDir, filename)
|
||
return os.Remove(filePath)
|
||
}
|
||
|
||
// ListFiles 列出所有文件
|
||
func (p *StoragePlugin) ListFiles() ([]string, error) {
|
||
p.mu.RLock()
|
||
defer p.mu.RUnlock()
|
||
|
||
if p.storageDir == "" {
|
||
return nil, fmt.Errorf("插件未初始化")
|
||
}
|
||
|
||
var files []string
|
||
entries, err := os.ReadDir(p.storageDir)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
for _, entry := range entries {
|
||
if !entry.IsDir() {
|
||
files = append(files, entry.Name())
|
||
}
|
||
}
|
||
|
||
return files, nil
|
||
}
|
||
|
||
// main 函数是必须的,但不会被调用
|
||
func main() {
|
||
// 不会被执行,仅用于编译插件
|
||
}
|