diff --git a/base/cli/system.go b/base/cli/system.go index 278b05be..3303b30e 100644 --- a/base/cli/system.go +++ b/base/cli/system.go @@ -1,8 +1,10 @@ package cli import ( - "github.com/shylinux/icebergs" - "github.com/shylinux/toolkits" + "strings" + + ice "github.com/shylinux/icebergs" + kit "github.com/shylinux/toolkits" "bytes" "fmt" @@ -23,6 +25,8 @@ const ( CMD_CODE = "cmd_code" ) +const ErrRun = "run err " + func _system_show(m *ice.Message, cmd *exec.Cmd) { out := bytes.NewBuffer(make([]byte, 0, 1024)) err := bytes.NewBuffer(make([]byte, 0, 1024)) @@ -34,7 +38,7 @@ func _system_show(m *ice.Message, cmd *exec.Cmd) { }() if e := cmd.Run(); e != nil { - m.Warn(e != nil, "%v run: %s", cmd.Args, kit.Select(e.Error(), err.String())) + m.Warn(e != nil, ErrRun, strings.Join(cmd.Args, " "), "\n", kit.Select(e.Error(), err.String())) } m.Push(CMD_CODE, int(cmd.ProcessState.ExitCode())) diff --git a/base/ctx/cmd.go b/base/ctx/cmd.go index 728b59aa..d7353c9b 100644 --- a/base/ctx/cmd.go +++ b/base/ctx/cmd.go @@ -1,8 +1,8 @@ package ctx import ( - "github.com/shylinux/icebergs" - "github.com/shylinux/toolkits" + ice "github.com/shylinux/icebergs" + kit "github.com/shylinux/toolkits" "sort" "strings" @@ -28,30 +28,22 @@ func _command_list(m *ice.Message, all bool, name string) { return } - // 命令列表 - 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) + list := []string{} + for k := range p.Target().Commands { + if k[0] == '/' || k[0] == '_' { + // 内部命令 + continue } - sort.Strings(list) + 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("name", kit.Format(v.Name)) - m.Push("help", kit.Simple(v.Help)[0]) - m.Push("meta", kit.Format(v.Meta)) - if len(v.List) == 0 { - _command_make(m, v) - } - m.Push("list", kit.Format(v.List)) - } - }) + for _, k := range list { + v := p.Target().Commands[k] + m.Push("key", k) + m.Push("name", kit.Format(v.Name)) + m.Push("help", kit.Simple(v.Help)[0]) + } } func _command_make(m *ice.Message, cmd *ice.Command) { var list []string diff --git a/base/ctx/conf.go b/base/ctx/conf.go index 9beccdc6..542ced8c 100644 --- a/base/ctx/conf.go +++ b/base/ctx/conf.go @@ -1,8 +1,10 @@ package ctx import ( - "github.com/shylinux/icebergs" - "github.com/shylinux/toolkits" + "sort" + + ice "github.com/shylinux/icebergs" + kit "github.com/shylinux/toolkits" "encoding/json" "os" @@ -15,12 +17,23 @@ func _config_list(m *ice.Message, all bool) { if all { p = ice.Pulse } - p.Travel(func(p *ice.Context, s *ice.Context, key string, conf *ice.Config) { - m.Push(kit.MDB_KEY, key) - m.Push(kit.MDB_NAME, conf.Name) - m.Push(kit.MDB_VALUE, kit.Format(conf.Value)) - }) + list := []string{} + for k := range p.Target().Configs { + if k[0] == '/' || k[0] == '_' { + // 内部命令 + continue + } + list = append(list, k) + } + sort.Strings(list) + + for _, k := range list { + v := p.Target().Configs[k] + m.Push(kit.MDB_KEY, k) + m.Push(kit.MDB_NAME, v.Name) + m.Push(kit.MDB_VALUE, kit.Format(v.Value)) + } } func _config_save(m *ice.Message, name string, arg ...string) { msg := m.Spawn(m.Source()) diff --git a/base/nfs/nfs.go b/base/nfs/nfs.go index d0e5b165..b781b75c 100644 --- a/base/nfs/nfs.go +++ b/base/nfs/nfs.go @@ -176,6 +176,7 @@ func _file_link(m *ice.Message, name string, from string) { _file_trash(m, name) os.MkdirAll(path.Dir(name), 0760) os.Link(from, name) + m.Echo(name) } func _file_trash(m *ice.Message, name string) { if s, e := os.Stat(name); e == nil { diff --git a/base/web/cache.go b/base/web/cache.go index 5a664e7d..e014f459 100644 --- a/base/web/cache.go +++ b/base/web/cache.go @@ -1,9 +1,9 @@ package web import ( - "github.com/shylinux/icebergs" + ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/nfs" - "github.com/shylinux/toolkits" + kit "github.com/shylinux/toolkits" "io" "io/ioutil" @@ -12,52 +12,35 @@ import ( "path" ) +func _cache_name(m *ice.Message, h string) string { + return path.Join(m.Conf(CACHE, "meta.path"), h[:2], h) +} + func _cache_list(m *ice.Message, key string) { if key == "" { m.Grows(CACHE, nil, "", "", func(index int, value map[string]interface{}) { - m.Push("", value, []string{kit.MDB_TIME, kit.MDB_ID, kit.MDB_TYPE}) + // 缓存列表 + m.Push("", value, []string{kit.MDB_TIME, kit.MDB_ID, DATA, kit.MDB_TYPE}) m.Push(kit.MDB_SIZE, kit.FmtSize(kit.Int64(value[kit.MDB_SIZE]))) - m.Push("", value, []string{kit.MDB_NAME, kit.MDB_TEXT, kit.MDB_DATA}) + m.Push("", value, []string{kit.MDB_NAME, kit.MDB_TEXT}) }) m.Sort(kit.MDB_ID, "int_r") return } m.Richs(CACHE, nil, key, func(key string, value map[string]interface{}) { + // 缓存详情 m.Push("detail", value) - m.Push(kit.MDB_KEY, "操作") - m.Push(kit.MDB_VALUE, ``) }) } -func _cache_show(m *ice.Message, kind, name, text string, arg ...string) { - if kind == "" && name == "" { - m.Richs(CACHE, nil, m.Option(kit.MDB_DATA), func(key string, value map[string]interface{}) { - kind = kit.Format(value[kit.MDB_TYPE]) - name = kit.Format(value[kit.MDB_NAME]) - text = kit.Format(value[kit.MDB_TEXT]) - arg = kit.Simple(value[kit.MDB_EXTRA]) - m.Log_EXPORT(kit.MDB_META, CACHE, kit.MDB_TYPE, kind, kit.MDB_NAME, name) - }) - } - FavorShow(m, kind, name, text, kit.Simple(arg)...) -} -func _cache_save(m *ice.Message, method, kind, name, text string, arg ...string) { - size := kit.Int(kit.Select(kit.Format(len(text)), arg, 1)) - if method == "add" && size > 512 { - file := kit.Hashs(text) - - // 创建文件 - if o, p, e := kit.Create(path.Join(m.Conf(CACHE, "meta.path"), file[:2], file)); m.Assert(e) { - defer o.Close() - - // 导入数据 - if n, e := o.WriteString(text); m.Assert(e) { - m.Log_EXPORT(kit.MDB_FILE, p, kit.MDB_SIZE, kit.FmtSize(int64(n))) - text, arg = p, kit.Simple(p, n) - } - } +func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { // file size + if len(text) > 512 { + // 存入文件 + p := m.Cmdx(nfs.SAVE, _cache_name(m, kit.Hashs(text)), text) + text, arg = p, kit.Simple(p, len(text)) } // 添加数据 + size := kit.Int(kit.Select(kit.Format(len(text)), arg, 1)) h := m.Rich(CACHE, nil, kit.Dict( kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text, kit.MDB_FILE, kit.Select("", arg, 0), kit.MDB_SIZE, size, @@ -67,7 +50,7 @@ func _cache_save(m *ice.Message, method, kind, name, text string, arg ...string) // 添加记录 m.Grow(CACHE, nil, kit.Dict( kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text, - kit.MDB_SIZE, size, kit.MDB_DATA, h, + kit.MDB_SIZE, size, DATA, h, )) // 返回结果 @@ -76,133 +59,120 @@ func _cache_save(m *ice.Message, method, kind, name, text string, arg ...string) m.Push(kit.MDB_NAME, name) m.Push(kit.MDB_TEXT, text) m.Push(kit.MDB_SIZE, size) - m.Push(kit.MDB_DATA, h) + m.Push(DATA, h) } func _cache_watch(m *ice.Message, key, file string) { - if m.Richs(CACHE, nil, key, func(key string, value map[string]interface{}) { - if value["file"] == "" { - m.Cmdy(nfs.SAVE, file, value["text"]) + m.Richs(CACHE, nil, key, func(key string, value map[string]interface{}) { + if value[kit.MDB_FILE] == nil { + m.Cmdy(nfs.SAVE, file, value[kit.MDB_TEXT]) } else { m.Cmdy(nfs.LINK, file, value[kit.MDB_FILE]) } - }) == nil { - m.Cmdy(SPIDE, "dev", "cache", "/cache/"+key) - m.Cmdy(nfs.LINK, file, m.Append(kit.MDB_FILE)) - } - m.Echo(file) + }) } -func _cache_catch(m *ice.Message, arg ...string) []string { - if r, ok := m.Optionv("response").(*http.Response); ok { - return _cache_download(m, r, arg...) - } else if r, ok := m.Optionv("request").(*http.Request); ok { - return _cache_upload(m, r, arg...) - } - - if f, e := os.Open(arg[2]); m.Assert(e) { +func _cache_catch(m *ice.Message, name string) (file, size string) { + if f, e := os.Open(name); m.Assert(e) { defer f.Close() + if s, e := f.Stat(); m.Assert(e) { + return m.Cmdx(nfs.LINK, _cache_name(m, kit.Hashs(f)), name), kit.Format(s.Size()) + } + } + return "", "0" +} +func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size string) { + if buf, h, e := r.FormFile(UPLOAD); m.Assert(e) { + defer buf.Close() + // 创建文件 - h := kit.Hashs(f) - if o, p, e := kit.Create(path.Join(m.Conf(CACHE, "meta.path"), h[:2], h)); m.Assert(e) { - defer o.Close() + if f, p, e := kit.Create(_cache_name(m, kit.Hashs(buf))); m.Assert(e) { + defer f.Close() // 导入数据 - f.Seek(0, os.SEEK_SET) - if n, e := io.Copy(o, f); m.Assert(e) { - m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, kit.FmtSize(n)) - arg = kit.Simple(arg[0], arg[1], arg[2], p, p, n) + buf.Seek(0, os.SEEK_SET) + if n, e := io.Copy(f, buf); m.Assert(e) { + m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, kit.FmtSize(int64(n))) + return h.Header.Get("Content-Type"), h.Filename, p, kit.Format(n) } } } - return arg + return "", "", "", "0" } -func _cache_upload(m *ice.Message, r *http.Request, arg ...string) []string { - if f, h, e := r.FormFile(kit.Select("upload", arg, 1)); e == nil { - defer f.Close() - - // 创建文件 - file := kit.Hashs(f) - if o, p, e := kit.Create(path.Join(m.Conf(CACHE, "meta.path"), file[:2], file)); m.Assert(e) { - defer o.Close() - f.Seek(0, os.SEEK_SET) - - // 导入数据 - if n, e := io.Copy(o, f); m.Assert(e) { - m.Log(ice.LOG_IMPORT, "%s: %s", kit.FmtSize(n), p) - arg = kit.Simple(arg[0], h.Header.Get("Content-Type"), h.Filename, p, p, n) - } - } - } - return arg -} -func _cache_download(m *ice.Message, r *http.Response, arg ...string) []string { +func _cache_download(m *ice.Message, r *http.Response) (file, size string) { if buf, e := ioutil.ReadAll(r.Body); m.Assert(e) { defer r.Body.Close() // 创建文件 - file := kit.Hashs(string(buf)) - if o, p, e := kit.Create(path.Join(m.Conf(CACHE, "meta.path"), file[:2], file)); m.Assert(e) { - defer o.Close() + if f, p, e := kit.Create(_cache_name(m, kit.Hashs(buf))); m.Assert(e) { + defer f.Close() // 导入数据 - if n, e := o.Write(buf); m.Assert(e) { + if n, e := f.Write(buf); m.Assert(e) { m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, kit.FmtSize(int64(n))) - arg = kit.Simple(arg[0], arg[1], arg[2], p, p, n) + return p, kit.Format(n) } } } - return arg + return "", "0" } -const CACHE = "cache" const ( - CATCH = "catch" WATCH = "watch" + CATCH = "catch" + WRITE = "write" + + UPLOAD = "upload" + DOWNLOAD = "download" ) +const CACHE = "cache" func init() { Index.Merge(&ice.Context{ Configs: map[string]*ice.Config{ CACHE: {Name: "cache", Help: "缓存池", Value: kit.Data( - kit.MDB_SHORT, "text", "path", "var/file", "store", "var/data", "fsize", "100000", "limit", "50", "least", "30", + kit.MDB_SHORT, kit.MDB_TEXT, + kit.MDB_PATH, "var/file", + kit.MDB_STORE, "var/data", + kit.MDB_FSIZE, "200000", + kit.MDB_LIMIT, "50", + kit.MDB_LEAST, "30", )}, }, Commands: map[string]*ice.Command{ CACHE: {Name: "cache data=auto auto", Help: "缓存池", Action: map[string]*ice.Action{ - CATCH: {Name: "catch type file", Help: "捕获", Hand: func(m *ice.Message, arg ...string) { - arg = _cache_catch(m, "catch", arg[0], arg[1]) - _cache_save(m, arg[0], arg[1], arg[2], arg[3], arg[4:]...) - }}, WATCH: {Name: "watch key file", Help: "查看", Hand: func(m *ice.Message, arg ...string) { _cache_watch(m, arg[0], arg[1]) }}, - kit.MDB_SHOW: {Name: "show type name text arg...", Help: "运行", Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 2 { - _cache_show(m, arg[0], arg[1], arg[2], arg[3:]...) - } else { - _cache_show(m, "", "", "") + WRITE: {Name: "write type name text", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + _cache_save(m, arg[0], arg[1], arg[2]) + }}, + CATCH: {Name: "catch type name", Help: "捕获", Hand: func(m *ice.Message, arg ...string) { + file, size := _cache_catch(m, arg[1]) + _cache_save(m, arg[0], arg[1], "", file, size) + }}, + UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { + if r, ok := m.Optionv("request").(*http.Request); ok { + kind, name, file, size := _cache_upload(m, r) + _cache_save(m, kind, name, "", file, size) + } + }}, + DOWNLOAD: {Name: "download type name", Help: "下载", Hand: func(m *ice.Message, arg ...string) { + if r, ok := m.Optionv("response").(*http.Response); ok { + file, size := _cache_download(m, r) + _cache_save(m, arg[0], arg[1], "", file, size) } }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 0 { - _cache_list(m, "") - return - } - - // TODO remove - switch arg[0] { - case "download", "upload": - arg = _cache_catch(m, arg...) - case "add": - _cache_save(m, arg[0], arg[1], arg[2], arg[3], arg[4:]...) - default: - _cache_list(m, arg[0]) - } + _cache_list(m, kit.Select("", arg, 0)) }}, "/cache/": {Name: "/cache/", Help: "缓存池", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Richs(CACHE, nil, arg[0], func(key string, value map[string]interface{}) { - m.Render(ice.RENDER_DOWNLOAD, value["file"]) + if value[kit.MDB_FILE] == nil { + m.Render(ice.RENDER_DOWNLOAD, value[kit.MDB_FILE]) + } else { + m.Render(ice.RENDER_RESULT, value[kit.MDB_TEXT]) + } }) }}, }}, nil) diff --git a/base/web/story.go b/base/web/story.go index 68d2c5ad..5d04b222 100644 --- a/base/web/story.go +++ b/base/web/story.go @@ -2,43 +2,256 @@ package web import ( ice "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/nfs" kit "github.com/shylinux/toolkits" "os" - "path" - "strings" "time" ) -func _story_share(m *ice.Message, story string, list string, arg ...string) { - if m.Echo("share: "); list == "" { - msg := m.Cmd(STORY, INDEX, story) - m.Cmdy(SHARE, "story", story, msg.Append("list")) - } else { - msg := m.Cmd(STORY, INDEX, list) - m.Cmdy(SHARE, msg.Append("scene"), msg.Append("story"), msg.Append("text")) - } -} -func _story_list(m *ice.Message, arg ...string) { - if len(arg) == 0 { - m.Richs(STORY, "head", "*", func(key string, value map[string]interface{}) { - m.Push(key, value, []string{"time", "story", "count"}) +func _story_list(m *ice.Message, name string, key string) { + if name == "" { + m.Richs(STORY, HEAD, kit.MDB_FOREACH, func(key string, value map[string]interface{}) { + m.Push(key, value, []string{kit.MDB_TIME, kit.MDB_COUNT, STORY}) }) - m.Sort("time", "time_r") + m.Sort(kit.MDB_TIME, "time_r") return } - if len(arg) == 1 { - m.Cmdy(STORY, "history", arg) + if key == "" { + _story_history(m, name) return } - m.Cmd(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.Richs(STORY, nil, key, func(key string, value map[string]interface{}) { + m.Push("detail", value) + }) + +} +func _story_index(m *ice.Message, name string, withdata bool) { + m.Richs(STORY, HEAD, name, func(key string, value map[string]interface{}) { + // 查询索引 + m.Push(HEAD, key) + name = kit.Format(value[LIST]) + }) + + m.Richs(STORY, nil, name, func(key string, value map[string]interface{}) { + // 查询节点 + m.Push(LIST, key) + m.Push(key, value, []string{SCENE, STORY}) + name = kit.Format(value[DATA]) + }) + + m.Richs(CACHE, nil, name, func(key string, value map[string]interface{}) { + // 查询数据 + m.Push(DATA, key) + m.Push(key, value, []string{kit.MDB_TEXT, kit.MDB_FILE, kit.MDB_SIZE, kit.MDB_TIME, kit.MDB_NAME, kit.MDB_TYPE}) + if withdata { + if value[kit.MDB_FILE] == "" { + m.Echo("%s", kit.Format(value[kit.MDB_TEXT])) + } else { + m.Echo("%s", m.Cmdx(nfs.CAT, value[kit.MDB_FILE])) + } } - m.Sort("key") }) } +func _story_history(m *ice.Message, name string) { + // 历史记录 + list := m.Cmd(STORY, INDEX, name).Append(LIST) + for i := 0; i < kit.Int(kit.Select("30", m.Option("cache.limit"))) && list != ""; i++ { + m.Richs(STORY, nil, list, func(key string, value map[string]interface{}) { + // 直连节点 + m.Push(key, value, []string{kit.MDB_TIME, kit.MDB_KEY, kit.MDB_COUNT, SCENE, STORY}) + m.Richs(CACHE, nil, value[DATA], func(key string, value map[string]interface{}) { + m.Push(DRAMA, value[kit.MDB_TEXT]) + m.Push(DATA, key) + }) + + kit.Fetch(value[LIST], func(key string, val string) { + m.Richs(STORY, nil, val, func(key string, value map[string]interface{}) { + // 复合节点 + m.Push(key, value, []string{kit.MDB_TIME, kit.MDB_KEY, kit.MDB_COUNT, SCENE, STORY}) + m.Richs(CACHE, nil, value[DATA], func(key string, value map[string]interface{}) { + m.Push(DRAMA, value[kit.MDB_TEXT]) + m.Push(DATA, key) + }) + }) + }) + + // 切换节点 + list = kit.Format(value[PREV]) + }) + } +} +func _story_write(m *ice.Message, scene, name, text string, arg ...string) { + if len(arg) < 1 || text == "" || m.Richs(CACHE, nil, text, func(key string, value map[string]interface{}) { text = key }) == nil { + // 添加缓存 + m.Cmdy(CACHE, CATCH, scene, name, text, arg) + scene, name, text = m.Append(kit.MDB_TYPE), m.Append(kit.MDB_NAME), m.Append(DATA) + } + + // 查询索引 + head, prev, value, count := "", "", kit.Dict(), 0 + m.Richs(STORY, HEAD, name, func(key string, val map[string]interface{}) { + head, prev, value, count = key, kit.Format(val[LIST]), val, kit.Int(val[kit.MDB_COUNT]) + m.Logs("info", HEAD, head, PREV, prev, kit.MDB_COUNT, count) + }) + + if last := m.Richs(STORY, nil, prev, nil); prev != "" && last != nil && last[DATA] == text { + // 重复提交 + m.Push(prev, last, []string{kit.MDB_TIME, kit.MDB_COUNT, kit.MDB_KEY}) + m.Logs("info", "file", "exists") + m.Echo(prev) + return + } + + // 添加节点 + list := m.Rich(STORY, nil, kit.Dict( + SCENE, scene, STORY, name, kit.MDB_COUNT, count+1, DATA, text, PREV, prev, + )) + m.Log_CREATE(STORY, list, kit.MDB_TYPE, scene, kit.MDB_NAME, name) + m.Push(kit.MDB_COUNT, count+1) + m.Push(kit.MDB_KEY, list) + + if head == "" { + // 添加索引 + m.Rich(STORY, HEAD, kit.Dict(SCENE, scene, STORY, name, kit.MDB_COUNT, count+1, LIST, list)) + } else { + // 更新索引 + value[kit.MDB_COUNT] = count + 1 + value[kit.MDB_TIME] = m.Time() + value[LIST] = list + } + m.Echo(list) +} +func _story_catch(m *ice.Message, scene, name string, arg ...string) { + if last := m.Richs(STORY, HEAD, name, nil); last != nil { + if t, e := time.ParseInLocation(ice.MOD_TIME, kit.Format(last[kit.MDB_TIME]), time.Local); e == nil { + if s, e := os.Stat(name); e == nil && s.ModTime().Before(t) { + m.Push(name, last, []string{kit.MDB_TIME, kit.MDB_COUNT, kit.MDB_KEY}) + m.Logs("info", "file", "exists") + m.Echo("%s", last[LIST]) + // 重复提交 + return + } + } + } + _story_write(m, scene, name, "", arg...) +} +func _story_watch(m *ice.Message, key, file string) { + _story_index(m, key, false) + _cache_watch(m, m.Append(DATA), file) +} + +const ( + HEAD = "head" + LIST = "list" + PREV = "prev" + DATA = "data" + + INDEX = "index" + HISTORY = "history" + + PULL = "pull" + PUSH = "push" + COMMIT = "commit" +) +const SCENE = "scene" +const STORY = "story" +const DRAMA = "drama" + +func init() { + Index.Merge(&ice.Context{ + Configs: map[string]*ice.Config{ + STORY: {Name: "story", Help: "故事会", Value: kit.Dict( + kit.MDB_META, kit.Dict(kit.MDB_SHORT, DATA), + HEAD, kit.Data(kit.MDB_SHORT, STORY), + )}, + }, + Commands: map[string]*ice.Command{ + STORY: {Name: "story story=auto key=auto auto", Help: "故事会", Action: map[string]*ice.Action{ + WRITE: {Name: "write type name text arg...", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + _story_write(m, arg[0], arg[1], arg[2], arg[3:]...) + }}, + CATCH: {Name: "catch type name arg...", Help: "捕捉", Hand: func(m *ice.Message, arg ...string) { + _story_catch(m, arg[0], arg[1], arg[2:]...) + }}, + WATCH: {Name: "watch key name", Help: "查看", Hand: func(m *ice.Message, arg ...string) { + _story_watch(m, arg[0], arg[1]) + }}, + INDEX: {Name: "index key", Help: "索引", Hand: func(m *ice.Message, arg ...string) { + _story_index(m, arg[0], false) + }}, + HISTORY: {Name: "history name", Help: "历史", Hand: func(m *ice.Message, arg ...string) { + _story_history(m, arg[0]) + }}, + "add": {Name: "add type name text arg...", Help: "淘汰", Hand: func(m *ice.Message, arg ...string) { + panic(m) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + _story_list(m, kit.Select("", arg, 0), kit.Select("", arg, 1)) + }}, + + "/story/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + switch arg[0] { + case PULL: + list := m.Cmd(STORY, INDEX, m.Option("begin")).Append("list") + for i := 0; i < 10 && list != "" && list != m.Option("end"); i++ { + if m.Richs(STORY, nil, list, func(key string, value map[string]interface{}) { + // 节点信息 + m.Push("list", key) + m.Push("node", kit.Format(value)) + m.Push("data", value["data"]) + m.Push("save", kit.Format(m.Richs(CACHE, nil, value["data"], nil))) + list = kit.Format(value["prev"]) + }) == nil { + break + } + } + m.Log(ice.LOG_EXPORT, "%s %s", m.Option("begin"), m.Format("append")) + + case PUSH: + if m.Richs(CACHE, nil, m.Option("data"), nil) == nil { + // 导入缓存 + m.Log(ice.LOG_IMPORT, "%v: %v", m.Option("data"), m.Option("save")) + m.Conf(CACHE, kit.Keys("hash", m.Option("data")), kit.UnMarshal(m.Option("save"))) + } + + node := kit.UnMarshal(m.Option("node")).(map[string]interface{}) + if m.Richs(STORY, nil, m.Option("list"), nil) == nil { + // 导入节点 + m.Log(ice.LOG_IMPORT, "%v: %v", m.Option("list"), m.Option("node")) + m.Conf(STORY, kit.Keys("hash", m.Option("list")), node) + } + + if head := m.Richs(STORY, "head", m.Option("story"), nil); head == nil { + // 自动创建 + h := m.Rich(STORY, "head", kit.Dict( + "scene", node["scene"], "story", m.Option("story"), + "count", node["count"], "list", m.Option("list"), + )) + m.Log(ice.LOG_CREATE, "%v: %v", h, m.Option("story")) + } else if head["list"] == kit.Format(node["prev"]) || head["list"] == kit.Format(node["pull"]) { + // 快速合并 + head["list"] = m.Option("list") + head["count"] = node["count"] + head["time"] = node["time"] + } else { + // 推送失败 + } + + case UPLOAD: + // 上传数据 + m.Cmdy(CACHE, "upload") + + case DOWNLOAD: + // 下载数据 + m.Cmdy(STORY, INDEX, arg[1]) + m.Render(kit.Select(ice.RENDER_DOWNLOAD, ice.RENDER_RESULT, m.Append("file") == ""), m.Append("text")) + } + }}, + }}, nil) +} + func _story_pull(m *ice.Message, arg ...string) { // 起止节点 prev, begin, end := "", arg[3], "" @@ -219,303 +432,3 @@ func _story_commit(m *ice.Message, arg ...string) { m.Echo(list) } - -func _story_add(m *ice.Message, arg ...string) { - if len(arg) < 4 || arg[3] == "" || m.Richs(CACHE, nil, arg[3], func(key string, value map[string]interface{}) { - // 复用缓存 - arg[3] = key - }) == nil { - // 添加缓存 - m.Cmdy(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(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.Logs("info", "head", head, "prev", prev, "count", count) - }) - - if last := m.Richs(STORY, nil, prev, nil); prev != "" && last != nil && last["data"] == arg[3] { - // 重复提交 - m.Push(prev, last, []string{"time", "count", "key"}) - m.Logs("info", "file", "exists") - m.Echo(prev) - } else { - // 添加节点 - list := m.Rich(STORY, nil, kit.Dict( - "scene", arg[1], "story", arg[2], "count", count+1, "data", arg[3], "prev", prev, - )) - m.Log_CREATE("story", list, "type", arg[1], "name", arg[2]) - m.Push("count", count+1) - m.Push("key", list) - - if head == "" { - // 添加索引 - m.Rich(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) - } - - // // 分发数据 - // for _, k := range []string{"you", "pod"} { - // if p := m.Option(k); p != "" { - // m.Option(k, "") - // m.Cmd(PROXY, p, STORY, PULL, arg[2], "dev", arg[2]) - // return - // } - // } - // m.Cmd(PROXY, m.Conf(FAVOR, "meta.proxy"), - // STORY, PULL, arg[2], "dev", arg[2]) -} -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_catch(m *ice.Message, arg ...string) { - if last := m.Richs(STORY, "head", arg[2], nil); last != nil { - if t, e := time.ParseInLocation(ice.MOD_TIME, kit.Format(last["time"]), time.Local); e == nil { - // 文件对比 - if s, e := os.Stat(arg[2]); e == nil && s.ModTime().Before(t) { - m.Push(arg[2], last, []string{"time", "count", "key"}) - m.Logs("info", "file", "exists") - m.Echo("%s", last["list"]) - return - } - } - } - _story_add(m, arg...) -} -func _story_watch(m *ice.Message, index string, arg ...string) { - // 备份文件 - name := kit.Select(index, arg, 0) - m.Cmd(STORY, TRASH, name) - - if msg := m.Cmd(STORY, INDEX, index); 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_index(m *ice.Message, name string, withdata bool) { - m.Richs(STORY, "head", name, func(key string, value map[string]interface{}) { - // 查询索引 - name = kit.Format(value["list"]) - }) - - m.Richs(STORY, nil, name, func(key string, value map[string]interface{}) { - // 查询节点 - m.Push("list", key) - m.Push(key, value, []string{"scene", "story"}) - name = kit.Format(value["data"]) - }) - - m.Richs(CACHE, nil, name, func(key string, value map[string]interface{}) { - // 查询数据 - m.Push("data", key) - m.Push(key, value, []string{"text", "time", "size", "type", "name", "file"}) - if withdata { - if kit.Format(value["file"]) != "" { - m.Echo("%s", m.Cmdx("nfs.cat", value["file"])) - } else { - m.Echo("%s", kit.Format(value["text"])) - } - } - }) -} -func _story_history(m *ice.Message, name string) { - // 历史记录 - list := m.Cmd(STORY, INDEX, name).Append("list") - for i := 0; i < kit.Int(kit.Select("30", m.Option("cache.limit"))) && list != ""; i++ { - - m.Richs(STORY, nil, list, func(key string, value map[string]interface{}) { - // 直连节点 - m.Push(key, value, []string{"time", "key", "count", "scene", "story"}) - m.Richs(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(STORY, nil, val, func(key string, value map[string]interface{}) { - // 复合节点 - m.Push(key, value, []string{"time", "key", "count", "scene", "story"}) - m.Richs(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 StoryHistory(m *ice.Message, name string) *ice.Message { _story_history(m, name); return m } -func StoryIndex(m *ice.Message, name string) *ice.Message { _story_index(m, name, true); return m } -func StoryWatch(m *ice.Message, index string, file string) { _story_watch(m, index, file) } -func StoryCatch(m *ice.Message, mime string, file string) *ice.Message { - _story_catch(m, "catch", kit.Select(mime, strings.TrimPrefix(path.Ext(file), ".")), file, "") - return m -} -func StoryAdd(m *ice.Message, mime string, name string, text string, arg ...string) *ice.Message { - _story_add(m, kit.Simple("add", mime, name, text, arg)...) - return m -} - -const STORY = "story" -const ( - TRASH = "trash" - // CATCH = "catch" - INDEX = "index" - - LIST = "list" - SHOW = "show" - - PULL = "pull" - PUSH = "push" - - UPLOAD = "upload" - DOWNLOAD = "download" -) - -func init() { - Index.Merge(&ice.Context{ - Configs: map[string]*ice.Config{ - STORY: {Name: "story", Help: "故事会", Value: kit.Dict( - kit.MDB_META, kit.Dict(kit.MDB_SHORT, "data"), - "head", kit.Data(kit.MDB_SHORT, "story"), - "mime", kit.Dict("md", "txt"), - )}, - }, - Commands: map[string]*ice.Command{ - STORY: {Name: "story story=auto key=auto auto", Help: "故事会", Meta: kit.Dict( - "exports", []string{"top", "story"}, "detail", []string{"共享", "更新", "推送"}, - ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) > 1 && arg[0] == "action" { - story, list := m.Option("story"), m.Option("list") - switch arg[2] { - case "story": - story = arg[3] - case "list": - list = arg[3] - } - - switch arg[1] { - case "share", "共享": - _story_share(m, story, list, arg...) - } - return - } - - if len(arg) == 0 { - _story_list(m, arg...) - return - } - - switch arg[0] { - case PULL: // story [spide [story]] - _story_pull(m, arg...) - case PUSH: - _story_push(m, arg...) - case "commit": - _story_commit(m, arg...) - - case TRASH: - _story_trash(m, arg...) - case SHOW: - _story_watch(m, arg[1], arg[2:]...) - case CATCH: - _story_catch(m, arg...) - case "add": - _story_add(m, arg...) - - case INDEX: - _story_index(m, arg[1], true) - case LIST: - _story_history(m, arg[1]) - default: - _story_list(m, arg...) - } - }}, - "/story/": {Name: "/story/", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - - switch arg[0] { - case PULL: - list := m.Cmd(STORY, INDEX, m.Option("begin")).Append("list") - for i := 0; i < 10 && list != "" && list != m.Option("end"); i++ { - if m.Richs(STORY, nil, list, func(key string, value map[string]interface{}) { - // 节点信息 - m.Push("list", key) - m.Push("node", kit.Format(value)) - m.Push("data", value["data"]) - m.Push("save", kit.Format(m.Richs(CACHE, nil, value["data"], nil))) - list = kit.Format(value["prev"]) - }) == nil { - break - } - } - m.Log(ice.LOG_EXPORT, "%s %s", m.Option("begin"), m.Format("append")) - - case PUSH: - if m.Richs(CACHE, nil, m.Option("data"), nil) == nil { - // 导入缓存 - m.Log(ice.LOG_IMPORT, "%v: %v", m.Option("data"), m.Option("save")) - m.Conf(CACHE, kit.Keys("hash", m.Option("data")), kit.UnMarshal(m.Option("save"))) - } - - node := kit.UnMarshal(m.Option("node")).(map[string]interface{}) - if m.Richs(STORY, nil, m.Option("list"), nil) == nil { - // 导入节点 - m.Log(ice.LOG_IMPORT, "%v: %v", m.Option("list"), m.Option("node")) - m.Conf(STORY, kit.Keys("hash", m.Option("list")), node) - } - - if head := m.Richs(STORY, "head", m.Option("story"), nil); head == nil { - // 自动创建 - h := m.Rich(STORY, "head", kit.Dict( - "scene", node["scene"], "story", m.Option("story"), - "count", node["count"], "list", m.Option("list"), - )) - m.Log(ice.LOG_CREATE, "%v: %v", h, m.Option("story")) - } else if head["list"] == kit.Format(node["prev"]) || head["list"] == kit.Format(node["pull"]) { - // 快速合并 - head["list"] = m.Option("list") - head["count"] = node["count"] - head["time"] = node["time"] - } else { - // 推送失败 - } - - case UPLOAD: - // 上传数据 - m.Cmdy(CACHE, "upload") - - case DOWNLOAD: - // 下载数据 - m.Cmdy(STORY, INDEX, arg[1]) - m.Render(kit.Select(ice.RENDER_DOWNLOAD, ice.RENDER_RESULT, m.Append("file") == ""), m.Append("text")) - } - }}, - }}, nil) -} diff --git a/core/chat/action.go b/core/chat/action.go index 4dff0016..fa297610 100644 --- a/core/chat/action.go +++ b/core/chat/action.go @@ -1,10 +1,10 @@ package chat import ( - "github.com/shylinux/icebergs" + ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/ctx" "github.com/shylinux/icebergs/base/web" - "github.com/shylinux/toolkits" + kit "github.com/shylinux/toolkits" "strconv" ) @@ -143,7 +143,7 @@ func init() { web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { msg := m.Cmd(web.STORY, web.UPLOAD) m.Option(kit.MDB_NAME, msg.Append(kit.MDB_NAME)) - m.Option(kit.MDB_DATA, msg.Append(kit.MDB_DATA)) + m.Option(web.DATA, msg.Append(web.DATA)) _action_show(m, m.Option(RIVER), m.Option(STORM), m.Option(ACTION), append([]string{ACTION, web.UPLOAD}, arg...)...) }}, diff --git a/core/code/code.go b/core/code/code.go index 4f205426..b7991715 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -1,8 +1,11 @@ package code import ( + "net/http" + ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/cli" + "github.com/shylinux/icebergs/base/nfs" "github.com/shylinux/icebergs/base/web" kit "github.com/shylinux/toolkits" @@ -20,27 +23,20 @@ const ( // CODE var Index = &ice.Context{Name: "code", Help: "编程中心", Configs: map[string]*ice.Config{ - "install": {Name: "install", Help: "安装", Value: kit.Data("path", "usr/install", + INSTALL: {Name: "install", Help: "安装", Value: kit.Data("path", "usr/install", "linux", "https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz", "darwin", "https://dl.google.com/go/go1.14.2.darwin-amd64.pkg", "windows", "https://dl.google.com/go/go1.14.2.windows-amd64.msi", "source", "https://dl.google.com/go/go1.14.2.src.tar.gz", - "target", "usr/local", "script", ".ish/pluged/golang/init.sh", "export", kit.Dict( + "target", "usr/local", + )}, + PREPARE: {Name: "prepare", Help: "配置", Value: kit.Data("path", "usr/prepare", + "script", ".ish/pluged/golang/init.sh", "export", kit.Dict( "GOPROXY", "https://goproxy.cn,direct", "GOPRIVATE", "https://github.com", ), )}, - "prepare": {Name: "prepare", Help: "配置", Value: kit.Data("path", "usr/prepare")}, - "project": {Name: "project", Help: "项目", Value: kit.Data("path", "usr/project")}, - - "compile": {Name: "compile", Help: "编译", Value: kit.Data("path", "usr/publish")}, - "publish": {Name: "publish", Help: "发布", Value: kit.Data("path", "usr/publish")}, - "upgrade": {Name: "upgrade", Help: "升级", Value: kit.Dict(kit.MDB_HASH, kit.Dict( - "system", kit.Dict(kit.MDB_LIST, kit.List( - kit.MDB_INPUT, "bin", "file", "ice.bin", "path", "bin/ice.bin", - kit.MDB_INPUT, "bin", "file", "ice.sh", "path", "bin/ice.sh", - )), - ))}, + PROJECT: {Name: "project", Help: "项目", Value: kit.Data("path", "usr/project")}, "login": {Name: "login", Help: "终端接入", Value: kit.Data()}, }, @@ -53,116 +49,39 @@ var Index = &ice.Context{Name: "code", Help: "编程中心", }}, INSTALL: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - p := path.Join(m.Conf("install", "meta.path"), path.Base(m.Conf("install", kit.Keys("meta", runtime.GOOS)))) - // 下载 + target := m.Conf(INSTALL, kit.Keys("meta", runtime.GOOS)) + p := path.Join(m.Conf(INSTALL, "meta.path"), path.Base(target)) + if _, e := os.Stat(p); e != nil { - m.Option("cmd_dir", m.Conf("install", "meta.path")) - m.Cmd(cli.SYSTEM, "wget", m.Conf("install", kit.Keys("meta", runtime.GOOS))) + // 下载 + m.Option(cli.CMD_DIR, m.Conf(INSTALL, "meta.path")) + msg := m.Cmd(web.SPIDE, web.CACHE, http.MethodGet, target) + m.Cmd(web.CACHE, web.WATCH, msg.Append(web.DATA), p) } // 安装 - m.Option("cmd_dir", "") - os.MkdirAll(m.Conf("install", kit.Keys("meta.target")), 0777) - m.Cmdy(cli.SYSTEM, "tar", "xvf", p, "-C", m.Conf("install", kit.Keys("meta.target"))) + m.Option(cli.CMD_DIR, "") + os.MkdirAll(m.Conf(INSTALL, kit.Keys("meta.target")), 0777) + m.Cmdy(cli.SYSTEM, "tar", "xvf", p, "-C", m.Conf(INSTALL, kit.Keys("meta.target"))) }}, PREPARE: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { export := []string{} - kit.Fetch(m.Confv("install", "meta.export"), func(key string, val string) { + kit.Fetch(m.Confv(PREPARE, "meta.export"), func(key string, val string) { export = append(export, key+"="+val) }) - m.Cmd("nfs.save", m.Conf("install", "meta.script"), kit.Format(` + m.Cmd(nfs.SAVE, m.Conf(PREPARE, "meta.script"), kit.Format(` export GOROOT=%s GOPATH=%s:$GOPATH GOBIN=%s export PATH=$GOBIN:$GOROOT/bin:$PATH export %s -`, kit.Path(m.Conf("install", kit.Keys("meta.target")), "go"), kit.Path("src"), kit.Path("bin"), strings.Join(export, " "))) +`, kit.Path(m.Conf(INSTALL, kit.Keys("meta.target")), "go"), kit.Path("src"), kit.Path("bin"), strings.Join(export, " "))) }}, PROJECT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { }}, - "install": {Name: "install", Help: "安装", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - }}, - "prepare": {Name: "prepare", Help: "配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - }}, - "project": {Name: "project", Help: "项目", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - }}, - - "compile": {Name: "compile [os [arch [main]]]", Help: "编译", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 0 { - // 目录列表 - m.Cmdy("nfs.dir", m.Conf(cmd, "meta.path"), "time size path") - return - } - - // 编译目标 - main := kit.Select("src/main.go", arg, 2) - arch := kit.Select(m.Conf(cli.RUNTIME, "host.GOARCH"), arg, 1) - goos := kit.Select(m.Conf(cli.RUNTIME, "host.GOOS"), arg, 0) - file := path.Join(m.Conf(cmd, "meta.path"), kit.Keys("ice", goos, arch)) - - // 编译参数 - m.Optionv("cmd_env", "GOCACHE", os.Getenv("GOCACHE"), "HOME", os.Getenv("HOME"), - "GOARCH", arch, "GOOS", goos, "CGO_ENABLED", "0") - m.Cmd(cli.SYSTEM, "go", "build", "-o", file, main) - - // 编译记录 - m.Cmdy(web.STORY, web.CATCH, "bin", file) - m.Logs(ice.LOG_EXPORT, "source", main, "target", file) - }}, - "publish": {Name: "publish [source]", Help: "发布", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 0 { - // 目录列表 - m.Cmdy("nfs.dir", m.Conf(cmd, "meta.path"), "time size path") - return - } - - if s, e := os.Stat(arg[0]); m.Assert(e) && s.IsDir() { - // 发布目录 - p := path.Base(arg[0]) + ".tar.gz" - m.Cmd(cli.SYSTEM, "tar", "-zcf", p, arg[0]) - defer func() { os.Remove(p) }() - arg[0] = p - } - - // 发布文件 - target := path.Join(m.Conf(cmd, "meta.path"), path.Base(arg[0])) - os.Remove(target) - os.MkdirAll(path.Dir(target), 0777) - os.Link(arg[0], target) - - // 发布记录 - m.Cmdy(web.STORY, web.CATCH, "bin", target) - m.Logs(ice.LOG_EXPORT, "source", arg[0], "target", target) - }}, - "upgrade": {Name: "upgrade which", Help: "升级", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - exit := false - m.Grows(cmd, kit.Keys(kit.MDB_HASH, kit.Select("system", arg, 0)), "", "", func(index int, value map[string]interface{}) { - if value["file"] == "ice.bin" { - // 程序文件 - value["file"] = kit.Keys("ice", m.Conf(cli.RUNTIME, "host.GOOS"), m.Conf(cli.RUNTIME, "host.GOARCH")) - exit = true - } - - // 下载文件 - h := m.Cmdx(web.SPIDE, "dev", "cache", "GET", "/publish/"+kit.Format(value["file"])) - if h == "" { - exit = false - return - } - - // 升级记录 - m.Cmd(web.STORY, "add", "bin", value["path"], h) - m.Cmd(web.STORY, web.SHOW, h, value["path"]) - os.Chmod(kit.Format(value["path"]), 0777) - }) - if exit { - m.Sleep("1s").Gos(m, func(m *ice.Message) { m.Cmd("exit") }) - } - }}, - "login": {Name: "login key", Help: "登录", Meta: kit.Dict( "detail", []string{"编辑", "删除", "清理", "清空"}, - ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + ), Action: map[string]*ice.Action{}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 && arg[0] == "action" { switch arg[1] { case "modify", "编辑": @@ -255,4 +174,4 @@ export %s }, } -func init() { web.Index.Register(Index, &web.Frame{}, BENCH, PPROF) } +func init() { web.Index.Register(Index, &web.Frame{}, COMPILE, BENCH, PPROF) } diff --git a/core/code/compile.go b/core/code/compile.go new file mode 100644 index 00000000..e1e91572 --- /dev/null +++ b/core/code/compile.go @@ -0,0 +1,57 @@ +package code + +import ( + ice "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/cli" + "github.com/shylinux/icebergs/base/nfs" + "github.com/shylinux/icebergs/base/web" + kit "github.com/shylinux/toolkits" + + "os" + "path" +) + +const COMPILE = "compile" + +func init() { + Index.Merge(&ice.Context{ + Configs: map[string]*ice.Config{ + COMPILE: {Name: "compile", Help: "编译", Value: kit.Data( + "path", "usr/publish", "env", kit.Dict( + "PATH", os.Getenv("PATH"), + "HOME", os.Getenv("HOME"), + "GOCACHE", os.Getenv("GOCACHE"), + "GOPROXY", "https://goproxy.cn,direct", + "GOPRIVATE", "github.com", + "CGO_ENABLED", "0", + ), "go", []interface{}{"go", "build", "-o"}, + )}, + }, + Commands: map[string]*ice.Command{ + COMPILE: {Name: "compile [os [arch [main]]]", Help: "编译", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + // 目录列表 + m.Cmdy(nfs.DIR, m.Conf(cmd, "meta.path"), "time size path") + return + } + + // 编译目标 + main := kit.Select("src/main.go", arg, 2) + arch := kit.Select(m.Conf(cli.RUNTIME, "host.GOARCH"), arg, 1) + goos := kit.Select(m.Conf(cli.RUNTIME, "host.GOOS"), arg, 0) + file := path.Join(m.Conf(cmd, "meta.path"), kit.Keys("ice", goos, arch)) + + // 编译参数 + m.Optionv(cli.CMD_ENV, kit.Simple(m.Confv(COMPILE, "meta.env"), "GOARCH", arch, "GOOS", goos)) + if msg := m.Cmd(cli.SYSTEM, m.Confv(COMPILE, "meta.go"), file, main); msg.Append(cli.CMD_CODE) != "0" { + m.Copy(msg) + return + } + + // 编译记录 + m.Cmdy(web.STORY, web.CATCH, "bin", file) + m.Log_EXPORT("source", main, "target", file) + }}, + }, + }, nil) +} diff --git a/core/code/inner.go b/core/code/inner.go index b5651c97..91219f90 100644 --- a/core/code/inner.go +++ b/core/code/inner.go @@ -115,7 +115,7 @@ func _inner_show(m *ice.Message, name string) { } func _inner_main(m *ice.Message, arg ...string) { if len(arg) > 2 && arg[2] != "" { - web.StoryIndex(m, arg[2]) + m.Cmdy(web.STORY, web.INDEX, arg[2]) return } _inner_list(m, path.Join(arg...)) @@ -163,34 +163,34 @@ func init() { web.FavorList(m, arg[0], arg[1], arg[2:]...) }}, "upload": {Name: "upload path name", Help: "上传", Hand: func(m *ice.Message, arg ...string) { - web.StoryWatch(m, m.Option("data"), path.Join(m.Option("path"), m.Option("name"))) + m.Cmd(web.STORY, web.WATCH, m.Option("data"), path.Join(m.Option("path"), m.Option("name"))) }}, "project": {Name: "project path", Help: "项目", Hand: func(m *ice.Message, arg ...string) { _inner_list(m, path.Join("./", kit.Select("", arg, 0))+"/") }}, "history": {Name: "history path name", Help: "历史", Hand: func(m *ice.Message, arg ...string) { - msg := web.StoryHistory(m.Spawn(), path.Join("./", arg[0], arg[1])) + msg := m.Cmd(web.STORY, web.HISTORY, path.Join("./", arg[0], arg[1])) m.Copy(msg, ice.MSG_APPEND, "time", "count", "key") if len(arg) > 2 && arg[2] != "" { - m.Echo(web.StoryIndex(m.Spawn(), arg[2]).Result()) + m.Echo(m.Cmd(web.STORY, web.INDEX, arg[2]).Result()) } }}, "commit": {Name: "commit path name", Help: "提交", Hand: func(m *ice.Message, arg ...string) { - msg := web.StoryCatch(m.Spawn(), "", path.Join("./", arg[0], arg[1])) + msg := m.Cmd(web.STORY, web.CATCH, "", path.Join("./", arg[0], arg[1])) m.Copy(msg, ice.MSG_APPEND, "time", "count", "key") }}, "recover": {Name: "recover", Help: "复盘", Hand: func(m *ice.Message, arg ...string) { - msg := web.StoryHistory(m.Spawn(), path.Join("./", arg[0], arg[1])+".display") + msg := m.Cmd(web.STORY, web.HISTORY, path.Join("./", arg[0], arg[1])+".display") m.Copy(msg, ice.MSG_APPEND, "time", "count", "key", "drama") if len(arg) > 2 && arg[2] != "" { - m.Echo(web.StoryIndex(m.Spawn(), arg[2]).Result()) + m.Echo(m.Cmd(web.STORY, web.INDEX, arg[2]).Result()) } }}, "record": {Name: "record", Help: "记录", Hand: func(m *ice.Message, arg ...string) { - msg := web.StoryAdd(m.Spawn(), "display", path.Join("./", m.Option("path"), m.Option("name"))+".display", m.Option("display")) + msg := m.Cmd(web.STORY, web.CATCH, "display", path.Join("./", m.Option("path"), m.Option("name"))+".display", m.Option("display")) m.Copy(msg, ice.MSG_APPEND, "time", "count", "key") }}, diff --git a/core/code/publish.go b/core/code/publish.go new file mode 100644 index 00000000..2a842ab5 --- /dev/null +++ b/core/code/publish.go @@ -0,0 +1,47 @@ +package code + +import ( + ice "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/cli" + "github.com/shylinux/icebergs/base/nfs" + "github.com/shylinux/icebergs/base/web" + kit "github.com/shylinux/toolkits" + + "os" + "path" +) + +const PUBLISH = "publish" + +func init() { + Index.Merge(&ice.Context{ + Configs: map[string]*ice.Config{ + PUBLISH: {Name: "publish", Help: "发布", Value: kit.Data("path", "usr/publish")}, + }, + Commands: map[string]*ice.Command{ + PUBLISH: {Name: "publish [source]", Help: "发布", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + // 目录列表 + m.Cmdy(nfs.DIR, m.Conf(cmd, "meta.path"), "time size path") + return + } + + if s, e := os.Stat(arg[0]); m.Assert(e) && s.IsDir() { + // 打包目录 + p := path.Base(arg[0]) + ".tar.gz" + m.Cmd(cli.SYSTEM, "tar", "-zcf", p, arg[0]) + defer func() { os.Remove(p) }() + arg[0] = p + } + + // 发布文件 + target := path.Join(m.Conf(cmd, "meta.path"), path.Base(arg[0])) + m.Cmd(nfs.LINK, target, arg[0]) + + // 发布记录 + m.Cmdy(web.STORY, web.CATCH, "bin", target) + m.Log_EXPORT("source", arg[0], "target", target) + }}, + }, + }, nil) +} diff --git a/core/code/upgrade.go b/core/code/upgrade.go new file mode 100644 index 00000000..9a04a787 --- /dev/null +++ b/core/code/upgrade.go @@ -0,0 +1,56 @@ +package code + +import ( + "net/http" + "path" + + ice "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/cli" + "github.com/shylinux/icebergs/base/web" + kit "github.com/shylinux/toolkits" + + "os" +) + +const UPGRADE = "upgrade" + +func init() { + Index.Merge(&ice.Context{ + Configs: map[string]*ice.Config{ + UPGRADE: {Name: "upgrade", Help: "升级", Value: kit.Dict(kit.MDB_HASH, kit.Dict( + "path", "usr/upgrade", "system", kit.Dict(kit.MDB_LIST, kit.List( + kit.MDB_INPUT, "bin", "file", "ice.bin", "path", "bin/ice.bin", + kit.MDB_INPUT, "bin", "file", "ice.sh", "path", "bin/ice.sh", + )), + ))}, + }, + Commands: map[string]*ice.Command{ + UPGRADE: {Name: "upgrade item", Help: "升级", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + exit := false + m.Grows(cmd, kit.Keys(kit.MDB_HASH, kit.Select("system", arg, 0)), "", "", func(index int, value map[string]interface{}) { + if value[kit.MDB_FILE] == "ice.bin" { + // 程序文件 + value[kit.MDB_FILE] = kit.Keys("ice", m.Conf(cli.RUNTIME, "host.GOOS"), m.Conf(cli.RUNTIME, "host.GOARCH")) + exit = true + } + + // 下载文件 + h := m.Cmdx(web.SPIDE, "dev", web.CACHE, http.MethodGet, "/publish/"+kit.Format(value[kit.MDB_FILE])) + if h == "" { + exit = false + return + } + + // 升级记录 + m.Cmd(web.STORY, web.CATCH, "bin", value[kit.MDB_PATH], h) + m.Cmd(web.STORY, web.WATCH, h, path.Join(m.Conf(UPGRADE, "meta.path"), kit.Format(value[kit.MDB_PATH]))) + m.Cmd(web.STORY, web.WATCH, h, value[kit.MDB_PATH]) + os.Chmod(kit.Format(value[kit.MDB_PATH]), 0770) + }) + if exit { + m.Sleep("1s").Gos(m, func(m *ice.Message) { m.Cmd("exit", 1) }) + } + }}, + }, + }, nil) +} diff --git a/core/code/video.go b/core/code/video.go index 152effea..8e630cd4 100644 --- a/core/code/video.go +++ b/core/code/video.go @@ -47,5 +47,4 @@ func init() { }}, }, }, nil) - } diff --git a/meta.go b/meta.go index 0e6ea79a..b9b07675 100644 --- a/meta.go +++ b/meta.go @@ -86,6 +86,7 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa case kit.MDB_KEY, kit.MDB_ZONE: if key != "" { v = key + break } fallthrough default: @@ -319,7 +320,6 @@ func (m *Message) Table(cbs ...func(index int, value map[string]string, head []s return m } func (m *Message) Render(cmd string, args ...interface{}) *Message { - // m.Log(LOG_EXPORT, "%s: %v", cmd, args) m.Optionv(MSG_OUTPUT, cmd) m.Optionv(MSG_ARGS, args) diff --git a/misc/alpha/alpha.go b/misc/alpha/alpha.go index 034c3a2b..3202d749 100644 --- a/misc/alpha/alpha.go +++ b/misc/alpha/alpha.go @@ -1,12 +1,12 @@ package alpha import ( - "github.com/shylinux/icebergs" + ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/cli" "github.com/shylinux/icebergs/base/mdb" "github.com/shylinux/icebergs/base/web" "github.com/shylinux/icebergs/core/wiki" - "github.com/shylinux/toolkits" + kit "github.com/shylinux/toolkits" "github.com/shylinux/toolkits/task" "io/ioutil" @@ -80,7 +80,7 @@ func _alpha_load(m *ice.Message, file, name string) { )) m.Cmd(mdb.IMPORT, ALPHA, name, kit.MDB_LIST, - m.Cmd(web.CACHE, "catch", "csv", file+".csv").Append(kit.MDB_DATA)) + m.Cmd(web.CACHE, "catch", "csv", file+".csv").Append(web.DATA)) // 保存词库 m.Conf(ALPHA, kit.Keys(name, "meta.limit"), 0) diff --git a/misc/docker/docker.go b/misc/docker/docker.go index 4887ec2f..4a65aede 100644 --- a/misc/docker/docker.go +++ b/misc/docker/docker.go @@ -1,31 +1,29 @@ package docker import ( - "github.com/shylinux/icebergs" + ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/cli" "github.com/shylinux/icebergs/base/gdb" "github.com/shylinux/icebergs/base/web" "github.com/shylinux/icebergs/core/code" - "github.com/shylinux/toolkits" + kit "github.com/shylinux/toolkits" "strings" ) -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", - )...) -} +const DOCKER = "docker" var Index = &ice.Context{Name: "docker", Help: "虚拟机", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - "docker": {Name: "docker", Help: "虚拟机", Value: kit.Data(kit.MDB_SHORT, "name", "build", []interface{}{})}, + INSTALL: {Name: "install", Help: "安装", Value: kit.Data("path", "usr/install", + "linux", "https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz", + "darwin", "https://dl.google.com/go/go1.14.2.darwin-amd64.pkg", + "windows", "https://dl.google.com/go/go1.14.2.windows-amd64.msi", + "source", "https://dl.google.com/go/go1.14.2.src.tar.gz", + "target", "usr/local", + )}, + DOCKER: {Name: "docker", Help: "虚拟机", Value: kit.Data(kit.MDB_SHORT, "name", "build", []interface{}{})}, }, Commands: map[string]*ice.Command{ "init": {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -154,3 +152,14 @@ var Index = &ice.Context{Name: "docker", Help: "虚拟机", } func init() { code.Index.Register(Index, nil) } + +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/misc/tmux/tmux.go b/misc/tmux/tmux.go index 4840c7b5..8892dc0c 100644 --- a/misc/tmux/tmux.go +++ b/misc/tmux/tmux.go @@ -81,7 +81,7 @@ var Index = &ice.Context{Name: "tmux", Help: "工作台", if _, e := os.Stat(p); e != nil && os.IsNotExist(e) { // 下载脚本 if h := m.Cmdx(web.SPIDE, "shy", "cache", "GET", "/publish/"+v); h != "" { - m.Cmd(web.STORY, web.SHOW, h, p) + m.Cmd(web.STORY, web.WATCH, h, p) } } } diff --git a/misc/totp/totp.go b/misc/totp/totp.go index da20dc3c..5e0a4b5a 100644 --- a/misc/totp/totp.go +++ b/misc/totp/totp.go @@ -1,9 +1,9 @@ package totp import ( - "github.com/shylinux/icebergs" + ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/aaa" - "github.com/shylinux/toolkits" + kit "github.com/shylinux/toolkits" "bytes" "crypto/hmac" @@ -15,13 +15,13 @@ import ( "time" ) -func gen(per int64) string { +func _totp_gen(per int64) string { buf := bytes.NewBuffer([]byte{}) 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, num int, per int64) string { +func _totp_get(key string, num int, per int64) string { now := kit.Int64(time.Now().Unix() / per) buf := []byte{} @@ -43,10 +43,14 @@ func get(key string, num int, per int64) string { return kit.Format(kit.Format("%%0%dd", num), res%int64(math.Pow10(num))) } +const TOTP = "totp" + var Index = &ice.Context{Name: "totp", Help: "动态码", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - "totp": {Name: "totp", Help: "动态码", Value: kit.Data(kit.MDB_SHORT, "name", "share", "otpauth://totp/%s?secret=%s")}, + TOTP: {Name: "totp", Help: "动态码", Value: kit.Data( + kit.MDB_SHORT, "name", "share", "otpauth://totp/%s?secret=%s", + )}, }, Commands: map[string]*ice.Command{ ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},