mirror of
https://github.com/akyaiy/GoSally-mvp.git
synced 2026-01-03 02:52:25 +00:00
Refactor configuration and update handling:
- Modify .luarc.json to include global Lua scripts. - Update Makefile to include LDFLAGS for versioning. - Enhance node.go to implement version checking and update handling. - Refactor Lua global variables in _globals.lua and echo.lua to use new structures. - Remove deprecated http.lua and update config.yaml for TLS and update settings. - Introduce new update.go for version management and update checking. - Add tests for version comparison in update_test.go. - Improve error handling in various server methods.
This commit is contained in:
@@ -2,6 +2,5 @@
|
|||||||
"runtime.version": "Lua 5.1",
|
"runtime.version": "Lua 5.1",
|
||||||
"workspace.library": [
|
"workspace.library": [
|
||||||
"./scripts/_globals.lua"
|
"./scripts/_globals.lua"
|
||||||
],
|
]
|
||||||
"diagnostics.globals": ["Params", "Result"]
|
|
||||||
}
|
}
|
||||||
13
Makefile
13
Makefile
@@ -2,6 +2,7 @@ APP_NAME := node
|
|||||||
BIN_DIR := bin
|
BIN_DIR := bin
|
||||||
GOPATH := $(shell go env GOPATH)
|
GOPATH := $(shell go env GOPATH)
|
||||||
export CONFIG_PATH := ./config.yaml
|
export CONFIG_PATH := ./config.yaml
|
||||||
|
LDFLAGS := -X 'github.com/akyaiy/GoSally-mvp/core/config.NodeVersion=version0.0.1-dev'
|
||||||
CGO_CFLAGS := -I/usr/local/include
|
CGO_CFLAGS := -I/usr/local/include
|
||||||
CGO_LDFLAGS := -L/usr/local/lib -llua5.1 -lm -ldl
|
CGO_LDFLAGS := -L/usr/local/lib -llua5.1 -lm -ldl
|
||||||
.PHONY: all build run runq test fmt vet lint check clean
|
.PHONY: all build run runq test fmt vet lint check clean
|
||||||
@@ -24,9 +25,10 @@ setup: lint-setup goimports-setup golicenses-setup
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
@echo "Building..."
|
@echo "Building..."
|
||||||
@echo "CGO_CFLAGS is: '$(CGO_CFLAGS)'"
|
@# @echo "CGO_CFLAGS is: '$(CGO_CFLAGS)'"
|
||||||
@echo "CGO_LDFLAGS is: '$(CGO_LDFLAGS)'"
|
@# @echo "CGO_LDFLAGS is: '$(CGO_LDFLAGS)'"
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" go build -o $(BIN_DIR)/$(APP_NAME) ./cmd/$(APP_NAME)
|
@# CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)"
|
||||||
|
go build -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/$(APP_NAME) ./cmd/$(APP_NAME)
|
||||||
|
|
||||||
run: build
|
run: build
|
||||||
@echo "Running!"
|
@echo "Running!"
|
||||||
@@ -56,4 +58,7 @@ licenses:
|
|||||||
@echo "Licenses have been exported to third_party/licenses"
|
@echo "Licenses have been exported to third_party/licenses"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf bin
|
@rm -rf bin
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Available commands: $$(cat Makefile | grep -E '^[a-zA-Z_-]+:.*?' | grep -v -- '-setup:' | sed 's/:.*//g' | sort | uniq | tr '\n' ' ')"
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"golang.org/x/net/netutil"
|
||||||
|
|
||||||
"github.com/akyaiy/GoSally-mvp/core/config"
|
"github.com/akyaiy/GoSally-mvp/core/config"
|
||||||
gs "github.com/akyaiy/GoSally-mvp/core/general_server"
|
gs "github.com/akyaiy/GoSally-mvp/core/general_server"
|
||||||
"github.com/akyaiy/GoSally-mvp/core/logs"
|
"github.com/akyaiy/GoSally-mvp/core/logs"
|
||||||
"github.com/akyaiy/GoSally-mvp/core/sv1"
|
"github.com/akyaiy/GoSally-mvp/core/sv1"
|
||||||
|
"github.com/akyaiy/GoSally-mvp/core/update"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
)
|
)
|
||||||
@@ -27,34 +32,63 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
updater := update.NewUpdater(*log, cfg)
|
||||||
|
versuion, versionType, _ := updater.GetCurrentVersion()
|
||||||
|
fmt.Printf("Current version: %s (%s)\n", versuion, versionType)
|
||||||
|
ver, vert, _ := updater.GetLatestVersion(versionType)
|
||||||
|
fmt.Printf("Latest version: %s (%s)\n", ver, vert)
|
||||||
|
|
||||||
|
fmt.Println("Checking for updates...")
|
||||||
|
isNewUpdate, _ := updater.CkeckUpdates()
|
||||||
|
fmt.Println("Update check result:", isNewUpdate)
|
||||||
serverv1 := sv1.InitV1Server(&sv1.HandlerV1InitStruct{
|
serverv1 := sv1.InitV1Server(&sv1.HandlerV1InitStruct{
|
||||||
Log: *logs.SetupLogger(cfg.Mode),
|
Log: *log,
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
AllowedCmd: regexp.MustCompile(`^[a-zA-Z0-9]+$`),
|
AllowedCmd: regexp.MustCompile(`^[a-zA-Z0-9]+$`),
|
||||||
ListAllowedCmd: regexp.MustCompile(`^[a-zA-Z0-9_-]+$`),
|
ListAllowedCmd: regexp.MustCompile(`^[a-zA-Z0-9_-]+$`),
|
||||||
Ver: "v1",
|
Ver: "v1",
|
||||||
})
|
})
|
||||||
s := gs.InitGeneral(&gs.GeneralServerInit{
|
s := gs.InitGeneral(&gs.GeneralServerInit{
|
||||||
Log: *logs.SetupLogger(cfg.Mode),
|
Log: *log,
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
}, serverv1)
|
}, serverv1)
|
||||||
|
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.Route("/api/{ver}/com", func(r chi.Router) {
|
r.Route(config.GetServerConsts().GetApiRoute()+config.GetServerConsts().GetComDirRoute(), func(r chi.Router) {
|
||||||
r.Get("/", s.HandleList)
|
r.Get("/", s.HandleList)
|
||||||
r.Get("/{cmd}", s.Handle)
|
r.Get("/{cmd}", s.Handle)
|
||||||
})
|
})
|
||||||
|
r.Route("/favicon.ico", func(r chi.Router) {
|
||||||
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
})
|
||||||
|
})
|
||||||
r.NotFound(serverv1.ErrNotFound)
|
r.NotFound(serverv1.ErrNotFound)
|
||||||
if cfg.TlsEnabled == "true" {
|
|
||||||
log.Info("Server started with TLS", slog.String("address", cfg.Address))
|
address := cfg.Address
|
||||||
err := http.ListenAndServeTLS(cfg.Address, cfg.CertFile, cfg.KeyFile, r)
|
if cfg.TlsEnabled {
|
||||||
|
log.Info("HTTPS server started with TLS", slog.String("address", address))
|
||||||
|
listener, err := net.Listen("tcp", address)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to start TLS listener", slog.String("error", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
limitedListener := netutil.LimitListener(listener, 100)
|
||||||
|
err = http.ServeTLS(limitedListener, r, cfg.CertFile, cfg.KeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to start HTTPS server", slog.String("error", err.Error()))
|
log.Error("Failed to start HTTPS server", slog.String("error", err.Error()))
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
log.Info("Server started", slog.String("address", cfg.Address))
|
log.Info("HTTP server started", slog.String("address", address))
|
||||||
err := http.ListenAndServe(cfg.Address, r)
|
listener, err := net.Listen("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to start HTTP server", slog.String("error", err.Error()))
|
log.Error("Failed to start listener", slog.String("error", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
limitedListener := netutil.LimitListener(listener, 100)
|
||||||
|
err = http.Serve(limitedListener, r)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to start HTTP server", slog.String("error", err.Error()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
---@alias AnyTable table<string, any>
|
---@alias AnyTable table<string, any>
|
||||||
|
|
||||||
---@type AnyTable
|
---@type AnyTable
|
||||||
Params = {}
|
In = {
|
||||||
|
Params = {},
|
||||||
|
}
|
||||||
|
|
||||||
---@type AnyTable
|
---@type AnyTable
|
||||||
Result = {}
|
Out = {
|
||||||
|
Result = {},
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
---@diagnostic disable: duplicate-set-field
|
||||||
package.path = package.path .. ";/usr/lib64/lua/5.1/?.lua;/usr/local/share/lua/5.1/?.lua" .. ";./com/?.lua;"
|
package.path = package.path .. ";/usr/lib64/lua/5.1/?.lua;/usr/local/share/lua/5.1/?.lua" .. ";./com/?.lua;"
|
||||||
package.cpath = package.cpath .. ";/usr/lib64/lua/5.1/?.so;/usr/local/lib/lua/5.1/?.so"
|
package.cpath = package.cpath .. ";/usr/lib64/lua/5.1/?.so;/usr/local/lib/lua/5.1/?.so"
|
||||||
|
|
||||||
@@ -5,4 +6,11 @@ print = function() end
|
|||||||
io.write = function(...) end
|
io.write = function(...) end
|
||||||
io.stdout = function() return nil end
|
io.stdout = function() return nil end
|
||||||
io.stderr = function() return nil end
|
io.stderr = function() return nil end
|
||||||
io.read = function(...) return nil end
|
io.read = function(...) return nil end
|
||||||
|
|
||||||
|
---@type table<string, any>
|
||||||
|
Status = {
|
||||||
|
ok = "ok",
|
||||||
|
error = "error",
|
||||||
|
invalid = "invalid",
|
||||||
|
}
|
||||||
|
|||||||
10
com/echo.lua
10
com/echo.lua
@@ -2,12 +2,12 @@
|
|||||||
--- #args
|
--- #args
|
||||||
--- msg = the message
|
--- msg = the message
|
||||||
|
|
||||||
if not Params.msg then
|
if not In.Params.msg or In.Params.msg == "" then
|
||||||
Result.status = "error"
|
Out.Result.status = Status.error
|
||||||
Result.error = "Missing parameter: msg"
|
Out.Result.error = "Missing parameter: msg"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
Result.status = "ok"
|
Out.Result.status = Status.ok
|
||||||
Result.answer = Params.msg
|
Out.Result.answer = In.Params.msg
|
||||||
return
|
return
|
||||||
15
com/http.lua
15
com/http.lua
@@ -1,15 +0,0 @@
|
|||||||
package.path = package.path .. ";/usr/lib64/lua/5.1/?.lua;/usr/local/share/lua/5.1/?.lua;" .. ";./com/?.lua;"
|
|
||||||
package.cpath = package.cpath .. ";/usr/lib64/lua/5.1/?.so;/usr/local/lib/lua/5.1/?.so;"
|
|
||||||
|
|
||||||
local https = require("ssl.https")
|
|
||||||
local ltn12 = require("ltn12")
|
|
||||||
|
|
||||||
local response = {}
|
|
||||||
local res, code, headers = https.request{
|
|
||||||
url = "https://localhost:8080/api/v1/echo?msg=sigma",
|
|
||||||
sink = ltn12.sink.table(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result.msg = table.concat(response)
|
|
||||||
Result.status = "ok"
|
|
||||||
24
config.yaml
24
config.yaml
@@ -1,7 +1,7 @@
|
|||||||
mode: "dev"
|
mode: "dev"
|
||||||
|
|
||||||
http_server:
|
http_server:
|
||||||
address: "localhost:8080"
|
address: "0.0.0.0:8080"
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
idle_timeout: 30s
|
idle_timeout: 30s
|
||||||
api:
|
api:
|
||||||
@@ -11,8 +11,22 @@ http_server:
|
|||||||
- s2
|
- s2
|
||||||
|
|
||||||
tls:
|
tls:
|
||||||
enabled: "true"
|
enabled: true
|
||||||
cert_file: "./cert/server.crt"
|
cert_file: "./cert/fullchain.pem"
|
||||||
key_file: "./cert/server.key"
|
key_file: "./cert/privkey.pem"
|
||||||
|
|
||||||
com_dir: "com/"
|
internal:
|
||||||
|
meta-dir: "./.meta/"
|
||||||
|
|
||||||
|
com_dir: "com/"
|
||||||
|
|
||||||
|
|
||||||
|
updates:
|
||||||
|
enabled: true
|
||||||
|
allow-auto-updates: true
|
||||||
|
allow-updates: true
|
||||||
|
allow-downgrades: false
|
||||||
|
|
||||||
|
check-interval: 1h
|
||||||
|
repository_url: "https://repo.serve.lv/raw/go-sally"
|
||||||
|
wanted-version: "latest-stable"
|
||||||
@@ -13,10 +13,26 @@ type ConfigConf struct {
|
|||||||
ComDir string `yaml:"com_dir" env-default:"./com/"`
|
ComDir string `yaml:"com_dir" env-default:"./com/"`
|
||||||
HTTPServer `yaml:"http_server"`
|
HTTPServer `yaml:"http_server"`
|
||||||
TLS `yaml:"tls"`
|
TLS `yaml:"tls"`
|
||||||
|
Internal `yaml:"internal"`
|
||||||
|
Updates `yaml:"updates"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Updates struct {
|
||||||
|
UpdatesEnabled bool `yaml:"enabled" env-default:"false"`
|
||||||
|
AllowAutoUpdates bool `yaml:"allow_auto_updates" env-default:"false"`
|
||||||
|
AllowUpdates bool `yaml:"allow_updates" env-default:"false"`
|
||||||
|
AllowDowngrades bool `yaml:"allow_downgrades" env-default:"false"`
|
||||||
|
CheckInterval time.Duration `yaml:"check_interval" env-default:"2h"`
|
||||||
|
RepositoryURL string `yaml:"repository_url" env-default:""`
|
||||||
|
WantedVersion string `yaml:"wanted_version" env-default:"latest-stable"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Internal struct {
|
||||||
|
MetaDir string `yaml:"meta_dir" env-default:"./.meta/"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TLS struct {
|
type TLS struct {
|
||||||
TlsEnabled string `yaml:"enabled" env-default:"false"`
|
TlsEnabled bool `yaml:"enabled" env-default:"false"`
|
||||||
CertFile string `yaml:"cert_file" env-default:"./cert/server.crt"`
|
CertFile string `yaml:"cert_file" env-default:"./cert/server.crt"`
|
||||||
KeyFile string `yaml:"key_file" env-default:"./cert/server.key"`
|
KeyFile string `yaml:"key_file" env-default:"./cert/server.key"`
|
||||||
}
|
}
|
||||||
|
|||||||
29
core/config/consts.go
Normal file
29
core/config/consts.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
var UUIDLength int = 4
|
||||||
|
|
||||||
|
var ApiRoute string = "/api/{ver}"
|
||||||
|
var ComDirRoute string = "/com"
|
||||||
|
|
||||||
|
var NodeVersion string
|
||||||
|
var ActualFileNanme string = "actual.txt"
|
||||||
|
|
||||||
|
type _internalConsts struct{}
|
||||||
|
type _serverConsts struct{}
|
||||||
|
type _updateConsts struct{}
|
||||||
|
|
||||||
|
func GetUpdateConsts() _updateConsts { return _updateConsts{} }
|
||||||
|
func (_ _updateConsts) GetNodeVersion() string {
|
||||||
|
if NodeVersion == "" {
|
||||||
|
return "version0.0.0-none"
|
||||||
|
}
|
||||||
|
return NodeVersion
|
||||||
|
}
|
||||||
|
func (_ _updateConsts) GetActualFileName() string { return ActualFileNanme }
|
||||||
|
|
||||||
|
func GetInternalConsts() _internalConsts { return _internalConsts{} }
|
||||||
|
func (_ _internalConsts) GetUUIDLength() int { return UUIDLength }
|
||||||
|
|
||||||
|
func GetServerConsts() _serverConsts { return _serverConsts{} }
|
||||||
|
func (_ _serverConsts) GetApiRoute() string { return ApiRoute }
|
||||||
|
func (_ _serverConsts) GetComDirRoute() string { return ComDirRoute }
|
||||||
@@ -160,5 +160,10 @@ func (s *GeneralServer) writeJSONError(status int, msg string) {
|
|||||||
"error": msg,
|
"error": msg,
|
||||||
"code": status,
|
"code": status,
|
||||||
}
|
}
|
||||||
json.NewEncoder(s.w).Encode(resp)
|
if err := json.NewEncoder(s.w).Encode(resp); err != nil {
|
||||||
|
s.log.Error("Failed to write JSON error response",
|
||||||
|
slog.String("error", err.Error()),
|
||||||
|
slog.Int("status", status))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
core/logs/mock.go
Normal file
35
core/logs/mock.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package logs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log/slog"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockHandler struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
Logs []slog.Record
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMockHandler() *MockHandler {
|
||||||
|
return &MockHandler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MockHandler) Enabled(_ context.Context, _ slog.Level) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MockHandler) Handle(_ context.Context, r slog.Record) error {
|
||||||
|
h.mu.Lock()
|
||||||
|
defer h.mu.Unlock()
|
||||||
|
h.Logs = append(h.Logs, r.Clone())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MockHandler) WithAttrs(_ []slog.Attr) slog.Handler {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MockHandler) WithGroup(_ string) slog.Handler {
|
||||||
|
return h
|
||||||
|
}
|
||||||
@@ -7,9 +7,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
lua "github.com/aarzilli/golua/lua"
|
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
|
lua "github.com/yuin/gopher-lua"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *HandlerV1) _handle() {
|
func (h *HandlerV1) _handle() {
|
||||||
@@ -28,8 +27,7 @@ func (h *HandlerV1) _handle() {
|
|||||||
log.Info("Received request")
|
log.Info("Received request")
|
||||||
|
|
||||||
cmd := chi.URLParam(h.r, "cmd")
|
cmd := chi.URLParam(h.r, "cmd")
|
||||||
var scriptPath string
|
if !h.allowedCmd.MatchString(string([]rune(cmd)[0])) || !h.listAllowedCmd.MatchString(cmd) {
|
||||||
if !h.allowedCmd.MatchString(string([]rune(cmd)[0])) {
|
|
||||||
log.Error("HTTP request error",
|
log.Error("HTTP request error",
|
||||||
slog.String("error", "invalid command"),
|
slog.String("error", "invalid command"),
|
||||||
slog.String("cmd", cmd),
|
slog.String("cmd", cmd),
|
||||||
@@ -37,15 +35,9 @@ func (h *HandlerV1) _handle() {
|
|||||||
h.writeJSONError(http.StatusBadRequest, "invalid command")
|
h.writeJSONError(http.StatusBadRequest, "invalid command")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !h.listAllowedCmd.MatchString(cmd) {
|
|
||||||
log.Error("HTTP request error",
|
scriptPath := h.comMatch(chi.URLParam(h.r, "ver"), cmd)
|
||||||
slog.String("error", "invalid command"),
|
if scriptPath == "" {
|
||||||
slog.String("cmd", cmd),
|
|
||||||
slog.Int("status", http.StatusBadRequest))
|
|
||||||
h.writeJSONError(http.StatusBadRequest, "invalid command")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if scriptPath = h.comMatch(chi.URLParam(h.r, "ver"), cmd); scriptPath == "" {
|
|
||||||
log.Error("HTTP request error",
|
log.Error("HTTP request error",
|
||||||
slog.String("error", "command not found"),
|
slog.String("error", "command not found"),
|
||||||
slog.String("cmd", cmd),
|
slog.String("cmd", cmd),
|
||||||
@@ -66,29 +58,27 @@ func (h *HandlerV1) _handle() {
|
|||||||
|
|
||||||
L := lua.NewState()
|
L := lua.NewState()
|
||||||
defer L.Close()
|
defer L.Close()
|
||||||
L.OpenLibs()
|
|
||||||
|
|
||||||
// Создаем таблицу Params
|
// Создаем таблицу Params
|
||||||
L.NewTable()
|
// Создаем таблицу In с Params
|
||||||
paramsTableIndex := L.GetTop() // Индекс таблицы в стеке
|
paramsTable := L.NewTable()
|
||||||
|
|
||||||
// Заполняем таблицу из query параметров
|
|
||||||
qt := h.r.URL.Query()
|
qt := h.r.URL.Query()
|
||||||
for k, v := range qt {
|
for k, v := range qt {
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
L.PushString(v[0]) // Значение
|
L.SetField(paramsTable, k, lua.LString(v[0]))
|
||||||
L.SetField(paramsTableIndex, k) // paramsTable[k] = v[0]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inTable := L.NewTable()
|
||||||
|
L.SetField(inTable, "Params", paramsTable)
|
||||||
|
L.SetGlobal("In", inTable)
|
||||||
|
|
||||||
// Помещаем Params в глобальные переменные
|
// Создаем таблицу Out с Result
|
||||||
L.SetGlobal("Params")
|
resultTable := L.NewTable()
|
||||||
|
outTable := L.NewTable()
|
||||||
|
L.SetField(outTable, "Result", resultTable)
|
||||||
|
L.SetGlobal("Out", outTable)
|
||||||
|
|
||||||
// Создаем пустую таблицу Result
|
// Скрипт подготовки окружения
|
||||||
L.NewTable()
|
|
||||||
L.SetGlobal("Result")
|
|
||||||
|
|
||||||
// Загружаем и выполняем скрипт подготовки окружения, если есть
|
|
||||||
prepareLuaEnv := filepath.Join(h.cfg.ComDir, "_prepare.lua")
|
prepareLuaEnv := filepath.Join(h.cfg.ComDir, "_prepare.lua")
|
||||||
if _, err := os.Stat(prepareLuaEnv); err == nil {
|
if _, err := os.Stat(prepareLuaEnv); err == nil {
|
||||||
if err := L.DoFile(prepareLuaEnv); err != nil {
|
if err := L.DoFile(prepareLuaEnv); err != nil {
|
||||||
@@ -98,77 +88,85 @@ func (h *HandlerV1) _handle() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Error("No environment preparation script found, skipping preparation",
|
log.Warn("No environment preparation script found, skipping preparation")
|
||||||
slog.String("error", err.Error()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Выполняем основной Lua скрипт
|
// Основной Lua скрипт
|
||||||
if err := L.DoFile(scriptPath); err != nil {
|
if err := L.DoFile(scriptPath); err != nil {
|
||||||
log.Error("Failed to execute lua script",
|
log.Error("Failed to execute lua script",
|
||||||
slog.Group("lua-status",
|
slog.String("error", err.Error()))
|
||||||
slog.String("error", err.Error()),
|
|
||||||
slog.String("lua-version", lua.LUA_VERSION)))
|
|
||||||
h.writeJSONError(http.StatusInternalServerError, "lua error: "+err.Error())
|
h.writeJSONError(http.StatusInternalServerError, "lua error: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Получаем глобальную переменную Result (таблица)
|
// Получаем Out
|
||||||
L.GetGlobal("Result")
|
lv := L.GetGlobal("Out")
|
||||||
if L.IsTable(-1) {
|
tbl, ok := lv.(*lua.LTable)
|
||||||
out := make(map[string]interface{})
|
if !ok {
|
||||||
|
log.Error("Lua global 'Out' is not a table")
|
||||||
|
h.writeJSONError(http.StatusInternalServerError, "'Out' is not a table")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
L.PushNil() // Первый ключ
|
// Получаем Result из Out
|
||||||
for {
|
resultVal := tbl.RawGetString("Result")
|
||||||
if L.Next(-2) == 0 {
|
resultTbl, ok := resultVal.(*lua.LTable)
|
||||||
break
|
if !ok {
|
||||||
}
|
|
||||||
// На стеке: -1 = value, -2 = key
|
|
||||||
key := L.ToString(-2)
|
|
||||||
var val interface{}
|
|
||||||
|
|
||||||
switch L.Type(-1) {
|
|
||||||
case lua.LUA_TSTRING:
|
|
||||||
val = L.ToString(-1)
|
|
||||||
case lua.LUA_TNUMBER:
|
|
||||||
val = L.ToNumber(-1)
|
|
||||||
case lua.LUA_TBOOLEAN:
|
|
||||||
val = L.ToBoolean(-1)
|
|
||||||
default:
|
|
||||||
// fallback
|
|
||||||
val = L.ToString(-1)
|
|
||||||
}
|
|
||||||
out[key] = val
|
|
||||||
L.Pop(1) // Удаляем value, key остаётся для следующего L.Next
|
|
||||||
}
|
|
||||||
L.Pop(1) // Удаляем таблицу Result со стека
|
|
||||||
|
|
||||||
h.w.Header().Set("Content-Type", "application/json")
|
|
||||||
if err := json.NewEncoder(h.w).Encode(out); err != nil {
|
|
||||||
log.Error("Failed to encode JSON response",
|
|
||||||
slog.String("error", err.Error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch out["status"] {
|
|
||||||
case "error":
|
|
||||||
log.Info("Command executed with error",
|
|
||||||
slog.String("cmd", cmd),
|
|
||||||
slog.Any("result", out))
|
|
||||||
case "ok":
|
|
||||||
log.Info("Command executed successfully",
|
|
||||||
slog.String("cmd", cmd), slog.Any("result", out))
|
|
||||||
default:
|
|
||||||
log.Info("Command executed and returned an unknown status",
|
|
||||||
slog.String("cmd", cmd),
|
|
||||||
slog.Any("result", out))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
L.Pop(1) // убираем не таблицу из стека
|
|
||||||
log.Error("Lua global 'Result' is not a table")
|
log.Error("Lua global 'Result' is not a table")
|
||||||
h.writeJSONError(http.StatusInternalServerError, "'Result' is not a table")
|
h.writeJSONError(http.StatusInternalServerError, "'Result' is not a table")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Session completed",
|
// Перебираем таблицу Result
|
||||||
slog.Group("lua-status",
|
out := make(map[string]interface{})
|
||||||
slog.String("lua-version", lua.LUA_VERSION)))
|
resultTbl.ForEach(func(key lua.LValue, value lua.LValue) {
|
||||||
|
out[key.String()] = convertTypes(value)
|
||||||
|
})
|
||||||
|
|
||||||
|
h.w.Header().Set("Content-Type", "application/json")
|
||||||
|
if err := json.NewEncoder(h.w).Encode(out); err != nil {
|
||||||
|
log.Error("Failed to encode JSON response",
|
||||||
|
slog.String("error", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ := out["status"].(string)
|
||||||
|
switch status {
|
||||||
|
case "error":
|
||||||
|
log.Info("Command executed with error",
|
||||||
|
slog.String("cmd", cmd),
|
||||||
|
slog.Any("result", out))
|
||||||
|
case "ok":
|
||||||
|
log.Info("Command executed successfully",
|
||||||
|
slog.String("cmd", cmd),
|
||||||
|
slog.Any("result", out))
|
||||||
|
default:
|
||||||
|
log.Info("Command executed and returned an unknown status",
|
||||||
|
slog.String("cmd", cmd),
|
||||||
|
slog.Any("result", out))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Session completed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertTypes(value lua.LValue) any {
|
||||||
|
switch value.Type() {
|
||||||
|
case lua.LTString:
|
||||||
|
return value.String()
|
||||||
|
case lua.LTNumber:
|
||||||
|
return float64(value.(lua.LNumber))
|
||||||
|
case lua.LTBool:
|
||||||
|
return bool(value.(lua.LBool))
|
||||||
|
case lua.LTTable:
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
if tbl, ok := value.(*lua.LTable); ok {
|
||||||
|
tbl.ForEach(func(key lua.LValue, value lua.LValue) {
|
||||||
|
result[key.String()] = convertTypes(value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
case lua.LTNil:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return value.String()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,5 +104,8 @@ func (h *HandlerV1) _handleList() {
|
|||||||
log.Info("Session completed")
|
log.Info("Session completed")
|
||||||
|
|
||||||
h.w.Header().Set("Content-Type", "application/json")
|
h.w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(h.w).Encode(commands)
|
if err := json.NewEncoder(h.w).Encode(commands); err != nil {
|
||||||
|
h.log.Error("Failed to write JSON error response",
|
||||||
|
slog.String("error", err.Error()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/akyaiy/GoSally-mvp/core/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *HandlerV1) ErrNotFound(w http.ResponseWriter, r *http.Request) {
|
func (h *HandlerV1) ErrNotFound(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -17,7 +19,7 @@ func (h *HandlerV1) ErrNotFound(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *HandlerV1) newUUID() string {
|
func (h *HandlerV1) newUUID() string {
|
||||||
bytes := make([]byte, 16)
|
bytes := make([]byte, int(config.GetInternalConsts().GetUUIDLength()/2))
|
||||||
_, err := rand.Read(bytes)
|
_, err := rand.Read(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.log.Error("Failed to generate UUID", slog.String("error", err.Error()))
|
h.log.Error("Failed to generate UUID", slog.String("error", err.Error()))
|
||||||
@@ -43,7 +45,12 @@ func (h *HandlerV1) writeJSONError(status int, msg string) {
|
|||||||
"error": msg,
|
"error": msg,
|
||||||
"code": status,
|
"code": status,
|
||||||
}
|
}
|
||||||
json.NewEncoder(h.w).Encode(resp)
|
if err := json.NewEncoder(h.w).Encode(resp); err != nil {
|
||||||
|
h.log.Error("Failed to write JSON error response",
|
||||||
|
slog.String("error", err.Error()),
|
||||||
|
slog.Int("status", status))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HandlerV1) extractDescriptionStatic(path string) (string, error) {
|
func (h *HandlerV1) extractDescriptionStatic(path string) (string, error) {
|
||||||
|
|||||||
216
core/update/update.go
Normal file
216
core/update/update.go
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
package update
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/akyaiy/GoSally-mvp/core/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
UpdateBranchStable = "stable"
|
||||||
|
UpdateBranchDev = "dev"
|
||||||
|
UpdateBranchTesting = "testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Version string
|
||||||
|
type Branch string
|
||||||
|
type IsNewUpdate bool
|
||||||
|
|
||||||
|
type UpdaterContract interface {
|
||||||
|
CkeckUpdates() (IsNewUpdate, error)
|
||||||
|
Update() error
|
||||||
|
GetCurrentVersion() (Version, Branch, error)
|
||||||
|
GetLatestVersion(updateBranch Branch) (Version, Branch, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
Log slog.Logger
|
||||||
|
Config *config.ConfigConf
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdater(log slog.Logger, cfg *config.ConfigConf) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
Log: log,
|
||||||
|
Config: cfg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitVersionString(versionStr string) (Version, Branch, error) {
|
||||||
|
versionStr = strings.TrimSpace(versionStr)
|
||||||
|
if !strings.HasPrefix(versionStr, "version") {
|
||||||
|
return "", "unknown", errors.New("version string does not start with 'version'")
|
||||||
|
}
|
||||||
|
parts := strings.SplitN(versionStr[len("version"):], "-", 2)
|
||||||
|
parts[0] = strings.TrimPrefix(parts[0], "version")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return Version(parts[0]), Branch("unknown"), errors.New("version string format invalid")
|
||||||
|
}
|
||||||
|
return Version(parts[0]), Branch(parts[1]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// isVersionNewer compares two version strings and returns true if the current version is newer than the latest version.
|
||||||
|
func isVersionNewer(current, latest Version) bool {
|
||||||
|
if current == latest {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
currentParts := strings.Split(string(current), ".")
|
||||||
|
latestParts := strings.Split(string(latest), ".")
|
||||||
|
|
||||||
|
maxLen := len(currentParts)
|
||||||
|
if len(latestParts) > maxLen {
|
||||||
|
maxLen = len(latestParts)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < maxLen; i++ {
|
||||||
|
var curPart, latPart int
|
||||||
|
|
||||||
|
if i < len(currentParts) {
|
||||||
|
cur, err := strconv.Atoi(currentParts[i])
|
||||||
|
if err != nil {
|
||||||
|
cur = 0 // или можно обработать ошибку иначе
|
||||||
|
}
|
||||||
|
curPart = cur
|
||||||
|
} else {
|
||||||
|
curPart = 0 // Если части в current меньше, считаем недостающие нулями
|
||||||
|
}
|
||||||
|
|
||||||
|
if i < len(latestParts) {
|
||||||
|
lat, err := strconv.Atoi(latestParts[i])
|
||||||
|
if err != nil {
|
||||||
|
lat = 0
|
||||||
|
}
|
||||||
|
latPart = lat
|
||||||
|
} else {
|
||||||
|
latPart = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if curPart < latPart {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if curPart > latPart {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// если равны — идём дальше
|
||||||
|
}
|
||||||
|
return false // все части равны, значит не новее
|
||||||
|
}
|
||||||
|
|
||||||
|
// if len(currentParts) >= 1 && len(latestParts) >= 1 {
|
||||||
|
// if currentParts[0] < latestParts[0] {
|
||||||
|
// if len(currentParts) < 2 || len(latestParts) < 2 {
|
||||||
|
// if currentParts[1] < latestParts[1] {
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
// if currentParts[1] > latestParts[1] {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if currentParts[0] > latestParts[0] {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// GetCurrentVersion reads the current version from the version file and returns it along with the branch.
|
||||||
|
func (u *Updater) GetCurrentVersion() (Version, Branch, error) {
|
||||||
|
version, branch, err := splitVersionString(string(config.GetUpdateConsts().GetNodeVersion()))
|
||||||
|
if err != nil {
|
||||||
|
u.Log.Error("Failed to parse version string", slog.String("version", string(config.GetUpdateConsts().GetNodeVersion())), slog.String("error", err.Error()))
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
switch branch {
|
||||||
|
case UpdateBranchDev, UpdateBranchStable, UpdateBranchTesting:
|
||||||
|
return Version(version), Branch(branch), nil
|
||||||
|
default:
|
||||||
|
return Version(version), Branch("unknown"), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Updater) GetLatestVersion(updateBranch Branch) (Version, Branch, error) {
|
||||||
|
repoURL := u.Config.Updates.RepositoryURL
|
||||||
|
if repoURL == "" {
|
||||||
|
u.Log.Error("RepositoryURL is empty in config")
|
||||||
|
return "", "", errors.New("repository URL is empty")
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(repoURL, "http://") && !strings.HasPrefix(repoURL, "https://") {
|
||||||
|
u.Log.Error("RepositoryURL does not start with http:// or https://", slog.String("RepositoryURL", repoURL))
|
||||||
|
return "", "", errors.New("repository URL must start with http:// or https://")
|
||||||
|
}
|
||||||
|
response, err := http.Get(repoURL + "/" + config.GetUpdateConsts().GetActualFileName())
|
||||||
|
if err != nil {
|
||||||
|
u.Log.Error("Failed to fetch latest version", slog.String("error", err.Error()))
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
u.Log.Error("Failed to fetch latest version", slog.Int("status", response.StatusCode))
|
||||||
|
return "", "", errors.New("failed to fetch latest version, status code: " + http.StatusText(response.StatusCode))
|
||||||
|
}
|
||||||
|
data, err := io.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
u.Log.Error("Failed to read latest version response", slog.String("error", err.Error()))
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" || strings.HasPrefix(line, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
version, branch, err := splitVersionString(string(line))
|
||||||
|
if err != nil {
|
||||||
|
u.Log.Error("Failed to parse version string", slog.String("version", string(line)), slog.String("error", err.Error()))
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
if branch == updateBranch {
|
||||||
|
return Version(version), Branch(branch), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u.Log.Warn("No version found for branch", slog.String("branch", string(updateBranch)))
|
||||||
|
return "", "", errors.New("no version found for branch: " + string(updateBranch))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Updater) CkeckUpdates() (IsNewUpdate, error) {
|
||||||
|
currentVersion, currentBranch, err := u.GetCurrentVersion()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
latestVersion, latestBranch, err := u.GetLatestVersion(currentBranch)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if currentVersion == latestVersion && currentBranch == latestBranch {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
u.Log.Info("New update available",
|
||||||
|
slog.String("current_version", string(currentVersion)),
|
||||||
|
slog.String("current_branch", string(currentBranch)),
|
||||||
|
slog.String("latest_version", string(latestVersion)),
|
||||||
|
slog.String("latest_branch", string(latestBranch)),
|
||||||
|
)
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (u *Updater) Update() error {
|
||||||
|
// if !(u.Config.UpdatesEnabled && u.Config.Updates.AllowUpdates && u.Config.Updates.AllowDowngrades) {
|
||||||
|
// u.Log.Info("Updates are disabled in config, skipping update")
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
// wantedVersion := u.Config.Updates.WantedVersion
|
||||||
|
// _, wantedBranch, _ := splitVersionString(wantedVersion)
|
||||||
|
// newVersion, newBranch, err := u.GetLatestVersion(wantedBranch)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// if wantedBranch != newBranch {
|
||||||
|
// u.Log.Info("Wanted version branch does not match latest version branch: updating wanted branch",
|
||||||
|
// slog.String("wanted_branch", string(wantedBranch)),
|
||||||
|
// slog.String("latest_branch", string(newBranch)),
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
30
core/update/update_test.go
Normal file
30
core/update/update_test.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package update
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFunc_isVersionNewer(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
current string
|
||||||
|
latest string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{"1.0.0", "1.0.0", false},
|
||||||
|
{"1.0.0", "1.0.1", true},
|
||||||
|
{"1.0.1", "1.0.0", false},
|
||||||
|
{"2.0.0", "1.9.9", false},
|
||||||
|
{"2.2.3", "1.9.9", false},
|
||||||
|
{"22.2.3", "1.9.9", false},
|
||||||
|
{"1.2.3", "1.99.9", true},
|
||||||
|
{"1.10", "1.5.99999", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.current+" vs "+tt.latest, func(t *testing.T) {
|
||||||
|
if got := isVersionNewer(Version(tt.current), Version(tt.latest)); got != tt.want {
|
||||||
|
t.Errorf("isVersionNewer(%q, %q) = %v; want %v", tt.current, tt.latest, got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
2
go.mod
2
go.mod
@@ -6,11 +6,11 @@ require (
|
|||||||
github.com/go-chi/chi/v5 v5.2.2
|
github.com/go-chi/chi/v5 v5.2.2
|
||||||
github.com/ilyakaznacheev/cleanenv v1.5.0
|
github.com/ilyakaznacheev/cleanenv v1.5.0
|
||||||
github.com/yuin/gopher-lua v1.1.1
|
github.com/yuin/gopher-lua v1.1.1
|
||||||
|
golang.org/x/net v0.41.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||||
github.com/aarzilli/golua v0.0.0-20250217091409-248753f411c4 // indirect
|
|
||||||
github.com/joho/godotenv v1.5.1 // indirect
|
github.com/joho/godotenv v1.5.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
|
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -1,12 +1,6 @@
|
|||||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/aarzilli/golua v0.0.0-20250217091409-248753f411c4 h1:gW5i3FQAMcbkNgo/A87gCKAbBMalAO8BlPIMo9Gk2Ow=
|
|
||||||
github.com/aarzilli/golua v0.0.0-20250217091409-248753f411c4/go.mod h1:hMjfaJVSqVnxenMlsxrq3Ni+vrm9Hs64tU4M7dhUoO4=
|
|
||||||
github.com/akyaiy/GoSally-mvp/config v0.0.0-20250622141207-5326dd45b694 h1:SJfxaud4HMVg9roTMMJaTQ+Odoz1LIw60TiS97EtWCE=
|
|
||||||
github.com/akyaiy/GoSally-mvp/config v0.0.0-20250622141207-5326dd45b694/go.mod h1:2eaoBiPQmvZoC9DAzn11zHzWmscBI4dMTi4HeGO96XQ=
|
|
||||||
github.com/akyaiy/GoSally-mvp/logs v0.0.0-20250622141207-5326dd45b694 h1:qYZIzX3NczqozwCnlLQ5M1vTLoCqIIF1qxxweub4zQo=
|
|
||||||
github.com/akyaiy/GoSally-mvp/logs v0.0.0-20250622141207-5326dd45b694/go.mod h1:o5ysbqTH4qQTlpx8cu2XaXbTI2blpDgaUI4CEvi0VGo=
|
|
||||||
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
||||||
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||||
github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4=
|
github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4=
|
||||||
@@ -15,6 +9,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
|||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
|
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
|
||||||
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||||
|
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||||
|
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
Reference in New Issue
Block a user