func (p *Plugin) apiTimerNew(l *lua.State) int { callback := luar.NewLuaObject(l, 1) timeout := l.ToInteger(2) t := &Timer{ cancel: make(chan bool), } go func() { defer func() { close(t.cancel) t.cancel = nil }() select { case <-time.After(time.Millisecond * time.Duration(timeout)): p.callValue(callback) callback.Close() case <-t.cancel: } }() obj := luar.NewLuaObjectFromValue(l, t) obj.Push() obj.Close() return 1 }
func (p *LuaPlugin) prepContext(L *lua.State, req *http.Request, ctx *apiplexy.APIContext) { var clientIP string if req.Header.Get("X-Forwarded-For") != "" { clientIP = req.Header.Get("X-Forwarded-For") } else { clientIP, _, _ = net.SplitHostPort(req.RemoteAddr) } headers := make(map[string]interface{}, len(req.Header)) for k, vs := range req.Header { headers[k] = strings.Join(vs, " ") } request := map[string]interface{}{ "path": req.URL.Path, "method": req.Method, "ip": clientIP, "referrer": req.Referer(), "browser": req.UserAgent(), "headers": headers, } pushMap(L, request, false) L.SetGlobal("request") pushMap(L, structs.Map(ctx), true) L.SetGlobal("context") }
func sliceSub(L *lua.State) int { slice, _ := valueOfProxy(L, 1) i1, i2 := L.ToInteger(2), L.ToInteger(3) newslice := slice.Slice(i1-1, i2) makeValueProxy(L, newslice, cSLICE_META) return 1 }
func callGoMethod(L *lua.State, name string, st reflect.Value) { ret := st.MethodByName(name) if !ret.IsValid() { fmt.Println("whoops") } L.PushGoFunction(GoLuaFunc(L, ret)) }
func GoLua(L *lua.State) int { go func() { LT := L.NewThread() L.PushValue(1) lua.XMove(L, LT, 1) res := LT.Resume(0) for res != 0 { if res == 2 { emsg := LT.ToString(-1) RaiseError(LT, emsg) } ch, t := valueOfProxy(LT, -2) if LT.ToBoolean(-1) { // send on a channel val := luaToGoValue(LT, t.Elem(), -3) ch.Send(val) res = LT.Resume(0) } else { // receive on a channel val, ok := ch.Recv() GoToLua(LT, t.Elem(), val, false) LT.PushBoolean(ok) res = LT.Resume(2) } } }() return 0 }
func MessThingIndex(state *lua.State) int { log.Println("HEY WE MADE IT") printStackTypes(state) state.GetMetaTable(1) state.LGetMetaTable(ThingMetaTableName) isThing := state.RawEqual(-1, -2) state.Pop(2) if !isThing { log.Println("!!! OMG ARG #1 IS NOT A MESS.THING !!!") } fieldName := state.CheckString(2) log.Println("Arg #2 checks out, it's a string") thing := checkThing(state, 1) log.Println("So we're tryin'a look up", fieldName, "on thing", thing.Id) if member, ok := MessThingMembers[fieldName]; ok { return member(state, thing) } // That wasn't one of our members, so look it up in our Table. if data, ok := thing.Table[fieldName]; ok { // TODO: instead of pushing a whole map if the script asks for one, maybe we should use another kind of userdata that tracks the name & can access its submembers until the script asks for the leaf (or a non-existent branch)? pushValue(state, data) return 1 } // uh... I guess we didn't do anything, so...? return 0 }
func (p *Plugin) apiAudioSetBitrate(l *lua.State) int { bitrate := l.ToInteger(1) if enc, ok := p.instance.Client.AudioEncoder.(*opus.Encoder); ok { enc.SetBitrate(bitrate) } return 0 }
func (p *Plugin) apiAudioPlay(l *lua.State) int { if p.instance.Audio.IsPlaying() { l.PushBoolean(false) return 1 } obj := luar.NewLuaObject(l, 1) filename := obj.Get("filename").(string) callback := obj.GetObject("callback") obj.Close() if enc, ok := p.instance.Client.AudioEncoder.(*opus.Encoder); ok { enc.SetApplication(gopus.Audio) } p.instance.Audio.Source = gumble_ffmpeg.SourceFile(filename) p.instance.Audio.Play() go func() { p.instance.Audio.Wait() if callback.Type != "nil" { p.callValue(callback) } callback.Close() }() return 0 }
func slice__newindex(L *lua.State) int { slice, t := valueOfProxy(L, 1) idx := L.ToInteger(2) val := LuaToGo(L, t.Elem(), 3) slice.Index(idx - 1).Set(valueOf(val)) return 0 }
// Also for arrays. func copySliceToTable(L *lua.State, vslice reflect.Value, visited visitor) int { ref := vslice for vslice.Kind() == reflect.Ptr { // For arrays. vslice = vslice.Elem() } if vslice.IsValid() && (vslice.Kind() == reflect.Slice || vslice.Kind() == reflect.Array) { n := vslice.Len() L.CreateTable(n, 0) if vslice.Kind() == reflect.Slice { visited.mark(vslice) } else if ref.Kind() == reflect.Ptr { visited.mark(ref) } for i := 0; i < n; i++ { L.PushInteger(int64(i + 1)) v := vslice.Index(i) if isNil(v) { v = nullv } goToLua(L, nil, v, true, visited) L.SetTable(-3) } return 1 } L.PushNil() L.PushString("not a slice/array") return 2 }
func proxy__gc(L *lua.State) int { vp := (*valueProxy)(L.ToUserdata(1)) mu.Lock() delete(proxyMap, vp) mu.Unlock() return 0 }
func LuaIntUTCTime(L *lua.State) int { luaAssertArgnum(L, 1, "utctime()") timestamp := L.ToInteger(1) PushTime(L, time.Unix(int64(timestamp), 0)) return 1 }
func PushStringVec(L *lua.State, v []string) { L.CheckStack(3) L.CreateTable(len(v), 0) for idx, val := range v { SetTableIntString(L, int64(idx+1), val) } }
func (p *Plugin) apiAudioBitrate(l *lua.State) int { if enc, ok := p.instance.Client.AudioEncoder.(*opus.Encoder); ok { l.PushInteger(int64(enc.Bitrate())) } else { l.PushInteger(-1) } return 1 }
func LuaIntShowRet(L *lua.State) int { L.CheckStack(2) tl := GetTasklistFromLua(L) tl.luaFlags.showReturnValue = true return 0 }
func printStackTypes(state *lua.State) { topIndex := state.GetTop() segments := make([]interface{}, topIndex+1) segments[0] = "Stack types:" for i := 1; i <= topIndex; i++ { segments[i] = state.LTypename(i) } log.Println(segments...) }
func LuaIntWriteCursor(L *lua.State) int { Logf(INFO, "Writing cursor") L.CheckStack(1) tl := GetTasklistFromLua(L) luaAssertNotFreeCursor(tl, "writecursor()") cursor := GetEntryFromLua(L, CURSOR, "writecursor()") tl.Update(cursor, false) return 0 }
func proxyType(L *lua.State) int { v := unwrapProxy(L, 1) if v != nil { GoToLua(L, nil, valueOf(reflect.TypeOf(v)), false) } else { L.PushNil() } return 1 }
// goToLua copies Go values to Lua and sets the result to global 'name'. // Compound types are deep-copied. // Functions are automatically converted to 'func (L *lua.State) int'. func goToLua(L *lua.State, name string, val interface{}) { t := reflect.TypeOf(val) if t.Kind() == reflect.Func { L.PushGoFunction(luar.GoLuaFunc(L, val)) } else { luar.GoToLua(L, t, reflect.ValueOf(val), true) } L.SetGlobal(name) }
func proxy__eq(L *lua.State) int { v1, t1 := valueOfProxy(L, 1) v2, t2 := valueOfProxy(L, 2) if t1 != t2 { RaiseError(L, sprintf("mismatched types %s and %s", t1, t2)) } L.PushBoolean(v1.Interface() == v2.Interface()) return 1 }
// ComplexImag defines 'luar.imag' when 'Init' is called. // It is the equivalent of Go's 'imag' function. // // WARNING: Deprecated, use the 'imag' index instead. func ComplexImag(L *lua.State) int { v := mustUnwrapProxy(L, 1) val := reflect.ValueOf(v) if unsizedKind(val) != reflect.Complex128 { RaiseError(L, "not a complex") } L.PushNumber(imag(val.Complex())) return 1 }
// Unproxify converts a proxy to an unproxified Lua value. // // Argument: proxy // // Returns: value (Lua value) func Unproxify(L *lua.State) int { if !isValueProxy(L, 1) { L.PushNil() return 1 } v, _ := valueOfProxy(L, 1) GoToLua(L, nil, v, true) return 1 }
func slice__newindex(L *lua.State) int { slice, t := valueOfProxy(L, 1) idx := L.ToInteger(2) val := luaToGoValue(L, t.Elem(), 3) if idx < 1 || idx > slice.Len() { RaiseError(L, "slice set: index out of range") } slice.Index(idx - 1).Set(val) return 0 }
// ProxyMethod pushes the proxy method on the stack. // // Argument: proxy // // Returns: method (function) func ProxyMethod(L *lua.State) int { if !isValueProxy(L, 1) { L.PushNil() return 1 } v, _ := valueOfProxy(L, 1) name := L.ToString(2) pushGoMethod(L, name, v) return 1 }
func LuaTableGetString(L *lua.State, key string) string { L.PushString(key) L.GetTable(-2) r := "" if !L.IsNil(-1) { r = L.ToString(-1) } L.Pop(1) return r }
// GoLuaFunc converts an arbitrary Go function into a Lua-compatible GoFunction. // There are special optimized cases for functions that go from strings to strings, // and doubles to doubles, but otherwise Go // reflection is used to provide a generic wrapper function func GoLuaFunc(L *lua.State, fun interface{}) lua.LuaGoFunction { switch f := fun.(type) { case func(*lua.State) int: return f case func(string) string: return func(L *lua.State) int { L.PushString(f(L.ToString(1))) return 1 } case func(float64) float64: return func(L *lua.State) int { L.PushNumber(f(L.ToNumber(1))) return 1 } default: } var funv reflect.Value switch ff := fun.(type) { case reflect.Value: funv = ff default: funv = valueOf(fun) } funt := funv.Type() targs, tout := functionArgRetTypes(funt) return func(L *lua.State) int { var lastT reflect.Type orig_targs := targs isVariadic := funt.IsVariadic() if isVariadic { n := len(targs) lastT = targs[n-1].Elem() targs = targs[0 : n-1] } args := make([]reflect.Value, len(targs)) for i, t := range targs { val := LuaToGo(L, t, i+1) args[i] = valueOfNil(val) //println(i,args[i].String()) } if isVariadic { n := L.GetTop() for i := len(targs) + 1; i <= n; i++ { ival := LuaToGo(L, lastT, i) args = append(args, valueOfNil(ival)) } targs = orig_targs } resv := callGo(L, funv, args) for i, val := range resv { GoToLua(L, tout[i], val, false) } return len(resv) } }
func struct__newindex(L *lua.State) int { st, t := valueOfProxy(L, 1) name := L.ToString(2) if t.Kind() == reflect.Ptr { st = st.Elem() } field := st.FieldByName(name) val := LuaToGo(L, field.Type(), 3) field.Set(valueOf(val)) return 0 }
func LuaIntRmColumn(L *lua.State) int { luaAssertArgnum(L, 1, "rmcolumn()") name := L.ToString(1) entry := GetEntryFromLua(L, CURSOR, "rmcolumn()") entry.RemoveColumn(name) tl := GetTasklistFromLua(L) if !tl.luaFlags.cursorCloned { tl.luaFlags.cursorEdited = true } return 0 }
func (p *Plugin) apiAudioNewTarget(l *lua.State) int { id := l.ToInteger(1) target := &gumble.VoiceTarget{} target.ID = uint32(id) obj := luar.NewLuaObjectFromValue(l, target) obj.Push() obj.Close() return 1 }
// ProxyRaw unproxifies a value. // // WARNING: Deprecated, use luar.unproxify instead. func ProxyRaw(L *lua.State) int { v := mustUnwrapProxy(L, 1) val := reflect.ValueOf(v) tp := predeclaredScalarType(val.Type()) if tp != nil { val = val.Convert(tp) GoToLua(L, nil, val, false) } else { L.PushNil() } return 1 }