From bfb8c9adcd2a0f35083cf0b26c8e11e0cf08e629 Mon Sep 17 00:00:00 2001 From: shaoying Date: Sat, 28 Dec 2019 13:46:12 +0800 Subject: [PATCH] opt miss --- base/cli/cli.go | 1 + base/web/web.go | 225 +++++++++++++++++++++++++++------------------- conf.go | 42 +++++---- core/chat/chat.go | 34 ++++--- core/code/code.go | 79 ++++++++++++++-- core/team/team.go | 175 ++++++++++++++++++++++++++---------- misc/shy.go | 1 + misc/tmux/tmux.go | 9 +- type.go | 49 +++++++--- 9 files changed, 430 insertions(+), 185 deletions(-) diff --git a/base/cli/cli.go b/base/cli/cli.go index 416a1308..375de234 100644 --- a/base/cli/cli.go +++ b/base/cli/cli.go @@ -37,6 +37,7 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块", if name, e := os.Getwd(); e == nil { m.Conf(ice.CLI_RUNTIME, "boot.pathname", path.Base(kit.Select(name, os.Getenv("PWD")))) } + m.Conf(ice.CLI_RUNTIME, "boot.time", m.Time()) m.Conf(ice.CLI_RUNTIME, "node.type", kit.MIME_WORKER) m.Conf(ice.CLI_RUNTIME, "node.name", m.Conf(ice.CLI_RUNTIME, "boot.pathname")) diff --git a/base/web/web.go b/base/web/web.go index 132a749a..4535ce2a 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -35,12 +35,14 @@ type Frame struct { } func Cookie(msg *ice.Message, sessid string) string { - w := msg.Optionv("response").(http.ResponseWriter) expire := time.Now().Add(kit.Duration(msg.Conf(ice.AAA_SESS, ice.Meta("expire")))) msg.Log("cookie", "expire:%v sessid:%s", kit.Format(expire), sessid) - http.SetCookie(w, &http.Cookie{Name: ice.WEB_SESS, Value: sessid, Path: "/", Expires: expire}) + http.SetCookie(msg.W, &http.Cookie{Name: ice.WEB_SESS, Value: sessid, Path: "/", Expires: expire}) return sessid } +func IsLocalIP(ip string) bool { + return ip == "::1" || ip == "127.0.0.1" +} func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool { if msg.Options(ice.WEB_SESS) { // 会话认证 @@ -49,7 +51,7 @@ func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request msg.Option(ice.MSG_USERNAME, sub.Append("username"))) } - if (!msg.Options(ice.MSG_SESSID) || !msg.Options(ice.MSG_USERNAME)) && msg.Option("user.ip") == "::1" { + if (!msg.Options(ice.MSG_SESSID) || !msg.Options(ice.MSG_USERNAME)) && IsLocalIP(msg.Option(ice.MSG_USERIP)) { // 自动认证 msg.Option(ice.MSG_USERNAME, msg.Conf(ice.CLI_RUNTIME, "boot.username")) msg.Option(ice.MSG_USERROLE, msg.Cmdx(ice.AAA_ROLE, "check", msg.Option(ice.MSG_USERNAME))) @@ -64,7 +66,7 @@ func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request // 权限检查 msg.Target().Run(msg, s, ice.WEB_LOGIN, kit.Simple(msg.Optionv("cmds"))...) } - return msg.Option("url") != "" + return msg.Option(ice.MSG_USERURL) != "" } func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn) bool { for { @@ -162,18 +164,14 @@ func (web *Frame) HandleCGI(m *ice.Message, alias map[string]interface{}, which func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) { web.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) { m.TryCatch(m.Spawns(), true, func(msg *ice.Message) { - defer func() { msg.Log("cost", "%s: %s %v", msg.Format("cost"), r.URL.Path, msg.Optionv("cmds")) }() + defer func() { msg.Cost("%s %v", r.URL.Path, msg.Optionv("cmds")) }() // 解析请求 - msg.Optionv("request", r) - msg.Optionv("response", w) - msg.Option("user.agent", r.Header.Get("User-Agent")) - msg.Option("user.ip", r.Header.Get("user.ip")) - msg.Option("referer", r.Header.Get("Referer")) - msg.Option("accept", r.Header.Get("Accept")) - msg.Option("method", r.Method) - msg.Option("url", r.URL.Path) + msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent")) + msg.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP)) + msg.Option(ice.MSG_USERURL, r.URL.Path) msg.Option(ice.WEB_SESS, "") + msg.R, msg.W = r, w // 请求环境 for _, v := range r.Cookies() { @@ -212,7 +210,7 @@ func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) { } // 执行命令 - if web.Login(msg, w, r) && msg.Target().Run(msg, cmd, msg.Option("url"), kit.Simple(msg.Optionv("cmds"))...) != nil { + if web.Login(msg, w, r) && msg.Target().Run(msg, cmd, msg.Option(ice.MSG_USERURL), kit.Simple(msg.Optionv("cmds"))...) != nil { // 输出响应 switch msg.Append("_output") { case "void": @@ -238,15 +236,15 @@ func (web *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) { if index { // 解析地址 if ip := r.Header.Get("X-Forwarded-For"); ip != "" { - r.Header.Set("user.ip", ip) + r.Header.Set(ice.MSG_USERIP, ip) } else if ip := r.Header.Get("X-Real-Ip"); ip != "" { - r.Header.Set("user.ip", ip) + r.Header.Set(ice.MSG_USERIP, ip) } else if strings.HasPrefix(r.RemoteAddr, "[") { - r.Header.Set("user.ip", strings.Split(r.RemoteAddr, "]")[0][1:]) + r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, "]")[0][1:]) } else { - r.Header.Set("user.ip", strings.Split(r.RemoteAddr, ":")[0]) + r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, ":")[0]) } - m.Info("").Info("%s %s %s", r.Header.Get("user.ip"), r.Method, r.URL) + m.Info("").Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL) // 解析地址 r.Header.Set("index.module", "some") @@ -320,7 +318,9 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool { // 启动服务 web.m, web.Server = m, &http.Server{Addr: port, Handler: web} + m.Event(ice.SERVE_START, arg[0]) m.Log("serve", "listen %s", web.Server.ListenAndServe()) + m.Event(ice.SERVE_CLOSE, arg[0]) }) return true } @@ -331,7 +331,7 @@ func (web *Frame) Close(m *ice.Message, arg ...string) bool { var Index = &ice.Context{Name: "web", Help: "网页模块", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - ice.WEB_SPIDE: {Name: "spide", Help: "客户端", Value: kit.Data(kit.MDB_SHORT, "name")}, + ice.WEB_SPIDE: {Name: "spide", Help: "蜘蛛侠", Value: kit.Data(kit.MDB_SHORT, "client.name")}, ice.WEB_SERVE: {Name: "serve", Help: "服务器", Value: kit.Data( "static", map[string]interface{}{"/": "usr/volcanos/", "/static/volcanos/": "usr/volcanos/", @@ -339,7 +339,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", "template", map[string]interface{}{"path": "usr/template", "list": []interface{}{ `{{define "raw"}}{{.Result}}{{end}}`, }}, - "logheaders", "true", + "logheaders", "false", )}, ice.WEB_SPACE: {Name: "space", Help: "空间站", Value: kit.Data(kit.MDB_SHORT, "name", "redial.a", 3000, "redial.b", 1000, "redial.c", 10, @@ -360,33 +360,53 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Cmd(ice.CTX_CONFIG, "load", "web.json") - m.Cmd(ice.WEB_SPIDE, "add", "self", "http://:9020") - m.Cmd(ice.WEB_SPIDE, "add", "shy", "https://shylinux.com") + if m.Richs(ice.WEB_SPIDE, nil, "self", nil) == nil { + m.Cmd(ice.WEB_SPIDE, "add", "self", "http://:9020") + m.Cmd(ice.WEB_SPIDE, "add", "self", kit.Select("http://:9020", os.Getenv("ctx_dev"))) + } + if m.Richs(ice.WEB_SPIDE, nil, "dev", nil) == nil { + m.Cmd(ice.WEB_SPIDE, "add", "dev", kit.Select("http://:9020", os.Getenv("ctx_dev"))) + } + if m.Richs(ice.WEB_SPIDE, nil, "shy", nil) == nil { + m.Cmd(ice.WEB_SPIDE, "add", "shy", "https://shylinux.com") + } }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Done() m.Cmd(ice.CTX_CONFIG, "save", "web.json", ice.WEB_SPIDE, ice.WEB_FAVOR, ice.WEB_CACHE, ice.WEB_STORY, ice.WEB_SHARE) }}, - ice.WEB_SPIDE: {Name: "spide", Help: "客户端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + ice.WEB_SPIDE: {Name: "spide", Help: "蜘蛛侠", List: kit.List( + kit.MDB_INPUT, "text", "name", "name", + kit.MDB_INPUT, "button", "value", "查看", "action", "auto", + kit.MDB_INPUT, "button", "value", "返回", "cb", "Last", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { // 爬虫列表 - m.Richs(ice.WEB_SPIDE, nil, "", func(key string, value map[string]interface{}) { - m.Push("name", value["name"]) - m.Push(key, value["client"], []string{"method", "protocol", "hostname", "path", "file"}) + m.Richs(ice.WEB_SPIDE, nil, "*", func(key string, value map[string]interface{}) { + m.Push(key, value["client"], []string{"name", "method", "url"}) + }) + m.Sort("name") + return + } + if len(arg) == 1 { + // 爬虫详情 + m.Richs(ice.WEB_SPIDE, nil, arg[0], func(key string, value map[string]interface{}) { + m.Push("detail", value) }) return } + switch arg[0] { case "add": // 添加爬虫 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( - "name", arg[1], "cookie", kit.Dict(), "header", kit.Dict(), "client", kit.Dict( + "name", arg[1], "logheaders", false, "timeout", "100s", "method", "POST", @@ -400,13 +420,14 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", )) } default: + // spide shy [cache] [POST|GET] uri file|data|form|part|json arg... m.Richs(ice.WEB_SPIDE, nil, arg[0], func(key string, value map[string]interface{}) { client := value["client"].(map[string]interface{}) - // 解析方法 - parse := "" + // 缓存数据 + cache := "" switch arg[1] { - case "parse": - parse, arg = "parse", arg[1:] + case "cache": + cache, arg = arg[1], arg[1:] } // 请求方法 @@ -460,6 +481,9 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", mp.Close() head["Content-Type"] = mp.FormDataContentType() body = buf + case "json": + arg = arg[1:] + fallthrough default: data := map[string]interface{}{} for i := 0; i < len(arg)-1; i += 2 { @@ -510,30 +534,29 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", } // 验证结果 - if m.Warn(e != nil, "%s", e) { + if m.Cost("%s %s: %s", res.Status, res.Header.Get("Content-Length"), res.Header.Get("Content-Type")); m.Warn(e != nil, "%s", e) { return } else if m.Warn(res.StatusCode != http.StatusOK, "%s", res.Status) { return } - switch parse { - case "parse": - data := map[string]interface{}{} - m.Assert(json.NewDecoder(res.Body).Decode(&data)) - for k, v := range data { - switch v := v.(type) { - case []interface{}: - m.Append(k, v) - default: - m.Append(k, kit.Format(v)) - } - } - - default: + switch cache { + case "cache": // 缓存结果 - m.Cost("%s %s: %s", res.Status, res.Header.Get("Content-Length"), res.Header.Get("Content-Type")) m.Optionv("response", res) m.Echo(m.Cmd(ice.WEB_CACHE, "download", res.Header.Get("Content-Type"), uri).Append("data")) + default: + // 解析结果 + var data interface{} + m.Assert(json.NewDecoder(res.Body).Decode(&data)) + kit.Fetch(data, func(key string, value interface{}) { + switch value := value.(type) { + case []interface{}: + m.Append(key, value) + default: + m.Append(key, kit.Format(value)) + } + }) } }) } @@ -553,42 +576,50 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", m.Target().Start(m, kit.Select("self", arg, 0)) }}, ice.WEB_SPACE: {Name: "space", Help: "空间站", Meta: kit.Dict("exports", []string{"pod", "name"}), List: kit.List( - kit.MDB_INPUT, "text", "name", "node", + kit.MDB_INPUT, "text", "name", "pod", kit.MDB_INPUT, "button", "value", "查看", "action", "auto", kit.MDB_INPUT, "button", "value", "返回", "cb", "Last", ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { // 节点列表 - m.Richs(ice.WEB_SPACE, nil, "", func(key string, value map[string]interface{}) { + m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) { m.Push(key, value, []string{"time", "type", "name", "user"}) }) m.Sort("name") return } + if len(arg) == 1 { + // 节点详情 + m.Richs(ice.WEB_SPACE, nil, arg[0], func(key string, value map[string]interface{}) { + m.Push("detail", value) + }) + return + } web := m.Target().Server().(*Frame) switch arg[0] { case "share": switch arg[1] { case "add": - m.Cmdy(ice.WEB_SPIDE, "self", "parse", path.Join("/space/share/add", path.Join(arg[2:]...))) + m.Cmdy(ice.WEB_SPIDE, "self", path.Join("/space/share/add", path.Join(arg[2:]...))) default: m.Richs(ice.WEB_SPIDE, nil, "self", func(key string, value map[string]interface{}) { value["share"] = arg[1] + m.Info("what %v", kit.Formats(value)) }) } case "upload": for _, file := range arg[2:] { msg := m.Cmd(ice.WEB_STORY, "index", file) - m.Cmdy(ice.WEB_SPIDE, arg[1], "POST", "/space/upload", "part", + m.Cmdy(ice.WEB_SPIDE, arg[1], "/space/upload", "part", "type", msg.Append("type"), "name", msg.Append("name"), "text", msg.Append("text"), "upload", "@"+msg.Append("file"), ) } case "download": m.Cmd(ice.WEB_STORY, "add", arg[1], arg[2], - m.Cmdx(ice.WEB_SPIDE, arg[3], "/space/download/"+arg[4])) + m.Cmdx(ice.WEB_SPIDE, arg[3], "cache", "/space/download/"+arg[4])) case "connect": // 基本信息 @@ -599,8 +630,8 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", m.Richs(ice.WEB_SPIDE, nil, kit.Select("self", arg, 1), func(key string, value map[string]interface{}) { host := kit.Format(kit.Value(value, "client.hostname")) - if u, e := url.Parse(kit.MergeURL("ws://"+host+"/space/", "node", node, "name", name, "user", user, "share", value["share"])); m.Assert(e) { - for i := 0; i < m.Confi(ice.WEB_SPACE, "meta.redial.c"); i++ { + for i := 0; i < m.Confi(ice.WEB_SPACE, "meta.redial.c"); i++ { + if u, e := url.Parse(kit.MergeURL("ws://"+host+"/space/", "node", node, "name", name, "user", user, "share", value["share"])); m.Assert(e) { if s, e := net.Dial("tcp", host); !m.Warn(e != nil, "%s", e) { if s, _, e := websocket.NewClient(s, u, nil, m.Confi(ice.WEB_SPACE, "meta.buffer.r"), m.Confi(ice.WEB_SPACE, "meta.buffer.w")); !m.Warn(e != nil, "%s", e) { // 连接成功 @@ -654,7 +685,6 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", "detail", []interface{}{"启动", "停止"}, ), List: kit.List( kit.MDB_INPUT, "text", "value", "", "name", "name", - kit.MDB_INPUT, "text", "value", "", "name", "type", kit.MDB_INPUT, "button", "value", "创建", "action", "auto", ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { if len(arg) > 1 { @@ -664,7 +694,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", case "停止", "stop": m.Cmd(ice.WEB_SPACE, arg[0], "exit", "1") time.Sleep(time.Second * 3) - m.Cmd(ice.GDB_EVENT, "action", ice.DREAM_CLOSE, arg[0]) + m.Event(ice.DREAM_CLOSE, arg[0]) arg = arg[:0] } } @@ -687,7 +717,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", m.Option("cmd_type", "daemon") m.Cmd(m.Confv(ice.WEB_DREAM, "meta.cmd"), "self", arg[0]) time.Sleep(time.Second * 3) - m.Cmd(ice.GDB_EVENT, "action", ice.DREAM_START, arg) + m.Event(ice.DREAM_START, arg...) } } @@ -757,11 +787,12 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", if len(arg) == 0 { // 收藏门类 - m.Richs(ice.WEB_FAVOR, nil, "", func(key string, value map[string]interface{}) { + m.Richs(ice.WEB_FAVOR, nil, "*", func(key string, value map[string]interface{}) { m.Push("time", kit.Value(value, "meta.time")) m.Push("favor", kit.Value(value, "meta.name")) m.Push("count", kit.Value(value, "meta.count")) }) + m.Sort("time", "time_r") return } @@ -774,10 +805,17 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", m.Info("create favor: %s name: %s", favor, arg[0]) } + extras := []string{} + if len(arg) == 3 && arg[1] == "extra" { + extras, arg = strings.Split(arg[2], " "), arg[:1] + } if len(arg) == 1 { // 收藏列表 m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, favor), "", "", func(index int, value map[string]interface{}) { m.Push(kit.Format(index), value, []string{kit.MDB_TIME, kit.MDB_ID, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT}) + for _, k := range extras { + m.Push(k, kit.Select("", kit.Value(value, "extra."+k))) + } }) return } @@ -785,16 +823,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", if len(arg) == 2 { // 收藏详情 m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, favor), "id", arg[1], func(index int, value map[string]interface{}) { - for k, v := range value { - if k == "extra" { - for k, v := range v.(map[string]interface{}) { - m.Push("key", "extra."+k).Push("value", kit.Format(v)) - } - } else { - m.Push("key", k).Push("value", kit.Format(v)) - } - } - m.Sort("key") + m.Push("detail", value) }) return } @@ -828,8 +857,8 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", switch arg[0] { case "upload", "download": // 打开文件 - if r, ok := m.Optionv("request").(*http.Request); ok { - if f, h, e := r.FormFile(kit.Select("upload", arg, 1)); m.Assert(e) { + if m.R != nil { + if f, h, e := m.R.FormFile(kit.Select("upload", arg, 1)); m.Assert(e) { defer f.Close() // 创建文件 @@ -893,6 +922,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", }}, ice.WEB_STORY: {Name: "story", Help: "故事会", Meta: kit.Dict("remote", "you", "exports", []string{"top", "story"}, "detail", []string{"归档", "共享", "下载"}), List: kit.List( kit.MDB_INPUT, "text", "name", "top", "action", "auto", + kit.MDB_INPUT, "text", "name", "list", "action", "auto", kit.MDB_INPUT, "button", "value", "查看", "action", "auto", kit.MDB_INPUT, "button", "value", "返回", "cb", "Last", ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -915,8 +945,8 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", if len(arg) == 0 { // 故事列表 - m.Richs(ice.WEB_STORY, "head", "", func(key string, value map[string]interface{}) { - m.Push(key, value, []string{"time", "scene", "story", "count"}) + m.Richs(ice.WEB_STORY, "head", "*", func(key string, value map[string]interface{}) { + m.Push(key, value, []string{"time", "story", "count"}) }) m.Sort("time", "time_r") return @@ -1047,26 +1077,42 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", m.Echo("%s", node["text"]) } default: - m.Cmd(ice.WEB_STORY, "history", arg).Table(func(index int, value map[string]string, head []string) { - m.Push("time", value["time"]) - m.Push("list", value["key"]) - m.Push("scene", value["scene"]) - m.Push("story", value["story"]) - m.Push("drama", value["drama"]) - m.Push("link", kit.Format(m.Conf(ice.WEB_SHARE, "meta.template.download"), - kit.Format(value["data"])+"&pod="+m.Conf(ice.CLI_RUNTIME, "node.name"), kit.Short(value["data"]))) + if len(arg) == 1 { + m.Cmd(ice.WEB_STORY, "history", arg).Table(func(index int, value map[string]string, head []string) { + m.Push("time", value["time"]) + m.Push("list", value["key"]) + m.Push("scene", value["scene"]) + m.Push("story", value["story"]) + m.Push("drama", value["drama"]) + m.Push("link", kit.Format(m.Conf(ice.WEB_SHARE, "meta.template.download"), + kit.Format(value["data"])+"&pod="+m.Conf(ice.CLI_RUNTIME, "node.name"), kit.Short(value["data"]))) + }) + break + } + m.Richs(ice.WEB_STORY, nil, arg[1], func(key string, value map[string]interface{}) { + m.Push("detail", value) }) } }}, - ice.WEB_SHARE: {Name: "share", Help: "共享链", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + ice.WEB_SHARE: {Name: "share", Help: "共享链", List: kit.List( + kit.MDB_INPUT, "text", "name", "share", "action", "auto", + kit.MDB_INPUT, "button", "value", "查看", "action", "auto", + kit.MDB_INPUT, "button", "value", "返回", "cb", "Last", + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { // 共享列表 m.Grows(ice.WEB_SHARE, nil, "", "", func(key int, value map[string]interface{}) { - m.Push(kit.Format(key), value, []string{kit.MDB_TIME, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT}) + m.Push(kit.Format(key), value, []string{kit.MDB_TIME, "share", kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT}) m.Push("link", fmt.Sprintf(m.Conf(ice.WEB_SHARE, "meta.template.share"), value["share"], value["share"])) }) return } + if len(arg) == 1 { + m.Richs(ice.WEB_SHARE, nil, arg[0], func(key string, value map[string]interface{}) { + m.Push("detail", value) + }) + return + } switch arg[0] { case "add": @@ -1121,8 +1167,6 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", }) }}, "/space/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - r := m.Optionv("request").(*http.Request) - w := m.Optionv("response").(http.ResponseWriter) list := strings.Split(cmd, "/") switch list[2] { @@ -1138,7 +1182,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", return } - if s, e := websocket.Upgrade(w, r, nil, m.Confi(ice.WEB_SPACE, "meta.buffer"), m.Confi(ice.WEB_SPACE, "meta.buffer")); m.Assert(e) { + if s, e := websocket.Upgrade(m.W, m.R, nil, m.Confi(ice.WEB_SPACE, "meta.buffer"), m.Confi(ice.WEB_SPACE, "meta.buffer")); m.Assert(e) { // 共享空间 share := m.Option("share") if m.Richs(ice.WEB_SHARE, nil, share, nil) == nil { @@ -1157,8 +1201,9 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", m.Gos(m, func(m *ice.Message) { // 监听消息 - web := m.Target().Server().(*Frame) - web.HandleWSS(m, false, s) + m.Event(ice.SPACE_START, m.Option("node"), m.Option("name")) + m.Target().Server().(*Frame).HandleWSS(m, false, s) + m.Event(ice.SPACE_CLOSE, m.Option("node"), m.Option("name")) m.Log("close", "%s: %s", m.Option(kit.MDB_NAME), kit.Format(m.Confv(ice.WEB_SPACE, kit.Keys(kit.MDB_HASH, h)))) m.Confv(ice.WEB_SPACE, kit.Keys(kit.MDB_HASH, h), "") }) @@ -1177,9 +1222,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", } m.Push("_output", "void") - r := m.Optionv("request").(*http.Request) - w := m.Optionv("response").(http.ResponseWriter) - http.ServeFile(w, r, path.Join("usr/volcanos", file)) + http.ServeFile(m.W, m.R, path.Join("usr/volcanos", file)) }}, }, } diff --git a/conf.go b/conf.go index e23d17ea..79a14c65 100644 --- a/conf.go +++ b/conf.go @@ -1,24 +1,24 @@ package ice -const ( +const ( // ICE ICE_CHAN = 10 ICE_INIT = "_init" ICE_EXIT = "_exit" ICE_DATE = "2006-01-02" ICE_TIME = "2006-01-02 15:04:05" ) -const ( +const ( // CTX CTX_STATUS = "status" CTX_STREAM = "stream" CTX_CONFIG = "config" CTX_COMMAND = "command" CTX_CONTEXT = "context" ) -const ( +const ( // CLI CLI_RUNTIME = "runtime" CLI_SYSTEM = "system" ) -const ( +const ( // MSG MSG_DETAIL = "detail" MSG_OPTION = "option" MSG_APPEND = "append" @@ -29,18 +29,21 @@ const ( MSG_HANDLE = "_handle" MSG_SESSID = "sessid" + MSG_USERIP = "user.ip" + MSG_USERUA = "user.ua" + MSG_USERURL = "user.url" MSG_USERNAME = "user.name" MSG_USERROLE = "user.role" MSG_RIVER = "sess.river" MSG_STORM = "sess.storm" ) -const ( +const ( // AAA AAA_ROLE = "role" AAA_USER = "user" AAA_SESS = "sess" ) -const ( +const ( // WEB WEB_PORT = ":9020" WEB_SESS = "sessid" WEB_TMPL = "render" @@ -60,7 +63,7 @@ const ( WEB_GROUP = "group" WEB_LABEL = "label" ) -const ( +const ( // LOG LOG_CMDS = "cmds" LOG_COST = "cost" LOG_INFO = "info" @@ -73,17 +76,19 @@ const ( LOG_BENCH = "bench" LOG_CLOSE = "close" ) -const ( +const ( // GDB GDB_SIGNAL = "signal" GDB_TIMER = "timer" GDB_EVENT = "event" - DREAM_START = "dream.start" - DREAM_CLOSE = "dream.close" + SERVE_START = "serve.start" + SERVE_CLOSE = "serve.close" SPACE_START = "space.start" SPACE_CLOSE = "space.close" + DREAM_START = "dream.start" + DREAM_CLOSE = "dream.close" ) -const ( +const ( // MDB MDB_REDIS = "redis" MDB_MYSQL = "mysql" MDB_CREATE = "create" @@ -97,22 +102,26 @@ const ( MDB_DELETE = "delete" ) -const ( +const ( // APP + APP_NOTE = "note" + APP_MISS = "miss" +) +const ( // CHAT CHAT_RIVER = "river" ) - -const ( +const ( // TYPE TYPE_SPACE = "space" TYPE_RIVER = "river" TYPE_STORM = "storm" TYPE_STORY = "story" TYPE_SHELL = "shell" + TYPE_VIMRC = "vimrc" TYPE_TABLE = "table" TYPE_INNER = "inner" TYPE_MEDIA = "media" ) -const ( +const ( // FAVOR FAVOR_CHAT = "chat.init" FAVOR_TMUX = "tmux.init" FAVOR_RIVER = "river.init" @@ -161,5 +170,6 @@ var Alias = map[string]string{ CHAT_RIVER: "web.chat.river", - "note": "web.wiki.note", + APP_NOTE: "web.wiki.note", + APP_MISS: "web.team.miss", } diff --git a/core/chat/chat.go b/core/chat/chat.go index a65c1d9b..f7943792 100644 --- a/core/chat/chat.go +++ b/core/chat/chat.go @@ -20,10 +20,10 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块", m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "river", "meet", "root") m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "user", m.Conf(ice.CLI_RUNTIME, "boot.username"), "root") m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "storm", "miss", "root") + m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "action", "spide", "root") m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "action", "space", "root") m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "action", "dream", "root") m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "action", "favor", "root") - m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "action", "cache", "root") m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "action", "story", "root") m.Cmd(ice.WEB_FAVOR, ice.FAVOR_RIVER, "action", "share", "root") } @@ -37,17 +37,18 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块", switch arg[0] { case "login": // 用户登录 - m.Option(ice.MSG_SESSID, (web.Cookie(m, m.Cmdx(ice.AAA_USER, "login", m.Option(ice.MSG_USERNAME, arg[1]), arg[2])))) - if m.Richs(ice.CHAT_RIVER, nil, "", nil) == nil { - // 默认群组 - m.Richs(ice.WEB_FAVOR, nil, "river.init", func(key string, value map[string]interface{}) { + m.Option(ice.MSG_SESSID, web.Cookie(m, m.Cmdx(ice.AAA_USER, "login", m.Option(ice.MSG_USERNAME, arg[1]), arg[2]))) + default: + // 默认群组 + if m.Richs(ice.CHAT_RIVER, nil, "%", nil) == nil { + m.Richs(ice.WEB_FAVOR, nil, ice.FAVOR_RIVER, func(key string, value map[string]interface{}) { m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) { switch kit.Format(value["type"]) { - case "river": + case ice.TYPE_RIVER: m.Option("river", m.Cmdx("/ocean", "spawn", value["name"])) case "user": m.Cmd("/river", m.Option("river"), "add", value["name"]) - case "storm": + case ice.TYPE_STORM: m.Option("storm", m.Cmdx("/steam", m.Option("river"), "spawn", value["name"])) case "action": m.Cmd("/storm", m.Option("river"), m.Option("storm"), "add", m.Conf(ice.CLI_RUNTIME, "node.name"), "", value["name"], value["text"]) @@ -55,7 +56,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块", }) }) } - default: + // 用户群组 m.Richs(ice.CHAT_RIVER, nil, arg[0], func(value map[string]interface{}) { m.Option(ice.MSG_RIVER, arg[0]) @@ -82,7 +83,14 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块", "/tutor": {Name: "/tutor", Help: "向导", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, "/debug": {Name: "/debug", Help: "调试", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, "/carte": {Name: "/carte", Help: "菜单", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, - "/favor": {Name: "/favor", Help: "收藏", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, + "/favor": {Name: "/favor", Help: "收藏", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Hand = false + if msg := m.Cmd(arg); !msg.Hand { + m.Set("result").Cmdy(ice.CLI_SYSTEM, arg) + } else { + m.Copy(msg) + } + }}, "/login": {Name: "/login", Help: "登录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[0] { case "check": @@ -95,7 +103,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块", "/ocean": {Name: "/ocean", Help: "大海洋", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { // 用户列表 - m.Richs(ice.AAA_USER, nil, "", func(key string, value map[string]interface{}) { + m.Richs(ice.AAA_USER, nil, "*", func(key string, value map[string]interface{}) { m.Push(key, value, []string{"username", "usernode"}) }) return @@ -114,7 +122,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块", switch len(arg) { case 0: // 群组列表 - m.Richs(ice.CHAT_RIVER, nil, "", func(key string, value map[string]interface{}) { + m.Richs(ice.CHAT_RIVER, nil, "*", func(key string, value map[string]interface{}) { m.Push(key, value["meta"], []string{kit.MDB_KEY, kit.MDB_NAME}) }) case 1: @@ -137,7 +145,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块", prefix := kit.Keys(kit.MDB_HASH, arg[0], "tool") if len(arg) < 2 { // 应用列表 - m.Richs(ice.CHAT_RIVER, prefix, "", func(key string, value map[string]interface{}) { + m.Richs(ice.CHAT_RIVER, prefix, "*", func(key string, value map[string]interface{}) { m.Push(key, value["meta"], []string{kit.MDB_KEY, kit.MDB_NAME}) }) m.Sort(kit.MDB_NAME) @@ -170,7 +178,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 len(arg) < 2 { // 设备列表 - m.Richs(ice.WEB_SPACE, nil, "", func(key string, value map[string]interface{}) { + m.Richs(ice.WEB_SPACE, nil, "*", func(key string, value map[string]interface{}) { m.Push(key, value, []string{"type", "name", "user"}) }) return diff --git a/core/code/code.go b/core/code/code.go index e870127c..5cc169c0 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -67,21 +67,38 @@ var Index = &ice.Context{Name: "code", Help: "编程模块", m.Echo(h) case "list": - m.Richs("login", nil, "", func(key string, value map[string]interface{}) { - m.Push(key, value) + m.Richs("login", nil, "*", func(key string, value map[string]interface{}) { + m.Push(key, value, []string{"time", "type", "status", "you"}) + pwd := strings.Split(kit.Format(value["pwd"]), "/") + if len(pwd) > 3 { + m.Push("pwd", strings.Join(pwd[len(pwd)-3:len(pwd)], "/")) + } else { + m.Push("pwd", value["pwd"]) + } + + m.Push(key, value, []string{"pid", "pane", "hostname", "username"}) + }) + + case "exit": + m.Richs("login", nil, m.Option("sid"), func(key string, value map[string]interface{}) { + m.Info("logout: %s", m.Option("sid")) + value["status"] = "logout" }) } }}, - "/zsh": {Name: "/zsh", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + "/zsh": {Name: "/zsh", Help: "命令行", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Option("you", "") m.Richs("login", nil, m.Option("sid"), func(key string, value map[string]interface{}) { m.Option("you", value["you"]) }) m.Info("%s%s %s arg: %v sub: %v", m.Option("you"), cmd, m.Option("cmd"), m.Optionv("arg"), m.Optionv("sub")) + m.Push("_output", "result") switch m.Option("cmd") { case "login": - m.Cmdy("login", "init", cmd).Push("_output", "result") + m.Cmdy("login", "init", cmd) + case "logout": + m.Cmdy("login", "exit") case "upload": // 缓存文件 msg := m.Cmd(ice.WEB_CACHE, "upload") @@ -101,13 +118,65 @@ var Index = &ice.Context{Name: "code", Help: "编程模块", if m.Cmdy(ice.WEB_STORY, "index", m.Option("arg")).Append("text") == "" { m.Cmdy(ice.WEB_SPACE, m.Option("pod"), ice.WEB_STORY, "index", m.Optionv("arg")) } - m.Push("_output", kit.Select("file", "result", m.Append("file") == "")) + m.Append("_output", kit.Select("file", "result", m.Append("file") == "")) case "history": vs := strings.SplitN(strings.TrimSpace(m.Option("arg")), " ", 2) m.Cmd(ice.WEB_SPACE, m.Option("you"), ice.WEB_FAVOR, "zsh.history", "shell", m.Option("sid"), kit.Select("", vs, 1), "sid", m.Option("sid"), "num", vs[0], "pwd", m.Option("pwd")) m.Push("_output", "void") + + case "favor": + if m.Options("arg") { + m.Cmdy(ice.WEB_SPACE, m.Option("you"), ice.WEB_FAVOR, + m.Option("tab"), ice.TYPE_SHELL, m.Option("note"), m.Option("arg")) + break + } + m.Echo("#/bin/sh\n\n") + m.Cmd(ice.WEB_SPACE, m.Option("you"), ice.WEB_FAVOR, m.Option("tab")).Table(func(index int, value map[string]string, head []string) { + switch value["type"] { + case ice.TYPE_SHELL: + m.Echo("# %v:%v\n%v\n\n", value["type"], value["name"], value["text"]) + } + }) + m.Push("_output", "result") + } + }}, + "/vim": {Name: "/vim", Help: "编辑器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option("you", "") + m.Richs("login", nil, m.Option("sid"), func(key string, value map[string]interface{}) { + m.Option("you", value["you"]) + }) + m.Info("%s%s %s arg: %v sub: %v", m.Option("you"), cmd, m.Option("cmd"), m.Optionv("arg"), m.Optionv("sub")) + + m.Push("_output", "result") + switch m.Option("cmd") { + case "login": + m.Cmdy("login", "init", cmd) + case "logout": + m.Cmdy("login", "exit") + + case "read", "write", "exec": + m.Cmd(ice.WEB_SPACE, m.Option("you"), ice.WEB_FAVOR, "vim.history", "vimrc", m.Option("cmd"), m.Option("arg"), + "sid", m.Option("sid"), "pwd", m.Option("pwd")) + + case "tasklet": + m.Cmd(ice.WEB_SPACE, m.Option("you"), ice.APP_MISS, "add", m.Option("tab"), m.Option("note"), m.Option("arg")) + + case "favor": + if m.Options("arg") { + m.Cmd(ice.WEB_SPACE, m.Option("you"), ice.WEB_FAVOR, m.Option("tab"), "vimrc", m.Option("note"), m.Option("arg"), + "buf", m.Option("buf"), "line", m.Option("line"), "col", m.Option("col"), + ) + break + } + m.Cmd(ice.WEB_SPACE, m.Option("you"), ice.WEB_FAVOR, m.Option("tab"), "extra", "buf line col").Table(func(index int, value map[string]string, head []string) { + switch value["type"] { + case ice.TYPE_VIMRC: + m.Echo("%v\n", m.Option("tab")).Echo("%v:%v:%v:(%v): %v\n", + value["buf"], value["line"], value["col"], value["name"], value["text"]) + } + }) } }}, diff --git a/core/team/team.go b/core/team/team.go index 43c55919..06daf503 100644 --- a/core/team/team.go +++ b/core/team/team.go @@ -1,70 +1,155 @@ package team import ( + "fmt" "github.com/shylinux/icebergs" _ "github.com/shylinux/icebergs/base" "github.com/shylinux/icebergs/base/web" "github.com/shylinux/toolkits" - - "os" - "path" - "strings" + "time" ) var Index = &ice.Context{Name: "team", Help: "团队模块", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - "miss": {Name: "miss", Help: "任务", Value: kit.Data( - "path", "usr/local/work", - "cmd", []interface{}{"cli.system", "sh", "ice.sh", "start", "web.space", "connect"}, - )}, + ice.APP_MISS: {Name: "miss", Help: "任务", Value: kit.Data()}, }, Commands: map[string]*ice.Command{ - "miss": {Name: "miss", Help: "任务", Meta: map[string]interface{}{ - "display": "github.com/shylinux/context/usr/librarys/code", - "detail": []interface{}{"启动", "停止"}, - "exports": []interface{}{"you", "name"}, - }, List: kit.List( - kit.MDB_INPUT, "text", "value", "", "name", "name", - kit.MDB_INPUT, "text", "value", "", "name", "type", - kit.MDB_INPUT, "button", "value", "创建", "action", "auto", - ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - return + ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Cmd(ice.CTX_CONFIG, "load", "team.json") + }}, + ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Cmd(ice.CTX_CONFIG, "save", "team.json", "web.team.miss") + }}, + + ice.APP_MISS: {Name: "miss", Help: "任务", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { if len(arg) > 1 { switch arg[1] { - case "启动": - case "停止": - m.Cmd(ice.WEB_SPACE, arg[0], "exit", "1") - m.Cmd(ice.GDB_EVENT, "action", "miss.stop", arg[0]) - return + case "modify": + // 修改任务 + m.Grows(ice.APP_MISS, nil, "id", arg[0], func(index int, value map[string]interface{}) { + value[arg[2]] = arg[3] + }) + arg = arg[:0] } } + if len(arg) == 0 { + // 任务列表 + m.Grows(ice.APP_MISS, nil, "", "", func(index int, value map[string]interface{}) { + m.Push(kit.Format(index), value, []string{"begin_time", "close_time", "status", "id", "type", "name", "text"}) + }) + return + } + + // 添加任务 + h := m.Grow(ice.APP_MISS, nil, kit.Dict( + kit.MDB_NAME, arg[0], + kit.MDB_TYPE, kit.Select("开发", arg, 1), + kit.MDB_TEXT, kit.Select("功能开发", arg, 2), + "status", kit.Select("准备中", arg, 3), + "begin_time", m.Time(), "close_time", m.Time(), + )) + m.Info("miss: %d", h) + m.Echo("%d", h) + }}, + "date": {Name: "date", Help: "日历", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + show := map[int]string{0: "周日", 1: "周一", 2: "周二", 3: "周三", 4: "周四", 5: "周五", 6: "周六"} + + space := m.Options("space") + today := time.Now() + now := today + n := kit.Int(kit.Select("1", m.Option("count"))) + + cur := now + for i := 0; i < n; i, now = i+1, now.AddDate(0, 1, 0) { + begin := time.Unix(now.Unix()-int64(now.Day()-1)*24*3600, 0) + last := time.Unix(begin.Unix()-int64(begin.Weekday())*24*3600, 0) + cur = last + + if last.Month() != now.Month() { + for month := cur.Month(); cur.Month() == month; cur = cur.AddDate(0, 0, 1) { + if space || i == 0 { + m.Push(show[int(cur.Weekday())], "") + } + } + } + for month := cur.Month(); cur.Month() == month; cur = cur.AddDate(0, 0, 1) { + data := fmt.Sprintf("%d", cur.Day()) + if cur.Year() == today.Year() && cur.YearDay() == today.YearDay() { + data = fmt.Sprintf(">%d<", cur.Day()) + } + if cur.Day() == 1 { + if cur.Month() == 1 { + data = fmt.Sprintf("%d年", cur.Year()) + } else { + data = fmt.Sprintf("%d月", cur.Month()) + } + } + m.Push(show[int(cur.Weekday())], data) + } + if space || i == n-1 { + for ; cur.Weekday() > 0; cur = cur.AddDate(0, 0, 1) { + m.Push(show[int(cur.Weekday())], "") + } + } + } + }}, + "stat": {Name: "stat", Help: "统计", Meta: kit.Dict( + // "display", "github.com/shylinux/icebergs/core/team/stat", + ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + m.Push("weekly", 10) + m.Push("month", 100) + m.Push("year", 1000) + }}, + "progress": {Name: "progress", Help: "进度", Meta: kit.Dict( + "display", "github.com/shylinux/icebergs/core/team/miss", + "detail", []string{"回退", "前进", "取消", "完成"}, + ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { if len(arg) > 0 { - // 规范命名 - if !strings.Contains(arg[0], "-") { - arg[0] = m.Time("20060102-") + arg[0] - } - - // 创建目录 - p := path.Join(m.Conf("miss", "meta.path"), arg[0]) - if _, e := os.Stat(p); e != nil { - os.MkdirAll(p, 0777) - } - - if !m.Confs(ice.WEB_SPACE, kit.Keys("hash", arg[0])) { - // 启动任务 - m.Option("cmd_dir", p) - m.Option("cmd_type", "daemon") - m.Cmd(ice.GDB_EVENT, "action", "miss.start", arg[0]) - m.Cmd(m.Confv("miss", "meta.cmd")) - } + m.Grows(ice.APP_MISS, nil, "id", arg[0], func(index int, value map[string]interface{}) { + switch value["status"] { + case "准备中": + switch arg[1] { + case "开始": + value["status"] = "进行中" + value["begin_time"] = m.Time() + value["close_time"] = m.Time("30m") + case "取消": + value["status"] = "已取消" + value["close_time"] = m.Time() + case "完成": + value["status"] = "已完成" + value["close_time"] = m.Time() + } + case "进行中": + switch arg[1] { + case "准备": + value["status"] = "准备中" + value["begin_time"] = m.Time() + value["close_time"] = m.Time() + case "取消": + value["status"] = "已取消" + value["close_time"] = m.Time() + case "完成": + value["status"] = "已完成" + value["close_time"] = m.Time() + } + } + }) } - // 任务列表 - m.Cmdy("nfs.dir", m.Conf("miss", "meta.path"), "", "time name") - m.Table(func(index int, value map[string]string, head []string) { - m.Push("status", kit.Select("start", "stop", m.Richs(ice.WEB_SPACE, nil, value["name"], nil) == nil)) + m.Push("准备中", "") + m.Push("开发中", "") + m.Push("测试中", "") + m.Push("发布中", "") + m.Push("已取消", "") + m.Push("已完成", "") + m.Grows(ice.APP_MISS, nil, "", "", func(index int, value map[string]interface{}) { + m.Push(kit.Format(value["status"]), + kit.Format(`%v`, + kit.Format("%s-%s\n%s", value["begin_time"], value["close_time"], value["text"]), + value["id"], value["name"])) }) }}, }, diff --git a/misc/shy.go b/misc/shy.go index 5b3d8395..848564d8 100644 --- a/misc/shy.go +++ b/misc/shy.go @@ -1,5 +1,6 @@ package misc import ( + _ "github.com/shylinux/icebergs/misc/git" _ "github.com/shylinux/icebergs/misc/tmux" ) diff --git a/misc/tmux/tmux.go b/misc/tmux/tmux.go index 89495479..8da685ef 100644 --- a/misc/tmux/tmux.go +++ b/misc/tmux/tmux.go @@ -52,9 +52,11 @@ var Index = &ice.Context{Name: "tmux", Help: "终端模块", }, Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd(ice.GDB_EVENT, "listen", ice.DREAM_START, "cli.tmux.auto") - if m.Richs(ice.WEB_STORY, "head", "auto.sh", nil) == nil { - m.Cmd(ice.WEB_STORY, "add", "shell", "auto.sh", m.Cmdx(ice.WEB_SPIDE, "shy", "GET", "/publish/auto.sh")) + m.Watch(ice.DREAM_START, "cli.tmux.auto") + for _, p := range []string{"auto.sh", "auto.vim"} { + if m.Richs(ice.WEB_STORY, "head", p, nil) == nil { + m.Cmd(ice.WEB_STORY, "add", ice.TYPE_SHELL, p, m.Cmdx(ice.WEB_SPIDE, "shy", "cache", "GET", "/publish/"+p)) + } } if m.Richs(ice.WEB_FAVOR, nil, ice.FAVOR_TMUX, nil) == nil { m.Cmd(ice.WEB_FAVOR, ice.FAVOR_TMUX, ice.TYPE_SHELL, "下载脚本", `curl -s "$ctx_dev/code/zsh?cmd=download&arg=auto.sh" > auto.sh`) @@ -63,6 +65,7 @@ var Index = &ice.Context{Name: "tmux", Help: "终端模块", }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { }}, + "buffer": {Name: "buffer", Help: "终端", List: kit.List( kit.MDB_INPUT, "text", "name", "buffer", "action", "auto", diff --git a/type.go b/type.go index b9b471a8..55af344c 100644 --- a/type.go +++ b/type.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "math/rand" + "net/http" "os" "path" "runtime" @@ -143,6 +144,7 @@ func (c *Context) Close(m *Message, arg ...string) bool { type Message struct { time time.Time code int + Hand bool meta map[string][]string data map[string]interface{} @@ -153,8 +155,10 @@ type Message struct { source *Context target *Context - Hand bool - cb func(*Message) *Message + + cb func(*Message) *Message + W http.ResponseWriter + R *http.Request } func (m *Message) Time(args ...interface{}) string { @@ -347,6 +351,9 @@ func (m *Message) Copy(msg *Message) *Message { func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Message { switch value := value.(type) { case map[string]interface{}: + if key == "detail" { + value = kit.KeyValue(map[string]interface{}{}, "", value) + } list := []string{} if len(arg) > 0 { list = kit.Simple(arg[0]) @@ -358,10 +365,16 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa } for _, k := range list { - if k == "key" { - m.Add(MSG_APPEND, k, key) - } else { - m.Add(MSG_APPEND, k, kit.Format(value[k])) + switch key { + case "detail": + m.Add(MSG_APPEND, "key", k) + m.Add(MSG_APPEND, "value", kit.Format(value[k])) + default: + if k == "key" { + m.Add(MSG_APPEND, k, key) + } else { + m.Add(MSG_APPEND, k, kit.Format(kit.Value(value, k))) + } } } return m @@ -642,6 +655,15 @@ func (m *Message) Trace(key string, str string, arg ...interface{}) *Message { return m } +func (m *Message) Event(key string, arg ...string) *Message { + m.Cmd(GDB_EVENT, "action", key, arg) + return m +} +func (m *Message) Watch(key string, arg ...string) *Message { + m.Cmd(GDB_EVENT, "listen", key, arg) + return m +} + func (m *Message) Assert(arg interface{}) bool { switch arg := arg.(type) { case nil: @@ -826,7 +848,7 @@ func (m *Message) Richs(key string, chain interface{}, raw interface{}, cb inter h := kit.Format(raw) switch h { - case "*", "": + case "*": // 全部遍历 switch cb := cb.(type) { case func(string, map[string]interface{}): @@ -838,12 +860,14 @@ func (m *Message) Richs(key string, chain interface{}, raw interface{}, cb inter return res case "%": // 随机选取 - list := []string{} - for k := range hash { - list = append(list, k) + if len(hash) > 0 { + list := []string{} + for k := range hash { + list = append(list, k) + } + h = list[rand.Intn(len(list))] + res, _ = hash[h].(map[string]interface{}) } - h = list[rand.Intn(len(list))] - res, _ = hash[h].(map[string]interface{}) default: // 单个查询 if res, ok = hash[h].(map[string]interface{}); !ok { @@ -1128,6 +1152,7 @@ func (m *Message) Cmd(arg ...interface{}) *Message { } else { c.Run(msg, cmd, key, list[1:]...) } + m.Hand, msg.Hand = true, true }) })