151 lines
3.4 KiB
Go
151 lines
3.4 KiB
Go
// /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()
|
||
}
|
||
}
|