From f2294a5b67affe82c5a7c9e061215aeaffb0020b Mon Sep 17 00:00:00 2001 From: shaoying Date: Mon, 25 Jun 2018 22:40:43 +0800 Subject: [PATCH] tce add Message.confx --- src/contexts/aaa/aaa.go | 6 +- src/contexts/cli/cli.go | 4 +- src/contexts/ctx.go | 568 +++++++++++++++++++++++++--------------- src/contexts/mdb/mdb.go | 355 ++++++++++--------------- src/contexts/ssh/ssh.go | 2 +- src/contexts/web/web.go | 2 +- 6 files changed, 510 insertions(+), 427 deletions(-) diff --git a/src/contexts/aaa/aaa.go b/src/contexts/aaa/aaa.go index 7c6f7274..1fc1cbcf 100644 --- a/src/contexts/aaa/aaa.go +++ b/src/contexts/aaa/aaa.go @@ -210,7 +210,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", // }}} }}, "md5": &ctx.Command{Name: "md5 [file filename][content]", Help: "散列", - Formats: map[string]int{"file": 1}, + Form: map[string]int{"file": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if m.Options("file") { // {{{ f, e := os.Open(m.Option("file")) @@ -235,7 +235,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", 解密: rsa decrypt keyfile key.pem mmfile mm.txt 签名: rsa sign keyfile key.pem signfile sign.txt hello 验签: rsa verify keyfile pubkey.pem signfile sign.txt hello`, - Formats: map[string]int{"keyfile": 1, "key": 1, "mmfile": 1, "mm": 1, "signfile": 1, "signs": 1, "file": 1}, + Form: map[string]int{"keyfile": 1, "key": 1, "mmfile": 1, "mm": 1, "signfile": 1, "signs": 1, "file": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if arg[0] == "gen" { // {{{ keys, e := rsa.GenerateKey(crand.Reader, 1024) @@ -355,7 +355,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", // }}} }}, "deal": &ctx.Command{Name: "deal init|sell|buy|done [keyfile name][key str]", Help: "散列", - Formats: map[string]int{"file": 1}, + Form: map[string]int{"file": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if m.Options("file") { // {{{ f, e := os.Open(m.Option("file")) diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 421fc1b5..59632285 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -322,8 +322,8 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } // }}} }}, "time": &ctx.Command{Name: "time [parse when] format when", - Formats: map[string]int{"parse": 1}, - Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Form: map[string]int{"parse": 1}, + Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { t := time.Now() // {{{ if m.Options("parse") { f := "2006-01-02 15:04:05" diff --git a/src/contexts/ctx.go b/src/contexts/ctx.go index f9ec096c..b2c9d931 100644 --- a/src/contexts/ctx.go +++ b/src/contexts/ctx.go @@ -3,6 +3,7 @@ package ctx // {{{ import ( // {{{ "crypto/md5" "encoding/hex" + "encoding/json" "errors" "fmt" "html/template" @@ -45,11 +46,12 @@ type Command struct { Name string Help string - Formats map[string]int - Options map[string]string Shares map[string][]string + Options map[string]string Appends map[string]string - Hand func(m *Message, c *Context, key string, arg ...string) + + Form map[string]int + Hand func(m *Message, c *Context, key string, arg ...string) } type Server interface { @@ -87,6 +89,144 @@ type Context struct { Server } +func (c *Context) Spawn(m *Message, name string, help string) *Context { // {{{ + s := &Context{Name: name, Help: help, root: c.root, context: c} + + if m.target = s; c.Server != nil { + c.Register(s, c.Server.Spawn(m, s, m.Meta["detail"]...)) + } else { + c.Register(s, nil) + } + + if m.Template != nil { + m.Template.source = s + } + + return s +} + +// }}} +func (c *Context) Begin(m *Message) *Context { // {{{ + c.Caches["status"] = &Cache{Name: "服务状态(begin/start/close)", Value: "begin", Help: "服务状态,begin:初始完成,start:正在运行,close:未在运行"} + c.Caches["stream"] = &Cache{Name: "服务数据", Value: "", Help: "服务数据"} + + item := []string{} + m.BackTrace(func(m *Message) bool { + item = append(item, m.target.Name) + return true + }) + for i := 0; i < len(item)/2; i++ { + item[i], item[len(item)-i-1] = item[len(item)-i-1], item[i] + } + c.Caches["module"] = &Cache{Name: "服务数据", Value: strings.Join(item, "."), Help: "服务数据"} + + m.Index = 1 + c.Pulse = m + c.Requests = []*Message{m} + c.Historys = []*Message{m} + c.Sessions = map[string]*Message{} + + c.master = m.master.master + c.Owner = m.master.Owner + + m.Log("begin", nil, "%d context %v %v", m.root.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"]) + for k, x := range c.Configs { + if x.Hand != nil { + m.Conf(k, x.Value) + } + } + + if c.Server != nil { + c.Server.Begin(m, m.Meta["detail"]...) + } + + return c +} + +// }}} +func (c *Context) Start(m *Message) bool { // {{{ + m.Hand = true + + if m != c.Requests[0] { + c.Requests, m.Index = append(c.Requests, m), len(c.Requests)+1 + } + + if m.Cap("status") != "start" { + running := make(chan bool) + go m.TryCatch(m, true, func(m *Message) { + m.Log(m.Cap("status", "start"), nil, "%d server %v %v", m.root.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"]) + + if running <- true; c.Server != nil && c.Server.Start(m, m.Meta["detail"]...) { + c.Close(m, m.Meta["detail"]...) + } + }) + <-running + } + return true +} + +// }}} +func (c *Context) Close(m *Message, arg ...string) bool { // {{{ + m.Log("close", c, "%d:%d %v", len(m.source.Sessions), len(m.target.Historys), arg) + + if m.target == c { + if m.Index == 0 { + for i := len(c.Requests) - 1; i >= 0; i-- { + v := c.Requests[i] + if v.Index = -1; v.source != c && !v.source.Close(v, arg...) { + v.Index = i + return false + } + c.Requests = c.Requests[:i] + } + } else if m.Index > 0 { + for i := m.Index - 1; i < len(c.Requests)-1; i++ { + c.Requests[i] = c.Requests[i+1] + } + c.Requests = c.Requests[:len(c.Requests)-1] + } + } + + if c.Server != nil && !c.Server.Close(m, arg...) { + return false + } + + if m.source == c && m.target != c { + if _, ok := c.Sessions[m.Name]; ok { + delete(c.Sessions, m.Name) + } + return true + } + + if len(c.Requests) > 1 { + return false + } + + if m.Cap("status") == "start" { + m.Log(m.Cap("status", "close"), nil, "%d server %v", m.root.Capi("nserver", -1)+1, arg) + for _, v := range c.Sessions { + if v.target != c { + v.target.Close(v, arg...) + } + } + } + + // if m.Index == 0 && c.context != nil && len(c.contexts) == 0 { + if c.context != nil { + m.Log("close", nil, "%d context %v", m.root.Capi("ncontext", -1)+1, arg) + delete(c.context.contexts, c.Name) + c.context = nil + if c.Exit != nil { + m.Log("info", nil, "before exit<-") + c.Exit <- true + m.Log("info", nil, "after exit<-") + } + } + return true +} + +// }}} + func (c *Context) Password(meta string) string { // {{{ bs := md5.Sum([]byte(fmt.Sprintln("%d%d%s", time.Now().Unix(), rand.Int(), meta))) sessid := hex.EncodeToString(bs[:]) @@ -179,143 +319,6 @@ func (c *Context) Check(m *Message, arg ...string) bool { // {{{ return false } -// }}} -func (c *Context) Spawn(m *Message, name string, help string) *Context { // {{{ - s := &Context{Name: name, Help: help, root: c.root, context: c} - - if m.target = s; c.Server != nil { - c.Register(s, c.Server.Spawn(m, s, m.Meta["detail"]...)) - } else { - c.Register(s, nil) - } - - if m.Template != nil { - m.Template.source = s - } - - return s -} - -// }}} -func (c *Context) Begin(m *Message) *Context { // {{{ - c.Caches["status"] = &Cache{Name: "服务状态(begin/start/close)", Value: "begin", Help: "服务状态,begin:初始完成,start:正在运行,close:未在运行"} - c.Caches["stream"] = &Cache{Name: "服务数据", Value: "", Help: "服务数据"} - - item := []string{} - m.BackTrace(func(m *Message) bool { - item = append(item, m.target.Name) - return true - }) - for i := 0; i < len(item)/2; i++ { - item[i], item[len(item)-i-1] = item[len(item)-i-1], item[i] - } - c.Caches["module"] = &Cache{Name: "服务数据", Value: strings.Join(item, "."), Help: "服务数据"} - - m.Index = 1 - c.Pulse = m - c.Requests = []*Message{m} - c.Historys = []*Message{m} - c.Sessions = map[string]*Message{} - - c.master = m.master.master - c.Owner = m.master.Owner - - m.Log("begin", nil, "%d context %v %v", m.root.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"]) - for k, x := range c.Configs { - if x.Hand != nil { - m.Conf(k, x.Value) - } - } - - if c.Server != nil { - c.Server.Begin(m, m.Meta["detail"]...) - } - - return c -} - -// }}} -func (c *Context) Start(m *Message) bool { // {{{ - m.Hand = true - - if m != c.Requests[0] { - c.Requests, m.Index = append(c.Requests, m), len(c.Requests)+1 - } - - if m.Cap("status") != "start" { - running := make(chan bool) - go m.AssertOne(m, true, func(m *Message) { - m.Log(m.Cap("status", "start"), nil, "%d server %v %v", m.root.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"]) - - if running <- true; c.Server != nil && c.Server.Start(m, m.Meta["detail"]...) { - c.Close(m, m.Meta["detail"]...) - } - }) - <-running - } - return true -} - -// }}} -func (c *Context) Close(m *Message, arg ...string) bool { // {{{ - m.Log("close", c, "%d:%d %v", len(m.source.Sessions), len(m.target.Historys), arg) - - if m.target == c { - if m.Index == 0 { - for i := len(c.Requests) - 1; i >= 0; i-- { - v := c.Requests[i] - if v.Index = -1; v.source != c && !v.source.Close(v, arg...) { - v.Index = i - return false - } - c.Requests = c.Requests[:i] - } - } else if m.Index > 0 { - for i := m.Index - 1; i < len(c.Requests)-1; i++ { - c.Requests[i] = c.Requests[i+1] - } - c.Requests = c.Requests[:len(c.Requests)-1] - } - } - - if c.Server != nil && !c.Server.Close(m, arg...) { - return false - } - - if m.source == c && m.target != c { - if _, ok := c.Sessions[m.Name]; ok { - delete(c.Sessions, m.Name) - } - return true - } - - if len(c.Requests) > 1 { - return false - } - - if m.Cap("status") == "start" { - m.Log(m.Cap("status", "close"), nil, "%d server %v", m.root.Capi("nserver", -1)+1, arg) - for _, v := range c.Sessions { - if v.target != c { - v.target.Close(v, arg...) - } - } - } - - // if m.Index == 0 && c.context != nil && len(c.contexts) == 0 { - if c.context != nil { - m.Log("close", nil, "%d context %v", m.root.Capi("ncontext", -1)+1, arg) - delete(c.context.contexts, c.Name) - c.context = nil - if c.Exit != nil { - m.Log("info", nil, "before exit<-") - c.Exit <- true - m.Log("info", nil, "after exit<-") - } - } - return true -} - // }}} func (c *Context) Context() *Context { // {{{ @@ -674,7 +677,7 @@ func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{ } // }}} -func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message)) *Message { // {{{ +func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message { // {{{ defer func() { if e := recover(); e != nil { @@ -691,7 +694,7 @@ func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message)) } if len(hand) > 1 { - m.AssertOne(msg, safe, hand[1:]...) + m.TryCatch(msg, safe, hand[1:]...) } else if !safe { msg.Assert(e) } @@ -1138,28 +1141,75 @@ func (m *Message) Copy(msg *Message, meta string, arg ...string) *Message { // { } // }}} -func (m *Message) Table(cb func(map[string]string) bool) *Message { // {{{ - if len(m.Meta["append"]) > 0 { - for i := 0; i < len(m.Meta[m.Meta["append"][0]]); i++ { - row := map[string]string{} - for _, k := range m.Meta["append"] { - if i < len(m.Meta[k]) { - row[k] = m.Meta[k][i] - } - } - if !cb(row) { - break +func (m *Message) Table(cb func(map[string]string, []string, int) bool) *Message { // {{{ + if len(m.Meta["append"]) == 0 { + return m + } + + width := make(map[string]int, len(m.Meta[m.Meta["append"][0]])) + for _, k := range m.Meta["append"] { + title := k + if m.Options("extras") && k == "extra" { + title = "extra." + m.Option("extras") + } + width[k] = len(title) + } + for i := 0; i < len(m.Meta[m.Meta["append"][0]]); i++ { + for _, k := range m.Meta["append"] { + data := m.Meta[k][i] + if len(data) > width[k] { + width[k] = len(data) } } } + + row := map[string]string{} + wor := []string{} + for _, k := range m.Meta["append"] { + title := k + if m.Options("extras") && k == "extra" { + title = "extra." + m.Option("extras") + } + row[k] = title + title += strings.Repeat(" ", width[k]-len(title)) + wor = append(wor, title) + } + if !cb(row, wor, -1) { + return m + } + + for i := 0; i < len(m.Meta[m.Meta["append"][0]]); i++ { + row := map[string]string{} + wor := []string{} + for _, k := range m.Meta["append"] { + data := m.Meta[k][i] + if m.Options("extras") && k == "extra" { + extra := map[string]interface{}{} + json.Unmarshal([]byte(data), &extra) + data = fmt.Sprintf("%v", extra[m.Option("extras")]) + } + + if i < len(m.Meta[k]) { + row[k] = data + data += strings.Repeat(" ", width[k]-len(data)) + wor = append(wor, data) + } + } + if !cb(row, wor, i) { + break + } + } + return m } // }}} -func (m *Message) Sort(key string, arg ...string) { +func (m *Message) Sort(key string, arg ...string) { // {{{ table := []map[string]string{} - m.Table(func(line map[string]string) bool { - table = append(table, line) + m.Table(func(line map[string]string, lists []string, index int) bool { + if index != -1 { + table = append(table, line) + } return true }) @@ -1215,6 +1265,8 @@ func (m *Message) Sort(key string, arg ...string) { } } +// }}} + func (m *Message) Insert(meta string, index int, arg ...interface{}) string { // {{{ if m.Meta == nil { m.Meta = make(map[string][]string) @@ -1351,6 +1403,15 @@ func (m *Message) Optionv(key string, arg ...interface{}) interface{} { // {{{ return nil } +// }}} +func (m *Message) Optionx(key string, format string) interface{} { // {{{ + value := m.Option(key) + if value != "" { + return fmt.Sprintf(format, value) + } + return "" +} + // }}} func (m *Message) Append(key string, arg ...interface{}) string { // {{{ m.Insert(key, 0, arg...) @@ -1427,7 +1488,7 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{ for s := c; s != nil; s = s.context { if x, ok := s.Commands[key]; ok && x.Hand != nil && c.Check(m, "commands", key) { - m.AssertOne(m, true, func(m *Message) { + m.TryCatch(m, true, func(m *Message) { m.Log("cmd", s, "%d %s %v %v", len(m.target.Historys), key, arg, m.Meta["option"]) if x.Options != nil { @@ -1441,9 +1502,9 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{ if m.Has("args") { m.Meta["args"] = nil } - if x.Formats != nil { + if x.Form != nil { for i := 0; i < len(arg); i++ { - n, ok := x.Formats[arg[i]] + n, ok := x.Form[arg[i]] if !ok { m.Add("option", "args", arg[i]) continue @@ -1496,7 +1557,7 @@ func (m *Message) Deal(pre func(msg *Message, arg ...string) bool, post func(msg } for run := true; run; { - m.AssertOne(<-m.target.messages, true, func(msg *Message) { + m.TryCatch(<-m.target.messages, true, func(msg *Message) { defer func() { if msg.Wait != nil { msg.Wait <- true @@ -1563,6 +1624,49 @@ func (m *Message) Cmd(arg ...interface{}) *Message { // {{{ // }}} +func (m *Message) Confx(key string, arg ...interface{}) string { // {{{ + if len(arg) == 0 { + return m.Conf(key) + } + + skip := false + if len(arg) > 1 { + if v, ok := arg[1].(bool); ok && !v { + skip = true + } + } + + if len(arg) > 0 { + switch v := arg[0].(type) { + case string: + if skip || v == "" { + return m.Conf(key) + } + return v + case []string: + which := 0 + if len(arg) > 1 { + if x, ok := arg[1].(int); ok { + which = x + } + } + if which < len(v) { + return v[which] + } + return m.Conf(key) + default: + x := fmt.Sprintf("%v", v) + if skip || v == nil || x == "" { + return m.Conf(key) + } + return x + } + } + + return "" +} + +// }}} func (m *Message) Confs(key string, arg ...bool) bool { // {{{ if len(arg) > 0 { if arg[0] { @@ -1637,6 +1741,49 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{ return "" } +// }}} +func (m *Message) Capx(key string, arg ...interface{}) string { // {{{ + if len(arg) == 0 { + return m.Cap(key) + } + + skip := false + if len(arg) > 1 { + if v, ok := arg[1].(bool); ok && !v { + skip = true + } + } + + if len(arg) > 0 { + switch v := arg[0].(type) { + case string: + if skip || v == "" { + return m.Cap(key) + } + return v + case []string: + which := 0 + if len(arg) > 1 { + if x, ok := arg[1].(int); ok { + which = x + } + } + if which < len(v) { + return v[which] + } + return m.Cap(key) + default: + x := fmt.Sprintf("%v", v) + if skip || v == nil || x == "" { + return m.Cap(key) + } + return x + } + } + + return "" +} + // }}} func (m *Message) Caps(key string, arg ...bool) bool { // {{{ if len(arg) > 0 { @@ -2282,8 +2429,10 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } // }}} }}, - "context": &Command{Name: "context back|[[home] [find|search] name] [info|lists|show|switch|[args]", Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块,args:启动参数", - Formats: map[string]int{ + "context": &Command{ + Name: "context back|[[home] [find|search] name] [info|lists|show|switch|[args]", + Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块,args:启动参数", + Form: map[string]int{ "back": 0, "home": 0, "find": 1, "search": 1, "info": 1, "lists": 0, "show": 0, "switch": 0, @@ -2456,43 +2605,47 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } // }}} }}, - "server": &Command{Name: "server [spawn|begin|start|close|][args]", Help: "服务启动停止切换", Hand: func(m *Message, c *Context, key string, arg ...string) { - switch len(arg) { // {{{ - case 0: - m.Travel(m.target.root, func(msg *Message) bool { - if msg.Cap("status") == "start" { - msg.Echo("%s(%s): %s\n", msg.target.Name, msg.Cap("stream"), msg.target.Help) - } - return true - }) + "server": &Command{ + Name: "server [spawn|begin|start|close|][args]", + Help: "服务启动停止切换", + Hand: func(m *Message, c *Context, key string, arg ...string) { + switch len(arg) { // {{{ + case 0: + m.Travel(m.target.root, func(msg *Message) bool { + if msg.Cap("status") == "start" { + msg.Echo("%s(%s): %s\n", msg.target.Name, msg.Cap("stream"), msg.target.Help) + } + return true + }) - default: - switch arg[0] { - case "spawn": - if len(arg) > 1 { + default: + switch arg[0] { + case "spawn": + if len(arg) > 1 { + msg := m.Spawn(m.Target()) + msg.Detail(0, arg[2:]) + msg.Target().Spawn(msg, arg[0], arg[1]) + } + + case "begin": msg := m.Spawn(m.Target()) - msg.Detail(0, arg[2:]) - msg.Target().Spawn(msg, arg[0], arg[1]) + msg.Detail(0, arg) + msg.Target().Begin(msg) + case "start": + msg := m.Spawn(m.Target()) + msg.Detail(0, arg) + msg.Target().Start(msg) + case "close": + msg := m.Spawn(m.Target()) + msg.Detail(0, arg) + msg.Target().Close(msg) } - - case "begin": - msg := m.Spawn(m.Target()) - msg.Detail(0, arg) - msg.Target().Begin(msg) - case "start": - msg := m.Spawn(m.Target()) - msg.Detail(0, arg) - msg.Target().Start(msg) - case "close": - msg := m.Spawn(m.Target()) - msg.Detail(0, arg) - msg.Target().Close(msg) } - } - // }}} - }}, - "command": &Command{Name: "command [all] add [key [name help]]", Help: "查看或修改命令", - Formats: map[string]int{"all": 0, "delete": 0, "void": 0, "condition": -1}, + // }}} + }}, + "command": &Command{ + Name: "command [all] add [key [name help]]", Help: "查看或修改命令", + Form: map[string]int{"all": 0, "delete": 0, "void": 0, "condition": -1}, Hand: func(m *Message, c *Context, key string, arg ...string) { all := m.Has("all") // {{{ if len(arg) == 0 { @@ -2681,8 +2834,10 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } // }}} }}, - "config": &Command{Name: "config [all] [[delete|void] key [value]|[name value help]]", Help: "删除、置空、查看、修改或添加配置", - Formats: map[string]int{"all": 0, "delete": 0, "void": 0}, + "config": &Command{ + Name: "config [all] [[delete|void] key [value]|[name value help]]", + Help: "删除、置空、查看、修改或添加配置", + Form: map[string]int{"all": 0, "delete": 0, "void": 0}, Hand: func(m *Message, c *Context, key string, arg ...string) { all := m.Has("all") // {{{ @@ -2741,8 +2896,10 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } // }}} }}, - "cache": &Command{Name: "cache [all] [[delete|void] key [value]|[name value help]]", Help: "删除、置空、查看、修改或添加缓存", - Formats: map[string]int{"all": 0, "delete": 0, "void": 0}, + "cache": &Command{ + Name: "cache [all] [[delete|void] key [value]|[name value help]]", + Help: "删除、置空、查看、修改或添加缓存", + Form: map[string]int{"all": 0, "delete": 0, "void": 0}, Hand: func(m *Message, c *Context, key string, arg ...string) { all := m.Has("all") // {{{ @@ -2795,9 +2952,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", // }}} }}, "right": &Command{ - Name: "right [share|add|del group [cache|config|command item]]", - Help: "用户组管理,查看、添加、删除用户组或是接口", - Formats: map[string]int{"check": 0, "add": 0, "del": 0, "brow": 0, "cache": 0, "config": 0, "command": 0}, + Name: "right [share|add|del group [cache|config|command item]]", + Help: "用户组管理,查看、添加、删除用户组或是接口", + Form: map[string]int{"check": 0, "add": 0, "del": 0, "brow": 0, "cache": 0, "config": 0, "command": 0}, Hand: func(m *Message, c *Context, key string, arg ...string) { index := m.Target().Index // {{{ if index == nil { @@ -3031,13 +3188,6 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } // }}} }}, - "sort": &Command{Name: "sort", Help: "服务启动停止切换", Hand: func(m *Message, c *Context, key string, arg ...string) { - m.Append("name", "shy", "yun") - m.Append("page", "10", "20") - m.Log("fuck", nil, "before %v", m.Meta) - m.Sort(arg[0], arg[1:]...) - m.Log("fuck", nil, "after %v", m.Meta) - }}, }, Index: map[string]*Context{ "void": &Context{Name: "void", diff --git a/src/contexts/mdb/mdb.go b/src/contexts/mdb/mdb.go index 2e85af50..8506cb70 100644 --- a/src/contexts/mdb/mdb.go +++ b/src/contexts/mdb/mdb.go @@ -2,14 +2,14 @@ package mdb // {{{ // }}} import ( // {{{ "contexts" - "encoding/json" - "strconv" - "strings" - "database/sql" + "encoding/json" _ "github.com/go-sql-driver/mysql" "fmt" + "os" + "strconv" + "strings" ) // }}} @@ -17,9 +17,6 @@ import ( // {{{ type MDB struct { *sql.DB - list map[string][]string - list_key []string - table []string *ctx.Context } @@ -73,7 +70,7 @@ func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { // {{{ switch mdb.Context { case m.Target(): if mdb.DB != nil { - m.Log("info", nil, "%d close %s %s", Pulse.Capi("nsource", -1)+1, m.Cap("driver"), m.Cap("source")) + m.Log("info", nil, "close") mdb.DB.Close() mdb.DB = nil } @@ -87,264 +84,200 @@ func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { // {{{ var Pulse *ctx.Message var Index = &ctx.Context{Name: "mdb", Help: "数据中心", Caches: map[string]*ctx.Cache{ - "count": &ctx.Cache{Name: "count", Value: "0", Help: "主机协议"}, "nsource": &ctx.Cache{Name: "数据源数量", Value: "0", Help: "已打开数据库的数量"}, + "dbname": &ctx.Cache{Name: "生成模块名", Value: "", Help: "生成模块名", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string { + return fmt.Sprintf("db%d", Pulse.Capi("nsource", 1)) + }}, }, Configs: map[string]*ctx.Config{ - "driver": &ctx.Config{Name: "数据库驱动(mysql)", Value: "mysql", Help: "数据库驱动"}, + "driver": &ctx.Config{Name: "数据库驱动(mysql)", Value: "mysql", Help: "数据库驱动"}, + "csv_sep": &ctx.Config{Name: "字段分隔符", Value: "\t", Help: "字段分隔符"}, }, Commands: map[string]*ctx.Command{ - "open": &ctx.Command{Name: "open source [name]", Help: "打开数据库", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "open": &ctx.Command{Name: "open source [name]", Help: "打开数据库, source: 数据源, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Assert(len(arg) > 0, "缺少参数") // {{{ - name := fmt.Sprintf("db%d", Pulse.Capi("nsource", 1)) - if len(arg) > 1 { - name = arg[1] - } - m.Start(name, "数据存储", arg...) - Pulse.Cap("stream", Pulse.Cap("nsource")) + m.Start(m.Capx("dbname", arg, 1), "数据存储", arg...) m.Echo(m.Target().Name) // }}} }}, - "exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库", + "exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库, sql: SQL语句, arg: 查询参数", Appends: map[string]string{"last": "最后插入元组的标识", "nrow": "修改元组的数量"}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - mdb, ok := m.Target().Server.(*MDB) // {{{ - m.Assert(ok, "目标模块类型错误") - m.Assert(len(arg) > 0, "缺少参数") - m.Assert(mdb.DB != nil, "数据库未打开") + if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) { // {{{ + which := make([]interface{}, 0, len(arg)) + for _, v := range arg[1:] { + which = append(which, v) + } + ret, e := mdb.Exec(arg[0], which...) + m.Assert(e) + id, e := ret.LastInsertId() + m.Assert(e) + n, e := ret.RowsAffected() + m.Assert(e) + + m.Log("info", nil, "last(%s) nrow(%s)", m.Append("last", id), m.Append("nrow", n)) + m.Echo("%d", id).Echo("%d", n) + } + // }}} + }}, + "query": &ctx.Command{Name: "query sql [arg]", Help: "查询数据库, sql: SQL语句, arg: 查询参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) { // {{{ which := make([]interface{}, 0, len(arg)) for _, v := range arg[1:] { which = append(which, v) } - ret, e := mdb.Exec(arg[0], which...) + rows, e := mdb.Query(arg[0], which...) m.Assert(e) - id, e := ret.LastInsertId() - m.Assert(e) - n, e := ret.RowsAffected() + defer rows.Close() + + cols, e := rows.Columns() m.Assert(e) + num := len(cols) - m.Echo("%d", id).Echo("%d", n) - m.Add("append", "last", fmt.Sprintf("%d", id)) - m.Add("append", "nrow", fmt.Sprintf("%d", n)) - m.Log("info", nil, "last(%d) nrow(%d)", id, n) - // }}} - }}, - "query": &ctx.Command{Name: "query sql [arg]", Help: "执行查询语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - mdb, ok := m.Target().Server.(*MDB) // {{{ - m.Assert(ok, "目标模块类型错误") - m.Assert(len(arg) > 0, "缺少参数") - m.Assert(mdb.DB != nil, "数据库未打开") + for rows.Next() { + vals := make([]interface{}, num) + ptrs := make([]interface{}, num) + for i := range vals { + ptrs[i] = &vals[i] + } + rows.Scan(ptrs...) - which := make([]interface{}, 0, len(arg)) - for _, v := range arg[1:] { - which = append(which, v) - } - - rows, e := mdb.Query(arg[0], which...) - m.Assert(e) - defer rows.Close() - - cols, e := rows.Columns() - m.Assert(e) - num := len(cols) - - for rows.Next() { - vals := make([]interface{}, num) - ptrs := make([]interface{}, num) - for i := range vals { - ptrs[i] = &vals[i] - } - rows.Scan(ptrs...) - - for i, k := range cols { - switch b := vals[i].(type) { - case []byte: - m.Add("append", k, string(b)) - case int64: - m.Add("append", k, fmt.Sprintf("%d", b)) - default: - m.Add("append", k, "") + for i, k := range cols { + switch b := vals[i].(type) { + case []byte: + m.Add("append", k, string(b)) + case int64: + m.Add("append", k, fmt.Sprintf("%d", b)) + default: + m.Add("append", k, fmt.Sprintf("%v", b)) + } } } - } - if len(m.Meta["append"]) > 0 { - m.Log("info", nil, "rows(%d) cols(%d)", len(m.Meta[m.Meta["append"][0]]), len(m.Meta["append"])) - } else { - m.Log("info", nil, "rows(0) cols(0)") + if len(m.Meta["append"]) > 0 { + m.Log("info", nil, "rows(%d) cols(%d)", len(m.Meta[m.Meta["append"][0]]), len(m.Meta["append"])) + } else { + m.Log("info", nil, "rows(0) cols(0)") + } } // }}} }}, - "table": &ctx.Command{Name: "table", Help: "执行查询语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - mdb, ok := m.Target().Server.(*MDB) // {{{ - m.Assert(ok) - msg := m.Spawn(m.Target()) - if len(arg) > 0 { + "table": &ctx.Command{Name: "table [which [field]]", Help: "查看关系表信息,which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) { // {{{ + msg := m.Spawn() + if len(arg) == 0 { + msg.Cmd("query", "show tables") + mdb.table = []string{} + for i, v := range msg.Meta[msg.Meta["append"][0]] { + mdb.table = append(mdb.table, v) + m.Echo("%d: %s\n", i, v) + } + return + } + table := arg[0] index, e := strconv.Atoi(arg[0]) if e == nil && index < len(mdb.table) { table = mdb.table[index] } - msg.Cmd("query", fmt.Sprintf("desc %s", table)) - if len(arg) > 1 { - for i, v := range msg.Meta[msg.Meta["append"][0]] { - if v == arg[1] { - for _, k := range msg.Meta["append"] { - m.Echo("%s: %s\n", k, msg.Meta[k][i]) - } - } - } - } else { + msg.Cmd("query", fmt.Sprintf("desc %s", table)) + if len(arg) == 1 { for _, v := range msg.Meta[msg.Meta["append"][0]] { m.Echo("%s\n", v) } + return } - } else { - msg.Cmd("query", "show tables") - mdb.table = []string{} + for i, v := range msg.Meta[msg.Meta["append"][0]] { - mdb.table = append(mdb.table, v) - m.Echo("%d: %s\n", i, v) + if v == arg[1] { + for _, k := range msg.Meta["append"] { + m.Echo("%s: %s\n", k, msg.Meta[k][i]) + } + } } } // }}} }}, - "get": &ctx.Command{Name: "get [where str] [parse str] [table [field]]", Help: "执行查询语句", - Formats: map[string]int{"where": 1, "parse": 1}, + "show": &ctx.Command{ + Name: "show table fields... [where conditions]|[group fields]|[order fields]|[save filename]", + Help: "查询数据库, table: 表名, fields: 字段, where: 查询条件, group: 聚合字段, order: 排序字段", + Form: map[string]int{"where": 1, "group": 1, "order": 1, "extras": 1, "save": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - where := m.Conf("where") // {{{ - if m.Options("where") { - where = m.Option("where") + if m.Options("extras") { // {{{ + arg = append(arg, "extra") + } + fields := strings.Join(arg[1:], ",") + + where := m.Optionx("where", "where %s") + group := m.Optionx("group", "group by %s") + order := m.Optionx("order", "order by %s") + + msg := m.Spawn().Cmd("query", fmt.Sprintf("select %s from %s %s %s %s", fields, arg[0], where, group, order)) + if !m.Options("save") { + m.Echo("\033[31m%s\033[0m %s %s %s\n", arg[0], where, group, order) + } + msg.Table(func(maps map[string]string, lists []string, index int) bool { + for i, v := range lists { + if m.Options("save") { + m.Echo(maps[msg.Meta["append"][i]]).Echo(m.Conf("csv_sep")) + } else if index == -1 { + m.Echo("\033[32m%s\033[0m", v).Echo(m.Conf("csv_sep")) + } else { + m.Echo(v).Echo(m.Conf("csv_sep")) + } + } + m.Echo("\n") + return true + }) + + if m.Options("save") { + f, e := os.Create(m.Option("save")) + m.Assert(e) + defer f.Close() + + for _, v := range m.Meta["result"] { + f.WriteString(v) + } + } + // }}} + }}, + "get": &ctx.Command{Name: "get [where str] [parse str] [table [field]]", Help: "执行查询语句", + Form: map[string]int{"where": 1, "parse": 2}, + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + where := m.Confx("where", m.Option("where")) // {{{ + if where != "" { + where = "where " + where } - parse := m.Conf("parse") - if m.Options("parse") { - parse = m.Option("parse") - } + parse := m.Confx("parse", m.Option("parse")) + extra := m.Confx("extra", m.Meta["parse"], 1) + table := m.Confx("table", arg, 0) + field := m.Confx("field", arg, 1) - table := m.Conf("table") - if len(arg) > 0 { - table = arg[0] - } - - field := m.Conf("field") - if len(arg) > 1 { - field = arg[1] - } - - rest := []string{} - if len(arg) > 2 { - rest = arg[2:] - } - - msg := m.Spawn(m.Target()) - msg.Cmd("query", fmt.Sprintf("select %s from %s where %s", field, table, where), rest) - m.Copy(msg, "result").Copy(msg, "append") - m.Table(func(row map[string]string) bool { + msg := m.Spawn().Cmd("query", fmt.Sprintf("select %s from %s %s", field, table, where)) + msg.Table(func(row map[string]string, lists []string, index int) bool { + if index == -1 { + return true + } data := map[string]interface{}{} switch parse { case "json": - json.Unmarshal([]byte(row[field]), data) - m.Echo("%v", data) + if json.Unmarshal([]byte(row[field]), &data); extra == "" { + for k, v := range data { + m.Echo("%s: %v\n", k, v) + } + } else if v, ok := data[extra]; ok { + m.Echo("%v", v) + } default: m.Echo("%v", row[field]) } return false }) // }}} }}, - "show": &ctx.Command{Name: "show table field [where conditions]|[group fields]|[order fields]", Help: "执行查询语句", - Formats: map[string]int{"where": 1, "group": 1, "order": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - msg := m.Spawn(m.Target()) // {{{ - - fields := strings.Join(arg[1:], ",") - condition := "" - if m.Options("where") { - condition = fmt.Sprintf("where %s", m.Option("where")) - } - group := "" - if m.Options("group") { - group = fmt.Sprintf("group by %s", m.Option("group")) - } - order := "" - if m.Options("order") { - order = fmt.Sprintf("order by %s", m.Option("order")) - } - - msg.Cmd("query", fmt.Sprintf("select %s from %s %s %s %s", fields, arg[0], condition, group, order)) - m.Echo("\033[31m%s\033[0m %s %s %s\n", arg[0], condition, group, order) - for _, k := range msg.Meta["append"] { - m.Echo("\033[32m%s\033[0m\t", k) - } - m.Echo("\n") - for i := 0; i < len(msg.Meta[msg.Meta["append"][0]]); i++ { - for _, k := range msg.Meta["append"] { - m.Echo("%s\t", msg.Meta[k][i]) - } - m.Echo("\n") - } - // }}} - }}, - "list": &ctx.Command{Name: "list add table field [where condition]", Help: "执行查询语句", - Formats: map[string]int{"where": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - mdb, ok := m.Target().Server.(*MDB) // {{{ - m.Assert(ok) - if len(arg) == 0 { - for _, k := range mdb.list_key { - m.Echo("%s: %v\n", k, mdb.list[k]) - } - return - } - - switch arg[0] { - case "add": - if mdb.list == nil { - mdb.list = make(map[string][]string) - } - mdb.list[m.Cap("count")] = append(mdb.list[m.Cap("count")], m.Option("where")) - mdb.list[m.Cap("count")] = append(mdb.list[m.Cap("count")], arg[1:]...) - mdb.list_key = append(mdb.list_key, m.Cap("count")) - m.Capi("count", 1) - case "set": - mdb.list[arg[1]] = []string{m.Option("where")} - mdb.list[arg[1]] = append(mdb.list[arg[1]], arg[2:]...) - default: - if table, ok := mdb.list[arg[0]]; ok { - msg := m.Spawn(m.Target()) - - fields := strings.Join(table[2:], ",") - condition := "" - if len(arg) > 1 && len(arg[1]) > 0 { - condition = fmt.Sprintf("where %s", arg[1]) - } else if len(table[0]) > 0 { - condition = fmt.Sprintf("where %s", table[0]) - } - - other := "" - if len(arg) > 2 { - other = strings.Join(arg[2:], " ") - } - - msg.Cmd("query", fmt.Sprintf("select %s from %s %s %s", fields, table[1], condition, other)) - m.Echo("%s %s\n", table[1], condition) - for _, k := range msg.Meta["append"] { - m.Echo("%s\t", k) - } - m.Echo("\n") - for i := 0; i < len(msg.Meta[msg.Meta["append"][0]]); i++ { - for _, k := range msg.Meta["append"] { - m.Echo("%s\t", msg.Meta[k][i]) - } - m.Echo("\n") - } - } - } - // }}} - }}, }, Index: map[string]*ctx.Context{ "void": &ctx.Context{Name: "void", diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index 8aab2f9e..292a5899 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -140,7 +140,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", // }}} }}, "send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行", - Formats: map[string]int{"domain": 1}, + Form: map[string]int{"domain": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{ diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index d3abcaa8..56511868 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -396,7 +396,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", // }}} }}, "get": &ctx.Command{Name: "get [method GET|POST] [file filename] url arg...", Help: "访问URL", - Formats: map[string]int{"method": 1, "file": 2}, + Form: map[string]int{"method": 1, "file": 2}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { web, ok := m.Target().Server.(*WEB) // {{{ m.Assert(ok)