// script package util import ( "encoding/json" "fmt" "log" qu "qfw/util" ljson "github.com/yuin/gopher-json" "github.com/yuin/gopher-lua" ) type LuaScript struct { Code, Name, Script string Doc map[string]interface{} //经过前置过滤的源信息 Block []*Block //分块信息 KvMap map[string][]map[string]interface{} Result map[string][]map[string]interface{} //抽取结果信息 L *lua.LState } func (s *LuaScript) ClearRunScript() map[string]interface{} { data := map[string]interface{}{} qu.Try(func() { s.L = lua.NewState() //创建lua虚拟机 s.L.PreloadModule("json", ljson.Loader) defer s.L.Close() if err := s.L.DoString(s.Script); err != nil { data["err"] = err.Error() } else { //doc:每条结果数据 //KvMap:合并数据的list tab := MapToLuaTable(s.L, s.Doc) kvMap := MapToLuaTable2(s.L, s.KvMap) if err := s.L.CallByParam(lua.P{ Fn: s.L.GetGlobal("main"), NRet: 1, Protect: true, }, lua.LString(s.Code), tab, kvMap); err != nil { data["err"] = err.Error() } ret := s.L.Get(-1) s.L.Pop(1) if tmp, ok := ret.(*lua.LTable); ok { data = LuaTableToMap(tmp) } else { data["rep"] = ret } } }, func(err interface{}) { log.Println("lua err:", data["err"]) }) return data } //stype per:前置,core:抽取,back:后置 func (s *LuaScript) RunScript(stype string) map[string]interface{} { data := map[string]interface{}{} qu.Try(func() { s.L = lua.NewState() s.L.PreloadModule("json", ljson.Loader) defer s.L.Close() if err := s.L.DoString(s.Script); err != nil { data["err"] = err.Error() } else { if stype == "pre" { tab := MapToLuaTable(s.L, s.Doc) if err := s.L.CallByParam(lua.P{ Fn: s.L.GetGlobal("main"), NRet: 1, Protect: true, }, lua.LString(s.Code), tab); err != nil { data["err"] = err.Error() } } else if stype == "core" { tab := MapToLuaTable(s.L, s.Doc) block, _ := json.Marshal(s.Block) kvMap := MapToLuaTable2(s.L, s.KvMap) if err := s.L.CallByParam(lua.P{ Fn: s.L.GetGlobal("main"), NRet: 1, Protect: true, }, lua.LString(s.Code), tab, lua.LString(block), kvMap); err != nil { data["err"] = err.Error() } } else if stype == "back" { result := MapToLuaTable2(s.L, s.Result) if err := s.L.CallByParam(lua.P{ Fn: s.L.GetGlobal("main"), NRet: 1, Protect: true, }, lua.LString(s.Code), result); err != nil { data["err"] = err.Error() } } ret := s.L.Get(-1) s.L.Pop(1) if tmp, ok := ret.(*lua.LTable); ok { data = LuaTableToMap(tmp) } else { data["rep"] = ret } } }, func(err interface{}) { log.Println("lua err:", err) }) return data } func Logic(str string, doc map[string]interface{}) bool { b := false var errs error qu.Try(func() { L := lua.NewState() L.PreloadModule("json", ljson.Loader) defer L.Close() if err := L.DoString(str); err != nil { errs = err } else { tab := MapToLuaTable(L, doc) if err := L.CallByParam(lua.P{ Fn: L.GetGlobal("logic"), NRet: 1, Protect: true, }, tab); err != nil { errs = err } ret := L.Get(-1) L.Pop(1) if ret.String() == "true" { b = true } } }, func(err interface{}) { log.Println("lua err:", errs) }) return b } func MapToLuaTable(l *lua.LState, obj map[string]interface{}) *lua.LTable { tab := l.NewTable() for k, v := range obj { if val, ok := v.(string); ok { tab.RawSet(lua.LString(k), lua.LString(val)) } else if val, ok := v.(int64); ok { tab.RawSet(lua.LString(k), lua.LNumber(val)) } else if val, ok := v.(int32); ok { tab.RawSet(lua.LString(k), lua.LNumber(val)) } else if val, ok := v.(int); ok { tab.RawSet(lua.LString(k), lua.LNumber(val)) } else if val, ok := v.(float64); ok { tab.RawSet(lua.LString(k), lua.LNumber(val)) } else if val, ok := v.(float32); ok { tab.RawSet(lua.LString(k), lua.LNumber(val)) } else if val, ok := v.(bool); ok { tab.RawSet(lua.LString(k), lua.LBool(val)) } else if val ,ok := v.(map[string]bool);ok{//把map的value值为true的存储为数组 tb := l.NewTable() var i int for k2,_ := range val{ tb.Insert(i, lua.LString(k2)) i+=1 } tab.RawSet(lua.LString(k), tb) } else if val, ok := v.(map[string]interface{}); ok { tab.RawSet(lua.LString(k), MapToLuaTable(l, val)) } else if val, ok := v.([]string); ok { tb := l.NewTable() for k, vv := range val { tb.Insert(k, lua.LString(vv)) } tab.RawSet(lua.LString(k), tb) } else if val, ok := v.([]map[string]interface{}); ok { tab2 := l.NewTable() for i, v := range val { tab2.Insert(i, MapToLuaTable(l, v)) } tab.RawSet(lua.LString(k), tab2) } else if val, ok := v.([]interface{}); ok { bs, _ := json.Marshal(val) tab.RawSet(lua.LString(k), lua.LString(string(bs))) } } return tab } func MapToLuaTable2(l *lua.LState, obj map[string][]map[string]interface{}) *lua.LTable { tab := l.NewTable() for k, ms := range obj { tab2 := l.NewTable() for i, v := range ms { tab2.Insert(i+1 /*加1防止顺序错乱*/, MapToLuaTable(l, v)) } tab.RawSet(lua.LString(k), tab2) } return tab } func LuaTableToMap(param *lua.LTable) map[string]interface{} { tmp := map[string]interface{}{} param.ForEach(func(key, val lua.LValue) { kk := fmt.Sprint(key) if v, ok := val.(lua.LString); ok { tmp[kk] = string(v) } else if v, ok := val.(*lua.LTable); ok { if kk == "blocktag"{//分块 t := map[string]bool{} v.ForEach(func(value lua.LValue, value2 lua.LValue) { t[value2.String()]=true }) tmp[kk] = t return } t := []map[string]interface{}{} v.ForEach(func(k, inv lua.LValue) { if vv, ok := inv.(*lua.LTable); ok { t = append(t, LuaTableToMap(vv)) } }) tmp[kk] = t } else if v, ok := val.(*lua.LBool); ok { if v.String() == "true" { tmp[kk] = true } else { tmp[kk] = false } } else if kk == "comeintime" || kk == "publishtime" { tmp[kk] = qu.Int64All(val.String()) } else if v, ok := val.(*lua.LNumber); ok { tmp[kk] = qu.Float64All(v.String()) } else if v, ok := val.(lua.LNumber); ok { tmp[kk] = qu.Float64All(v.String()) } else { tmp[kk] = val } }) return tmp }