Skip to content

Instantly share code, notes, and snippets.

@jebjerg
Last active September 19, 2021 19:04
Show Gist options
  • Save jebjerg/3cd74ba28e137f7f8bdd to your computer and use it in GitHub Desktop.
Save jebjerg/3cd74ba28e137f7f8bdd to your computer and use it in GitHub Desktop.
Go + lua = <3
package main
import (
"fmt"
lua "github.com/yuin/gopher-lua"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
)
// some Go function
func Debug(text string) {
fmt.Printf("[GO]\t%v\n", text)
}
// lua wrapper
func DebugLUA(L *lua.LState) int {
t := L.ToString(1)
Debug(t)
return 0
}
var states map[*lua.LState]map[string][]*lua.LFunction
func init() {
LoadScripts()
go func() {
reload_sig := make(chan os.Signal, 1)
signal.Notify(reload_sig, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGHUP)
for {
<-reload_sig
fmt.Println("reloading scripts")
Cleanup()
LoadScripts()
}
}()
}
func LoadScripts() {
states = make(map[*lua.LState]map[string][]*lua.LFunction)
files, err := filepath.Glob("*.lua")
if err != nil {
return
}
for _, file := range files {
state := lua.NewState()
// bootstrap state
state.SetGlobal("debug", state.NewFunction(DebugLUA))
state.SetGlobal("hook", state.NewFunction(LuaHook))
states[state] = make(map[string][]*lua.LFunction)
if err := state.DoFile(file); err != nil {
states[state] = nil
state = nil
fmt.Println(file, "failed:", err)
continue
}
fmt.Println(file, "initialized")
}
}
func Cleanup() {
states = nil
}
func LuaHook(L *lua.LState) int {
event := L.ToString(1)
fn := L.ToFunction(2)
if event == "" || fn == nil {
return 1
}
if states[L][event] != nil {
states[L][event] = append(states[L][event], fn)
} else {
funcs := []*lua.LFunction{fn}
states[L][event] = funcs
}
return 0
}
func PrivMsg(channel, text string) error {
return Trigger("PRIVMSG", lua.LString(channel), lua.LString(text))
}
func Trigger(event string, args ...lua.LValue) error {
for state, fnmap := range states {
if fns := fnmap[event]; fns != nil {
for _, fn := range fns {
state.CallByParam(lua.P{
Fn: fn,
NRet: 0,
Protect: true,
}, args...)
}
}
}
return nil
}
func main() {
// cleanup when we're done
defer Cleanup()
interval := time.NewTicker(10 * time.Second)
go func() {
for {
PrivMsg("#channel", "text")
<-interval.C
}
}()
forever := make(chan bool)
<-forever
}
/*
whoo
[GO] hoo
test.lua initialized
#herp: derp
saving to disk: #herp: derp
...
reloading scripts
*/
function on_privmsgs(channel, text)
print(channel..": "..text)
-- if text == "status" then
-- bot.privmsg(channel, "hell no")
-- end
end
function log_privmsgs(channel, text)
print("saving to disk: "..channel..": "..text)
end
print("whoo")
debug("hoo")
-- change to lua module bot, i.e. bot.hook, bot.privmsg, ...
hook("PRIVMSG", on_privmsgs)
hook("PRIVMSG", log_privmsgs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment