This repository has been archived by the owner on Oct 28, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
lua.go
96 lines (85 loc) · 2.69 KB
/
lua.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package factoid
import (
"context"
"strings"
"github.com/pkg/errors"
"github.com/yuin/gopher-lua"
"github.com/riking/marvin"
"github.com/riking/marvin/lualib"
"github.com/riking/marvin/util"
)
type ctxKeyOutputFlags struct{}
func RunFactoidLua(ctx context.Context, mod *FactoidModule, factoidName, factoidSource string, factoidArgs []string, of *OutputFlags, actSource marvin.ActionSource) (string, error) {
var result string
err := util.PCall(func() error {
var err error
result, err = runLua(ctx, mod, factoidName, factoidSource, factoidArgs, of, actSource)
return err
})
return result, err
}
func runLua(ctx context.Context, mod *FactoidModule, factoidName, factoidSource string, factoidArgs []string, of *OutputFlags, actionSource marvin.ActionSource) (string, error) {
ctx = context.WithValue(ctx, ctxKeyOutputFlags{}, of)
g := lualib.NewLua(ctx, mod.team, actionSource)
g.OpenLibraries()
// Set globals
argv := g.L.NewTable()
for _, v := range factoidArgs {
argv.Append(lua.LString(v))
}
g.L.SetGlobal("argv", argv)
g.L.SetGlobal("args", lua.LString(strings.Join(factoidArgs, " ")))
u, err := lualib.LNewUser(g, actionSource.UserID(), true)
if err != nil {
panic(err)
}
g.L.SetGlobal("user", u)
g.L.SetGlobal("channel", lualib.LNewChannel(g, actionSource.ChannelID()))
g.L.SetGlobal("_G", g.L.Get(lua.GlobalsIndex))
// factoid global
(*LFactoid)(nil).SetupMetatable(g.L)
g.L.SetGlobal("factoidname", lua.LString(factoidName))
mt := g.L.NewTable()
mt.RawSetString("__index", g.L.NewFunction(func(L *lua.LState) int {
L.CheckUserData(1)
name := L.CheckString(2)
L.Push(LNewFactoid(g, mod, name))
return 1
}))
fmodUD := g.L.NewUserData()
fmodUD.Value = nil
fmodUD.Metatable = mt
g.L.SetGlobal("factoid", fmodUD)
// factoidmap data
(*LFDataMap)(nil).SetupMetatable(g.L)
mt = g.L.NewTable()
mt.RawSetString("__index", g.L.NewFunction(func(L *lua.LState) int {
L.CheckUserData(1)
mapName := L.CheckString(2)
L.Push(LNewFDataMap(g, mod, "M-"+mapName))
return 1
}))
fmapUD := g.L.NewUserData()
fmapUD.Value = nil
fmapUD.Metatable = mt
g.L.SetGlobal("fmap", fmapUD)
g.L.SetGlobal("fdata", LNewFDataMap(g, mod, "F-"+factoidName))
// ------- setup done
// Load and call factoid code
fn, err := g.L.Load(strings.NewReader(factoidSource), "<factoid>")
if err != nil {
return "", ErrUser{errors.Wrap(err, "lua.compile")}
}
g.L.Push(fn)
err = g.L.PCall(0, 1, nil)
if err != nil {
return "", ErrUser{errors.Wrap(err, "lua error")}
}
str := lua.LVAsString(g.L.ToStringMeta(g.L.Get(-1)))
isStr := lua.LVCanConvToString(g.L.Get(-1))
g.L.Pop(1)
if str != "" && (isStr || g.PrintBuf.Len() == 0) {
g.PrintBuf.WriteString(str)
}
return g.PrintBuf.String(), nil
}