diff --git a/base/ctx/ctx.go b/base/ctx/ctx.go index 51cb5274..c5b38707 100644 --- a/base/ctx/ctx.go +++ b/base/ctx/ctx.go @@ -11,37 +11,192 @@ import ( "strings" ) +func _parse_arg_all(m *ice.Message, arg ...string) (bool, []string) { + if len(arg) > 0 && arg[0] == "all" { + return true, arg[1:] + } + return false, arg + +} +func _parse_arg_chain(m *ice.Message, arg ...string) (string, []string) { + if len(arg) > 1 { + return kit.Keys(arg[0], arg[1]), arg[2:] + } + return arg[0], arg[1:] +} + +func _config_list(m *ice.Message, all bool) { + p := m.Spawn(m.Source()) + if all { + p = ice.Pulse + } + p.Travel(func(p *ice.Context, s *ice.Context, key string, conf *ice.Config) { + m.Push("key", key) + m.Push("name", conf.Name) + m.Push("value", kit.Format(conf.Value)) + }) + +} +func _config_save(m *ice.Message, name string, arg ...string) { + msg := m.Spawn(m.Source()) + // 保存配置 + if m.Cap(ice.CTX_STATUS) != ice.ICE_START { + return + } + name = path.Join(msg.Conf(ice.CTX_CONFIG, "meta.path"), name) + if f, p, e := kit.Create(name); m.Assert(e) { + data := map[string]interface{}{} + for _, k := range arg { + data[k] = msg.Confv(k) + } + if s, e := json.MarshalIndent(data, "", " "); m.Assert(e) { + if n, e := f.Write(s); m.Assert(e) { + m.Log("info", "save %d %s", n, p) + } + } + m.Echo(p) + } +} +func _config_load(m *ice.Message, name string, arg ...string) { + msg := m.Spawn(m.Source()) + // 加载配置 + name = path.Join(msg.Conf(ice.CTX_CONFIG, "meta.path"), name) + if f, e := os.Open(name); e == nil { + data := map[string]interface{}{} + json.NewDecoder(f).Decode(&data) + + for k, v := range data { + msg.Search(k, func(p *ice.Context, s *ice.Context, key string) { + m.Log("info", "load %s.%s %v", s.Name, key, kit.Format(v)) + s.Configs[key].Value = v + }) + } + } +} +func _config_make(m *ice.Message, chain string, arg ...string) { + msg := m.Spawn(m.Source()) + if len(arg) > 1 { + if strings.HasPrefix(arg[1], "@") { + msg.Conf(chain, arg[0], msg.Cmdx("nfs.cat", arg[1][1:])) + } else { + msg.Conf(chain, arg[0], kit.Parse(nil, "", arg[1:]...)) + } + } + + if len(arg) > 0 { + // 读取配置 + m.Echo(kit.Formats(msg.Confv(chain, arg[0]))) + } else { + // 读取配置 + m.Echo(kit.Formats(msg.Confv(chain))) + } +} + +func _command_list(m *ice.Message, all bool) { + p := m.Spawn(m.Source()) + if all { + p = ice.Pulse + } + + // 命令列表 + p.Travel(func(p *ice.Context, s *ice.Context) { + list := []string{} + for k := range s.Commands { + if k[0] == '/' || k[0] == '_' { + // 内部命令 + continue + } + list = append(list, k) + } + sort.Strings(list) + + for _, k := range list { + v := s.Commands[k] + m.Push("key", s.Cap(ice.CTX_FOLLOW)) + m.Push("index", k) + m.Push("name", kit.Format(v.Name)) + m.Push("help", kit.Simple(v.Help)[0]) + // m.Push("list", kit.Format(v.List)) + } + }) +} +func _command_make(m *ice.Message, cmd *ice.Command) { + var list []string + switch name := cmd.Name.(type) { + case []string, []interface{}: + list = kit.Split(kit.Simple(name)[0]) + default: + list = kit.Split(strings.Split(kit.Format(name), ";")[0]) + } + + button := false + for i, v := range list { + if i > 0 { + switch ls := kit.Split(v, ":="); ls[0] { + case "[", "]": + case "auto": + cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "button", "name", "查看", "value", "auto")...) + cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "button", "name", "返回", "value", "Last")...) + button = true + default: + kind, value := "text", "" + if len(ls) == 3 { + kind, value = ls[1], ls[2] + } else if len(ls) == 2 { + if strings.Contains(v, "=") { + value = ls[1] + } else { + kind = ls[1] + } + } + if kind == "button" { + button = true + } + cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, kind, "name", ls[0], "value", value)...) + } + } + } + if len(cmd.List) == 0 { + cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "text", "name", "name")...) + } + if !button { + cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "button", "name", "查看")...) + cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "button", "name", "返回", "value", "Last")...) + } +} + +func _context_list(m *ice.Message, all bool) { + p := m.Spawn(m.Source()) + if all { + p = ice.Pulse + } + + p.Travel(func(p *ice.Context, s *ice.Context) { + if p != nil { + m.Push("ups", kit.Select("shy", p.Cap(ice.CTX_FOLLOW))) + } else { + m.Push("ups", "shy") + } + m.Push("name", s.Name) + m.Push(ice.CTX_STATUS, s.Cap(ice.CTX_STATUS)) + m.Push(ice.CTX_STREAM, s.Cap(ice.CTX_STREAM)) + m.Push("help", s.Help) + }) +} + var Index = &ice.Context{Name: "ctx", Help: "配置模块", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ ice.CTX_CONFIG: {Name: "config", Help: "配置", Value: kit.Data("path", "var/conf")}, - "demo": {Name: "demo", Help: "配置", Value: kit.Data("path", "var/conf")}, }, Commands: map[string]*ice.Command{ ice.CTX_CONTEXT: {Name: "context [all]", Help: "模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - all := false - if len(arg) > 0 && arg[0] == "all" { - all, arg = true, arg[1:] + if all, arg := _parse_arg_all(m, arg...); len(arg) == 0 { + _context_list(m, all) + return } - if p := m.Spawn(m.Source()); len(arg) == 0 { - if all == true { - p = ice.Pulse - } - // 模块列表 - p.Travel(func(p *ice.Context, s *ice.Context) { - if p != nil { - m.Push("ups", kit.Select("shy", p.Cap(ice.CTX_FOLLOW))) - } else { - m.Push("ups", "shy") - } - m.Push("name", s.Name) - m.Push(ice.CTX_STATUS, s.Cap(ice.CTX_STATUS)) - m.Push(ice.CTX_STREAM, s.Cap(ice.CTX_STREAM)) - m.Push("help", s.Help) - }) - return - } else if len(arg) == 1 { + if len(arg) == 1 { m.Cmdy(ice.CTX_COMMAND, arg[0]+".") } else { m.Search(arg[0]+".", func(p *ice.Context, s *ice.Context, key string) { @@ -51,7 +206,6 @@ var Index = &ice.Context{Name: "ctx", Help: "配置模块", msg.Cmdy(ice.CTX_COMMAND, arg[0], arg[2:]) case "config": msg.Cmdy(ice.CTX_CONFIG, arg[2:]) - case "cache": } m.Copy(msg) }) @@ -59,45 +213,12 @@ var Index = &ice.Context{Name: "ctx", Help: "配置模块", }}, ice.CTX_COMMAND: {Name: "command [all] [context [command run arg...]]", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - all := false - if len(arg) > 0 && arg[0] == "all" { - all, arg = true, arg[1:] - } - - if p := m.Spawn(m.Source()); len(arg) == 0 { - if all == true { - p = ice.Pulse - } - // 命令列表 - p.Travel(func(p *ice.Context, s *ice.Context) { - list := []string{} - for k := range s.Commands { - if k[0] == '/' || k[0] == '_' { - // 内部命令 - continue - } - list = append(list, k) - } - sort.Strings(list) - - for _, k := range list { - v := s.Commands[k] - m.Push("key", s.Cap(ice.CTX_FOLLOW)) - m.Push("index", k) - m.Push("name", kit.Format(v.Name)) - m.Push("help", kit.Simple(v.Help)[0]) - m.Push("list", kit.Format(v.List)) - } - }) + if all, arg := _parse_arg_all(m, arg...); len(arg) == 0 { + _command_list(m, all) return } - chain := arg[0] - if len(arg) > 1 { - chain = kit.Keys(arg[0], arg[1]) - arg = arg[1:] - } - arg = arg[1:] + chain, arg := _parse_arg_chain(m, arg...) m.Search(chain, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) { if len(arg) == 0 { // 命令列表 @@ -106,54 +227,13 @@ var Index = &ice.Context{Name: "ctx", Help: "配置模块", m.Push("help", kit.Simple(cmd.Help)[0]) m.Push("meta", kit.Format(cmd.Meta)) if len(cmd.List) == 0 { - var list []string - switch name := cmd.Name.(type) { - case []string, []interface{}: - list = kit.Split(kit.Simple(name)[0]) - default: - list = kit.Split(strings.Split(kit.Format(name), ";")[0]) - } - - button := false - for i, v := range list { - if i > 0 { - switch ls := kit.Split(v, ":="); ls[0] { - case "[", "]": - case "auto": - cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "button", "name", "查看", "value", "auto")...) - cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "button", "name", "返回", "value", "Last")...) - button = true - default: - kind, value := "text", "" - if len(ls) == 3 { - kind, value = ls[1], ls[2] - } else if len(ls) == 2 { - if strings.Contains(v, "=") { - value = ls[1] - } else { - kind = ls[1] - } - } - if kind == "button" { - button = true - } - cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, kind, "name", ls[0], "value", value)...) - } - } - } - if len(cmd.List) == 0 { - cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "text", "name", "name")...) - } - if !button { - cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "button", "name", "查看")...) - cmd.List = append(cmd.List, kit.List(kit.MDB_INPUT, "button", "name", "返回", "value", "Last")...) - } + _command_make(m, cmd) } m.Push("list", kit.Format(cmd.List)) } else { if you := m.Option(kit.Format(kit.Value(cmd.Meta, "remote"))); you != "" { // 远程命令 - m.Copy(m.Spawns(s).Cmd(ice.WEB_SPACE, you, "ctx.command", chain, "run", arg[1:])) + m.Copy(m.Spawns(s).Cmd(ice.WEB_SPACE, you, ice.CTX_COMMAND, chain, "run", arg[1:])) } else { // 本地命令 m.Copy(s.Run(m.Spawns(s), cmd, key, arg[1:]...)) @@ -161,75 +241,19 @@ var Index = &ice.Context{Name: "ctx", Help: "配置模块", } }) }}, - ice.CTX_CONFIG: {Name: "config [all] [save|load] chain key arg...", Help: "配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - all := false - if len(arg) > 0 && arg[0] == "all" { - all, arg = true, arg[1:] - } - - msg := m.Spawn(m.Source()) - if len(arg) == 0 { - if all == true { - msg = ice.Pulse - } - // 配置列表 - msg.Travel(func(p *ice.Context, s *ice.Context, key string, conf *ice.Config) { - m.Push("key", key) - m.Push("name", conf.Name) - m.Push("value", kit.Format(conf.Value)) - }) + ice.CTX_CONFIG: {Name: "config [all] [chain [key [arg...]]]", Help: "配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if all, arg := _parse_arg_all(m, arg...); len(arg) == 0 { + _config_list(m, all) return } switch arg[0] { case "save": - // 保存配置 - if m.Cap(ice.CTX_STATUS) != ice.ICE_START { - break - } - arg[1] = path.Join(msg.Conf(ice.CTX_CONFIG, "meta.path"), arg[1]) - if f, p, e := kit.Create(arg[1]); m.Assert(e) { - data := map[string]interface{}{} - for _, k := range arg[2:] { - data[k] = msg.Confv(k) - } - if s, e := json.MarshalIndent(data, "", " "); m.Assert(e) { - if n, e := f.Write(s); m.Assert(e) { - m.Log("info", "save %d %s", n, p) - } - } - m.Echo(p) - } + _config_save(m, arg[1], arg[2:]...) case "load": - // 加载配置 - arg[1] = path.Join(msg.Conf(ice.CTX_CONFIG, "meta.path"), arg[1]) - if f, e := os.Open(arg[1]); e == nil { - data := map[string]interface{}{} - json.NewDecoder(f).Decode(&data) - - for k, v := range data { - msg.Search(k, func(p *ice.Context, s *ice.Context, key string) { - m.Log("info", "load %s.%s %v", s.Name, key, kit.Format(v)) - s.Configs[key].Value = v - }) - } - } + _config_load(m, arg[1], arg[2:]...) default: - if len(arg) > 2 { - if strings.HasPrefix(arg[2], "@") { - msg.Conf(arg[0], arg[1], msg.Cmdx("nfs.cat", arg[2][1:])) - } else { - msg.Conf(arg[0], arg[1], kit.Parse(nil, "", arg[2:]...)) - } - } - - if len(arg) > 1 { - // 读取配置 - m.Echo(kit.Formats(msg.Confv(arg[0], arg[1]))) - } else { - // 读取配置 - m.Echo(kit.Formats(msg.Confv(arg[0]))) - } + _config_make(m, arg[0], arg[1:]...) } }}, }, diff --git a/base/web/story.go b/base/web/story.go index 850bc973..28189c70 100644 --- a/base/web/story.go +++ b/base/web/story.go @@ -6,9 +6,367 @@ import ( "os" "path" + "strings" "time" ) +func _story_share(m *ice.Message, story string, list string, arg ...string) { + if m.Echo("share: "); list == "" { + msg := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, story) + m.Cmdy(ice.WEB_SHARE, "add", "story", story, msg.Append("list")) + } else { + msg := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, list) + m.Cmdy(ice.WEB_SHARE, "add", msg.Append("scene"), msg.Append("story"), msg.Append("text")) + } +} +func _story_list(m *ice.Message, arg ...string) { + // 故事列表 + 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") +} +func _story_show(m *ice.Message, arg ...string) { + if len(arg) == 1 { + // 故事记录 + m.Cmdy(ice.WEB_STORY, "history", arg) + return + } + // 故事详情 + m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, arg[1]).Table(func(index int, value map[string]string, head []string) { + for k, v := range value { + m.Push("key", k) + m.Push("value", v) + } + m.Sort("key") + }) +} + +func _story_pull(m *ice.Message, arg ...string) { + // 起止节点 + prev, begin, end := "", arg[3], "" + repos := kit.Keys("remote", arg[2], arg[3]) + m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { + end = kit.Format(kit.Value(val, kit.Keys(repos, "pull", "list"))) + prev = kit.Format(val["list"]) + }) + + pull := end + var first map[string]interface{} + for begin != "" && begin != end { + if m.Cmd(ice.WEB_SPIDE, arg[2], "msg", "/story/pull", "begin", begin, "end", end).Table(func(index int, value map[string]string, head []string) { + if m.Richs(ice.WEB_CACHE, nil, value["data"], nil) == nil { + m.Log(ice.LOG_IMPORT, "%v: %v", value["data"], value["save"]) + if node := kit.UnMarshal(value["save"]); kit.Format(kit.Value(node, "file")) != "" { + // 下载文件 + m.Cmd(ice.WEB_SPIDE, arg[2], "cache", "GET", "/story/download/"+value["data"]) + } else { + // 导入缓存 + m.Conf(ice.WEB_CACHE, kit.Keys("hash", value["data"]), node) + } + } + + node := kit.UnMarshal(value["node"]).(map[string]interface{}) + if m.Richs(ice.WEB_STORY, nil, value["list"], nil) == nil { + // 导入节点 + m.Log(ice.LOG_IMPORT, "%v: %v", value["list"], value["node"]) + m.Conf(ice.WEB_STORY, kit.Keys("hash", value["list"]), node) + } + + if first == nil { + if m.Richs(ice.WEB_STORY, "head", arg[1], nil) == nil { + // 自动创建 + h := m.Rich(ice.WEB_STORY, "head", kit.Dict( + "scene", node["scene"], "story", arg[1], + "count", node["count"], "list", value["list"], + )) + m.Log(ice.LOG_CREATE, "%v: %v", h, node["story"]) + } + + pull, first = kit.Format(value["list"]), node + m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { + prev = kit.Format(val["list"]) + if kit.Int(node["count"]) > kit.Int(kit.Value(val, kit.Keys(repos, "pull", "count"))) { + // 更新分支 + m.Log(ice.LOG_IMPORT, "%v: %v", arg[2], pull) + kit.Value(val, kit.Keys(repos, "pull"), kit.Dict( + "head", arg[3], "time", node["time"], "list", pull, "count", node["count"], + )) + } + }) + } + + if prev == kit.Format(node["prev"]) || prev == kit.Format(node["push"]) { + // 快速合并 + m.Log(ice.LOG_IMPORT, "%v: %v", pull, arg[2]) + m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { + val["count"] = first["count"] + val["time"] = first["time"] + val["list"] = pull + }) + prev = pull + } + + begin = kit.Format(node["prev"]) + }).Appendv("list") == nil { + break + } + } + +} +func _story_push(m *ice.Message, arg ...string) { + // 更新分支 + m.Cmdx(ice.WEB_STORY, "pull", arg[1:]) + + repos := kit.Keys("remote", arg[2], arg[3]) + // 查询索引 + prev, pull, some, list := "", "", "", "" + m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { + prev = kit.Format(val["list"]) + pull = kit.Format(kit.Value(val, kit.Keys(repos, "pull", "list"))) + for some = pull; prev != some && some != ""; { + local := m.Richs(ice.WEB_STORY, nil, prev, nil) + remote := m.Richs(ice.WEB_STORY, nil, some, nil) + if diff := kit.Time(kit.Format(remote["time"])) - kit.Time(kit.Format(local["time"])); diff > 0 { + some = kit.Format(remote["prev"]) + } else if diff < 0 { + prev = kit.Format(local["prev"]) + } + } + + if prev = kit.Format(val["list"]); prev == pull { + // 相同节点 + return + } + + if some != pull { + // 合并节点 + local := m.Richs(ice.WEB_STORY, nil, prev, nil) + remote := m.Richs(ice.WEB_STORY, nil, pull, nil) + list = m.Rich(ice.WEB_STORY, nil, kit.Dict( + "scene", val["scene"], "story", val["story"], "count", kit.Int(remote["count"])+1, + "data", local["data"], "prev", pull, "push", prev, + )) + m.Log(ice.LOG_CREATE, "merge: %s %s->%s", list, prev, pull) + val["list"] = list + prev = list + val["count"] = kit.Int(remote["count"]) + 1 + } + + // 查询节点 + nodes := []string{} + for list = prev; list != some; { + m.Richs(ice.WEB_STORY, nil, list, func(key string, value map[string]interface{}) { + nodes, list = append(nodes, list), kit.Format(value["prev"]) + }) + } + + for _, v := range kit.Revert(nodes) { + m.Richs(ice.WEB_STORY, nil, v, func(list string, node map[string]interface{}) { + m.Richs(ice.WEB_CACHE, nil, node["data"], func(data string, save map[string]interface{}) { + if kit.Format(save["file"]) != "" { + // 推送缓存 + m.Cmd(ice.WEB_SPIDE, arg[2], "/story/upload", + "part", "upload", "@"+kit.Format(save["file"]), + ) + } + + // 推送节点 + m.Log(ice.LOG_EXPORT, "%s: %s", v, kit.Format(node)) + m.Cmd(ice.WEB_SPIDE, arg[2], "/story/push", + "story", arg[3], "list", v, "node", kit.Format(node), + "data", node["data"], "save", kit.Format(save), + ) + }) + }) + } + }) + + // 更新分支 + m.Cmd(ice.WEB_STORY, "pull", arg[1:]) + +} +func _story_commit(m *ice.Message, arg ...string) { + // 查询索引 + head, prev, value, count := "", "", map[string]interface{}{}, 0 + m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { + head, prev, value, count = key, kit.Format(val["list"]), val, kit.Int(val["count"]) + m.Log("info", "head: %v prev: %v count: %v", head, prev, count) + }) + + // 提交信息 + arg[2] = m.Cmdx(ice.WEB_STORY, "add", "submit", arg[2], "hostname,username") + + // 节点信息 + menu := map[string]string{} + for i := 3; i < len(arg); i++ { + menu[arg[i]] = m.Cmdx(ice.WEB_STORY, ice.STORY_INDEX, arg[i]) + } + + // 添加节点 + list := m.Rich(ice.WEB_STORY, nil, kit.Dict( + "scene", "commit", "story", arg[1], "count", count+1, "data", arg[2], "list", menu, "prev", prev, + )) + m.Log(ice.LOG_CREATE, "commit: %s %s: %s", list, arg[1], arg[2]) + m.Push("list", list) + + if head == "" { + // 添加索引 + m.Rich(ice.WEB_STORY, "head", kit.Dict("scene", "commit", "story", arg[1], "count", count+1, "list", list)) + } else { + // 更新索引 + value["count"] = count + 1 + value["time"] = m.Time() + value["list"] = list + } + m.Echo(list) + +} + +func _story_trash(m *ice.Message, arg ...string) { + bak := kit.Select(kit.Keys(arg[1], "bak"), arg, 2) + os.Remove(bak) + os.Rename(arg[1], bak) +} +func _story_watch(m *ice.Message, arg ...string) { + // 备份文件 + name := kit.Select(arg[1], arg, 2) + m.Cmd(ice.WEB_STORY, ice.STORY_TRASH, name) + + if msg := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, arg[1]); msg.Append("file") != "" { + p := path.Dir(name) + os.MkdirAll(p, 0777) + + // 导出文件 + os.Link(msg.Append("file"), name) + m.Log(ice.LOG_EXPORT, "%s: %s", msg.Append("file"), name) + } else { + if f, p, e := kit.Create(name); m.Assert(e) { + defer f.Close() + // 导出数据 + f.WriteString(msg.Append("text")) + m.Log(ice.LOG_EXPORT, "%s: %s", msg.Append("text"), p) + } + } + m.Echo(name) +} +func _story_catch(m *ice.Message, arg ...string) { + if last := m.Richs(ice.WEB_STORY, "head", arg[2], nil); last != nil { + if t, e := time.ParseInLocation(ice.ICE_TIME, kit.Format(last["time"]), time.Local); e == nil { + // 文件对比 + if s, e := os.Stat(arg[2]); e == nil && s.ModTime().Before(t) { + m.Info("%s last: %s", arg[2], kit.Format(t)) + m.Echo("%s", last["list"]) + return + } + } + } + _story_add(m, arg...) +} +func _story_add(m *ice.Message, arg ...string) { + if m.Richs(ice.WEB_CACHE, nil, kit.Select("", arg, 3), func(key string, value map[string]interface{}) { + // 复用缓存 + arg[3] = key + }) == nil { + // 添加缓存 + m.Cmdy(ice.WEB_CACHE, arg) + arg = []string{arg[0], m.Append("type"), m.Append("name"), m.Append("data")} + } + + // 查询索引 + head, prev, value, count := "", "", map[string]interface{}{}, 0 + m.Richs(ice.WEB_STORY, "head", arg[2], func(key string, val map[string]interface{}) { + head, prev, value, count = key, kit.Format(val["list"]), val, kit.Int(val["count"]) + m.Log("info", "head: %v prev: %v count: %v", head, prev, count) + }) + + if last := m.Richs(ice.WEB_STORY, nil, prev, nil); prev != "" && last != nil && last["data"] == arg[3] { + // 重复提交 + m.Echo(prev) + } else { + // 添加节点 + list := m.Rich(ice.WEB_STORY, nil, kit.Dict( + "scene", arg[1], "story", arg[2], "count", count+1, "data", arg[3], "prev", prev, + )) + m.Log(ice.LOG_CREATE, "story: %s %s: %s", list, arg[1], arg[2]) + m.Push("list", list) + + if head == "" { + // 添加索引 + m.Rich(ice.WEB_STORY, "head", kit.Dict("scene", arg[1], "story", arg[2], "count", count+1, "list", list)) + } else { + // 更新索引 + value["count"] = count + 1 + value["time"] = m.Time() + value["list"] = list + } + m.Echo(list) + } + + // 分发数据 + if p := kit.Select(m.Conf(ice.WEB_FAVOR, "meta.proxy"), m.Option("you")); p != "" { + m.Info("what %v", p) + m.Option("you", "") + m.Cmd(ice.WEB_PROXY, p, ice.WEB_STORY, ice.STORY_PULL, arg[2], "dev", arg[2]) + } + +} + +func _story_index(m *ice.Message, arg ...string) { + m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, value map[string]interface{}) { + // 查询索引 + arg[1] = kit.Format(value["list"]) + }) + + m.Richs(ice.WEB_STORY, nil, arg[1], func(key string, value map[string]interface{}) { + // 查询节点 + m.Push("list", key) + m.Push(key, value, []string{"scene", "story"}) + arg[1] = kit.Format(value["data"]) + }) + + m.Richs(ice.WEB_CACHE, nil, arg[1], func(key string, value map[string]interface{}) { + // 查询数据 + m.Push("data", key) + m.Push(key, value, []string{"text", "time", "size", "type", "name", "file"}) + m.Echo("%s", value["text"]) + }) +} +func _story_history(m *ice.Message, arg ...string) { + // 历史记录 + list := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, arg[1]).Append("list") + for i := 0; i < kit.Int(kit.Select("30", m.Option("cache.limit"))) && list != ""; i++ { + + m.Richs(ice.WEB_STORY, nil, list, func(key string, value map[string]interface{}) { + // 直连节点 + m.Push(key, value, []string{"time", "key", "count", "scene", "story"}) + m.Richs(ice.WEB_CACHE, nil, value["data"], func(key string, value map[string]interface{}) { + m.Push("drama", value["text"]) + m.Push("data", key) + }) + + kit.Fetch(value["list"], func(key string, val string) { + m.Richs(ice.WEB_STORY, nil, val, func(key string, value map[string]interface{}) { + // 复合节点 + m.Push(key, value, []string{"time", "key", "count", "scene", "story"}) + m.Richs(ice.WEB_CACHE, nil, value["data"], func(key string, value map[string]interface{}) { + m.Push("drama", value["text"]) + m.Push("data", key) + }) + }) + }) + + // 切换节点 + list = kit.Format(value["prev"]) + }) + } +} + +func StoryWatch(m *ice.Message, file string, name string) { _story_watch(m, file, name) } +func StoryCatch(m *ice.Message, mime string, file string) { + _story_catch(m, "catch", kit.Select(mime, strings.TrimPrefix(path.Ext(file), ".")), file) +} + func init() { Index.Merge(&ice.Context{ Configs: map[string]*ice.Config{ @@ -33,361 +391,46 @@ func init() { switch arg[1] { case "share", "共享": - if m.Echo("share: "); list == "" { - msg := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, story) - m.Cmdy(ice.WEB_SHARE, "add", "story", story, msg.Append("list")) - } else { - msg := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, list) - m.Cmdy(ice.WEB_SHARE, "add", msg.Append("scene"), msg.Append("story"), msg.Append("text")) - } + _story_share(m, story, list, arg...) } return } if len(arg) == 0 { - // 故事列表 - 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") + _story_list(m, arg...) return } switch arg[0] { case ice.STORY_PULL: // story [spide [story]] - // 起止节点 - prev, begin, end := "", arg[3], "" - repos := kit.Keys("remote", arg[2], arg[3]) - m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { - end = kit.Format(kit.Value(val, kit.Keys(repos, "pull", "list"))) - prev = kit.Format(val["list"]) - }) - - pull := end - var first map[string]interface{} - for begin != "" && begin != end { - if m.Cmd(ice.WEB_SPIDE, arg[2], "msg", "/story/pull", "begin", begin, "end", end).Table(func(index int, value map[string]string, head []string) { - if m.Richs(ice.WEB_CACHE, nil, value["data"], nil) == nil { - m.Log(ice.LOG_IMPORT, "%v: %v", value["data"], value["save"]) - if node := kit.UnMarshal(value["save"]); kit.Format(kit.Value(node, "file")) != "" { - // 下载文件 - m.Cmd(ice.WEB_SPIDE, arg[2], "cache", "GET", "/story/download/"+value["data"]) - } else { - // 导入缓存 - m.Conf(ice.WEB_CACHE, kit.Keys("hash", value["data"]), node) - } - } - - node := kit.UnMarshal(value["node"]).(map[string]interface{}) - if m.Richs(ice.WEB_STORY, nil, value["list"], nil) == nil { - // 导入节点 - m.Log(ice.LOG_IMPORT, "%v: %v", value["list"], value["node"]) - m.Conf(ice.WEB_STORY, kit.Keys("hash", value["list"]), node) - } - - if first == nil { - if m.Richs(ice.WEB_STORY, "head", arg[1], nil) == nil { - // 自动创建 - h := m.Rich(ice.WEB_STORY, "head", kit.Dict( - "scene", node["scene"], "story", arg[1], - "count", node["count"], "list", value["list"], - )) - m.Log(ice.LOG_CREATE, "%v: %v", h, node["story"]) - } - - pull, first = kit.Format(value["list"]), node - m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { - prev = kit.Format(val["list"]) - if kit.Int(node["count"]) > kit.Int(kit.Value(val, kit.Keys(repos, "pull", "count"))) { - // 更新分支 - m.Log(ice.LOG_IMPORT, "%v: %v", arg[2], pull) - kit.Value(val, kit.Keys(repos, "pull"), kit.Dict( - "head", arg[3], "time", node["time"], "list", pull, "count", node["count"], - )) - } - }) - } - - if prev == kit.Format(node["prev"]) || prev == kit.Format(node["push"]) { - // 快速合并 - m.Log(ice.LOG_IMPORT, "%v: %v", pull, arg[2]) - m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { - val["count"] = first["count"] - val["time"] = first["time"] - val["list"] = pull - }) - prev = pull - } - - begin = kit.Format(node["prev"]) - }).Appendv("list") == nil { - break - } - } - + _story_pull(m, arg...) case ice.STORY_PUSH: - // 更新分支 - m.Cmdx(ice.WEB_STORY, "pull", arg[1:]) - - repos := kit.Keys("remote", arg[2], arg[3]) - // 查询索引 - prev, pull, some, list := "", "", "", "" - m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { - prev = kit.Format(val["list"]) - pull = kit.Format(kit.Value(val, kit.Keys(repos, "pull", "list"))) - for some = pull; prev != some && some != ""; { - local := m.Richs(ice.WEB_STORY, nil, prev, nil) - remote := m.Richs(ice.WEB_STORY, nil, some, nil) - if diff := kit.Time(kit.Format(remote["time"])) - kit.Time(kit.Format(local["time"])); diff > 0 { - some = kit.Format(remote["prev"]) - } else if diff < 0 { - prev = kit.Format(local["prev"]) - } - } - - if prev = kit.Format(val["list"]); prev == pull { - // 相同节点 - return - } - - if some != pull { - // 合并节点 - local := m.Richs(ice.WEB_STORY, nil, prev, nil) - remote := m.Richs(ice.WEB_STORY, nil, pull, nil) - list = m.Rich(ice.WEB_STORY, nil, kit.Dict( - "scene", val["scene"], "story", val["story"], "count", kit.Int(remote["count"])+1, - "data", local["data"], "prev", pull, "push", prev, - )) - m.Log(ice.LOG_CREATE, "merge: %s %s->%s", list, prev, pull) - val["list"] = list - prev = list - val["count"] = kit.Int(remote["count"]) + 1 - } - - // 查询节点 - nodes := []string{} - for list = prev; list != some; { - m.Richs(ice.WEB_STORY, nil, list, func(key string, value map[string]interface{}) { - nodes, list = append(nodes, list), kit.Format(value["prev"]) - }) - } - - for _, v := range kit.Revert(nodes) { - m.Richs(ice.WEB_STORY, nil, v, func(list string, node map[string]interface{}) { - m.Richs(ice.WEB_CACHE, nil, node["data"], func(data string, save map[string]interface{}) { - if kit.Format(save["file"]) != "" { - // 推送缓存 - m.Cmd(ice.WEB_SPIDE, arg[2], "/story/upload", - "part", "upload", "@"+kit.Format(save["file"]), - ) - } - - // 推送节点 - m.Log(ice.LOG_EXPORT, "%s: %s", v, kit.Format(node)) - m.Cmd(ice.WEB_SPIDE, arg[2], "/story/push", - "story", arg[3], "list", v, "node", kit.Format(node), - "data", node["data"], "save", kit.Format(save), - ) - }) - }) - } - }) - - // 更新分支 - m.Cmd(ice.WEB_STORY, "pull", arg[1:]) + _story_push(m, arg...) case "commit": - // 查询索引 - head, prev, value, count := "", "", map[string]interface{}{}, 0 - m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, val map[string]interface{}) { - head, prev, value, count = key, kit.Format(val["list"]), val, kit.Int(val["count"]) - m.Log("info", "head: %v prev: %v count: %v", head, prev, count) - }) - - // 提交信息 - arg[2] = m.Cmdx(ice.WEB_STORY, "add", "submit", arg[2], "hostname,username") - - // 节点信息 - menu := map[string]string{} - for i := 3; i < len(arg); i++ { - menu[arg[i]] = m.Cmdx(ice.WEB_STORY, ice.STORY_INDEX, arg[i]) - } - - // 添加节点 - list := m.Rich(ice.WEB_STORY, nil, kit.Dict( - "scene", "commit", "story", arg[1], "count", count+1, "data", arg[2], "list", menu, "prev", prev, - )) - m.Log(ice.LOG_CREATE, "commit: %s %s: %s", list, arg[1], arg[2]) - m.Push("list", list) - - if head == "" { - // 添加索引 - m.Rich(ice.WEB_STORY, "head", kit.Dict("scene", "commit", "story", arg[1], "count", count+1, "list", list)) - } else { - // 更新索引 - value["count"] = count + 1 - value["time"] = m.Time() - value["list"] = list - } - m.Echo(list) + _story_commit(m, arg...) case ice.STORY_TRASH: - bak := kit.Select(kit.Keys(arg[1], "bak"), arg, 2) - os.Remove(bak) - os.Rename(arg[1], bak) - + _story_trash(m, arg...) case ice.STORY_WATCH: - // 备份文件 - name := kit.Select(arg[1], arg, 2) - m.Cmd(ice.WEB_STORY, ice.STORY_TRASH, name) - - if msg := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, arg[1]); msg.Append("file") != "" { - p := path.Dir(name) - os.MkdirAll(p, 0777) - - // 导出文件 - os.Link(msg.Append("file"), name) - m.Log(ice.LOG_EXPORT, "%s: %s", msg.Append("file"), name) - } else { - if f, p, e := kit.Create(name); m.Assert(e) { - defer f.Close() - // 导出数据 - f.WriteString(msg.Append("text")) - m.Log(ice.LOG_EXPORT, "%s: %s", msg.Append("text"), p) - } - } - m.Echo(name) - + _story_watch(m, arg...) case ice.STORY_CATCH: - if last := m.Richs(ice.WEB_STORY, "head", arg[2], nil); last != nil { - if t, e := time.ParseInLocation(ice.ICE_TIME, kit.Format(last["time"]), time.Local); e == nil { - // 文件对比 - if s, e := os.Stat(arg[2]); e == nil && s.ModTime().Before(t) { - m.Info("%s last: %s", arg[2], kit.Format(t)) - m.Echo("%s", last["list"]) - break - } - } - } - fallthrough + _story_catch(m, arg...) case "add", ice.STORY_UPLOAD, ice.STORY_DOWNLOAD: - if m.Richs(ice.WEB_CACHE, nil, kit.Select("", arg, 3), func(key string, value map[string]interface{}) { - // 复用缓存 - arg[3] = key - }) == nil { - // 添加缓存 - m.Cmdy(ice.WEB_CACHE, arg) - arg = []string{arg[0], m.Append("type"), m.Append("name"), m.Append("data")} - } - - // 查询索引 - head, prev, value, count := "", "", map[string]interface{}{}, 0 - m.Richs(ice.WEB_STORY, "head", arg[2], func(key string, val map[string]interface{}) { - head, prev, value, count = key, kit.Format(val["list"]), val, kit.Int(val["count"]) - m.Log("info", "head: %v prev: %v count: %v", head, prev, count) - }) - - if last := m.Richs(ice.WEB_STORY, nil, prev, nil); prev != "" && last != nil && last["data"] == arg[3] { - // 重复提交 - m.Echo(prev) - } else { - // 添加节点 - list := m.Rich(ice.WEB_STORY, nil, kit.Dict( - "scene", arg[1], "story", arg[2], "count", count+1, "data", arg[3], "prev", prev, - )) - m.Log(ice.LOG_CREATE, "story: %s %s: %s", list, arg[1], arg[2]) - m.Push("list", list) - - if head == "" { - // 添加索引 - m.Rich(ice.WEB_STORY, "head", kit.Dict("scene", arg[1], "story", arg[2], "count", count+1, "list", list)) - } else { - // 更新索引 - value["count"] = count + 1 - value["time"] = m.Time() - value["list"] = list - } - m.Echo(list) - } - - // 分发数据 - if p := kit.Select(m.Conf(ice.WEB_FAVOR, "meta.proxy"), m.Option("you")); p != "" { - m.Info("what %v", p) - m.Option("you", "") - m.Cmd(ice.WEB_PROXY, p, ice.WEB_STORY, ice.STORY_PULL, arg[2], "dev", arg[2]) - } + _story_add(m, arg...) case ice.STORY_INDEX: - m.Richs(ice.WEB_STORY, "head", arg[1], func(key string, value map[string]interface{}) { - // 查询索引 - arg[1] = kit.Format(value["list"]) - }) - - m.Richs(ice.WEB_STORY, nil, arg[1], func(key string, value map[string]interface{}) { - // 查询节点 - m.Push("list", key) - m.Push(key, value, []string{"scene", "story"}) - arg[1] = kit.Format(value["data"]) - }) - - m.Richs(ice.WEB_CACHE, nil, arg[1], func(key string, value map[string]interface{}) { - // 查询数据 - m.Push("data", key) - m.Push(key, value, []string{"text", "time", "size", "type", "name", "file"}) - m.Echo("%s", value["text"]) - }) - + _story_index(m, arg...) case ice.STORY_HISTORY: - // 历史记录 - list := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, arg[1]).Append("list") - for i := 0; i < kit.Int(kit.Select("30", m.Option("cache.limit"))) && list != ""; i++ { - - m.Richs(ice.WEB_STORY, nil, list, func(key string, value map[string]interface{}) { - // 直连节点 - m.Push(key, value, []string{"time", "key", "count", "scene", "story"}) - m.Richs(ice.WEB_CACHE, nil, value["data"], func(key string, value map[string]interface{}) { - m.Push("drama", value["text"]) - m.Push("data", key) - }) - - kit.Fetch(value["list"], func(key string, val string) { - m.Richs(ice.WEB_STORY, nil, val, func(key string, value map[string]interface{}) { - // 复合节点 - m.Push(key, value, []string{"time", "key", "count", "scene", "story"}) - m.Richs(ice.WEB_CACHE, nil, value["data"], func(key string, value map[string]interface{}) { - m.Push("drama", value["text"]) - m.Push("data", key) - }) - }) - }) - - // 切换节点 - list = kit.Format(value["prev"]) - }) - } - + _story_history(m, arg...) default: - if len(arg) == 1 { - // 故事记录 - m.Cmdy(ice.WEB_STORY, "history", arg) - break - } - // 故事详情 - m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, arg[1]).Table(func(index int, value map[string]string, head []string) { - for k, v := range value { - m.Push("key", k) - m.Push("value", v) - } - m.Sort("key") - }) + _story_show(m, arg...) } }}, "/story/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[0] { case ice.STORY_PULL: - // 下载节点 - list := m.Cmd(ice.WEB_STORY, ice.STORY_INDEX, m.Option("begin")).Append("list") for i := 0; i < 10 && list != "" && list != m.Option("end"); i++ { if m.Richs(ice.WEB_STORY, nil, list, func(key string, value map[string]interface{}) { @@ -404,8 +447,6 @@ func init() { m.Log(ice.LOG_EXPORT, "%s %s", m.Option("begin"), m.Format("append")) case ice.STORY_PUSH: - // 上传节点 - if m.Richs(ice.WEB_CACHE, nil, m.Option("data"), nil) == nil { // 导入缓存 m.Log(ice.LOG_IMPORT, "%v: %v", m.Option("data"), m.Option("save")) diff --git a/base/web/web.go b/base/web/web.go index 30ebb81a..627509e3 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -46,7 +46,9 @@ func Format(key string, arg ...interface{}) string { return "" } func Render(msg *ice.Message, cmd string, args ...interface{}) { - msg.Log(ice.LOG_EXPORT, "%s: %v", cmd, args) + if cmd != "" { + msg.Log(ice.LOG_EXPORT, "%s: %v", cmd, args) + } switch arg := kit.Simple(args...); cmd { case ice.RENDER_OUTPUT: case "redirect": diff --git a/core/chat/action.go b/core/chat/action.go index 699cc9f9..69ec8e81 100644 --- a/core/chat/action.go +++ b/core/chat/action.go @@ -5,7 +5,7 @@ import ( "github.com/shylinux/toolkits" ) -func _action_share_create(m *ice.Message, c *ice.Context, cmd string, arg ...string) { +func _action_share_create(m *ice.Message, arg ...string) { if m.Option("index") != "" { arg = append(arg, "tool.0.pod", m.Option("node")) arg = append(arg, "tool.0.ctx", m.Option("group")) @@ -96,7 +96,7 @@ func init() { "/action": {Name: "/action", Help: "工作台", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[0] { case "share": - _action_share_create(m, c, cmd, arg...) + _action_share_create(m, arg...) return } if len(arg) == 0 || arg[0] == "" { diff --git a/core/wiki/inner.go b/core/wiki/inner.go new file mode 100644 index 00000000..4ace8d75 --- /dev/null +++ b/core/wiki/inner.go @@ -0,0 +1,44 @@ +package wiki + +import ( + ice "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/web" + kit "github.com/shylinux/toolkits" + + "os" +) + +func _inner_save(m *ice.Message, name, text string) { + if f, e := os.Create(name); m.Assert(e) { + defer f.Close() + if n, e := f.WriteString(text); m.Assert(e) { + m.Logs(ice.LOG_EXPORT, "file", name, "size", n) + } + } +} + +func init() { + const ( + INNER = "inner" + SAVE = "save" + COMMIT = "commit" + ) + + Index.Merge(&ice.Context{ + Configs: map[string]*ice.Config{ + INNER: {Name: "inner", Help: "编辑器", Value: kit.Data(kit.MDB_SHORT, INNER)}, + }, + Commands: map[string]*ice.Command{ + INNER: {Name: "inner path=auto auto", Help: "编辑器", Action: map[string]*ice.Action{ + SAVE: {Name: "save name content", Help: "保存", Hand: func(m *ice.Message, arg ...string) { + _inner_save(m, arg[0], kit.Select(m.Option("content"), arg, 1)) + }}, + COMMIT: {Name: "commit name", Help: "提交", Hand: func(m *ice.Message, arg ...string) { + web.StoryCatch(m, "", arg[0]) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Cmdy("nfs.dir", arg) + }}, + }, + }, nil) +} diff --git a/info.go b/info.go index f8e8de2a..16e0d40c 100644 --- a/info.go +++ b/info.go @@ -14,7 +14,7 @@ func (m *Message) Logs(level string, arg ...interface{}) *Message { for i := 0; i < len(arg)-1; i += 2 { list = append(list, fmt.Sprintf("%v: %v", arg[i], arg[i+1])) } - m.Log(level, strings.Join(list, " ")) + m.log(level, strings.Join(list, " ")) return m } func (m *Message) Log(level string, str string, arg ...interface{}) *Message { @@ -43,18 +43,22 @@ func (m *Message) log(level string, str string, arg ...interface{}) *Message { prefix, suffix = "\033[31m", "\033[0m" } - _, file, line, _ := runtime.Caller(2) - ls := strings.Split(file, "/") - if len(ls) > 2 { - ls = ls[len(ls)-2:] + switch level { + case LOG_CMDS, LOG_INFO, LOG_WARN, LOG_COST: + default: + _, file, line, _ := runtime.Caller(2) + ls := strings.Split(file, "/") + if len(ls) > 2 { + ls = ls[len(ls)-2:] + } + suffix += fmt.Sprintf(" %s:%d", strings.Join(ls, "/"), line) } if os.Getenv("ctx_mod") != "" && m != nil { // 输出日志 - fmt.Fprintf(os.Stderr, "%s %02d %9s %s%s %s%s %s\n", + fmt.Fprintf(os.Stderr, "%s %02d %9s %s%s %s%s\n", m.time.Format(ICE_TIME), m.code, fmt.Sprintf("%4s->%-4s", m.source.Name, m.target.Name), prefix, level, str, suffix, - fmt.Sprintf("%s:%d", strings.Join(ls, "/"), line), ) } return m diff --git a/type.go b/type.go index a841c502..41f4b5c4 100644 --- a/type.go +++ b/type.go @@ -29,12 +29,18 @@ type Config struct { Help string Value interface{} } +type Action struct { + Name string + Help string + Hand func(m *Message, arg ...string) +} type Command struct { - Name interface{} // string []string - Help interface{} // string []string - List []interface{} - Meta map[string]interface{} - Hand func(m *Message, c *Context, key string, arg ...string) + Name interface{} // string []string + Help interface{} // string []string + List []interface{} + Meta map[string]interface{} + Hand func(m *Message, c *Context, key string, arg ...string) + Action map[string]*Action } type Context struct { Name string @@ -73,8 +79,19 @@ func (c *Context) Cap(key string, arg ...interface{}) string { return c.Caches[key].Value } func (c *Context) Run(m *Message, cmd *Command, key string, arg ...string) *Message { - m.Hand = true m.Log(LOG_CMDS, "%s.%s %d %v", c.Name, key, len(arg), arg) + if m.Hand = true; len(arg) > 1 && arg[0] == "action" && cmd.Action != nil { + if h, ok := cmd.Action[arg[1]]; ok { + h.Hand(m, arg[2:]...) + return m + } + for _, h := range cmd.Action { + if h.Name == arg[1] || h.Help == arg[1] { + h.Hand(m, arg[2:]...) + return m + } + } + } cmd.Hand(m, c, key, arg...) return m } @@ -654,17 +671,6 @@ func (m *Message) Cmd(arg ...interface{}) *Message { m.Hand, msg.Hand = true, true msg.meta[MSG_DETAIL] = list - // _key := kit.Format(kit.Value(cmd.Meta, "remote")) - // if you := m.Option(_key); you != "" { - // // 远程命令 - // msg.Option(_key, "") - // msg.Option("_option", m.Optionv("option")) - // msg.Copy(msg.Spawns(c).Cmd(WEB_LABEL, you, list[0], list[1:])) - // } else { - // // 本地命令 - // p.Run(msg, cmd, key, list[1:]...) - // } - p.Run(msg, cmd, key, list[1:]...) m.Hand, msg.Hand, m = true, true, msg })