From 431c4064a4590bec9b8074b0be328f1347ecd619 Mon Sep 17 00:00:00 2001 From: shylinux Date: Thu, 14 Oct 2021 03:20:26 +0800 Subject: [PATCH] opt input --- base/cli/cli.go | 7 +- base/cli/system.go | 2 +- base/ctx/command.go | 5 +- base/ctx/config.go | 7 ++ base/mdb/hash.go | 8 +- base/mdb/zone.go | 2 +- base/nfs/cat.go | 2 +- base/ssh/connect.go | 6 +- base/ssh/scripts.go | 2 +- base/web/dream.go | 8 +- base/web/serve.go | 6 +- base/web/spide.go | 6 +- base/web/web.go | 2 +- cmd.go | 117 ------------------- conf.go | 142 +++++++++++++---------- core/chat/header.go | 7 ++ core/code/autogen.go | 12 +- core/code/binpack.go | 10 +- core/code/c.go | 13 +-- core/code/compile.go | 2 +- core/code/publish.go | 2 +- core/code/upgrade.go | 2 +- core/code/vimer.go | 2 +- core/team/plan.go | 2 +- data.go | 29 +++-- exec.go | 37 +++--- go.mod | 2 +- go.sum | 2 - init.go | 188 ++++++++++-------------------- logs.go | 193 ++++++++++++++++++++++-------- meta.go | 48 ++++---- misc.go | 264 ++++++++++-------------------------------- misc/bash/trash.go | 2 +- misc/chrome/favor.go | 2 +- misc/input/input.go | 2 +- misc/tmux/session.go | 2 +- misc/wework/bot.go | 70 +++++++---- misc/wework/wework.go | 10 ++ option.go | 104 +++++------------ render.go | 126 ++++++++++++++------ type.go | 55 ++++----- 41 files changed, 667 insertions(+), 843 deletions(-) delete mode 100644 cmd.go diff --git a/base/cli/cli.go b/base/cli/cli.go index 47e19cd9..b62d6cb1 100644 --- a/base/cli/cli.go +++ b/base/cli/cli.go @@ -18,7 +18,7 @@ func _cli_init(m *ice.Message) { }) // 环境变量 - for _, k := range []string{CTX_SELF, CTX_DEV, CTX_SHY, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER} { + for _, k := range []string{CTX_SHY, CTX_DEV, CTX_WEB, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER} { m.Conf(RUNTIME, kit.Keys(CONF, k), os.Getenv(k)) } @@ -83,10 +83,11 @@ const ( USERNAME = "username" ) const ( - CTX_SELF = "ctx_self" - CTX_DEV = "ctx_dev" CTX_SHY = "ctx_shy" + CTX_DEV = "ctx_dev" + CTX_WEB = "ctx_web" CTX_PID = "ctx_pid" + CTX_LOG = "ctx_log" CTX_USER = "ctx_user" CTX_SHARE = "ctx_share" CTX_RIVER = "ctx_river" diff --git a/base/cli/system.go b/base/cli/system.go index d1ef1f95..7a02d494 100644 --- a/base/cli/system.go +++ b/base/cli/system.go @@ -93,7 +93,7 @@ func init() { SYSTEM: {Name: SYSTEM, Help: "系统命令", Value: kit.Data()}, }, Commands: map[string]*ice.Command{ - SYSTEM: {Name: "system cmd= run:button", Help: "系统命令", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + SYSTEM: {Name: "system cmd run:button", Help: "系统命令", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { if len(arg) == 0 { m.Fields(len(arg), "time,id,cmd") m.Cmdy(mdb.SELECT, SYSTEM, "", mdb.LIST) diff --git a/base/ctx/command.go b/base/ctx/command.go index 5fa0965d..ab1d891c 100644 --- a/base/ctx/command.go +++ b/base/ctx/command.go @@ -33,7 +33,7 @@ func _command_list(m *ice.Message, name string) { }) } func _command_search(m *ice.Message, kind, name, text string) { - ice.Pulse.Travel(func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) { + m.Travel(func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) { if key[0] == '/' || key[0] == '_' { return // 内部命令 } @@ -41,8 +41,9 @@ func _command_search(m *ice.Message, kind, name, text string) { return } - m.PushSearch("cmd", COMMAND, CONTEXT, s.Cap(ice.CTX_FOLLOW), COMMAND, key, + m.PushSearch("cmd", COMMAND, kit.MDB_TYPE, kind, kit.MDB_NAME, key, kit.MDB_TEXT, s.Cap(ice.CTX_FOLLOW), + CONTEXT, s.Cap(ice.CTX_FOLLOW), COMMAND, key, ) }) } diff --git a/base/ctx/config.go b/base/ctx/config.go index 7135f94c..bedf0ef2 100644 --- a/base/ctx/config.go +++ b/base/ctx/config.go @@ -116,6 +116,13 @@ func init() { m.Conf(arg[0], "", "") m.Cmd("exit", 1) }}, + "list": {Name: "list", Help: "列表", Hand: func(m *ice.Message, arg ...string) { + list := []interface{}{} + for _, v := range arg[2:] { + list = append(list, v) + } + m.Confv(arg[0], arg[1], kit.List(list...)) + }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { _config_list(m) diff --git a/base/mdb/hash.go b/base/mdb/hash.go index 5caa9384..c2d564c0 100644 --- a/base/mdb/hash.go +++ b/base/mdb/hash.go @@ -152,10 +152,10 @@ func HashAction(fields ...string) map[string]*ice.Action { m.Cmdy(INSERT, m.PrefixKey(), "", HASH, arg) }}, REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(kit.MDB_HASH)) + m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(m.Config(kit.MDB_SHORT))) }}, MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(MODIFY, m.PrefixKey(), "", HASH, m.OptionSimple(kit.MDB_HASH), arg) + m.Cmdy(MODIFY, m.PrefixKey(), "", HASH, m.OptionSimple(m.Config(kit.MDB_SHORT)), arg) }}, EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(EXPORT, m.PrefixKey(), "", HASH) @@ -177,3 +177,7 @@ func HashAction(fields ...string) map[string]*ice.Action { }}, }, fields...) } +func HashSelect(m *ice.Message, arg ...string) { + m.Fields(len(arg), m.Config(kit.MDB_FIELD)) + m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(kit.MDB_SHORT), arg) +} diff --git a/base/mdb/zone.go b/base/mdb/zone.go index aa459933..d0ae6175 100644 --- a/base/mdb/zone.go +++ b/base/mdb/zone.go @@ -136,7 +136,7 @@ func ZoneAction(fields ...string) map[string]*ice.Action { CREATE: {Name: "create zone", Help: "创建", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(INSERT, m.PrefixKey(), "", HASH, arg) }}, - INSERT: {Name: "insert zone= type=go name=hi text=hello", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + INSERT: {Name: "insert zone type=go name=hi text=hello", Help: "添加", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(INSERT, m.PrefixKey(), "", HASH, _zone(m), arg[1]) m.Cmdy(INSERT, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), arg[2:]) }}, diff --git a/base/nfs/cat.go b/base/nfs/cat.go index 6c6cf0fc..4ef16823 100644 --- a/base/nfs/cat.go +++ b/base/nfs/cat.go @@ -31,7 +31,7 @@ func _cat_find(m *ice.Message, name string) io.ReadCloser { return f } - if b, ok := ice.Info.BinPack[name]; ok { + if b, ok := ice.Info.Pack[name]; ok { m.Logs("binpack", len(b), name) return kit.NewReadCloser(bytes.NewBuffer(b)) } diff --git a/base/ssh/connect.go b/base/ssh/connect.go index b0f26117..b9fa3054 100644 --- a/base/ssh/connect.go +++ b/base/ssh/connect.go @@ -8,6 +8,8 @@ import ( "path" "strings" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/terminal" ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/cli" @@ -16,8 +18,6 @@ import ( "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" - "golang.org/x/crypto/ssh" - "golang.org/x/crypto/ssh/terminal" ) func _ssh_open(m *ice.Message, arg ...string) { @@ -166,7 +166,7 @@ func init() { }) }}, CONNECT: {Name: "connect hash auto dial prunes", Help: "连接", Action: map[string]*ice.Action{ - tcp.OPEN: {Name: "open authfile= username=shy password= verfiy= host=shylinux.com port=22 private=.ssh/id_rsa", Help: "终端", Hand: func(m *ice.Message, arg ...string) { + tcp.OPEN: {Name: "open authfile username=shy password verfiy host=shylinux.com port=22 private=.ssh/id_rsa", Help: "终端", Hand: func(m *ice.Message, arg ...string) { _ssh_open(m.OptionLoad(m.Option("authfile")), arg...) m.Echo("exit %v:%v\n", m.Option(tcp.HOST), m.Option(tcp.PORT)) }}, diff --git a/base/ssh/scripts.go b/base/ssh/scripts.go index 1bda2f2e..655cf92a 100644 --- a/base/ssh/scripts.go +++ b/base/ssh/scripts.go @@ -185,7 +185,7 @@ func (f *Frame) parse(m *ice.Message, line string) string { } if async { - msg.Gos(msg, func(msg *ice.Message) { msg.Cmd(ls[0], ls[1:]) }) + msg.Go(func() { msg.Cmd(ls[0], ls[1:]) }) continue } else { msg.Cmdy(ls[0], ls[1:]) diff --git a/base/web/dream.go b/base/web/dream.go index 22ec6d76..8ee90d63 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -47,7 +47,7 @@ func _dream_show(m *ice.Message, name string) { // 任务模板 if m.Option(kit.MDB_TEMPLATE) != "" { - for _, file := range []string{ice.ETC_MISS, ice.SRC_MAIN_SHY, ice.SRC_MAIN_GO, ice.GO_MOD, ice.MAKEFILE} { + for _, file := range []string{ice.ETC_MISS_SH, ice.SRC_MAIN_SHY, ice.SRC_MAIN_GO, ice.GO_MOD, ice.MAKEFILE} { if _, e := os.Stat(path.Join(p, file)); os.IsNotExist(e) { switch m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(m.Option(kit.MDB_TEMPLATE), file)); file { case ice.GO_MOD: @@ -60,7 +60,7 @@ func _dream_show(m *ice.Message, name string) { } // 任务脚本 - miss := path.Join(p, ice.ETC_MISS) + miss := path.Join(p, ice.ETC_MISS_SH) if _, e := os.Stat(miss); os.IsNotExist(e) { m.Cmd(nfs.SAVE, miss, m.Conf(DREAM, kit.Keym("miss"))) } @@ -115,7 +115,7 @@ func init() { m.ProcessInner() }}, cli.START: {Name: "start name repos river", Help: "启动", Hand: func(m *ice.Message, arg ...string) { - if m.Option(kit.MDB_NAME) == SPIDE_SELF { + if m.Option(kit.MDB_NAME) == SPIDE_WEB { m.Option(kit.MDB_NAME, "") } _dream_show(m, m.Option(kit.MDB_NAME, kit.Select(path.Base(m.Option(kit.SSH_REPOS)), m.Option(kit.MDB_NAME)))) @@ -140,7 +140,7 @@ func init() { Configs: map[string]*ice.Config{ DREAM: {Name: DREAM, Help: "梦想家", Value: kit.Data(kit.MDB_PATH, ice.USR_LOCAL_WORK, cli.CMD, []interface{}{"ice.bin", SPACE, tcp.DIAL}, - cli.ENV, kit.Dict(ice.CTX_LOG, ice.BIN_BOOTLOG), + cli.ENV, kit.Dict(cli.CTX_LOG, ice.BIN_BOOTLOG), "miss", `#!/bin/bash if [ "$ISH_CONF_PRE" = "" ]; then [ -f $PWD/.ish/plug.sh ] || [ -f $HOME/.ish/plug.sh ] || git clone ${ISH_CONF_HUB_PROXY:="https://"}shylinux.com/x/intshell $PWD/.ish diff --git a/base/web/serve.go b/base/web/serve.go index e99de4b5..cb1cd052 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -174,7 +174,7 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon // 执行命令 if cmds, ok := _serve_login(msg, kit.Simple(msg.Optionv(ice.MSG_CMDS)), w, r); ok { msg.Option(ice.MSG_OPTS, msg.Optionv(ice.MSG_OPTION)) - msg.Target().Cmd(msg, key, r.URL.Path, cmds...) + msg.Target().Cmd(msg, key, cmds...) msg.Cost(kit.Format("%s %v %v", r.URL.Path, cmds, msg.Format(ice.MSG_APPEND))) } @@ -198,7 +198,7 @@ func _serve_login(msg *ice.Message, cmds []string, w http.ResponseWriter, r *htt if _, ok := msg.Target().Commands[WEB_LOGIN]; ok { // 权限检查 - msg.Target().Cmd(msg, WEB_LOGIN, r.URL.Path, cmds...) + msg.Target().Cmd(msg, WEB_LOGIN, cmds...) return cmds, msg.Result(0) != ice.ErrWarn && msg.Result() != ice.FALSE } @@ -268,7 +268,7 @@ func init() { m.Conf(SERVE, kit.Keys(kit.MDB_META, aaa.WHITE, k), true) } }}, - cli.START: {Name: "start dev= name=self proto=http host= port=9020", Help: "启动", Hand: func(m *ice.Message, arg ...string) { + cli.START: {Name: "start dev name=web proto=http host port=9020", Help: "启动", Hand: func(m *ice.Message, arg ...string) { if cli.NodeInfo(m, SERVER, ice.Info.HostName); m.Option(tcp.PORT) == tcp.RANDOM { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) } diff --git a/base/web/spide.go b/base/web/spide.go index cfb65653..2d7823f3 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -287,9 +287,9 @@ func _spide_save(m *ice.Message, cache, save, uri string, res *http.Response) { } const ( - SPIDE_SHY = "shy" - SPIDE_DEV = "dev" - SPIDE_SELF = "self" + SPIDE_SHY = "shy" + SPIDE_DEV = "dev" + SPIDE_WEB = "web" SPIDE_RAW = "raw" SPIDE_MSG = "msg" diff --git a/base/web/web.go b/base/web/web.go index 8b5fd998..ba6d0462 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -100,8 +100,8 @@ var Index = &ice.Context{Name: WEB, Help: "网络模块", Commands: map[string]* m.Conf(SPACE, kit.MDB_HASH, "") m.Cmd(mdb.SEARCH, mdb.CREATE, SPACE, m.Prefix(SPACE)) + m.Cmd(SPIDE, mdb.CREATE, SPIDE_WEB, kit.Select("http://:9020", m.Conf(cli.RUNTIME, "conf.ctx_web"))) m.Cmd(SPIDE, mdb.CREATE, SPIDE_DEV, kit.Select("http://:9020", m.Conf(cli.RUNTIME, "conf.ctx_dev"))) - m.Cmd(SPIDE, mdb.CREATE, SPIDE_SELF, kit.Select("http://:9020", m.Conf(cli.RUNTIME, "conf.ctx_self"))) m.Cmd(SPIDE, mdb.CREATE, SPIDE_SHY, kit.Select("https://shylinux.com:443", m.Conf(cli.RUNTIME, "conf.ctx_shy"))) }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { diff --git a/cmd.go b/cmd.go deleted file mode 100644 index dadbf2a0..00000000 --- a/cmd.go +++ /dev/null @@ -1,117 +0,0 @@ -package ice - -import ( - "reflect" - "strings" - - kit "shylinux.com/x/toolkits" -) - -func ref(obj interface{}) (reflect.Type, reflect.Value) { - t := reflect.TypeOf(obj) - v := reflect.ValueOf(obj) - if t.Kind() == reflect.Ptr { - t, v = t.Elem(), v.Elem() - } - return t, v -} -func val(m *Message, arg ...string) []reflect.Value { - args := []reflect.Value{reflect.ValueOf(m)} - for _, v := range arg { - args = append(args, reflect.ValueOf(v)) - } - return args -} -func transMethod(config *Config, command *Command, obj interface{}) { - t, v := ref(obj) - for i := 0; i < v.NumMethod(); i++ { - method := v.Method(i) - var h func(*Message, ...string) - switch method.Interface().(type) { - case func(*Message, ...string): - h = func(m *Message, arg ...string) { method.Call(val(m, arg...)) } - case func(*Message): - h = func(m *Message, arg ...string) { method.Call(val(m)) } - default: - continue - } - - if key := strings.ToLower(t.Method(i).Name); key == "list" { - command.Hand = func(m *Message, c *Context, cmd string, arg ...string) { h(m, arg...) } - } else { - if action, ok := command.Action[key]; !ok { - command.Action[key] = &Action{Hand: h} - } else { - action.Hand = h - } - } - } - -} -func transField(config *Config, command *Command, obj interface{}) { - t, v := ref(obj) - for i := 0; i < v.NumField(); i++ { - if t.Field(i).Type.Kind() == reflect.Struct { - if v.Field(i).CanInterface() { - transField(config, command, v.Field(i).Interface()) - } - } - } - - meta := kit.Value(config.Value, kit.MDB_META) - for i := 0; i < v.NumField(); i++ { - key, tag := t.Field(i).Name, t.Field(i).Tag - if data := tag.Get("data"); data != "" { - kit.Value(meta, key, data) - } - - if name := tag.Get("name"); name != "" { - if help := tag.Get("help"); key == "list" { - command.Name, command.Help = name, help - config.Name, config.Help = name, help - } else if action, ok := command.Action[key]; ok { - action.Name, action.Help = name, help - } - } - } -} -func Cmd(key string, obj interface{}) { - if obj == nil { - return - } - command := &Command{Action: map[string]*Action{}} - config := &Config{Value: kit.Data()} - transMethod(config, command, obj) - transField(config, command, obj) - - last := Index - list := strings.Split(key, ".") - for i := 1; i < len(list); i++ { - has := false - Pulse.Search(strings.Join(list[:i], ".")+".", func(p *Context, s *Context) { - has, last = true, s - }) - if !has { - context := &Context{Name: list[i-1]} - last.Register(context, nil) - last = context - } - if i < len(list)-1 { - continue - } - - last.Merge(&Context{Commands: map[string]*Command{ - CTX_INIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { - if action, ok := command.Action["init"]; ok { - action.Hand(m, arg...) - } else { - m.Load() - } - }}, - CTX_EXIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { - m.Save() - }}, - list[i]: command, - }, Configs: map[string]*Config{list[i]: config}}) - } -} diff --git a/conf.go b/conf.go index 08787a66..38ad1ce4 100644 --- a/conf.go +++ b/conf.go @@ -3,6 +3,23 @@ package ice const ( SP = " " NL = "\n" + + OK = "ok" + TRUE = "true" + FALSE = "false" + SUCCESS = "success" + FAILURE = "failure" + + INIT = "init" + EXIT = "exit" + SAVE = "save" + LOAD = "load" + HELP = "help" + + ICE = "ice" + SHY = "shy" + DEV = "dev" + WEB = "web" ) const ( // MOD MOD_DIR = 0750 @@ -21,15 +38,9 @@ const ( // REPOS INTSHELL = "intshell" CONTEXTS = "contexts" - INSTALL = "install" REQUIRE = "require" + INSTALL = "install" PUBLISH = "publish" - - SUCCESS = "success" - FAILURE = "failure" - FALSE = "false" - TRUE = "true" - OK = "ok" ) const ( // DIR USR_VOLCANOS = "usr/volcanos" @@ -41,10 +52,10 @@ const ( // DIR USR_LOCAL = "usr/local" USR_LOCAL_WORK = "usr/local/work" - USR_LOCAL_RIVER = "usr/local/river" USR_LOCAL_IMAGE = "usr/local/image" - USR_LOCAL_EXPORT = "usr/local/export" + USR_LOCAL_RIVER = "usr/local/river" USR_LOCAL_DAEMON = "usr/local/daemon" + USR_LOCAL_EXPORT = "usr/local/export" FAVICON = "favicon.ico" PROTO_JS = "proto.js" @@ -54,36 +65,29 @@ const ( // DIR ORDER_SH = "order.sh" INDEX_SH = "index.sh" - VAR_TMP = "var/tmp" - VAR_RUN = "var/run" - VAR_LOG = "var/log" - VAR_CONF = "var/conf" - VAR_DATA = "var/data" - VAR_FILE = "var/file" - VAR_PROXY = "var/proxy" - VAR_TRASH = "var/trash" - BIN_ICE = "bin/ice.sh" - BIN_ICE_SH = "bin/ice.sh" - BIN_ICE_BIN = "bin/ice.bin" - BIN_BOOTLOG = "bin/boot.log" - ETC_INIT = "etc/init.shy" - ETC_EXIT = "etc/exit.shy" - ETC_MISS = "etc/miss.sh" - ETC_MISS_SH = "etc/miss.sh" + VAR_RUN = "var/run" + VAR_TMP = "var/tmp" + VAR_LOG = "var/log" + VAR_CONF = "var/conf" + VAR_DATA = "var/data" + VAR_FILE = "var/file" + VAR_PROXY = "var/proxy" + VAR_TRASH = "var/trash" + BIN_ICE_SH = "bin/ice.sh" + BIN_ICE_BIN = "bin/ice.bin" + BIN_BOOTLOG = "bin/boot.log" + ETC_INIT_SHY = "etc/init.shy" + ETC_EXIT_SHY = "etc/exit.shy" + ETC_MISS_SH = "etc/miss.sh" - SRC_HELP = "src/help" - SRC_MAIN_SHY = "src/main.shy" - SRC_MAIN_GO = "src/main.go" - SRC_VERSION = "src/version.go" - SRC_BINPACK = "src/binpack.go" - MAKEFILE = "makefile" - GO_MOD = "go.mod" - GO_SUM = "go.sum" - - CTX_DEBUG = "ctx_debug" - CTX_DEV = "ctx_dev" - CTX_PID = "ctx_pid" - CTX_LOG = "ctx_log" + SRC_HELP = "src/help" + SRC_MAIN_SHY = "src/main.shy" + SRC_MAIN_GO = "src/main.go" + SRC_VERSION_GO = "src/version.go" + SRC_BINPACK_GO = "src/binpack.go" + MAKEFILE = "makefile" + GO_MOD = "go.mod" + GO_SUM = "go.sum" ) const ( // MSG MSG_DETAIL = "detail" @@ -124,12 +128,18 @@ const ( // MSG MSG_USERNAME = "user.name" MSG_USERZONE = "user.zone" MSG_USERROLE = "user.role" + MSG_LANGUAGE = "user.lang" MSG_TITLE = "sess.title" MSG_RIVER = "sess.river" MSG_STORM = "sess.storm" MSG_LOCAL = "sess.local" MSG_TOAST = "sess.toast" + + CACHE_LIMIT = "cache.limit" + CACHE_BEGIN = "cache.begin" + CACHE_COUNT = "cache.count" + CACHE_OFFEND = "cache.offend" ) const ( // RENDER RENDER_RAW = "_raw" @@ -137,40 +147,51 @@ const ( // RENDER RENDER_RESULT = "_result" RENDER_ANCHOR = "_anchor" RENDER_BUTTON = "_button" + RENDER_SCRIPT = "_script" + RENDER_QRCODE = "_qrcode" RENDER_IMAGES = "_images" RENDER_VIDEOS = "_videos" - RENDER_QRCODE = "_qrcode" - RENDER_SCRIPT = "_script" RENDER_TEMPLATE = "_template" RENDER_DOWNLOAD = "_download" RENDER_REDIRECT = "_redirect" ) const ( // PROCESS PROCESS_LOCATION = "_location" - PROCESS_REFRESH = "_refresh" PROCESS_REWRITE = "_rewrite" + PROCESS_REFRESH = "_refresh" PROCESS_DISPLAY = "_display" PROCESS_FIELD = "_field" PROCESS_INNER = "_inner" PROCESS_AGAIN = "_again" + PROCESS_OPEN = "_open" PROCESS_HOLD = "_hold" PROCESS_BACK = "_back" PROCESS_GROW = "_grow" - PROCESS_OPEN = "_open" FIELD_PREFIX = "_prefix" ) +const ( // Err + ErrWarn = "warn: " + ErrExpire = "expire: " + ErrExists = "exists: " + ErrNotLogin = "not login: " + ErrNotFound = "not found: " + ErrNotRight = "not right: " +) const ( // LOG - // 数据 - LOG_CREATE = "create" - LOG_REMOVE = "remove" - LOG_MODIFY = "modify" - LOG_INSERT = "insert" - LOG_DELETE = "delete" - LOG_SELECT = "select" - LOG_EXPORT = "export" - LOG_IMPORT = "import" + // 通用 + LOG_INFO = "info" + LOG_COST = "cost" + LOG_WARN = "warn" + LOG_ERROR = "error" + LOG_DEBUG = "debug" + + // 命令 + LOG_AUTH = "auth" + LOG_CMDS = "cmds" + LOG_SEND = "send" + LOG_RECV = "recv" // 状态 LOG_BEGIN = "begin" @@ -178,16 +199,15 @@ const ( // LOG LOG_SERVE = "serve" LOG_CLOSE = "close" - // 分类 - LOG_CMDS = "cmds" - LOG_AUTH = "auth" - LOG_SEND = "send" - LOG_RECV = "recv" - LOG_COST = "cost" - LOG_INFO = "info" - LOG_WARN = "warn" - LOG_ERROR = "error" - LOG_DEBUG = "debug" + // 数据 + LOG_CREATE = "create" + LOG_REMOVE = "remove" + LOG_INSERT = "insert" + LOG_DELETE = "delete" + LOG_MODIFY = "modify" + LOG_SELECT = "select" + LOG_EXPORT = "export" + LOG_IMPORT = "import" ) const ( // CTX CTX_FOLLOW = "follow" diff --git a/core/chat/header.go b/core/chat/header.go index 6d468e3c..42f4056e 100644 --- a/core/chat/header.go +++ b/core/chat/header.go @@ -1,6 +1,8 @@ package chat import ( + "strings" + ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/ctx" @@ -27,6 +29,7 @@ func _header_check(m *ice.Message, arg ...string) { if m.Option(ice.MSG_USERNAME) == "" { // 单点登录 m.Option(web.SSO, m.Conf(web.SERVE, kit.Keym(web.SSO))) + m.Option(web.LOGIN, m.Config(web.LOGIN)) } } func _header_share(m *ice.Message, arg ...string) { @@ -36,6 +39,8 @@ func _header_share(m *ice.Message, arg ...string) { m.Option(kit.MDB_LINK, tcp.ReplaceLocalhost(m, m.Option(kit.MDB_LINK))) } + m.Option(kit.MDB_LINK, strings.Split(m.Option(kit.MDB_LINK), "?")[0]) + m.Set(kit.MDB_NAME, kit.MDB_TEXT) m.Push(kit.MDB_NAME, m.Option(kit.MDB_LINK)) m.PushQRCode(kit.MDB_TEXT, m.Option(kit.MDB_LINK)) @@ -63,6 +68,7 @@ const ( CHECK = "check" SHARE = "share" GRANT = "grant" + LOGIN = "login" ) const HEADER = "header" @@ -70,6 +76,7 @@ func init() { Index.Merge(&ice.Context{Configs: map[string]*ice.Config{ HEADER: {Name: HEADER, Help: "标题栏", Value: kit.Data( TITLE, "shylinux.com/x/contexts", MENUS, `["header", ["setting", "black", "white", "print", "webpack", "unpack"]]`, + LOGIN, kit.List("登录", "扫码"), )}, }, Commands: map[string]*ice.Command{ "/header": {Name: "/header", Help: "标题栏", Action: map[string]*ice.Action{ diff --git a/core/code/autogen.go b/core/code/autogen.go index 5ebe4a85..cdc1c4c2 100644 --- a/core/code/autogen.go +++ b/core/code/autogen.go @@ -100,7 +100,7 @@ func _autogen_version(m *ice.Message) { m.Cmdy(cli.SYSTEM, "go", "mod", "init", path.Base(kit.Path(""))) } - file := ice.SRC_VERSION + file := ice.SRC_VERSION_GO m.Cmd(nfs.SAVE, file, kit.Format(`package main import ( @@ -127,14 +127,14 @@ func init() { defer m.Cmdy(nfs.CAT, file) m.Cmdy(nfs.DIR, file, "time,size,line,path") - m.Cmdy(nfs.DIR, ice.SRC_BINPACK, "time,size,line,path") + m.Cmdy(nfs.DIR, ice.SRC_BINPACK_GO, "time,size,line,path") m.Cmdy(nfs.DIR, ice.SRC_MAIN_GO, "time,size,line,path") } func _autogen_miss(m *ice.Message) { - m.Cmd(nfs.DEFS, ice.ETC_MISS, m.Conf(web.DREAM, kit.Keym("miss"))) - defer m.Cmdy(nfs.CAT, ice.ETC_MISS) + m.Cmd(nfs.DEFS, ice.ETC_MISS_SH, m.Conf(web.DREAM, kit.Keym("miss"))) + defer m.Cmdy(nfs.CAT, ice.ETC_MISS_SH) - m.Cmdy(nfs.DIR, ice.ETC_MISS, "time,size,line,path") + m.Cmdy(nfs.DIR, ice.ETC_MISS_SH, "time,size,line,path") m.Cmdy(nfs.DIR, ice.GO_MOD, "time,size,line,path") m.Cmdy(nfs.DIR, ice.GO_SUM, "time,size,line,path") } @@ -144,7 +144,7 @@ const AUTOGEN = "autogen" func init() { Index.Merge(&ice.Context{Commands: map[string]*ice.Command{ AUTOGEN: {Name: "autogen path auto create binpack script", Help: "生成", Action: map[string]*ice.Action{ - mdb.CREATE: {Name: "create main=src/main.go@key key= zone= type=Zone,Hash,Data name=hi list= help=", Help: "模块", Hand: func(m *ice.Message, arg ...string) { + mdb.CREATE: {Name: "create main=src/main.go@key key zone type=Zone,Hash,Data name=hi list help", Help: "模块", Hand: func(m *ice.Message, arg ...string) { _defs(m, "zone", m.Option("name"), "help", m.Option("name")) _defs(m, "key", kit.Keys("web.code", m.Option("zone"), m.Option("name"))) switch m.Option("type") { diff --git a/core/code/binpack.go b/core/code/binpack.go index 3a99f209..3b6ae677 100644 --- a/core/code/binpack.go +++ b/core/code/binpack.go @@ -82,7 +82,7 @@ func init() { Index.Merge(&ice.Context{Commands: map[string]*ice.Command{ BINPACK: {Name: "binpack path auto create remove export", Help: "打包", Action: map[string]*ice.Action{ mdb.CREATE: {Name: "create", Help: "创建", Hand: func(m *ice.Message, arg ...string) { - if pack, p, e := kit.Create(ice.SRC_BINPACK); m.Assert(e) { + if pack, p, e := kit.Create(ice.SRC_BINPACK_GO); m.Assert(e) { defer pack.Close() _pack_write(pack, `package main`) @@ -93,7 +93,7 @@ func init() { _pack_write(pack, "") _pack_write(pack, `func init() {`) - _pack_write(pack, ` ice.Info.BinPack = map[string][]byte{`) + _pack_write(pack, ` ice.Info.Pack = map[string][]byte{`) _pack_volcanos(m, pack, ice.USR_VOLCANOS) _pack_dir(m, pack, ice.USR_LEARNING) @@ -108,10 +108,10 @@ func init() { } }}, mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - ice.Info.BinPack = map[string][]byte{} + ice.Info.Pack = map[string][]byte{} }}, mdb.EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { - for key, value := range ice.Info.BinPack { + for key, value := range ice.Info.Pack { if strings.HasPrefix(key, "/") { key = ice.USR_VOLCANOS + key } @@ -120,7 +120,7 @@ func init() { } }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - for k, v := range ice.Info.BinPack { + for k, v := range ice.Info.Pack { m.Push(kit.MDB_NAME, k) m.Push(kit.MDB_SIZE, len(v)) } diff --git a/core/code/c.go b/core/code/c.go index 8a073631..ff902362 100644 --- a/core/code/c.go +++ b/core/code/c.go @@ -110,18 +110,7 @@ func init() { } for _, i := range []string{"1", "2", "3", "8"} { if text := _c_help(m, i, kit.Select(kit.MDB_MAIN, arg, 1)); text != "" { - for _, k := range kit.Split(m.Option(mdb.FIELDS)) { - switch k { - case kit.MDB_FILE: - m.Push(k, kit.Keys(arg[1], MAN+i)) - case kit.MDB_LINE: - m.Push(k, 1) - case kit.MDB_TEXT: - m.Push(k, text) - default: - m.Push(k, "") - } - } + m.PushSearch(cli.CMD, "c", kit.MDB_FILE, kit.Keys(arg[1], MAN+i), kit.MDB_LINE, 1, kit.MDB_TEXT, text) } } }}, diff --git a/core/code/compile.go b/core/code/compile.go index 50088aa6..468e6fb0 100644 --- a/core/code/compile.go +++ b/core/code/compile.go @@ -59,7 +59,7 @@ func init() { // 编译参数 m.Optionv(cli.CMD_ENV, kit.Simple(m.Confv(COMPILE, kit.Keym(cli.ENV)), "GOARCH", arch, "GOOS", goos)) if msg := m.Cmd(cli.SYSTEM, m.Confv(COMPILE, kit.Keym(GO)), - "-o", file, main, ice.SRC_VERSION, ice.SRC_BINPACK); msg.Append(cli.CMD_CODE) != "0" { + "-o", file, main, ice.SRC_VERSION_GO, ice.SRC_BINPACK_GO); msg.Append(cli.CMD_CODE) != "0" { m.Copy(msg) return } diff --git a/core/code/publish.go b/core/code/publish.go index 35da42f1..f646ac48 100644 --- a/core/code/publish.go +++ b/core/code/publish.go @@ -56,7 +56,7 @@ func init() { ice.VOLCANOS: {Name: "volcanos", Help: "火山架", Hand: func(m *ice.Message, arg ...string) { defer func() { m.EchoQRCode(m.Option(ice.MSG_USERWEB)) }() defer func() { m.Cmdy(PUBLISH, ice.CONTEXTS, "miss") }() - m.Cmd(PUBLISH, mdb.CREATE, kit.MDB_FILE, ice.ETC_MISS) + m.Cmd(PUBLISH, mdb.CREATE, kit.MDB_FILE, ice.ETC_MISS_SH) m.Cmd(PUBLISH, mdb.CREATE, kit.MDB_FILE, ice.GO_MOD) m.Cmd(nfs.DEFS, path.Join(m.Conf(PUBLISH, kit.META_PATH), ice.ORDER_JS), m.Conf(PUBLISH, kit.Keym(JS))) diff --git a/core/code/upgrade.go b/core/code/upgrade.go index 8ca8138a..f800436e 100644 --- a/core/code/upgrade.go +++ b/core/code/upgrade.go @@ -16,7 +16,7 @@ func init() { Configs: map[string]*ice.Config{ UPGRADE: {Name: UPGRADE, Help: "升级", Value: kit.Dict(kit.MDB_HASH, kit.Dict( cli.SYSTEM, kit.Dict(kit.MDB_LIST, kit.List( - kit.MDB_INPUT, "bin", kit.MDB_FILE, "ice.sh", kit.MDB_PATH, ice.BIN_ICE, + kit.MDB_INPUT, "bin", kit.MDB_FILE, "ice.sh", kit.MDB_PATH, ice.BIN_ICE_SH, kit.MDB_INPUT, "bin", kit.MDB_FILE, "ice.bin", kit.MDB_PATH, ice.BIN_ICE_BIN, )), cli.SOURCE, kit.Dict(kit.MDB_LIST, kit.List( diff --git a/core/code/vimer.go b/core/code/vimer.go index 103d45f7..a5da62b1 100644 --- a/core/code/vimer.go +++ b/core/code/vimer.go @@ -33,7 +33,7 @@ func init() { nfs.SAVE: {Name: "save type file path", Help: "保存", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(nfs.SAVE, path.Join(m.Option(kit.MDB_PATH), m.Option(kit.MDB_FILE))) }}, - AUTOGEN: {Name: "create main=src/main.go@key key= zone= type=Zone,Hash,Data name=hi list= help=", Help: "模块", Hand: func(m *ice.Message, arg ...string) { + AUTOGEN: {Name: "create main=src/main.go@key key zone type=Zone,Hash,Data name=hi list help", Help: "模块", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(AUTOGEN, mdb.CREATE, arg) }}, COMPILE: {Name: "compile", Help: "编译", Hand: func(m *ice.Message, arg ...string) { diff --git a/core/team/plan.go b/core/team/plan.go index 7fbfc087..71b9257d 100644 --- a/core/team/plan.go +++ b/core/team/plan.go @@ -35,7 +35,7 @@ const PLAN = "plan" func init() { Index.Merge(&ice.Context{ Commands: map[string]*ice.Command{ - PLAN: {Name: "plan scale=day,week,month,year,long begin_time@date auto insert export import", Help: "计划", Meta: kit.Dict( + PLAN: {Name: "plan scale=week,day,week,month,year,long begin_time@date auto insert export import", Help: "计划", Meta: kit.Dict( ice.Display("/plugin/local/team/plan.js", PLAN), ), Action: map[string]*ice.Action{ mdb.INSERT: {Name: "insert zone type=once,step,week name text begin_time@date close_time@date", Help: "添加", Hand: func(m *ice.Message, arg ...string) { diff --git a/data.go b/data.go index b57b42f1..67e5493e 100644 --- a/data.go +++ b/data.go @@ -8,11 +8,17 @@ import ( "shylinux.com/x/toolkits/miss" ) +func (m *Message) PrefixKey(arg ...string) string { + return kit.Keys(m.Cap(CTX_FOLLOW), strings.TrimPrefix(m._key, "/"), arg) +} func (m *Message) Prefix(arg ...string) string { return kit.Keys(m.Cap(CTX_FOLLOW), arg) } -func (m *Message) PrefixKey(arg ...string) string { - return kit.Keys(m.Cap(CTX_FOLLOW), m._key, arg) +func (m *Message) Config(key string) string { + return m.Conf(m.PrefixKey(), kit.Keym(key)) +} +func (m *Message) ConfigSimple(key string) []string { + return []string{key, m.Conf(m.PrefixKey(), kit.Keym(key))} } func (m *Message) Save(arg ...string) *Message { if len(arg) == 0 { @@ -24,7 +30,7 @@ func (m *Message) Save(arg ...string) *Message { for _, k := range arg { list = append(list, m.Prefix(k)) } - m.Cmd("ctx.config", "save", m.Prefix("json"), list) + m.Cmd("ctx.config", SAVE, m.Prefix("json"), list) return m } func (m *Message) Load(arg ...string) *Message { @@ -32,7 +38,7 @@ func (m *Message) Load(arg ...string) *Message { for _, k := range arg { list = append(list, m.Prefix(k)) } - m.Cmd("ctx.config", "load", m.Prefix("json"), list) + m.Cmd("ctx.config", LOAD, m.Prefix("json"), list) return m } @@ -48,6 +54,7 @@ func (m *Message) Richs(prefix string, chain interface{}, raw interface{}, cb in wg := &sync.WaitGroup{} defer wg.Wait() + res = miss.Richs(kit.Keys(prefix, chain), cache, raw, func(key string, value map[string]interface{}) { wg.Add(1) @@ -84,18 +91,18 @@ func (m *Message) Grows(prefix string, chain interface{}, match string, value st return nil } - limit := kit.Int(m.Option("cache.limit")) - if begin := kit.Int(m.Option("cache.begin")); begin != 0 && limit > 0 { - count := kit.Int(m.Option("cache.count", kit.Int(kit.Value(cache, kit.Keym("count"))))) + limit := kit.Int(m.Option(CACHE_LIMIT)) + if begin := kit.Int(m.Option(CACHE_BEGIN)); begin != 0 && limit > 0 { + count := kit.Int(m.Option(CACHE_COUNT, kit.Int(kit.Value(cache, kit.Keym(kit.MDB_COUNT))))) if begin > 0 { - m.Option("cache.offend", count-begin-limit) + m.Option(CACHE_OFFEND, count-begin-limit) } else { - m.Option("cache.offend", -begin-limit) + m.Option(CACHE_OFFEND, -begin-limit) } } return miss.Grows(kit.Keys(prefix, chain), cache, - kit.Int(kit.Select("0", strings.TrimPrefix(m.Option("cache.offend"), "-"))), - kit.Int(kit.Select("10", m.Option("cache.limit"))), + kit.Int(kit.Select("0", strings.TrimPrefix(m.Option(CACHE_OFFEND), "-"))), + kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))), match, value, cb) } diff --git a/exec.go b/exec.go index b08014a8..985754ae 100644 --- a/exec.go +++ b/exec.go @@ -2,7 +2,6 @@ package ice import ( "errors" - "fmt" "io" "strings" "time" @@ -36,22 +35,22 @@ func (m *Message) TryCatch(msg *Message, silent bool, hand ...func(msg *Message) } return m } -func (m *Message) Assert(arg interface{}) bool { - switch arg := arg.(type) { +func (m *Message) Assert(expr interface{}) bool { + switch expr := expr.(type) { case nil: return true + case error: + panic(expr) case bool: - if arg == true { + if expr == true { return true } - case error: - panic(arg) } - panic(errors.New(fmt.Sprintf("error: %v", arg))) + panic(errors.New(kit.Format("error: %v", expr))) } -func (m *Message) Sleep(arg string) *Message { - m.Debug("sleep %s %s", arg, kit.FileLine(2, 3)) - time.Sleep(kit.Duration(arg)) +func (m *Message) Sleep(d string) *Message { + m.Debug("sleep %s %s", d, kit.FileLine(2, 3)) + time.Sleep(kit.Duration(d)) return m } func (m *Message) Hold(n int) *Message { @@ -77,15 +76,16 @@ func (m *Message) Done(b bool) bool { ctx.wg.Done() return true } - func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message { wait := make(chan bool, 2) + p := kit.Select("10s", m.Option("timeout")) t := time.AfterFunc(kit.Duration(p), func() { m.Warn(true, "%s timeout %v", p, m.Detailv()) wait <- false m.Back(nil) }) + m.cb = func(sub *Message) *Message { if sync { wait <- true @@ -109,26 +109,19 @@ func (m *Message) Back(res *Message) *Message { } return m } -func (m *Message) Gos(msg *Message, cb interface{}, args ...interface{}) *Message { +func (m *Message) Go(cb interface{}, args ...interface{}) *Message { task.Put(kit.FileLine(3, 3), func(task *task.Task) error { - msg.TryCatch(msg, true, func(msg *Message) { + m.TryCatch(m, true, func(m *Message) { switch cb := cb.(type) { case func(*Message): - cb(msg) + cb(m.Spawn()) case func(): cb() } }) return nil }) - return msg -} -func (m *Message) Go(cb interface{}, args ...interface{}) *Message { - switch cb := cb.(type) { - case func(*Message): - return m.Gos(m.Spawn(), cb, args...) - } - return m.Gos(m, cb, args...) + return m } func (m *Message) Watch(key string, arg ...string) *Message { diff --git a/go.mod b/go.mod index 37b2b1ea..39cd3543 100644 --- a/go.mod +++ b/go.mod @@ -7,5 +7,5 @@ require ( github.com/kr/pty v1.1.8 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 - shylinux.com/x/toolkits v0.3.3 + shylinux.com/x/toolkits v0.3.4 ) diff --git a/go.sum b/go.sum index 5a228589..95cf1101 100644 --- a/go.sum +++ b/go.sum @@ -15,7 +15,5 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -shylinux.com/x/toolkits v0.3.0 h1:rF9SIE02VCfgpuI2P/H7EoJaWpf+zomxAaRHiYD7yjE= -shylinux.com/x/toolkits v0.3.0/go.mod h1:8LbYHe7oxBIqb6s4MSOD+4d28QvPdvkyCVtwB/JW7AA= shylinux.com/x/toolkits v0.3.3 h1:yNH54CANAv7cPT264tpnDt9G2BVfGwLC9y3rxtU6pkg= shylinux.com/x/toolkits v0.3.3/go.mod h1:8LbYHe7oxBIqb6s4MSOD+4d28QvPdvkyCVtwB/JW7AA= diff --git a/init.go b/init.go index 76bd33fb..0037f8d6 100644 --- a/init.go +++ b/init.go @@ -1,7 +1,6 @@ package ice import ( - "io" "os" "strings" "sync" @@ -11,8 +10,7 @@ import ( ) type Frame struct { - code int - wait chan bool + wait chan int } func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server { @@ -36,10 +34,10 @@ func (f *Frame) Start(m *Message, arg ...string) bool { m.Log(LOG_START, "ice") defer m.Cost("start ice") - m.Cap(CTX_STATUS, "start") + m.Cap(CTX_STATUS, CTX_START) m.Cap(CTX_STREAM, strings.Split(m.Time(), " ")[1]) - m.Cmdy("init", arg) + m.Cmdy(INIT, arg) return true } func (f *Frame) Close(m *Message, arg ...string) bool { @@ -60,68 +58,50 @@ func (f *Frame) Close(m *Message, arg ...string) bool { return true } -var Index = &Context{Name: "ice", Help: "冰山模块", - Caches: map[string]*Cache{ - CTX_FOLLOW: {Value: "ice"}, - CTX_STREAM: {Value: "shy"}, - CTX_STATUS: {Value: "begin"}, - }, - Configs: map[string]*Config{ - "help": {Value: map[string]interface{}{ - "index": []interface{}{ - "^_^ 欢迎使用冰山框架 ^_^", - "^_^ Welcome to Icebergs World ^_^", - "", - "report: shylinuxc@gmail.com", - "server: https://shylinux.com", - "source: https://shylinux.com/x/icebergs", - "", - }, - }}, - }, - Commands: map[string]*Command{ - CTX_INIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { - defer m.Cost("_init ice") - m.Travel(func(p *Context, c *Context) { - if cmd, ok := c.Commands[CTX_INIT]; ok && p != nil { - c.cmd(m.Spawn(c), cmd, CTX_INIT, arg...) - } - }) - }}, - "init": {Name: "init", Help: "启动", Hand: func(m *Message, c *Context, cmd string, arg ...string) { - if m.target != m.target.root { - return +var Index = &Context{Name: "ice", Help: "冰山模块", Caches: map[string]*Cache{ + CTX_FOLLOW: {Value: "ice"}, CTX_STREAM: {Value: "shy"}, CTX_STATUS: {Value: CTX_BEGIN}, +}, Configs: map[string]*Config{ + HELP: {Value: kit.Data("index", _help)}, +}, Commands: map[string]*Command{ + CTX_INIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { + defer m.Cost(CTX_INIT) + m.root.Travel(func(p *Context, c *Context) { + if cmd, ok := c.Commands[CTX_INIT]; ok && p != nil { + c.cmd(m.Spawn(c), cmd, CTX_INIT, arg...) } - m.root.Cmd(CTX_INIT) - m.target.root.wg = &sync.WaitGroup{} - for _, k := range kit.Split(kit.Select("gdb,log,ssh,mdb")) { - m.Start(k) + }) + + m.target.root.wg = &sync.WaitGroup{} + for _, k := range kit.Split(kit.Select("gdb,log,ssh,mdb")) { + m.Start(k) + } + }}, + INIT: {Name: "init", Help: "启动", Hand: func(m *Message, c *Context, cmd string, arg ...string) { + m.root.Cmd(CTX_INIT) + m.Cmd("ssh.source", ETC_INIT_SHY, "init.shy", "启动配置") + m.Cmdy(arg) + }}, + HELP: {Name: "help", Help: "帮助", Hand: func(m *Message, c *Context, cmd string, arg ...string) { + m.Echo(m.Config("index")) + }}, + EXIT: {Name: "exit", Help: "结束", Hand: func(m *Message, c *Context, cmd string, arg ...string) { + m.root.Option(EXIT, kit.Select("0", arg, 0)) + m.Cmd("ssh.source", ETC_EXIT_SHY, "exit.shy", "退出配置") + m.root.Cmd(CTX_EXIT) + }}, + CTX_EXIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { + defer m.Cost(CTX_EXIT) + m.root.Travel(func(p *Context, c *Context) { + if cmd, ok := c.Commands[CTX_EXIT]; ok && p != nil { + m.TryCatch(m.Spawn(c), true, func(msg *Message) { + c.cmd(msg, cmd, CTX_EXIT, arg...) + }) } - m.Cmd("ssh.source", ETC_INIT, "init.shy", "启动配置") - m.Cmdy(arg) - }}, - "help": {Name: "help", Help: "帮助", Hand: func(m *Message, c *Context, cmd string, arg ...string) { - m.Echo(strings.Join(kit.Simple(m.Confv("help", "index")), "\n")) - }}, - "exit": {Name: "exit restart:button", Help: "结束", Hand: func(m *Message, c *Context, cmd string, arg ...string) { - m.root.target.server.(*Frame).code = kit.Int(kit.Select("0", arg, 0)) - m.Cmd("ssh.source", ETC_EXIT, "exit.shy", "退出配置") - m.root.Cmd(CTX_EXIT) - }}, - CTX_EXIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { - defer m.Cost(CTX_EXIT) - m.root.Travel(func(p *Context, c *Context) { - if cmd, ok := c.Commands[CTX_EXIT]; ok && p != nil { - m.TryCatch(m.Spawn(c), true, func(msg *Message) { - c.cmd(msg, cmd, CTX_EXIT, arg...) - }) - } - }) - f := c.server.(*Frame) - f.wait <- true - }}, - }, -} + }) + + c.server.(*Frame).wait <- kit.Int(m.root.Option(EXIT)) + }}, +}} var Pulse = &Message{ time: time.Now(), code: 0, meta: map[string][]string{}, @@ -129,87 +109,30 @@ var Pulse = &Message{ source: Index, target: Index, Hand: true, } -var Info = struct { - HostName string - PathName string - UserName string - PassWord string - NodeType string - NodeName string - CtxShare string - CtxRiver string - - Make struct { - Time string - Hash string - Remote string - Branch string - Version string - HostName string - UserName string - } - - BinPack map[string][]byte - names map[string]interface{} -}{ - BinPack: map[string][]byte{}, - names: map[string]interface{}{}, -} - -func Dump(w io.Writer, name string, cb func(string)) bool { - for _, key := range []string{name, strings.TrimPrefix(name, USR_VOLCANOS)} { - if b, ok := Info.BinPack[key]; ok { - if cb != nil { - cb(name) - } - w.Write(b) - return true - } - } - return false -} -func Name(name string, value interface{}) string { - if s, ok := Info.names[name]; ok { - last := "" - switch s := s.(type) { - case *Context: - last = s.Name - } - panic(kit.Format("%s %s %v", ErrExists, name, last)) - } - - Info.names[name] = value - return name -} func Run(arg ...string) string { if len(arg) == 0 { arg = os.Args[1:] } if len(arg) == 0 { - arg = append(arg, "help") + arg = append(arg, HELP) } - frame := &Frame{wait: make(chan bool, 1)} - Index.root = Index - Index.server = frame + frame := &Frame{wait: make(chan int, 1)} Index.Merge(Index) - + Index.server = frame + Index.root = Index Pulse.root = Pulse - Pulse.Option("name", "") - Pulse.Option("cache.limit", "30") - Pulse.Option("begin_time", Pulse.Time()) + switch kit.Select("", arg, 0) { case "space", "serve": if _log_disable = false; frame.Begin(Pulse.Spawn(), arg...).Start(Pulse, arg...) { frame.Close(Pulse.Spawn(), arg...) } - <-frame.wait - os.Exit(frame.code) + os.Exit(<-frame.wait) default: - _log_disable = os.Getenv(CTX_DEBUG) != TRUE if Pulse.Cmdy(arg); Pulse.Result() == "" { Pulse.Table() } @@ -221,3 +144,12 @@ func Run(arg ...string) string { return Pulse.Result() } + +var _help = ` +^_^ 欢迎使用冰山框架 ^_^ +^_^ Welcome to Icebergs World ^_^ + +report: shylinuxc@gmail.com +server: https://shylinux.com +source: https://shylinux.com/x/icebergs +` diff --git a/logs.go b/logs.go index 10b336b0..d1c3bc09 100644 --- a/logs.go +++ b/logs.go @@ -1,22 +1,16 @@ package ice import ( + "encoding/json" "fmt" + "runtime" "strings" + "time" kit "shylinux.com/x/toolkits" log "shylinux.com/x/toolkits/logs" ) -const ( - ErrWarn = "warn: " - ErrExists = "exists: " - ErrExpire = "expire: " - ErrNotLogin = "not login: " - ErrNotFound = "not found: " - ErrNotRight = "not right: " -) - var _log_disable = true var Log func(m *Message, p, l, s string) @@ -27,16 +21,12 @@ func (m *Message) log(level string, str string, arg ...interface{}) *Message { if str = strings.TrimSpace(kit.Format(str, arg...)); Log != nil { Log(m, m.Format(kit.MDB_PREFIX), level, str) // 日志分流 } - if m.Option("_disable_log") == TRUE { - return m // 屏蔽日志 - } // 日志颜色 prefix, suffix := "", "" switch level { case LOG_IMPORT, LOG_CREATE, LOG_INSERT, LOG_MODIFY, LOG_EXPORT: prefix, suffix = "\033[36;44m", "\033[0m" - case LOG_CMDS, LOG_START, LOG_SERVE: prefix, suffix = "\033[32m", "\033[0m" case LOG_WARN, LOG_CLOSE, LOG_ERROR: @@ -48,7 +38,7 @@ func (m *Message) log(level string, str string, arg ...interface{}) *Message { // 文件行号 switch level { case LOG_CMDS, LOG_INFO, "refer", "form": - case "begin": + case LOG_BEGIN: default: suffix += " " + kit.FileLine(3, 3) } @@ -66,19 +56,6 @@ func (m *Message) log(level string, str string, arg ...interface{}) *Message { fmt.Sprintf("%4s->%-4s", m.source.Name, m.target.Name), prefix, level, str, suffix)) return m } -func (m *Message) Log(level string, str string, arg ...interface{}) *Message { - return m.log(level, str, arg...) -} -func (m *Message) Info(str string, arg ...interface{}) *Message { - if m == nil { - return m - } - return m.log(LOG_INFO, str, arg...) -} -func (m *Message) Cost(arg ...interface{}) *Message { - list := []string{m.Format("cost"), m.join(arg...)} - return m.log(LOG_COST, strings.Join(list, " ")) -} func (m *Message) join(arg ...interface{}) string { list := []string{} for i := 0; i < len(arg); i += 2 { @@ -90,6 +67,17 @@ func (m *Message) join(arg ...interface{}) string { } return strings.Join(list, " ") } + +func (m *Message) Log(level string, str string, arg ...interface{}) *Message { + return m.log(level, str, arg...) +} +func (m *Message) Info(str string, arg ...interface{}) *Message { + return m.log(LOG_INFO, str, arg...) +} +func (m *Message) Cost(arg ...interface{}) *Message { + list := []string{m.FormatCost(), m.join(arg...)} + return m.log(LOG_COST, strings.Join(list, " ")) +} func (m *Message) Warn(err bool, arg ...interface{}) bool { if !err || len(m.meta[MSG_RESULT]) > 0 && m.meta[MSG_RESULT][0] == ErrWarn { return err @@ -113,43 +101,152 @@ func (m *Message) Debug(str string, arg ...interface{}) { m.log(LOG_DEBUG, str, arg...) } -func log_fields(arg ...interface{}) string { - list := []string{} - for i := 0; i < len(arg)-1; i += 2 { - list = append(list, fmt.Sprintf("%v: %v", arg[i], arg[i+1])) - } - return strings.Join(list, " ") -} func (m *Message) Logs(level string, arg ...interface{}) *Message { - return m.log(level, log_fields(arg...)) + return m.log(level, m.join(arg...)) } func (m *Message) Log_AUTH(arg ...interface{}) *Message { - return m.log(LOG_AUTH, log_fields(arg...)) + return m.log(LOG_AUTH, m.join(arg...)) } func (m *Message) Log_SEND(arg ...interface{}) *Message { - return m.log(LOG_AUTH, log_fields(arg...)) + return m.log(LOG_AUTH, m.join(arg...)) } func (m *Message) Log_CREATE(arg ...interface{}) *Message { - return m.log(LOG_CREATE, log_fields(arg...)) + return m.log(LOG_CREATE, m.join(arg...)) } func (m *Message) Log_REMOVE(arg ...interface{}) *Message { - return m.log(LOG_REMOVE, log_fields(arg...)) + return m.log(LOG_REMOVE, m.join(arg...)) } func (m *Message) Log_INSERT(arg ...interface{}) *Message { - return m.log(LOG_INSERT, log_fields(arg...)) + return m.log(LOG_INSERT, m.join(arg...)) } func (m *Message) Log_DELETE(arg ...interface{}) *Message { - return m.log(LOG_DELETE, log_fields(arg...)) -} -func (m *Message) Log_SELECT(arg ...interface{}) *Message { - return m.log(LOG_SELECT, log_fields(arg...)) + return m.log(LOG_DELETE, m.join(arg...)) } func (m *Message) Log_MODIFY(arg ...interface{}) *Message { - return m.log(LOG_MODIFY, log_fields(arg...)) + return m.log(LOG_MODIFY, m.join(arg...)) } -func (m *Message) Log_IMPORT(arg ...interface{}) *Message { - return m.log(LOG_IMPORT, log_fields(arg...)) +func (m *Message) Log_SELECT(arg ...interface{}) *Message { + return m.log(LOG_SELECT, m.join(arg...)) } func (m *Message) Log_EXPORT(arg ...interface{}) *Message { - return m.log(LOG_EXPORT, log_fields(arg...)) + return m.log(LOG_EXPORT, m.join(arg...)) +} +func (m *Message) Log_IMPORT(arg ...interface{}) *Message { + return m.log(LOG_IMPORT, m.join(arg...)) +} + +func (m *Message) FormatStack() string { + // 调用栈 + pc := make([]uintptr, 100) + pc = pc[:runtime.Callers(5, pc)] + frames := runtime.CallersFrames(pc) + + meta := []string{} + for { + frame, more := frames.Next() + file := strings.Split(frame.File, "/") + name := strings.Split(frame.Function, "/") + meta = append(meta, fmt.Sprintf("\n%s:%d\t%s", file[len(file)-1], frame.Line, name[len(name)-1])) + if !more { + break + } + } + return strings.Join(meta, "") +} +func (m *Message) FormatChain() string { + ms := []*Message{} + for msg := m; msg != nil; msg = msg.message { + ms = append(ms, msg) + } + + meta := append([]string{}, "\n\n") + for i := len(ms) - 1; i >= 0; i-- { + msg := ms[i] + + meta = append(meta, fmt.Sprintf("%s ", msg.Format("prefix"))) + if len(msg.meta[MSG_DETAIL]) > 0 { + meta = append(meta, fmt.Sprintf("detail:%d %v", len(msg.meta[MSG_DETAIL]), msg.meta[MSG_DETAIL])) + } + + if len(msg.meta[MSG_OPTION]) > 0 { + meta = append(meta, fmt.Sprintf("option:%d %v\n", len(msg.meta[MSG_OPTION]), msg.meta[MSG_OPTION])) + for _, k := range msg.meta[MSG_OPTION] { + if v, ok := msg.meta[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) + } + } + } else { + meta = append(meta, "\n") + } + + if len(msg.meta[MSG_APPEND]) > 0 { + meta = append(meta, fmt.Sprintf(" append:%d %v\n", len(msg.meta[MSG_APPEND]), msg.meta[MSG_APPEND])) + for _, k := range msg.meta[MSG_APPEND] { + if v, ok := msg.meta[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) + } + } + } + if len(msg.meta[MSG_RESULT]) > 0 { + meta = append(meta, fmt.Sprintf(" result:%d %v\n", len(msg.meta[MSG_RESULT]), msg.meta[MSG_RESULT])) + } + } + return strings.Join(meta, "") +} +func (m *Message) FormatTime() string { + return m.Format("time") +} +func (m *Message) FormatMeta() string { + return m.Format("meta") +} +func (m *Message) FormatSize() string { + return m.Format("size") +} +func (m *Message) FormatCost() string { + return m.Format("cost") +} +func (m *Message) Format(key interface{}) string { + switch key := key.(type) { + case []byte: + json.Unmarshal(key, &m.meta) + case string: + switch key { + case "cost": + return kit.FmtTime(kit.Int64(time.Since(m.time))) + case "meta": + return kit.Format(m.meta) + case "size": + if len(m.meta["append"]) == 0 { + return fmt.Sprintf("%dx%d", 0, 0) + } else { + return fmt.Sprintf("%dx%d", len(m.meta[m.meta["append"][0]]), len(m.meta["append"])) + } + case "append": + if len(m.meta["append"]) == 0 { + return fmt.Sprintf("%dx%d %s", 0, 0, "[]") + } else { + return fmt.Sprintf("%dx%d %s", len(m.meta[m.meta["append"][0]]), len(m.meta["append"]), kit.Format(m.meta["append"])) + } + + case "time": + return m.Time() + case "ship": + return fmt.Sprintf("%s->%s", m.source.Name, m.target.Name) + case "prefix": + return fmt.Sprintf("%s %d %s->%s", m.Time(), m.code, m.source.Name, m.target.Name) + + case "chain": + return m.FormatChain() + case "stack": + return m.FormatStack() + } + } + return m.time.Format(MOD_TIME) +} +func (m *Message) Formats(key string) string { + switch key { + case "meta": + return kit.Formats(m.meta) + } + return m.Format(key) } diff --git a/meta.go b/meta.go index 11d542d4..0bfd658f 100644 --- a/meta.go +++ b/meta.go @@ -9,21 +9,6 @@ import ( kit "shylinux.com/x/toolkits" ) -func (m *Message) Add(key string, arg ...string) *Message { - switch key { - case MSG_DETAIL, MSG_RESULT: - m.meta[key] = append(m.meta[key], arg...) - - case MSG_OPTION, MSG_APPEND: - if len(arg) > 0 { - if kit.IndexOf(m.meta[key], arg[0]) == -1 { - m.meta[key] = append(m.meta[key], arg[0]) - } - m.meta[arg[0]] = append(m.meta[arg[0]], arg[1:]...) - } - } - return m -} func (m *Message) SetResult(arg ...interface{}) *Message { m.Set(MSG_RESULT) if len(arg) > 0 { @@ -69,6 +54,25 @@ func (m *Message) Set(key string, arg ...string) *Message { } return m.Add(key, arg...) } +func (m *Message) Add(key string, arg ...string) *Message { + switch key { + case MSG_DETAIL, MSG_RESULT: + m.meta[key] = append(m.meta[key], arg...) + + case MSG_OPTION, MSG_APPEND: + if len(arg) > 0 { + if kit.IndexOf(m.meta[key], arg[0]) == -1 { + m.meta[key] = append(m.meta[key], arg[0]) + } + m.meta[arg[0]] = append(m.meta[arg[0]], arg[1:]...) + } + } + return m +} +func (m *Message) Cut(fields ...string) *Message { + m.meta[MSG_APPEND] = kit.Split(kit.Join(fields)) + return m +} func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Message { switch value := value.(type) { case map[string]string: @@ -87,14 +91,14 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa case map[string]interface{}: // 键值排序 - list := []string{} + head := kit.Simple() if len(arg) > 0 { - list = kit.Simple(arg[0]) + head = kit.Simple(arg[0]) } else { for k := range kit.KeyValue(map[string]interface{}{}, "", value) { - list = append(list, k) + head = append(head, k) } - sort.Strings(list) + sort.Strings(head) } var val map[string]interface{} @@ -102,7 +106,7 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa val, _ = arg[1].(map[string]interface{}) } - for _, k := range list { + for _, k := range head { // 查找数据 var v interface{} switch k { @@ -472,7 +476,3 @@ func (m *Message) SortStr(key string) { m.Sort(key, "str") } func (m *Message) SortStrR(key string) { m.Sort(key, "str_r") } func (m *Message) SortTime(key string) { m.Sort(key, "time") } func (m *Message) SortTimeR(key string) { m.Sort(key, "time_r") } - -func (m *Message) FormatMeta() string { return m.Format("meta") } -func (m *Message) FormatSize() string { return m.Format("size") } -func (m *Message) FormatCost() string { return m.Format("cost") } diff --git a/misc.go b/misc.go index d8f66ee1..5f867965 100644 --- a/misc.go +++ b/misc.go @@ -3,22 +3,14 @@ package ice import ( "bytes" "encoding/csv" - "encoding/json" - "fmt" "net/url" "path" "reflect" - "runtime" "strings" - "time" kit "shylinux.com/x/toolkits" ) -func (m *Message) Cut(fields ...string) *Message { - m.meta[MSG_APPEND] = strings.Split(strings.Join(fields, ","), ",") - return m -} func (m *Message) CSV(text string, head ...string) *Message { bio := bytes.NewBufferString(text) r := csv.NewReader(bio) @@ -102,111 +94,17 @@ func (m *Message) Split(str string, field string, space string, enter string) *M } return m } -func (m *Message) FormatStack() string { - // 调用栈 - pc := make([]uintptr, 100) - pc = pc[:runtime.Callers(5, pc)] - frames := runtime.CallersFrames(pc) - meta := []string{} - for { - frame, more := frames.Next() - file := strings.Split(frame.File, "/") - name := strings.Split(frame.Function, "/") - meta = append(meta, fmt.Sprintf("\n%s:%d\t%s", file[len(file)-1], frame.Line, name[len(name)-1])) - if !more { - break - } - } - return strings.Join(meta, "") +func (m *Message) ShowPlugin(pod, ctx, cmd string, arg ...string) { + m.Cmdy("web.space", pod, "context", ctx, "command", cmd) + m.Option(MSG_PROCESS, PROCESS_FIELD) + m.Option(FIELD_PREFIX, arg) } -func (m *Message) FormatChain() string { - ms := []*Message{} - for msg := m; msg != nil; msg = msg.message { - ms = append(ms, msg) - } - - meta := append([]string{}, "\n\n") - for i := len(ms) - 1; i >= 0; i-- { - msg := ms[i] - - meta = append(meta, fmt.Sprintf("%s ", msg.Format("prefix"))) - if len(msg.meta[MSG_DETAIL]) > 0 { - meta = append(meta, fmt.Sprintf("detail:%d %v", len(msg.meta[MSG_DETAIL]), msg.meta[MSG_DETAIL])) - } - - if len(msg.meta[MSG_OPTION]) > 0 { - meta = append(meta, fmt.Sprintf("option:%d %v\n", len(msg.meta[MSG_OPTION]), msg.meta[MSG_OPTION])) - for _, k := range msg.meta[MSG_OPTION] { - if v, ok := msg.meta[k]; ok { - meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) - } - } - } else { - meta = append(meta, "\n") - } - - if len(msg.meta[MSG_APPEND]) > 0 { - meta = append(meta, fmt.Sprintf(" append:%d %v\n", len(msg.meta[MSG_APPEND]), msg.meta[MSG_APPEND])) - for _, k := range msg.meta[MSG_APPEND] { - if v, ok := msg.meta[k]; ok { - meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) - } - } - } - if len(msg.meta[MSG_RESULT]) > 0 { - meta = append(meta, fmt.Sprintf(" result:%d %v\n", len(msg.meta[MSG_RESULT]), msg.meta[MSG_RESULT])) - } - } - return strings.Join(meta, "") +func (m *Message) OptionUserWeb() *url.URL { + return kit.ParseURL(m.Option(MSG_USERWEB)) } -func (m *Message) FormatTime() string { - return m.Format("time") -} -func (m *Message) Format(key interface{}) string { - switch key := key.(type) { - case []byte: - json.Unmarshal(key, &m.meta) - case string: - switch key { - case "cost": - return kit.FmtTime(kit.Int64(time.Since(m.time))) - case "meta": - return kit.Format(m.meta) - case "size": - if len(m.meta["append"]) == 0 { - return fmt.Sprintf("%dx%d", 0, 0) - } else { - return fmt.Sprintf("%dx%d", len(m.meta[m.meta["append"][0]]), len(m.meta["append"])) - } - case "append": - if len(m.meta["append"]) == 0 { - return fmt.Sprintf("%dx%d %s", 0, 0, "[]") - } else { - return fmt.Sprintf("%dx%d %s", len(m.meta[m.meta["append"][0]]), len(m.meta["append"]), kit.Format(m.meta["append"])) - } - - case "time": - return m.Time() - case "ship": - return fmt.Sprintf("%s->%s", m.source.Name, m.target.Name) - case "prefix": - return fmt.Sprintf("%s %d %s->%s", m.Time(), m.code, m.source.Name, m.target.Name) - - case "chain": - return m.FormatChain() - case "stack": - return m.FormatStack() - } - } - return m.time.Format(MOD_TIME) -} -func (m *Message) Formats(key string) string { - switch key { - case "meta": - return kit.Formats(m.meta) - } - return m.Format(key) +func (m *Message) SetAppend(key ...string) { + m.Set(MSG_APPEND, key...) } func (m *Message) RenameAppend(from, to string) { for i, v := range m.meta[MSG_APPEND] { @@ -217,6 +115,22 @@ func (m *Message) RenameAppend(from, to string) { } } } +func (m *Message) AppendSimple(key ...string) (res []string) { + if len(key) == 0 { + key = append(key, m.Appendv(MSG_APPEND)...) + } + for _, k := range key { + res = append(res, k, m.Append(k)) + } + return +} +func (m *Message) AppendTrans(cb func(value string, key string, index int) string) { + for _, k := range m.meta[MSG_APPEND] { + for i, v := range m.meta[k] { + m.meta[k][i] = cb(v, k, i) + } + } +} func (m *Message) cmd(arg ...interface{}) *Message { opts := map[string]interface{}{} @@ -362,73 +276,57 @@ func (c *Context) _cmd(m *Message, cmd *Command, key string, k string, h *Action } return m } -func (c *Context) split(key string, cmd *Command, name string) []interface{} { +func (c *Context) split(name string) (list []interface{}) { const ( - BUTTON = "button" - SELECT = "select" TEXT = "text" TEXTAREA = "textarea" + SELECT = "select" + BUTTON = "button" ) - button, list := false, []interface{}{} - for _, v := range kit.Split(kit.Select("key", name), " ", " ")[1:] { - switch v { + item, button := kit.Dict(), false + ls := kit.Split(name, " ", ":=@") + for i := 1; i < len(ls); i++ { + switch ls[i] { case "text": - list = append(list, kit.List(kit.MDB_INPUT, TEXTAREA, kit.MDB_NAME, "text", kit.MDB_VALUE, "@key")...) - continue - case "page": - list = append(list, kit.List(kit.MDB_INPUT, TEXT, kit.MDB_NAME, "limit")...) - list = append(list, kit.List(kit.MDB_INPUT, TEXT, kit.MDB_NAME, "offend")...) - list = append(list, kit.List(kit.MDB_INPUT, BUTTON, kit.MDB_NAME, "prev")...) - list = append(list, kit.List(kit.MDB_INPUT, BUTTON, kit.MDB_NAME, "next")...) - continue + list = append(list, kit.List(kit.MDB_TYPE, TEXTAREA, kit.MDB_NAME, "text")...) case "auto": - list = append(list, kit.List(kit.MDB_INPUT, BUTTON, kit.MDB_NAME, "list", kit.MDB_VALUE, "auto")...) - list = append(list, kit.List(kit.MDB_INPUT, BUTTON, kit.MDB_NAME, "back")...) + list = append(list, kit.List(kit.MDB_TYPE, BUTTON, kit.MDB_NAME, "list", kit.MDB_VALUE, "auto")...) + list = append(list, kit.List(kit.MDB_TYPE, BUTTON, kit.MDB_NAME, "back")...) button = true - continue - } + case "page": + list = append(list, kit.List(kit.MDB_TYPE, TEXT, kit.MDB_NAME, "limit")...) + list = append(list, kit.List(kit.MDB_TYPE, TEXT, kit.MDB_NAME, "offend")...) + list = append(list, kit.List(kit.MDB_TYPE, BUTTON, kit.MDB_NAME, "prev")...) + list = append(list, kit.List(kit.MDB_TYPE, BUTTON, kit.MDB_NAME, "next")...) - ls, value := kit.Split(v, " ", ":=@"), "" - item := kit.Dict(kit.MDB_INPUT, kit.Select(TEXT, BUTTON, button)) - if kit.Value(item, kit.MDB_NAME, ls[0]); item[kit.MDB_INPUT] == TEXT { - kit.Value(item, kit.MDB_VALUE, kit.Select("@key", "auto", strings.Contains(name, "auto"))) - } - - for i := 1; i < len(ls); i += 2 { - switch ls[i] { - case ":": - switch kit.Value(item, kit.MDB_INPUT, ls[i+1]); ls[i+1] { - case TEXTAREA: - kit.Value(item, "style.width", "360") - kit.Value(item, "style.height", "60") - case BUTTON: - kit.Value(item, kit.MDB_VALUE, "") - button = true - } - case "=": - if value = kit.Select("", ls, i+1); len(ls) > i+1 && strings.Contains(ls[i+1], ",") { - vs := strings.Split(ls[i+1], ",") - kit.Value(item, "values", vs) - kit.Value(item, kit.MDB_VALUE, vs[0]) - kit.Value(item, kit.MDB_INPUT, SELECT) - if kit.Value(item, kit.MDB_NAME) == "scale" { - kit.Value(item, kit.MDB_VALUE, "week") - } - } else { - kit.Value(item, kit.MDB_VALUE, value) - } - case "@": - if len(ls) > i+1 { - if kit.Value(item, kit.MDB_INPUT) == BUTTON { - kit.Value(item, "action", ls[i+1]) - } else { - kit.Value(item, kit.MDB_VALUE, "@"+ls[i+1]+"="+value) - } - } + case ":": + if item[kit.MDB_TYPE] = kit.Select("", ls, i+1); item[kit.MDB_TYPE] == BUTTON { + button = true } + i++ + case "=": + if value := kit.Select("", ls, i+1); strings.Contains(value, ",") { + vs := strings.Split(value, ",") + if strings.Count(value, vs[0]) > 1 { + item["values"] = vs[1:] + } else { + item["values"] = vs + } + item[kit.MDB_VALUE] = vs[0] + item[kit.MDB_TYPE] = SELECT + } else { + item[kit.MDB_VALUE] = value + } + i++ + case "@": + item["action"] = kit.Select("", ls, i+1) + i++ + + default: + item = kit.Dict(kit.MDB_TYPE, kit.Select(TEXT, BUTTON, button), kit.MDB_NAME, ls[i]) + list = append(list, item) } - list = append(list, item) } return list } @@ -456,36 +354,6 @@ func MergeAction(list ...map[string]*Action) map[string]*Action { } return list[0] } - -func (m *Message) AppendSimple(key ...string) (res []string) { - if len(key) == 0 { - key = append(key, m.Appendv(MSG_APPEND)...) - } - for _, k := range key { - res = append(res, k, m.Append(k)) - } - return -} - -func (m *Message) AppendTrans(cb func(value string, key string, index int) string) { - for _, k := range m.meta[MSG_APPEND] { - for i, v := range m.meta[k] { - m.meta[k][i] = cb(v, k, i) - } - } -} - -func (m *Message) OptionUserWeb() *url.URL { - return kit.ParseURL(m.Option(MSG_USERWEB)) -} - -func (m *Message) Config(key string) string { - return m.Conf(m.PrefixKey(), kit.Keym(key)) -} -func (m *Message) ConfigSimple(key string) []string { - return []string{key, m.Conf(m.PrefixKey(), kit.Keym(key))} -} - func SelectAction(list map[string]*Action, fields ...string) map[string]*Action { if len(fields) == 0 { return list @@ -497,7 +365,3 @@ func SelectAction(list map[string]*Action, fields ...string) map[string]*Action } return res } - -func (m *Message) SetAppend(key ...string) { - m.Set(MSG_APPEND, key...) -} diff --git a/misc/bash/trash.go b/misc/bash/trash.go index 411c3e9e..a986b19c 100644 --- a/misc/bash/trash.go +++ b/misc/bash/trash.go @@ -30,7 +30,7 @@ func init() { }}, }}, TRASH: {Name: "TRASH hash path auto prunes", Help: "回收站", Action: map[string]*ice.Action{ - mdb.INSERT: {Name: "insert from= to=", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + mdb.INSERT: {Name: "insert from to", Help: "添加", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.INSERT, m.Prefix(TRASH), "", mdb.HASH, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME, kit.MDB_SIZE, FROM, TO)) }}, mdb.REVERT: {Name: "revert", Help: "恢复", Hand: func(m *ice.Message, arg ...string) { diff --git a/misc/chrome/favor.go b/misc/chrome/favor.go index e7c58b46..829d5bfd 100644 --- a/misc/chrome/favor.go +++ b/misc/chrome/favor.go @@ -21,7 +21,7 @@ func init() { mdb.CREATE: {Name: "create zone", Help: "创建", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.INSERT, m.Prefix(FAVOR), "", mdb.HASH, arg) }}, - mdb.INSERT: {Name: "insert zone=数据结构 type= name=hi text=hello", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + mdb.INSERT: {Name: "insert zone=数据结构 type name=hi text=hello", Help: "添加", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.INSERT, m.Prefix(FAVOR), "", mdb.HASH, m.OptionSimple(kit.MDB_ZONE)) m.Cmdy(mdb.INSERT, m.Prefix(FAVOR), kit.KeyHash(m.Option(kit.MDB_ZONE)), mdb.LIST, arg) }}, diff --git a/misc/input/input.go b/misc/input/input.go index 792dad78..6ffdd110 100644 --- a/misc/input/input.go +++ b/misc/input/input.go @@ -170,7 +170,7 @@ var Index = &ice.Context{Name: INPUT, Help: "输入法", mdb.EXPORT: {Name: "export file=usr/wubi-dict/person zone=person", Help: "导出", Hand: func(m *ice.Message, arg ...string) { // _input_save(m, kit.Select("usr/wubi-dict/person", m.Option("file")), m.Option("zone")) }}, - mdb.IMPORT: {Name: "import file=usr/wubi-dict/person zone=", Help: "导入", Hand: func(m *ice.Message, arg ...string) { + mdb.IMPORT: {Name: "import file=usr/wubi-dict/person zone", Help: "导入", Hand: func(m *ice.Message, arg ...string) { _input_load(m, kit.Select("usr/wubi-dict/person", m.Option(FILE)), m.Option(ZONE)) }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { diff --git a/misc/tmux/session.go b/misc/tmux/session.go index 49215c81..d1e50de8 100644 --- a/misc/tmux/session.go +++ b/misc/tmux/session.go @@ -61,7 +61,7 @@ func init() { m.Cmdy(cli.SYSTEM, TMUX, "split-window", "-t", kit.Keys(name, "2"), "-h") m.Cmd(cli.SYSTEM, TMUX, "send-keys", "-t", kit.Keys(name, "3"), "ish_miss_log", "Enter") - m.Cmd(cli.SYSTEM, TMUX, "send-keys", "-t", kit.Keys(name, "2"), "ish_miss_space dev self") + m.Cmd(cli.SYSTEM, TMUX, "send-keys", "-t", kit.Keys(name, "2"), "ish_miss_space dev web") m.Cmd(cli.SYSTEM, TMUX, "send-keys", "-t", kit.Keys(name, "1"), "vi etc/miss.sh", "Enter") m.Cmdy(cli.SYSTEM, TMUX, "link-window", "-s", name, "-t", "miss:") diff --git a/misc/wework/bot.go b/misc/wework/bot.go index cea56da2..52e9f8b3 100644 --- a/misc/wework/bot.go +++ b/misc/wework/bot.go @@ -1,6 +1,14 @@ package wework import ( + "crypto/aes" + "crypto/cipher" + "crypto/sha1" + "encoding/base64" + "encoding/hex" + "sort" + "strings" + ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/web" @@ -9,30 +17,44 @@ import ( const BOT = "bot" -type Bot struct { - short string `data:"name"` - field string `data:"time,name,token,ekey,hook"` +func init() { + Index.Merge(&ice.Context{Configs: map[string]*ice.Config{ + BOT: {Name: "bot", Help: "机器人", Value: kit.Data( + kit.MDB_SHORT, "name", kit.MDB_FIELD, "time,name,token,ekey,hook", + )}, + }, Commands: map[string]*ice.Command{ + ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Load() }}, + ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Save() }}, + web.WEB_LOGIN: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, + "/bot/": {Name: "/bot", Help: "机器人", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + msg := m.Cmd(BOT, arg[0]) + list := []string{msg.Append("token"), m.Option("nonce"), m.Option("timestamp"), m.Option("echostr")} + sort.Strings(list) + res := sha1.Sum([]byte(strings.Join(list, ""))) + m.Debug(hex.EncodeToString(res[:])) - create string `name:"list name token ekey hook" help:"创建"` - list string `name:"list name chat text:textarea auto create" help:"机器人"` -} + aeskey, err := base64.StdEncoding.DecodeString(msg.Append("ekey")) + m.Assert(err) + en_msg, err := base64.StdEncoding.DecodeString(m.Option("echostr")) + m.Assert(err) + block, err := aes.NewCipher(aeskey) + m.Assert(err) + mode := cipher.NewCBCDecrypter(block, aeskey[:aes.BlockSize]) + mode.CryptBlocks(en_msg, en_msg) -func (b Bot) Create(m *ice.Message, arg ...string) { - m.Cmdy(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, arg) + }}, + BOT: {Name: "bot name chat text:textarea auto create", Help: "机器人", Action: ice.MergeAction(map[string]*ice.Action{ + mdb.CREATE: {Name: "create name token ekey hook", Help: "创建"}, + }, mdb.HashAction()), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if mdb.HashSelect(m, arg...); len(arg) > 2 { + m.SetAppend() + m.Cmd(web.SPIDE, mdb.CREATE, arg[0], m.Append("hook")) + m.Cmdy(web.SPIDE, arg[0], "", kit.Format(kit.Dict( + "chatid", arg[1], "msgtype", "text", "text.content", arg[2], + ))) + } else { + m.PushAction(mdb.REMOVE) + } + }}, + }}) } -func (b Bot) List(m *ice.Message, arg ...string) { - m.Fields(len(arg), m.Config(kit.MDB_FIELD)) - m.Cmdy(mdb.SELECT, m.PrefixKey(), "", mdb.HASH, m.Config(kit.MDB_SHORT), arg) - if len(arg) > 2 { - m.Cmd(web.SPIDE, mdb.CREATE, arg[0], m.Append("hook")) - m.SetAppend() - m.Cmdy(web.SPIDE, arg[0], "", kit.Format(kit.Dict( - "chatid", arg[1], - "msgtype", "text", "text", kit.Dict( - "content", arg[2], - ), - ))) - } -} - -func init() { ice.Cmd("web.chat.wework.bot", Bot{}) } diff --git a/misc/wework/wework.go b/misc/wework/wework.go index 8cc73370..67a978a8 100644 --- a/misc/wework/wework.go +++ b/misc/wework/wework.go @@ -1 +1,11 @@ package wework + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/web" + "shylinux.com/x/icebergs/core/chat" +) + +var Index = &ice.Context{Name: "wework", Help: "企业微信"} + +func init() { chat.Index.Register(Index, &web.Frame{}) } diff --git a/option.go b/option.go index f936e907..1b80b879 100644 --- a/option.go +++ b/option.go @@ -2,7 +2,6 @@ package ice import ( "encoding/json" - "net/url" "os" "path" "strings" @@ -15,22 +14,24 @@ type Sort struct { Fields string Method string } + type Option struct { Name string Value interface{} } -func OptionHash(str string) Option { return Option{kit.MDB_HASH, str} } -func OptionFields(str ...string) Option { return Option{MSG_FIELDS, strings.Join(str, ",")} } -func (m *Message) OptionFields(str ...string) string { - if len(str) > 0 { - m.Option(MSG_FIELDS, strings.Join(str, ",")) +func OptionHash(arg string) Option { return Option{kit.MDB_HASH, arg} } +func OptionFields(arg ...string) Option { return Option{MSG_FIELDS, kit.Join(arg)} } + +func (m *Message) OptionFields(arg ...string) string { + if len(arg) > 0 { + m.Option(MSG_FIELDS, kit.Join(arg)) } return m.Option(MSG_FIELDS) } func (m *Message) OptionPage(arg ...string) { - m.Option("cache.offend", kit.Select("0", arg, 1)) - m.Option("cache.limit", kit.Select("10", arg, 0)) + m.Option(CACHE_LIMIT, kit.Select("10", arg, 0)) + m.Option(CACHE_OFFEND, kit.Select("0", arg, 1)) } func (m *Message) OptionLoad(file string) *Message { if f, e := os.Open(file); e == nil { @@ -43,14 +44,14 @@ func (m *Message) OptionLoad(file string) *Message { } return m } -func (m *Message) OptionSplit(fields ...string) (res []string) { - for _, k := range strings.Split(strings.Join(fields, ","), ",") { +func (m *Message) OptionSplit(key ...string) (res []string) { + for _, k := range kit.Split(kit.Join(key)) { res = append(res, m.Option(k)) } return res } func (m *Message) OptionSimple(key ...string) (res []string) { - for _, k := range strings.Split(strings.Join(key, ","), ",") { + for _, k := range kit.Split(kit.Join(key)) { if k == "" || m.Option(k) == "" { continue } @@ -96,26 +97,24 @@ func (m *Message) Action(arg ...string) { m.Option(MSG_ACTION, kit.Format(arg)) } func (m *Message) Status(arg ...interface{}) { + list := kit.List() args := kit.Simple(arg) - list := []map[string]interface{}{} for i := 0; i < len(args)-1; i += 2 { - list = append(list, map[string]interface{}{ - kit.MDB_NAME: args[i], kit.MDB_VALUE: args[i+1], - }) + list = append(list, kit.Dict(kit.MDB_NAME, args[i], kit.MDB_VALUE, args[i+1])) } m.Option(MSG_STATUS, kit.Format(list)) } func (m *Message) StatusTime(arg ...interface{}) { - m.Status(kit.MDB_TIME, m.Time(), arg, "cost", m.FormatCost()) + m.Status(kit.MDB_TIME, m.Time(), arg, kit.MDB_COST, m.FormatCost()) } func (m *Message) StatusTimeCount(arg ...interface{}) { - m.Status(kit.MDB_TIME, m.Time(), kit.MDB_COUNT, m.FormatSize(), arg, "cost", m.FormatCost()) + m.Status(kit.MDB_TIME, m.Time(), kit.MDB_COUNT, m.FormatSize(), arg, kit.MDB_COST, m.FormatCost()) } func (m *Message) StatusTimeCountTotal(arg ...interface{}) { - m.Status(kit.MDB_TIME, m.Time(), kit.MDB_COUNT, m.FormatSize(), "total", arg, "cost", m.FormatCost()) + m.Status(kit.MDB_TIME, m.Time(), kit.MDB_COUNT, m.FormatSize(), kit.MDB_TOTAL, arg, kit.MDB_COST, m.FormatCost()) } -func (m *Message) Toast(content string, arg ...interface{}) { +func (m *Message) Toast(text string, arg ...interface{}) { // [title [duration]] if len(arg) > 1 { switch val := arg[1].(type) { case string: @@ -126,9 +125,9 @@ func (m *Message) Toast(content string, arg ...interface{}) { } if m.Option(MSG_USERPOD) == "" { - m.Cmd("web.space", m.Option(MSG_DAEMON), "toast", "", content, arg) + m.Cmd("web.space", m.Option(MSG_DAEMON), "toast", "", text, arg) } else { - m.Option(MSG_TOAST, kit.Simple(content, arg)) + m.Option(MSG_TOAST, kit.Simple(text, arg)) } } func (m *Message) GoToast(title string, cb func(toast func(string, int, int))) { @@ -163,6 +162,11 @@ func (m *Message) ProcessRefresh(delay string) { func (m *Message) ProcessRefresh30ms() { m.ProcessRefresh("30ms") } func (m *Message) ProcessRefresh300ms() { m.ProcessRefresh("300ms") } func (m *Message) ProcessRefresh3s() { m.ProcessRefresh("3s") } +func (m *Message) ProcessDisplay(arg ...interface{}) { + m.Process(PROCESS_DISPLAY) + m.Option("_display", arg...) +} + func (m *Message) ProcessCommand(cmd string, val []string, arg ...string) { if len(arg) > 0 && arg[0] == "run" { m.Cmdy(cmd, arg[1:]) @@ -180,64 +184,8 @@ func (m *Message) ProcessField(arg ...interface{}) { m.Process(PROCESS_FIELD) m.Option("_prefix", arg...) } -func (m *Message) ProcessDisplay(arg ...interface{}) { - m.Process(PROCESS_DISPLAY) - m.Option("_display", arg...) -} func (m *Message) ProcessInner() { m.Process(PROCESS_INNER) } func (m *Message) ProcessAgain() { m.Process(PROCESS_AGAIN) } +func (m *Message) ProcessOpen(url string) { m.Process(PROCESS_OPEN, url) } func (m *Message) ProcessHold() { m.Process(PROCESS_HOLD) } func (m *Message) ProcessBack() { m.Process(PROCESS_BACK) } -func (m *Message) ProcessOpen(url string) { m.Process(PROCESS_OPEN, url) } - -func (m *Message) ShowPlugin(pod, ctx, cmd string, arg ...string) { - m.Cmdy("web.space", pod, "context", ctx, "command", cmd) - m.Option(MSG_PROCESS, PROCESS_FIELD) - m.Option(FIELD_PREFIX, arg) -} -func (m *Message) PushPodCmd(cmd string, arg ...string) { - m.Table(func(index int, value map[string]string, head []string) { - m.Push("pod", m.Option(MSG_USERPOD)) - }) - - m.Cmd("web.space").Table(func(index int, value map[string]string, head []string) { - switch value[kit.MDB_TYPE] { - case "worker", "server": - if value[kit.MDB_NAME] == Info.HostName { - break - } - m.Cmd("web.space", value[kit.MDB_NAME], m.Prefix(cmd), arg).Table(func(index int, val map[string]string, head []string) { - val["pod"] = kit.Keys(value[kit.MDB_NAME], val["pod"]) - m.Push("", val, head) - }) - } - }) -} -func (m *Message) PushSearch(args ...interface{}) { - data := kit.Dict(args...) - for _, k := range kit.Split(m.Option(MSG_FIELDS)) { - switch k { - case "pod": - // m.Push(k, kit.Select(m.Option(MSG_USERPOD), data[kit.SSH_POD])) - case "ctx": - m.Push(k, m.Prefix()) - case "cmd": - m.Push(k, kit.Format(data["cmd"])) - case kit.MDB_TIME: - m.Push(k, kit.Select(m.Time(), data[k])) - default: - m.Push(k, kit.Format(kit.Select("", data[k]))) - } - } -} -func (m *Message) PushSearchWeb(cmd string, name string) { - msg := m.Spawn() - msg.Option(MSG_FIELDS, "type,name,text") - msg.Cmd("mdb.select", m.Prefix(cmd), "", kit.MDB_HASH).Table(func(index int, value map[string]string, head []string) { - text := kit.MergeURL(value[kit.MDB_TEXT], value[kit.MDB_NAME], name) - if value[kit.MDB_NAME] == "" { - text = kit.MergeURL(value[kit.MDB_TEXT] + url.QueryEscape(name)) - } - m.PushSearch("cmd", cmd, kit.MDB_TYPE, kit.Select("", value[kit.MDB_TYPE]), kit.MDB_NAME, name, kit.MDB_TEXT, text) - }) -} diff --git a/render.go b/render.go index 7bc2c9b2..b70746b7 100644 --- a/render.go +++ b/render.go @@ -1,8 +1,8 @@ package ice import ( + "net/url" "path" - "reflect" "strings" kit "shylinux.com/x/toolkits" @@ -28,9 +28,9 @@ func Render(m *Message, cmd string, args ...interface{}) string { break } list := []string{} - for _, k := range kit.Split(kit.Join(arg)) { + for _, k := range kit.Split(strings.ToLower(kit.Join(arg))) { list = append(list, kit.Format(``, - k, kit.Select(k, kit.Value(m._cmd.Meta, kit.Keys("_trans", k)), m.Option("language") != "en"))) + k, kit.Select(k, kit.Value(m._cmd.Meta, kit.Keys("_trans", k)), m.Option(MSG_LANGUAGE) != "en"))) } return kit.Join(list, " ") @@ -45,8 +45,12 @@ func Render(m *Message, cmd string, args ...interface{}) string { } return "" } -func (m *Message) PushRender(key, view, name string, arg ...string) *Message { - return m.Push(key, Render(m, view, name, arg)) + +func (m *Message) IsCliUA() bool { + if m.Option(MSG_USERUA) == "" || !strings.HasPrefix(m.Option(MSG_USERUA), "Mozilla/5.0") { + return true + } + return false } func (m *Message) PushDownload(key string, arg ...interface{}) { // [name] file if !m.IsCliUA() { @@ -58,59 +62,107 @@ func (m *Message) PushAnchor(arg ...interface{}) { // [name] link m.Push(kit.MDB_LINK, Render(m, RENDER_ANCHOR, arg...)) } } -func (m *Message) PushButton(list ...interface{}) { - if m.IsCliUA() { - return +func (m *Message) PushButton(arg ...interface{}) { // name... + if !m.IsCliUA() { + m.Push(kit.MDB_ACTION, Render(m, RENDER_BUTTON, arg...)) } - for i, item := range list { - if t := reflect.TypeOf(item); t.Kind() == reflect.Func { - list[i] = kit.FuncName(item) - } +} +func (m *Message) PushScript(arg ...string) { // [type] text... + if !m.IsCliUA() { + m.Push(kit.MDB_SCRIPT, Render(m, RENDER_SCRIPT, arg)) } - m.Push(kit.MDB_ACTION, Render(m, RENDER_BUTTON, strings.ToLower(kit.Join(kit.Simple(list))))) } -func (m *Message) PushScript(arg ...string) *Message { // [type] text... - return m.Push(kit.MDB_SCRIPT, Render(m, RENDER_SCRIPT, arg)) -} -func (m *Message) PushQRCode(key string, text string, arg ...string) { // key text [size] - m.Push(key, Render(m, RENDER_QRCODE, text, arg)) +func (m *Message) PushQRCode(key string, src string, arg ...string) { // key src [size] + if !m.IsCliUA() { + m.Push(key, Render(m, RENDER_QRCODE, src, arg)) + } } func (m *Message) PushImages(key, src string, arg ...string) { // key src [size] - m.Push(key, Render(m, RENDER_IMAGES, src, arg)) + if !m.IsCliUA() { + m.Push(key, Render(m, RENDER_IMAGES, src, arg)) + } } func (m *Message) PushVideos(key, src string, arg ...string) { // key src [size] - m.Push(key, Render(m, RENDER_VIDEOS, src, arg)) + if !m.IsCliUA() { + m.Push(key, Render(m, RENDER_VIDEOS, src, arg)) + } } + func (m *Message) PushAction(list ...interface{}) { m.Table(func(index int, value map[string]string, head []string) { m.PushButton(list...) }) } +func (m *Message) PushPodCmd(cmd string, arg ...string) { + if strings.Contains(m.OptionFields(), "pod") { + m.Table(func(index int, value map[string]string, head []string) { + m.Push("pod", m.Option(MSG_USERPOD)) + }) + } -func (m *Message) EchoDownload(arg ...interface{}) { // [name] file - m.Echo(Render(m, RENDER_DOWNLOAD, arg...)) + m.Cmd("web.space").Table(func(index int, value map[string]string, head []string) { + switch value[kit.MDB_TYPE] { + case "worker", "server": + if value[kit.MDB_NAME] == Info.HostName { + break + } + m.Cmd("web.space", value[kit.MDB_NAME], m.Prefix(cmd), arg).Table(func(index int, val map[string]string, head []string) { + val["pod"] = kit.Keys(value[kit.MDB_NAME], val["pod"]) + m.Push("", val, head) + }) + } + }) +} +func (m *Message) PushSearch(args ...interface{}) { + data := kit.Dict(args...) + for _, k := range kit.Split(m.OptionFields()) { + switch k { + case "pod": + m.Push(k, "") + // m.Push(k, kit.Select(m.Option(MSG_USERPOD), data[kit.SSH_POD])) + case "ctx": + m.Push(k, m.Prefix()) + case "cmd": + m.Push(k, kit.Format(data["cmd"])) + case kit.MDB_TIME: + m.Push(k, kit.Select(m.Time(), data[k])) + default: + m.Push(k, kit.Format(kit.Select("", data[k]))) + } + } +} +func (m *Message) PushSearchWeb(cmd string, name string) { + msg := m.Spawn() + msg.Option(MSG_FIELDS, "type,name,text") + msg.Cmd("mdb.select", m.Prefix(cmd), "", kit.MDB_HASH).Table(func(index int, value map[string]string, head []string) { + text := kit.MergeURL(value[kit.MDB_TEXT], value[kit.MDB_NAME], name) + if value[kit.MDB_NAME] == "" { + text = kit.MergeURL(value[kit.MDB_TEXT] + url.QueryEscape(name)) + } + m.PushSearch("cmd", cmd, kit.MDB_TYPE, kit.Select("", value[kit.MDB_TYPE]), kit.MDB_NAME, name, kit.MDB_TEXT, text) + }) +} + +func (m *Message) EchoDownload(arg ...interface{}) *Message { // [name] file + return m.Echo(Render(m, RENDER_DOWNLOAD, arg...)) } func (m *Message) EchoAnchor(arg ...interface{}) *Message { // [name] link return m.Echo(Render(m, RENDER_ANCHOR, arg...)) } -func (m *Message) EchoButton(arg ...string) *Message { - return m.Echo(Render(m, RENDER_BUTTON, kit.Join(arg))) +func (m *Message) EchoButton(arg ...interface{}) *Message { // name... + return m.Echo(Render(m, RENDER_BUTTON, arg...)) } -func (m *Message) EchoScript(arg ...string) *Message { +func (m *Message) EchoScript(arg ...string) *Message { // [type] text... return m.Echo(Render(m, RENDER_SCRIPT, arg)) } -func (m *Message) EchoQRCode(text string, arg ...string) *Message { // text [size] - return m.Echo(Render(m, RENDER_QRCODE, text, arg)) +func (m *Message) EchoQRCode(src string, arg ...string) *Message { // src [size] + return m.Echo(Render(m, RENDER_QRCODE, src, arg)) } -func (m *Message) EchoImages(src string, arg ...string) *Message { +func (m *Message) EchoImages(src string, arg ...string) *Message { // src [size] return m.Echo(Render(m, RENDER_IMAGES, src, arg)) } - -func (m *Message) IsCliUA() bool { - if m.Option(MSG_USERUA) == "" || !strings.HasPrefix(m.Option(MSG_USERUA), "Mozilla/5.0") { - return true - } - return false +func (m *Message) EchoVideos(src string, arg ...string) *Message { // src [size] + return m.Echo(Render(m, RENDER_VIDEOS, src, arg)) } func (m *Message) Render(cmd string, args ...interface{}) *Message { @@ -134,12 +186,12 @@ func (m *Message) RenderResult(args ...interface{}) *Message { func (m *Message) RenderTemplate(args ...interface{}) *Message { return m.Render(RENDER_TEMPLATE, args...) } -func (m *Message) RenderDownload(args ...interface{}) *Message { - return m.Render(RENDER_DOWNLOAD, args...) -} func (m *Message) RenderRedirect(args ...interface{}) *Message { return m.Render(RENDER_REDIRECT, args...) } +func (m *Message) RenderDownload(args ...interface{}) *Message { + return m.Render(RENDER_DOWNLOAD, args...) +} func (m *Message) RenderIndex(serve, repos string, file ...string) *Message { return m.RenderDownload(path.Join(m.Conf(serve, kit.Keym(repos, kit.SSH_PATH)), kit.Select(m.Conf(serve, kit.Keym(repos, kit.SSH_INDEX)), path.Join(file...)))) } diff --git a/type.go b/type.go index 86daeb8c..da156abe 100644 --- a/type.go +++ b/type.go @@ -27,16 +27,22 @@ type Config struct { type Action struct { Name string Help string - List []interface{} Hand func(m *Message, arg ...string) + List []interface{} } type Command struct { Name string Help string - List []interface{} + Action map[string]*Action Meta map[string]interface{} Hand func(m *Message, c *Context, key string, arg ...string) - Action map[string]*Action + List []interface{} +} +type Server interface { + Spawn(m *Message, c *Context, arg ...string) Server + Begin(m *Message, arg ...string) Server + Start(m *Message, arg ...string) bool + Close(m *Message, arg ...string) bool } type Context struct { Name string @@ -57,12 +63,6 @@ type Context struct { wg *sync.WaitGroup id int32 } -type Server interface { - Spawn(m *Message, c *Context, arg ...string) Server - Begin(m *Message, arg ...string) Server - Start(m *Message, arg ...string) bool - Close(m *Message, arg ...string) bool -} func (c *Context) ID() int32 { if c == nil { @@ -76,21 +76,21 @@ func (c *Context) Cap(key string, arg ...interface{}) string { } return c.Caches[key].Value } -func (c *Context) Cmd(m *Message, cmd string, key string, arg ...string) *Message { - return c.cmd(m, m.Target().Commands[cmd], cmd, arg...) +func (c *Context) Cmd(m *Message, key string, arg ...string) *Message { + return c.cmd(m, m.target.Commands[key], key, arg...) } func (c *Context) Server() Server { return c.server } func (c *Context) Register(s *Context, x Server, name ...string) *Context { - if s.Name == "" { + if s.Merge(s); s.Name == "" { s.Name = kit.Split(kit.Split(kit.FileLine(2, 3), ":")[0], "/")[1] } + for _, n := range name { Name(n, s) } - s.Merge(s) if c.contexts == nil { c.contexts = map[string]*Context{} @@ -123,18 +123,15 @@ func (c *Context) Merge(s *Context) *Context { }() } - c.Commands[k] = v - - if v.List == nil { - v.List = c.split(k, v, v.Name) - } if v.Meta == nil { v.Meta = kit.Dict() } - if p := kit.Format(v.Meta[kit.MDB_STYLE]); p == "" { v.Meta[kit.MDB_STYLE] = k } + if c.Commands[k] = v; v.List == nil { + v.List = c.split(v.Name) + } for k, a := range v.Action { help := strings.SplitN(a.Help, ":", 2) @@ -149,7 +146,7 @@ func (c *Context) Merge(s *Context) *Context { continue } if a.List == nil { - a.List = c.split(k, nil, a.Name) + a.List = c.split(a.Name) } if len(a.List) > 0 { v.Meta[k] = a.List @@ -252,9 +249,8 @@ func (m *Message) Time(args ...interface{}) string { // [duration] [format [args t := m.time if len(args) > 0 { switch arg := args[0].(type) { - case string: + case string: // 时间偏移 if d, e := time.ParseDuration(arg); e == nil { - // 时间偏移 t, args = t.Add(d), args[1:] } } @@ -262,9 +258,8 @@ func (m *Message) Time(args ...interface{}) string { // [duration] [format [args f := MOD_TIME if len(args) > 0 { switch arg := args[0].(type) { - case string: + case string: // 时间格式 if f = arg; len(args) > 1 { - // 时间格式 f = fmt.Sprintf(f, args[1:]...) } } @@ -279,19 +274,13 @@ func (m *Message) Source() *Context { } func (m *Message) Spawn(arg ...interface{}) *Message { msg := &Message{ - time: time.Now(), - code: int(m.target.root.ID()), - + time: time.Now(), code: int(m.target.root.ID()), meta: map[string][]string{}, data: map[string]interface{}{}, message: m, root: m.root, - - source: m.target, - target: m.target, - - W: m.W, R: m.R, - O: m.O, I: m.I, + source: m.target, target: m.target, + W: m.W, R: m.R, O: m.O, I: m.I, } if len(arg) > 0 {