diff --git a/base.go b/base.go index 84517cd4..fa743ef5 100644 --- a/base.go +++ b/base.go @@ -156,10 +156,13 @@ func Run(arg ...string) string { os.Exit(frame.code) return "" } -func ListLook(name string) []interface{} { - return kit.List( - kit.MDB_INPUT, "text", "name", name, "action", "auto", +func ListLook(name ...string) []interface{} { + list := []interface{}{} + for _, k := range name { + list = append(list, kit.MDB_INPUT, "text", "name", k, "action", "auto") + } + return kit.List(append(list, kit.MDB_INPUT, "button", "name", "查看", "action", "auto", kit.MDB_INPUT, "button", "name", "返回", "cb", "Last", - ) + )...) } diff --git a/base/cli/cli.go b/base/cli/cli.go index 65a267fd..fb3a545b 100644 --- a/base/cli/cli.go +++ b/base/cli/cli.go @@ -138,17 +138,13 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块", prefix := []string{ice.CLI_SYSTEM, m.Conf("python", "meta.python")} switch arg[0] { case "qrcode": - m.Cmdy(prefix, "-c", fmt.Sprintf(`import pyqrcode; print(pyqrcode.create("%s").terminal(quiet_zone=1))`, arg[1])) + m.Cmdy(prefix, "-c", fmt.Sprintf(`import pyqrcode; print(pyqrcode.create('%s').terminal(module_color='%s', quiet_zone=1))`, kit.Select("hello world", arg, 1), kit.Select("blue", arg, 2))) case "install": m.Cmdy(prefix[:1], m.Conf("python", "meta.pip"), "install", arg[1:]) default: m.Cmdy(prefix, arg) } }}, - - "qrcode": {Name: "qrcode text", Help: "二", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Render(ice.RENDER_QRCODE, kit.Select("hello world", arg, 0)) - }}, }, } diff --git a/base/ssh/ssh.go b/base/ssh/ssh.go index 53acb6b2..9f6ef8f8 100644 --- a/base/ssh/ssh.go +++ b/base/ssh/ssh.go @@ -36,8 +36,13 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) { fmt.Fprintf(msg.O, msg.Result()) case ice.RENDER_QRCODE: - msg.Cmdy("cli.python", "qrcode", kit.Format(args[0], args[1:]...)) - fallthrough + if len(args) > 0 { + fmt.Println(msg.Cmdx("cli.python", "qrcode", kit.Format(args[0], args[1:]...))) + } else { + fmt.Println(msg.Cmdx("cli.python", "qrcode", kit.Format(kit.Dict( + kit.MDB_TYPE, "cmd", kit.MDB_NAME, msg.Option("_cmd"), kit.MDB_TEXT, strings.TrimSpace(msg.Result()), + )))) + } default: // 转换结果 res := msg.Result() @@ -146,6 +151,12 @@ func (f *Frame) parse(m *ice.Message, line string) *Frame { } } + if ln[0] == "qrcode" { + msg.Option(ice.MSG_OUTPUT, ice.RENDER_QRCODE) + ln = ln[1:] + } + msg.Option("_cmd", one) + // 执行命令 msg.Cmdy(ln[0], ln[1:]) @@ -294,6 +305,7 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块", m.Done() } }}, + "history": {Name: "history", Help: "历史", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { m.Grows("history", nil, "", "", func(index int, value map[string]interface{}) { @@ -307,6 +319,11 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块", f.parse(m, kit.Format(value["line"])) }) }}, + "return": {Name: "return", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")) + f := m.Target().Server().(*Frame) + f.exit = true + }}, "source": {Name: "source file", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { buf := bytes.NewBuffer(make([]byte, 0, 4096)) m.Optionv(ice.MSG_STDOUT, buf) @@ -314,18 +331,6 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块", m.Starts(strings.Replace(arg[0], ".", "_", -1), arg[0], arg[0:]...) m.Echo(buf.String()) }}, - "print": {Name: "print", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - f := m.Target().Server().(*Frame) - f.printf(m, arg[0]) - f.printf(m, arg[0]) - f.printf(m, arg[0]) - f.printf(m, arg[0]) - }}, - "prompt": {Name: "print", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")) - f := m.Target().Server().(*Frame) - f.prompt(m) - }}, "show": {Name: "show", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { f, e := os.Open("usr/local/what/hi.shy") m.Assert(e) @@ -337,11 +342,6 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块", m.Info("%v", ls) } }}, - "return": {Name: "return", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")) - f := m.Target().Server().(*Frame) - f.exit = true - }}, "super": {Name: "super user remote port local", Help: "上位机", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { key := m.Rich("super", nil, kit.Dict( diff --git a/base/web/web.go b/base/web/web.go index 1be3b926..9ad655d2 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -113,7 +113,7 @@ func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request msg.Option(ice.MSG_USERROLE, msg.Cmdx(ice.AAA_ROLE, "check", msg.Option(ice.MSG_USERNAME))) if strings.HasPrefix(msg.Option(ice.MSG_USERUA), "Mozilla/5.0") { msg.Option(ice.MSG_SESSID, msg.Cmdx(ice.AAA_SESS, "create", msg.Option(ice.MSG_USERNAME), msg.Option(ice.MSG_USERROLE))) - Render(msg, "cookie", msg.Option(ice.MSG_SESSID)) + msg.Render("cookie", msg.Option(ice.MSG_SESSID)) } msg.Log(ice.LOG_LOGIN, "user: %s role: %s sess: %s", msg.Option(ice.MSG_USERNAME), msg.Option(ice.MSG_USERROLE), msg.Option(ice.MSG_SESSID)) } @@ -129,11 +129,11 @@ func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request } else if strings.HasPrefix(msg.Option(ice.MSG_USERURL), "/share/") { } else { if msg.Warn(!msg.Options(ice.MSG_USERNAME), "not login %s", msg.Option(ice.MSG_USERURL)) { - Render(msg, "status", 401, "not login") + msg.Render("status", 401, "not login") return false } if !msg.Right(msg.Option(ice.MSG_USERURL)) { - Render(msg, "status", 403, "not auth") + msg.Render("status", 403, "not auth") return false } } @@ -287,7 +287,7 @@ func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) { // 请求参数 for k, v := range r.Form { if msg.Optionv(k, v); k == ice.MSG_SESSID { - Render(msg, "cookie", v[0]) + msg.Render("cookie", v[0]) } } @@ -299,7 +299,7 @@ func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) { // 登录检查 if !web.Login(msg, w, r) { - // Render(msg, "status", 401, "not login") + // msg.Render("status", 401, "not login") return } @@ -349,7 +349,7 @@ func (web *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) { m.Conf(ice.WEB_SERVE, "meta.init", "true") } m.W = w - Render(m, "refresh") + m.Render("refresh") m.Event(ice.SYSTEM_INIT) m.W = nil } else { @@ -442,7 +442,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", "logheaders", "false", "init", "false", )}, - ice.WEB_SPACE: {Name: "space", Help: "空间站", Value: kit.Data(kit.MDB_SHORT, "name", + ice.WEB_SPACE: {Name: "space", Help: "空间站", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME, "redial.a", 3000, "redial.b", 1000, "redial.c", 1000, "buffer.r", 4096, "buffer.w", 4096, "timeout.c", "30s", @@ -465,10 +465,10 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", )}, ice.WEB_SHARE: {Name: "share", Help: "共享链", Value: kit.Data("index", "usr/volcanos/share.html", "template", share_template)}, - ice.WEB_ROUTE: {Name: "route", Help: "路由", Value: kit.Data()}, + ice.WEB_ROUTE: {Name: "route", Help: "路由", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME)}, ice.WEB_PROXY: {Name: "proxy", Help: "代理", Value: kit.Data()}, - ice.WEB_GROUP: {Name: "group", Help: "分组", Value: kit.Data()}, - ice.WEB_LABEL: {Name: "label", Help: "标签", Value: kit.Data()}, + ice.WEB_GROUP: {Name: "group", Help: "分组", Value: kit.Data(kit.MDB_SHORT, "group")}, + ice.WEB_LABEL: {Name: "label", Help: "标签", Value: kit.Data(kit.MDB_SHORT, "label")}, }, Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -494,7 +494,9 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Save(ice.WEB_SPIDE, ice.WEB_SERVE, - ice.WEB_FAVOR, ice.WEB_CACHE, ice.WEB_STORY, ice.WEB_SHARE) + ice.WEB_GROUP, ice.WEB_LABEL, + ice.WEB_FAVOR, ice.WEB_CACHE, ice.WEB_STORY, ice.WEB_SHARE, + ) m.Done() m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) { @@ -534,16 +536,22 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", // 添加爬虫 if uri, e := url.Parse(arg[2]); e == nil && arg[2] != "" { dir, file := path.Split(uri.EscapedPath()) - m.Rich(ice.WEB_SPIDE, nil, kit.Dict( - "cookie", kit.Dict(), "header", kit.Dict(), "client", kit.Dict( - "share", m.Cmdx(ice.WEB_SHARE, "add", ice.TYPE_SPIDE, arg[1], arg[2]), - "type", "POST", "name", arg[1], "text", arg[2], - "name", arg[1], "url", arg[2], "method", "POST", - "protocol", uri.Scheme, "hostname", uri.Host, - "path", dir, "file", file, "query", uri.RawQuery, - "timeout", "100s", "logheaders", false, - ), - )) + if m.Richs(ice.WEB_SPIDE, nil, arg[1], func(key string, value map[string]interface{}) { + value["name"] = arg[1] + value["text"] = arg[2] + value["url"] = arg[2] + }) != nil { + m.Rich(ice.WEB_SPIDE, nil, kit.Dict( + "cookie", kit.Dict(), "header", kit.Dict(), "client", kit.Dict( + "share", m.Cmdx(ice.WEB_SHARE, "add", ice.TYPE_SPIDE, arg[1], arg[2]), + "type", "POST", "name", arg[1], "text", arg[2], + "name", arg[1], "url", arg[2], "method", "POST", + "protocol", uri.Scheme, "hostname", uri.Host, + "path", dir, "file", file, "query", uri.RawQuery, + "timeout", "100s", "logheaders", false, + ), + )) + } m.Log(ice.LOG_CREATE, "%s: %v", arg[1], arg[2:]) } return @@ -724,7 +732,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", }}, ice.WEB_SERVE: {Name: "serve [shy|dev|self]", Help: "服务器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { // 节点信息 - m.Conf(ice.CLI_RUNTIME, "node.name", m.Conf(ice.CLI_RUNTIME, "boot.hostname")) + // m.Conf(ice.CLI_RUNTIME, "node.name", m.Conf(ice.CLI_RUNTIME, "boot.hostname")) m.Conf(ice.CLI_RUNTIME, "node.type", ice.WEB_SERVER) switch kit.Select("def", arg, 0) { @@ -762,16 +770,6 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", web := m.Target().Server().(*Frame) switch arg[0] { - // case "auth": - // m.Richs(ice.WEB_SPACE, nil, arg[1], func(key string, value map[string]interface{}) { - // sessid := kit.Format(kit.Value(value, "sessid")) - // if value["user"] = arg[2]; sessid == "" || m.Cmdx(ice.AAA_SESS, "check", sessid) != arg[1] { - // sessid = m.Cmdx(ice.AAA_SESS, "create", arg[2:]) - // value["sessid"] = sessid - // } - // m.Cmd(ice.WEB_SPACE, arg[1], "sessid", sessid) - // }) - case "share": m.Richs(ice.WEB_SPIDE, nil, m.Option("_dev"), func(key string, value map[string]interface{}) { m.Log(ice.LOG_CREATE, "dev: %s share: %s", m.Option("_dev"), arg[1]) @@ -782,7 +780,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", // 基本信息 dev := kit.Select("dev", arg, 1) node := m.Conf(ice.CLI_RUNTIME, "node.type") - name := m.Conf(ice.CLI_RUNTIME, "node.name") + name := kit.Select(m.Conf(ice.CLI_RUNTIME, "node.name"), arg, 2) user := m.Conf(ice.CLI_RUNTIME, "boot.username") m.Hold(1).Gos(m, func(msg *ice.Message) { @@ -791,7 +789,8 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", host := kit.Format(kit.Value(value, "client.hostname")) for i := 0; i < kit.Int(msg.Conf(ice.WEB_SPACE, "meta.redial.c")); i++ { - if u, e := url.Parse(kit.MergeURL(proto+"://"+host+"/space/", "node", node, "name", name, "user", user, "share", value["share"])); msg.Assert(e) { + if u, e := url.Parse(kit.MergeURL(proto+"://"+host+"/space/", "node", node, "name", name, "user", user, + "proxy", kit.Select("master", arg, 3), "group", kit.Select("worker", arg, 4), "share", value["share"])); msg.Assert(e) { if s, e := net.Dial("tcp", host); !msg.Warn(e != nil, "%s", e) { if s, _, e := websocket.NewClient(s, u, nil, kit.Int(msg.Conf(ice.WEB_SPACE, "meta.buffer.r")), kit.Int(msg.Conf(ice.WEB_SPACE, "meta.buffer.w"))); !msg.Warn(e != nil, "%s", e) { msg = m.Spawn() @@ -1629,15 +1628,51 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", } }}, - ice.WEB_ROUTE: {Name: "route", Help: "路由", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Richs(ice.WEB_SPACE, nil, arg[0], func(key string, value map[string]interface{}) { + ice.WEB_ROUTE: {Name: "route", Help: "路由", Meta: kit.Dict( + "detail", []string{"分组"}, + ), List: ice.ListLook("name"), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) > 1 && arg[0] == "action" { + switch arg[1] { + case "group", "分组": + if m.Option("grp") != "" && m.Option("name") != "" { + m.Cmdy(ice.WEB_GROUP, m.Option("grp"), "add", m.Option("name")) + } + } + return + } + + m.Richs(ice.WEB_SPACE, nil, kit.Select("*", arg, 0), func(key string, value map[string]interface{}) { switch value[kit.MDB_TYPE] { case ice.WEB_MASTER: + return + case ice.WEB_BETTER: + return + } + if value[kit.MDB_NAME] == m.Conf(ice.CLI_RUNTIME, "node.name") { + // 避免循环 + return + } + + if len(arg) > 1 { + // 发送命令 + m.Cmdy(ice.WEB_SPACE, value[kit.MDB_NAME], arg[1:]) + return + } + + switch value[kit.MDB_TYPE] { case ice.WEB_SERVER: + // 远程查询 + m.Cmd(ice.WEB_SPACE, value[kit.MDB_NAME], ice.WEB_ROUTE).Table(func(index int, val map[string]string, head []string) { + m.Push(kit.MDB_TYPE, val[kit.MDB_TYPE]) + m.Push(kit.MDB_NAME, kit.Keys(value[kit.MDB_NAME], val[kit.MDB_NAME])) + }) + fallthrough case ice.WEB_WORKER: + // 本机查询 + m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE]) + m.Push(kit.MDB_NAME, value[kit.MDB_NAME]) } }) - m.Cmdy(ice.WEB_SPACE, arg[0], arg[1:]) }}, ice.WEB_PROXY: {Name: "proxy", Help: "代理", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Richs(ice.WEB_SPACE, nil, arg[0], func(key string, value map[string]interface{}) { @@ -1656,17 +1691,166 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", m.Cmdy(ice.WEB_ROUTE, arg[0], arg[1:]) }}, - ice.WEB_GROUP: {Name: "group", Help: "分组", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmdy(ice.WEB_PROXY, arg[0], arg[1:]) + ice.WEB_GROUP: {Name: "group", Help: "分组", Meta: kit.Dict( + "exports", []string{"grp", "group"}, + "detail", []string{"标签", "退还"}, + ), List: ice.ListLook("group", "name"), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) > 1 && arg[0] == "action" { + switch arg[1] { + case "label", "标签": + if m.Option("lab") != "" && m.Option("group") != "" { + m.Cmdy(ice.WEB_LABEL, m.Option("lab"), "add", m.Option("group"), m.Option("name")) + } + case "del", "退还": + if m.Option("group") != "" && m.Option("name") != "" { + m.Cmdy(ice.WEB_GROUP, m.Option("group"), "del", m.Option("name")) + } + } + return + } + + if len(arg) < 2 { + // 分组列表 + m.Richs(cmd, nil, kit.Select("*", arg, 0), func(key string, value map[string]interface{}) { + if len(arg) < 1 { + m.Push(key, value[kit.MDB_META]) + return + } + m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), "*", func(key string, value map[string]interface{}) { + m.Push(key, value) + }) + }) + m.Logs(ice.LOG_SELECT, cmd, m.Format(ice.MSG_APPEND)) + return + } + + if m.Richs(cmd, nil, arg[0], nil) == nil { + // 添加分组 + n := m.Rich(cmd, nil, kit.Data(kit.MDB_SHORT, kit.MDB_NAME, cmd, arg[0])) + m.Logs(ice.LOG_CREATE, cmd, n) + } + + m.Richs(cmd, nil, arg[0], func(key string, value map[string]interface{}) { + if m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), arg[1], func(key string, value map[string]interface{}) { + // 分组详情 + m.Push("detail", value) + }) != nil { + return + } + + switch arg[1] { + case "add": + if m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), arg[2], func(key string, value map[string]interface{}) { + if value[kit.MDB_STATUS] == "void" { + value[kit.MDB_STATUS] = "free" + } + m.Logs(ice.LOG_MODIFY, cmd, key, kit.MDB_NAME, arg[2], kit.MDB_STATUS, value[kit.MDB_STATUS]) + }) == nil { + m.Logs(ice.LOG_INSERT, cmd, key, kit.MDB_NAME, arg[2]) + m.Rich(cmd, kit.Keys(kit.MDB_HASH, key), kit.Dict(kit.MDB_NAME, arg[2], kit.MDB_STATUS, "free")) + } + m.Echo(arg[0]) + case "del": + m.Logs(ice.LOG_MODIFY, cmd, key, kit.MDB_NAME, arg[2], kit.MDB_STATUS, "void") + m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), arg[2], func(sub string, value map[string]interface{}) { + value[kit.MDB_STATUS] = "void" + }) + case "get": + m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), kit.Select("%", arg, 2), func(sub string, value map[string]interface{}) { + m.Logs(ice.LOG_MODIFY, cmd, key, kit.MDB_NAME, value[kit.MDB_NAME], kit.MDB_STATUS, "busy") + value[kit.MDB_STATUS] = "busy" + m.Echo("%s", value[kit.MDB_NAME]) + }) + case "put": + m.Logs(ice.LOG_MODIFY, cmd, key, kit.MDB_NAME, arg[2], kit.MDB_STATUS, "free") + m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), arg[2], func(sub string, value map[string]interface{}) { + value[kit.MDB_STATUS] = "free" + }) + default: + m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), "*", func(key string, value map[string]interface{}) { + // 执行命令 + m.Cmdy(ice.WEB_PROXY, value["name"], arg[1:]) + }) + } + }) }}, - ice.WEB_LABEL: {Name: "label", Help: "标签", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmdy(ice.WEB_GROUP, arg[0], arg[1:]) + ice.WEB_LABEL: {Name: "label", Help: "标签", Meta: kit.Dict( + "exports", []string{"lab", "label"}, + "detail", []string{"退还"}, + ), List: ice.ListLook("label", "name"), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) > 1 && arg[0] == "action" { + switch arg[1] { + case "del", "退还": + if m.Option("label") != "" && m.Option("name") != "" { + m.Cmdy(ice.WEB_LABEL, m.Option("label"), "del", m.Option("name")) + } + } + return + } + + if len(arg) < 2 { + // 分组列表 + m.Richs(cmd, nil, kit.Select("*", arg, 0), func(key string, value map[string]interface{}) { + if len(arg) < 1 { + m.Push(key, value[kit.MDB_META]) + return + } + m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), "*", func(key string, value map[string]interface{}) { + m.Push(key, value) + }) + }) + m.Logs(ice.LOG_SELECT, cmd, m.Format(ice.MSG_APPEND)) + return + } + + if m.Richs(cmd, nil, arg[0], nil) == nil { + // 添加分组 + n := m.Rich(cmd, nil, kit.Data(kit.MDB_SHORT, kit.MDB_NAME, cmd, arg[0])) + m.Logs(ice.LOG_CREATE, cmd, n) + } + + m.Richs(cmd, nil, arg[0], func(key string, value map[string]interface{}) { + if m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), arg[1], func(key string, value map[string]interface{}) { + // 分组详情 + m.Push("detail", value) + }) != nil { + return + } + + switch arg[1] { + case "add": + if pod := m.Cmdx(ice.WEB_GROUP, arg[2], "get", arg[3:]); pod != "" { + if m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), pod, func(key string, value map[string]interface{}) { + if value[kit.MDB_STATUS] == "void" { + value[kit.MDB_STATUS] = "free" + } + m.Logs(ice.LOG_MODIFY, cmd, key, kit.MDB_NAME, pod, kit.MDB_STATUS, value[kit.MDB_STATUS]) + }) == nil { + m.Logs(ice.LOG_INSERT, cmd, key, kit.MDB_NAME, pod) + m.Rich(cmd, kit.Keys(kit.MDB_HASH, key), kit.Dict(kit.MDB_NAME, pod, "group", arg[2], kit.MDB_STATUS, "free")) + } + } + m.Echo(arg[0]) + case "del": + m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), arg[2], func(sub string, value map[string]interface{}) { + m.Cmdx(ice.WEB_GROUP, value["group"], "put", arg[2]) + m.Logs(ice.LOG_MODIFY, cmd, key, kit.MDB_NAME, arg[2], kit.MDB_STATUS, "void") + value[kit.MDB_STATUS] = "void" + m.Echo(arg[2]) + }) + default: + m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), "*", func(key string, value map[string]interface{}) { + // 远程命令 + m.Cmdy(ice.WEB_PROXY, value["name"], arg[1:]) + }) + } + }) }}, "/share/": {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[0] { case "local": - Render(m, "download", m.Cmdx(arg[1], path.Join(arg[2:]...))) + m.Render(ice.RENDER_DOWNLOAD, m.Cmdx(arg[1], path.Join(arg[2:]...))) return } @@ -1688,38 +1872,38 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", switch kit.Select("", arg, 1) { case "download", "下载": if strings.HasPrefix(kit.Format(value["text"]), m.Conf(ice.WEB_CACHE, "meta.path")) { - Render(m, "download", value["text"], value["type"], value["name"]) + m.Render(ice.RENDER_DOWNLOAD, value["text"], value["type"], value["name"]) } else { - Render(m, "%s", value["text"]) + m.Render("%s", value["text"]) } return case "detail", "详情": - Render(m, kit.Formats(value)) + m.Render(kit.Formats(value)) return case "share", "共享码": - Render(m, "qrcode", kit.Format("%s/share/%s/", m.Conf(ice.WEB_SHARE, "meta.domain"), key)) + m.Render(ice.RENDER_QRCODE, kit.Format("%s/share/%s/", m.Conf(ice.WEB_SHARE, "meta.domain"), key)) return case "value", "数据值": - Render(m, "qrcode", kit.Format(value)) + m.Render(ice.RENDER_QRCODE, kit.Format(value)) return case "text": - Render(m, "qrcode", kit.Format(value["text"])) + m.Render(ice.RENDER_QRCODE, kit.Format(value["text"])) return } switch value["type"] { case ice.TYPE_RIVER: // 共享群组 - Render(m, "redirect", "/", "share", key, "river", kit.Format(value["text"])) + m.Render("redirect", "/", "share", key, "river", kit.Format(value["text"])) case ice.TYPE_STORM: // 共享应用 - Render(m, "redirect", "/", "share", key, "storm", kit.Format(value["text"]), "river", kit.Format(kit.Value(value, "extra.river"))) + m.Render("redirect", "/", "share", key, "storm", kit.Format(value["text"]), "river", kit.Format(kit.Value(value, "extra.river"))) case ice.TYPE_ACTION: if len(arg) == 1 { // 跳转主页 - Render(m, "redirect", "/share/"+arg[0]+"/", "title", kit.Format(value["name"])) + m.Render("redirect", "/share/"+arg[0]+"/", "title", kit.Format(value["name"])) break } @@ -1770,7 +1954,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", case ice.TYPE_ACTIVE: // 扫码数据 - Render(m, "qrcode", kit.Format(value)) + m.Render(ice.RENDER_QRCODE, kit.Format(value)) default: // 查看数据 @@ -1842,7 +2026,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", case ice.STORY_DOWNLOAD: // 下载数据 m.Cmdy(ice.WEB_STORY, ice.STORY_INDEX, arg[1]) - Render(m, kit.Select("download", "result", m.Append("file") == ""), m.Append("text")) + m.Render(kit.Select(ice.RENDER_DOWNLOAD, ice.RENDER_RESULT, m.Append("file") == ""), m.Append("text")) } }}, "/favor/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -1877,8 +2061,8 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", sessid := m.Cmdx(ice.AAA_SESS, "create", "") share := m.Cmdx(ice.WEB_SHARE, "add", "login", m.Option(ice.MSG_USERIP), sessid) m.Rich(ice.WEB_ROUTE, nil, kit.Dict("share", share, "sessid", sessid)) - Render(m, "cookie", sessid) - Render(m, share) + m.Render("cookie", sessid) + m.Render(share) } } }}, @@ -1894,6 +2078,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", if m.Richs(ice.WEB_SHARE, nil, share, nil) == nil { share = m.Cmdx(ice.WEB_SHARE, "add", m.Option("node"), m.Option("name"), m.Option("user")) } + // m.Cmd(ice.WEB_GROUP, m.Option("group"), "add", m.Option("name")) // 添加节点 h := m.Rich(ice.WEB_SPACE, nil, kit.Dict( @@ -1928,7 +2113,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", path.Join("usr/volcanos", strings.Join(strings.Split(cmd, "/")[3:7], "/"))) } - Render(m, "download", path.Join("usr/volcanos", file)) + m.Render(ice.RENDER_DOWNLOAD, path.Join("usr/volcanos", file)) }}, "/plugin/github.com/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if _, e := os.Stat(path.Join("usr/volcanos", cmd)); e != nil { @@ -1936,7 +2121,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块", path.Join("usr/volcanos", strings.Join(strings.Split(cmd, "/")[1:5], "/"))) } - Render(m, "download", path.Join("usr/volcanos", cmd)) + m.Render(ice.RENDER_DOWNLOAD, path.Join("usr/volcanos", cmd)) }}, }, } diff --git a/core/chat/chat.go b/core/chat/chat.go index b29b4d81..a479d7eb 100644 --- a/core/chat/chat.go +++ b/core/chat/chat.go @@ -153,7 +153,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", case "login": // 密码登录 if len(arg) > 2 { - web.Render(m, "cookie", m.Option(ice.MSG_SESSID, m.Cmdx(ice.AAA_USER, "login", m.Option(ice.MSG_USERNAME, arg[1]), arg[2]))) + m.Render("cookie", m.Option(ice.MSG_SESSID, m.Cmdx(ice.AAA_USER, "login", m.Option(ice.MSG_USERNAME, arg[1]), arg[2]))) } default: @@ -177,14 +177,14 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", // 登录检查 if m.Warn(!m.Options(ice.MSG_USERNAME), "not login") { - web.Render(m, "status", 401, "not login") + m.Render("status", 401, "not login") m.Option(ice.MSG_USERURL, "") return } // 权限检查 if m.Warn(!m.Right(m.Option(ice.MSG_USERURL), m.Optionv("cmds")), "not auth") { - web.Render(m, "status", 403, "not auth") + m.Render("status", 403, "not auth") m.Option(ice.MSG_USERURL, "") return } @@ -268,7 +268,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", } if !m.Right(cmd, arg[1]) { - web.Render(m, "status", 403, "not auth") + m.Render("status", 403, "not auth") return } @@ -296,7 +296,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", }}, "/storm": {Name: "/storm", Help: "暴风雨", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if m.Warn(m.Option(ice.MSG_RIVER) == "", "not join") { - web.Render(m, "status", 402, "not join") + m.Render("status", 402, "not join") return } @@ -312,7 +312,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", } if !m.Right(cmd, arg[2]) { - web.Render(m, "status", 403, "not auth") + m.Render("status", 403, "not auth") return } @@ -342,7 +342,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", }}, "/steam": {Name: "/steam", Help: "大气层", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if m.Warn(m.Option(ice.MSG_RIVER) == "", "not join") { - web.Render(m, "status", 402, "not join") + m.Render("status", 402, "not join") return } @@ -363,7 +363,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", } if !m.Right(cmd, arg[1]) { - web.Render(m, "status", 403, "not auth") + m.Render("status", 403, "not auth") return } @@ -395,7 +395,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", "/source": {Name: "/source", Help: "输入框", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, "/action": {Name: "/action", Help: "工作台", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if m.Warn(m.Option(ice.MSG_RIVER) == "" || m.Option(ice.MSG_STORM) == "", "not join") { - web.Render(m, "status", 402, "not join") + m.Render("status", 402, "not join") return } @@ -488,7 +488,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天中心", } if !m.Right(cmds) { - web.Render(m, "status", 403, "not auth") + m.Render("status", 403, "not auth") return } diff --git a/core/wiki/wiki.go b/core/wiki/wiki.go index 18799ee3..e71959c5 100644 --- a/core/wiki/wiki.go +++ b/core/wiki/wiki.go @@ -113,11 +113,11 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", switch arg[0] { case "endmenu": // 后置目录 - m.Render(endmenu) + m.Render(ice.RENDER_TEMPLATE, endmenu) return case "premenu": // 前置目录 - m.Render(premenu) + m.Render(ice.RENDER_TEMPLATE, premenu) return case "section": arg = arg[1:] @@ -148,7 +148,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", }) // 生成网页 - m.Render(m.Conf("title", "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf("title", "meta.template")) }}, "brief": {Name: "brief name text", Help: "摘要", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { @@ -161,7 +161,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", m.Option(kit.MDB_TYPE, cmd) m.Option(kit.MDB_NAME, arg[0]) m.Option(kit.MDB_TEXT, arg[1]) - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) }}, "refer": {Name: "refer name text", Help: "参考", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Option(kit.MDB_TYPE, cmd) @@ -173,7 +173,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", list = append(list, kit.Split(v, " ")) } m.Optionv("list", list) - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) }}, "spark": {Name: "spark name text", Help: "感悟", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { @@ -188,7 +188,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", m.Option(kit.MDB_NAME, arg[0]) m.Option(kit.MDB_TEXT, arg[1]) m.Optionv("list", kit.Split(arg[1], "\n")) - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) }}, "local": {Name: "local name text", Help: "文件", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -218,7 +218,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", list = append(list, "") m.Optionv("input", list) } - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) }}, "shell": {Name: "shell name dir cmd", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Option(kit.MDB_TYPE, cmd) @@ -236,7 +236,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", m.Option("input", input) m.Option("output", output) - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) }}, "field": {Name: "field name text", Help: "插件", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Option(kit.MDB_TYPE, cmd) @@ -261,7 +261,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", } m.Option("meta", data) - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) }}, "order": {Name: "order name text", Help: "列表", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -269,7 +269,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", m.Option(kit.MDB_NAME, arg[0]) m.Option(kit.MDB_TEXT, arg[1]) m.Optionv("list", kit.Split(strings.TrimSpace(arg[1]), "\n")) - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) }}, "table": {Name: "table name text", Help: "表格", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Option(kit.MDB_TYPE, cmd) @@ -302,7 +302,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", } m.Optionv("head", head) m.Optionv("list", list) - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) }}, "stack": {Name: "stack name text", Help: "结构", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Option(kit.MDB_TYPE, cmd) @@ -310,7 +310,7 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", m.Option(kit.MDB_TEXT, arg[1]) chain := &Chain{} - m.Render(m.Conf(cmd, "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) Stack(m, cmd, 0, kit.Parse(nil, "", chain.show(m, arg[1])...)) m.Echo("") }}, @@ -355,9 +355,9 @@ var Index = &ice.Context{Name: "wiki", Help: "文档中心", m.Option("height", chart.GetHeight()) // 渲染绘图 - m.Render(m.Conf("chart", "meta.template")) + m.Render(ice.RENDER_TEMPLATE, m.Conf("chart", "meta.template")) chart.Draw(m, 0, 0) - m.Render(m.Conf("chart", "meta.suffix")) + m.Render(ice.RENDER_TEMPLATE, m.Conf("chart", "meta.suffix")) }}, "draw": {Name: "draw", Help: "思维导图", Meta: kit.Dict("remote", "pod", "display", "wiki/draw"), List: kit.List( diff --git a/misc/mp/mp.go b/misc/mp/mp.go index 01dd8889..8cadec48 100644 --- a/misc/mp/mp.go +++ b/misc/mp/mp.go @@ -77,11 +77,11 @@ var Index = &ice.Context{Name: "mp", Help: "小程序", }) case "scan": - web.Render(m, "qrcode", m.Option("scan")) + m.Render(ice.RENDER_QRCODE, m.Option("scan")) case "auth": if !m.Options(ice.MSG_USERNAME) { - web.Render(m, "status", 401, "not login") + m.Render("status", 401, "not login") break } @@ -93,17 +93,17 @@ var Index = &ice.Context{Name: "mp", Help: "小程序", case "upload": msg := m.Cmd(ice.WEB_CACHE, "upload") - m.Cmdy(ice.WEB_STORY, ice.STORY_WATCH, msg.Append("data"), path.Join("usr/local/mp/", path.Base(msg.Append("name")))) - web.Render(m, msg.Append("data")) - m.Cmdy(ice.WEB_FAVOR, "device", "file", msg.Append("name"), msg.Append("data")) + m.Cmd(ice.WEB_STORY, ice.STORY_WATCH, msg.Append("data"), path.Join("usr/local/mp/", path.Base(msg.Append("name")))) + m.Cmd(ice.WEB_FAVOR, "device", "file", msg.Append("name"), msg.Append("data")) + m.Render(msg.Append("data")) case "cmds": if !m.Options(ice.MSG_USERNAME) { - web.Render(m, "status", 401, "not login") + m.Render("status", 401, "not login") break } if arg = kit.Split(arg[1]); !m.Right(arg) { - web.Render(m, "status", 403, "not auth") + m.Render("status", 403, "not auth") break } diff --git a/misc/totp/totp.go b/misc/totp/totp.go index 173dd920..ac458d91 100644 --- a/misc/totp/totp.go +++ b/misc/totp/totp.go @@ -10,34 +10,37 @@ import ( "crypto/sha1" "encoding/base32" "encoding/binary" + "math" "strings" "time" ) -func gen() string { +func gen(per int64) string { buf := bytes.NewBuffer([]byte{}) - binary.Write(buf, binary.BigEndian, time.Now().Unix()/30) + binary.Write(buf, binary.BigEndian, time.Now().Unix()/per) b := hmac.New(sha1.New, buf.Bytes()).Sum(nil) return strings.ToUpper(base32.StdEncoding.EncodeToString(b[:])) } -func get(key string) string { +func get(key string, num int, per int64) string { + now := kit.Int64(time.Now().Unix() / per) + buf := []byte{} - now := kit.Int64(time.Now().Unix() / 30) for i := 0; i < 8; i++ { buf = append(buf, byte((now >> ((7 - i) * 8)))) } + if l := len(key) % 8; l != 0 { + key += strings.Repeat("=", 8-l) + } s, _ := base32.StdEncoding.DecodeString(strings.ToUpper(key)) hm := hmac.New(sha1.New, s) hm.Write(buf) b := hm.Sum(nil) - o := b[len(b)-1] & 0x0F - p := b[o : o+4] - p[0] = p[0] & 0x7f - res := int64(p[0])<<24 + int64(p[1])<<16 + int64(p[2])<<8 + int64(p[3]) - return kit.Format("%06d", res%1000000) + n := b[len(b)-1] & 0x0F + res := int64(b[n]&0x7F)<<24 | int64(b[n+1]&0xFF)<<16 | int64(b[n+2]&0xFF)<<8 | int64(b[n+3]&0xFF) + return kit.Format(kit.Format("%%0%dd", num), res%int64(math.Pow10(num))) } var Index = &ice.Context{Name: "totp", Help: "动态码", @@ -71,40 +74,28 @@ var Index = &ice.Context{Name: "totp", Help: "动态码", if len(arg) == 1 { // 创建密钥 - arg = append(arg, gen()) + arg = append(arg, gen(30)) } // 添加密钥 m.Log(ice.LOG_CREATE, "%s: %s", arg[0], m.Rich("totp", nil, kit.Dict( kit.MDB_NAME, arg[0], kit.MDB_TEXT, arg[1], kit.MDB_EXTRA, kit.Dict(arg[2:]), ))) - - // 创建共享 - defer m.Cmdy(ice.WEB_SHARE, "optauth", arg[0], kit.Format(m.Conf("totp", "meta.share"), arg[0], arg[1])) }}, - "get": {Name: "get user [secret]", Help: "获取密码", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + "get": {Name: "get [user [number [period]]]", Help: "获取密码", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { // 密码列表 m.Richs("totp", nil, "*", func(key string, value map[string]interface{}) { m.Push("name", value["name"]) - m.Push("code", m.Cmdx("get", value["name"], value["text"])) + m.Push("code", get(kit.Format(value["text"]), kit.Int(kit.Select("6", value["number"])), kit.Int64(kit.Select("30", value["period"])))) }) return } - if len(arg) == 1 { - // 获取密钥 - m.Richs("totp", nil, arg[0], func(key string, value map[string]interface{}) { - arg = append(arg, kit.Format(value["text"])) - }) - } - if len(arg) == 1 { - // 创建密钥 - arg = append(arg, m.Cmdx("new", arg[0])) - } - - // 获取密码 - m.Echo(get(arg[1])) + m.Richs("totp", nil, arg[0], func(key string, value map[string]interface{}) { + // 获取密码 + m.Echo(get(kit.Format(value["text"]), kit.Int(kit.Select("6", arg, 1)), kit.Int64(kit.Select("30", arg, 2)))) + }) }}, }, } diff --git a/misc/wx/wx.go b/misc/wx/wx.go index 6edfe7f1..f22944a1 100644 --- a/misc/wx/wx.go +++ b/misc/wx/wx.go @@ -32,7 +32,6 @@ func parse(m *ice.Message) { } func reply(m *ice.Message) { - m.Option(ice.MSG_OUTPUT, ice.RENDER_RESULT) m.Render(m.Conf("login", "meta.template.text")) } func action(m *ice.Message) { @@ -115,7 +114,7 @@ var Index = &ice.Context{Name: "wx", Help: "公众号", if m.Option("echostr") != "" { // 绑定验证 - web.Render(m, m.Option("echostr")) + m.Render(m.Option("echostr")) return } diff --git a/type.go b/type.go index 9926451e..572c8889 100644 --- a/type.go +++ b/type.go @@ -632,10 +632,10 @@ func (m *Message) Render(cmd string, args ...interface{}) *Message { switch cmd { case RENDER_TEMPLATE: - if len(args) == 0 { + if len(args) == 1 { args = append(args, m) } - if res, err := kit.Render(cmd, args[0]); m.Assert(err) { + if res, err := kit.Render(args[0].(string), args[1]); m.Assert(err) { m.Echo(string(res)) } } @@ -790,6 +790,14 @@ func (m *Message) Result(arg ...interface{}) string { return strings.Join(m.Resultv(arg...), "") } +func (m *Message) Logs(level string, arg ...interface{}) *Message { + list := []string{} + for i := 0; i < len(arg)-1; i++ { + list = append(list, fmt.Sprintf("%v: %v", arg[i], arg[i+1])) + } + m.Log(level, strings.Join(list, " ")) + return m +} func (m *Message) Log(level string, str string, arg ...interface{}) *Message { if str = strings.TrimSpace(fmt.Sprintf(str, arg...)); Log != nil { // 日志模块