futriis/internal/lua/plugin.go

151 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// /futriis/internal/lua/plugin.go
// Пакет lua реализует поддержку Lua плагинов
package lua
import (
"fmt"
"io/ioutil"
"path/filepath"
"sync"
"futriis/pkg/config"
"futriis/pkg/utils"
"github.com/yuin/gopher-lua"
)
// PluginManager управляет Lua плагинами
type PluginManager struct {
state *lua.LState
plugins map[string]*lua.LFunction
mu sync.RWMutex
enabled bool
}
// NewPluginManager создаёт новый менеджер плагинов
func NewPluginManager(cfg *config.LuaConfig) *PluginManager {
pm := &PluginManager{
plugins: make(map[string]*lua.LFunction),
enabled: cfg.Enabled,
}
if cfg.Enabled {
pm.state = lua.NewState()
pm.registerFunctions()
}
return pm
}
// registerFunctions регистрирует функции Go, доступные из Lua
func (pm *PluginManager) registerFunctions() {
if !pm.enabled || pm.state == nil {
return
}
// Регистрируем функции для работы с данными
pm.state.SetGlobal("print", pm.state.NewFunction(func(L *lua.LState) int {
top := L.GetTop()
args := make([]interface{}, top)
for i := 1; i <= top; i++ {
args[i-1] = L.Get(i).String()
}
utils.PrintInfo(fmt.Sprint(args...))
return 0
}))
pm.state.SetGlobal("get", pm.state.NewFunction(func(L *lua.LState) int {
key := L.ToString(1)
// TODO: получить значение из хранилища
L.Push(lua.LString(key))
return 1
}))
pm.state.SetGlobal("set", pm.state.NewFunction(func(L *lua.LState) int {
key := L.ToString(1)
value := L.ToString(2)
// TODO: установить значение в хранилище
utils.PrintInfo("Lua set: %s = %s", key, value)
return 0
}))
}
// LoadPlugins загружает все Lua плагины из директории
func (pm *PluginManager) LoadPlugins(pluginsDir string) error {
if !pm.enabled || pm.state == nil {
return nil
}
files, err := ioutil.ReadDir(pluginsDir)
if err != nil {
return err
}
for _, file := range files {
if filepath.Ext(file.Name()) == ".lua" {
if err := pm.LoadPlugin(filepath.Join(pluginsDir, file.Name())); err != nil {
utils.PrintError("Ошибка загрузки плагина %s: %v", file.Name(), err)
}
}
}
return nil
}
// LoadPlugin загружает один Lua плагин
func (pm *PluginManager) LoadPlugin(path string) error {
if !pm.enabled || pm.state == nil {
return nil
}
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
fn, err := pm.state.LoadString(string(data))
if err != nil {
return err
}
pm.mu.Lock()
pm.plugins[filepath.Base(path)] = fn
pm.mu.Unlock()
utils.PrintSuccess("Загружен плагин: %s", filepath.Base(path))
return nil
}
// ExecutePlugin выполняет функцию плагина
func (pm *PluginManager) ExecutePlugin(name string, args ...lua.LValue) error {
if !pm.enabled || pm.state == nil {
return nil
}
pm.mu.RLock()
fn, exists := pm.plugins[name]
pm.mu.RUnlock()
if !exists {
return fmt.Errorf("плагин %s не найден", name)
}
pm.state.Push(fn)
for _, arg := range args {
pm.state.Push(arg)
}
if err := pm.state.PCall(len(args), lua.MultRet, nil); err != nil {
return err
}
return nil
}
// Close закрывает Lua состояние
func (pm *PluginManager) Close() {
if pm.state != nil {
pm.state.Close()
}
}