diff --git a/base/aaa/role.go b/base/aaa/role.go index 52abfc49..6c13f06b 100644 --- a/base/aaa/role.go +++ b/base/aaa/role.go @@ -1,39 +1,29 @@ package aaa import ( + "path" + "strings" + ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" ) -func _role_list(m *ice.Message, userrole string) { - m.Richs(ROLE, nil, kit.Select(mdb.FOREACH, userrole), func(key string, value ice.Map) { - kit.Fetch(value[BLACK], func(k string, v ice.Any) { - m.Push(ROLE, kit.Value(value, mdb.NAME)) - m.Push(mdb.ZONE, BLACK) - m.Push(mdb.KEY, k) - }) - kit.Fetch(value[WHITE], func(k string, v ice.Any) { - m.Push(ROLE, kit.Value(value, mdb.NAME)) - m.Push(mdb.ZONE, WHITE) - m.Push(mdb.KEY, k) - }) - }) -} func _role_chain(arg ...string) string { - return kit.ReplaceAll(kit.ReplaceAll(kit.Keys(arg), ice.PS, ice.PT), "..", ".") + key := path.Join(strings.ReplaceAll(kit.Keys(arg), ice.PT, ice.PS)) + return strings.TrimPrefix(strings.TrimSuffix(strings.ReplaceAll(key, ice.PS, ice.PT), ice.PT), ice.PT) } func _role_black(m *ice.Message, userrole, chain string) { - m.Richs(ROLE, nil, userrole, func(key string, value ice.Map) { - list := value[BLACK].(ice.Map) + mdb.HashSelectUpdate(m, userrole, func(value ice.Map) { m.Log_INSERT(ROLE, userrole, BLACK, chain) + list := value[BLACK].(ice.Map) list[chain] = true }) } func _role_white(m *ice.Message, userrole, chain string) { - m.Richs(ROLE, nil, userrole, func(key string, value ice.Map) { - list := value[WHITE].(ice.Map) + mdb.HashSelectUpdate(m, userrole, func(value ice.Map) { m.Log_INSERT(ROLE, userrole, WHITE, chain) + list := value[WHITE].(ice.Map) list[chain] = true }) } @@ -42,7 +32,7 @@ func _role_right(m *ice.Message, userrole string, keys ...string) (ok bool) { return true // 超级权限 } - m.Richs(ROLE, nil, kit.Select(VOID, userrole), func(key string, value ice.Map) { + mdb.HashSelectDetail(m, kit.Select(VOID, userrole), func(value ice.Map) { ok = true list := value[BLACK].(ice.Map) for i := 0; i < len(keys); i++ { @@ -73,9 +63,20 @@ func _role_right(m *ice.Message, userrole string, keys ...string) (ok bool) { }) return ok } - -func RoleRight(m *ice.Message, userrole string, keys ...string) bool { - return _role_right(m, userrole, kit.Split(kit.Keys(keys), ice.PT)...) +func _role_list(m *ice.Message, userrole string) *ice.Message { + mdb.HashSelectDetail(m, kit.Select(VOID, userrole), func(value ice.Map) { + kit.Fetch(value[BLACK], func(k string, v ice.Any) { + m.Push(ROLE, kit.Value(value, mdb.NAME)) + m.Push(mdb.ZONE, BLACK) + m.Push(mdb.KEY, k) + }) + kit.Fetch(value[WHITE], func(k string, v ice.Any) { + m.Push(ROLE, kit.Value(value, mdb.NAME)) + m.Push(mdb.ZONE, WHITE) + m.Push(mdb.KEY, k) + }) + }) + return m } const ( @@ -91,10 +92,8 @@ const ( const ROLE = "role" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - ROLE: {Name: ROLE, Help: "角色", Value: kit.Data(mdb.SHORT, mdb.NAME)}, - }, Commands: ice.Commands{ - ROLE: {Name: "role role auto insert", Help: "角色", Actions: ice.Actions{ + Index.MergeCommands(ice.Commands{ + ROLE: {Name: "role role auto insert", Help: "角色", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Rich(ROLE, nil, kit.Dict(mdb.NAME, TECH, BLACK, kit.Dict(), WHITE, kit.Dict())) m.Rich(ROLE, nil, kit.Dict(mdb.NAME, VOID, WHITE, kit.Dict(), BLACK, kit.Dict())) @@ -105,17 +104,17 @@ func init() { m.Cmd(ROLE, WHITE, VOID, ice.USR_LOCAL_GO) }}, mdb.INSERT: {Name: "insert role=void,tech zone=white,black key=", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - m.Richs(ROLE, nil, m.Option(ROLE), func(key string, value ice.Map) { + mdb.HashSelectUpdate(m, m.Option(ROLE), func(key string, value ice.Map) { m.Log_INSERT(ROLE, m.Option(ROLE), m.Option(mdb.ZONE), m.Option(mdb.KEY)) list := value[m.Option(mdb.ZONE)].(ice.Map) - list[m.Option(mdb.KEY)] = true + list[_role_chain(m.Option(mdb.KEY))] = true }) }}, mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Richs(ROLE, nil, m.Option(ROLE), func(key string, value ice.Map) { + mdb.HashSelectUpdate(m, m.Option(ROLE), func(key string, value ice.Map) { m.Log_DELETE(ROLE, m.Option(ROLE), m.Option(mdb.ZONE), m.Option(mdb.KEY)) list := value[m.Option(mdb.ZONE)].(ice.Map) - delete(list, m.Option(mdb.KEY)) + delete(list, _role_chain(m.Option(mdb.KEY))) }) }}, @@ -130,9 +129,12 @@ func init() { m.Echo(ice.OK) } }}, - }, Hand: func(m *ice.Message, arg ...string) { - _role_list(m, kit.Select("", arg, 0)) - m.PushAction(mdb.DELETE) + }, mdb.HashAction(mdb.SHORT, mdb.NAME)), Hand: func(m *ice.Message, arg ...string) { + _role_list(m, kit.Select("", arg, 0)).PushAction(mdb.DELETE) }}, - }}) + }) +} + +func RoleRight(m *ice.Message, userrole string, arg ...string) bool { + return m.Cmdx(ROLE, RIGHT, userrole, arg) == ice.OK } diff --git a/base/aaa/sess.go b/base/aaa/sess.go index e5452dc4..bc6bc866 100644 --- a/base/aaa/sess.go +++ b/base/aaa/sess.go @@ -4,54 +4,44 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) -func _sess_check(m *ice.Message, sessid string) bool { +func _sess_check(m *ice.Message, sessid string) { m.Option(ice.MSG_USERROLE, VOID) m.Option(ice.MSG_USERNAME, "") m.Option(ice.MSG_USERNICK, "") if sessid == "" { - return false + return } - m.Richs(SESS, nil, sessid, func(value ice.Map) { - if value = kit.GetMeta(value); m.Warn(kit.Time(kit.Format(value[mdb.TIME])) < kit.Time(m.Time()), ice.ErrNotValid) { + _source := logs.FileLineMeta(logs.FileLine(-1, 3)) + mdb.HashSelectDetail(m, sessid, func(value ice.Map) { + if m.Warn(kit.Time(kit.Format(value[mdb.TIME])) < kit.Time(m.Time()), ice.ErrNotValid, sessid) { return // 会话超时 } - if m.Richs(USER, nil, value[USERNAME], func(value ice.Map) { - m.Log_AUTH( - USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), - USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]), - USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]), - ) - }) == nil { - m.Log_AUTH( - USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), - USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]), - USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]), - ) - } + m.Log_AUTH( + USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), + USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]), + USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]), + _source, + ) }) - return m.Option(ice.MSG_USERNAME) != "" } func _sess_create(m *ice.Message, username string) string { if username == "" { return "" } - - h := m.Cmdx(mdb.INSERT, SESS, "", mdb.HASH, mdb.TIME, m.Time(m.Conf(SESS, kit.Keym(mdb.EXPIRE))), - USERROLE, UserRole(m, username), USERNAME, username, USERNICK, UserNick(m, username), - IP, m.Option(ice.MSG_USERIP), UA, m.Option(ice.MSG_USERUA), - ) - m.Event(SESS_CREATE, SESS, h, USERNAME, username) - return h -} - -func SessCreate(m *ice.Message, username string) string { - return m.Option(ice.MSG_SESSID, _sess_create(m, username)) -} -func SessCheck(m *ice.Message, sessid string) bool { - return _sess_check(m, sessid) + msg := m.Cmd(USER, username) + if msg.Length() > 0 { + h := mdb.HashCreate(m, msg.AppendSimple(USERROLE, USERNAME, USERNICK), IP, m.Option(ice.MSG_USERIP), UA, m.Option(ice.MSG_USERUA)).Result() + m.Event(SESS_CREATE, SESS, h, USERNAME, username) + return h + } else { + h := mdb.HashCreate(m, m.OptionSimple(USERROLE, USERNAME, USERNICK), IP, m.Option(ice.MSG_USERIP), UA, m.Option(ice.MSG_USERUA)).Result() + m.Event(SESS_CREATE, SESS, h, USERNAME, username) + return h + } } const ( @@ -59,10 +49,11 @@ const ( UA = "ua" ) const ( + CHECK = "check" GRANT = "grant" LOGIN = "login" LOGOUT = "logout" - EXPIRE = "expire" + SESSID = "sessid" ) const ( SESS_CREATE = "sess.create" @@ -70,15 +61,21 @@ const ( const SESS = "sess" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SESS: {Name: SESS, Help: "会话", Value: kit.Data( - mdb.SHORT, "uniq", mdb.FIELD, "time,hash,userrole,username,usernick,ip,ua", mdb.EXPIRE, "720h", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SESS: {Name: "sess hash auto prunes", Help: "会话", Actions: ice.MergeAction(ice.Actions{ - mdb.CREATE: {Name: "create username", Help: "创建"}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelect(m, arg...) - }}, - }}) + mdb.CREATE: {Name: "create username", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + _sess_create(m, m.Option(USERNAME)) + }}, + CHECK: {Name: "check sessid", Help: "检查", Hand: func(m *ice.Message, arg ...string) { + _sess_check(m, m.Option(SESSID)) + }}, + }, mdb.HashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,userrole,username,usernick,ip,ua", mdb.EXPIRE, "720h"))}, + }) +} + +func SessCreate(m *ice.Message, username string) string { + return m.Option(ice.MSG_SESSID, m.Cmdx(SESS, mdb.CREATE, username)) +} +func SessCheck(m *ice.Message, sessid string) bool { + return m.Cmdy(SESS, CHECK, sessid).Option(ice.MSG_USERNAME) != "" } diff --git a/base/aaa/totp.go b/base/aaa/totp.go index ee67def5..429ce8cf 100644 --- a/base/aaa/totp.go +++ b/base/aaa/totp.go @@ -43,8 +43,6 @@ func _totp_get(key string, num int, per int64) string { return kit.Format(kit.Format("%%0%dd", num), res%int64(math.Pow10(num))) } -func TOTP_GET(key string, num int, per int64) string { return _totp_get(key, num, per) } - const ( SECRET = "secret" PERIOD = "period" @@ -55,20 +53,15 @@ const ( const TOTP = "totp" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - TOTP: {Name: TOTP, Help: "令牌", Value: kit.Data( - mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,secret,period,number", mdb.LINK, "otpauth://totp/%s?secret=%s", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TOTP: {Name: "totp name auto create", Help: "令牌", Actions: ice.MergeAction(ice.Actions{ mdb.CREATE: {Name: "create name=hi secret period=30 number=6", Help: "添加", Hand: func(m *ice.Message, arg ...string) { if m.Option(SECRET) == "" { // 创建密钥 m.Option(SECRET, _totp_gen(kit.Int64(m.Option(PERIOD)))) } - - m.Cmd(mdb.INSERT, TOTP, "", mdb.HASH, m.OptionSimple(mdb.NAME, SECRET, PERIOD, NUMBER)) + mdb.HashCreate(m, m.OptionSimple(mdb.NAME, SECRET, PERIOD, NUMBER)) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,secret,period,number", mdb.LINK, "otpauth://totp/%s?secret=%s")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m.Spawn(), arg...).Tables(func(value ice.Maps) { if len(arg) > 0 { m.OptionFields(mdb.DETAIL) @@ -86,5 +79,7 @@ func init() { } }) }}, - }}) + }) } + +func TOTP_GET(key string, num int, per int64) string { return _totp_get(key, num, per) } diff --git a/base/aaa/user.go b/base/aaa/user.go index 98968d0d..5350d5c4 100644 --- a/base/aaa/user.go +++ b/base/aaa/user.go @@ -4,95 +4,52 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) -func _user_exists(m *ice.Message, name string) bool { - return m.Richs(USER, nil, name, nil) != nil -} -func _user_login(m *ice.Message, name, word string) (ok bool) { - if !_user_exists(m, name) { +func _user_login(m *ice.Message, name, word string) { + if m.Warn(name == "", ice.ErrNotValid, name) { + return + } + if !mdb.HashSelectDetail(m, name, nil) { _user_create(m, VOID, name, word) } - m.Richs(USER, nil, name, func(key string, value ice.Map) { - if ok = !m.Warn(word != "" && word != value[PASSWORD], ice.ErrNotRight); ok { - m.Log_AUTH( - USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), - USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]), - USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]), - ) + _source := logs.FileLineMeta(logs.FileLine(-1, 3)) + mdb.HashSelectDetail(m, name, func(value ice.Map) { + if m.Warn(word != "" && word != kit.Format(kit.Value(value, kit.Keys(mdb.EXTRA, PASSWORD))), ice.ErrNotRight) { + return } + m.Log_AUTH( + USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), + USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]), + USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]), + _source, + ) }) - return ok } -func _user_create(m *ice.Message, role, name, word string) { - if name == "" { +func _user_create(m *ice.Message, name, word string, arg ...string) { + if m.Warn(name == "", ice.ErrNotValid, name) { return } if word == "" { - if m.Richs(USER, nil, name, func(key string, value ice.Map) { - word = kit.Format(value[PASSWORD]) - }) == nil { - word = kit.Hashs() - } + word = m.CmdAppend(USER, name, PASSWORD) } - m.Rich(USER, nil, kit.Dict(USERROLE, role, USERNAME, name, PASSWORD, word)) + if word == "" { + word = kit.Hashs() + } + mdb.HashCreate(m, USERNAME, name, PASSWORD, word, arg) m.Event(USER_CREATE, USER, name) } -func _user_search(m *ice.Message, name, text string) { - m.Richs(USER, nil, mdb.FOREACH, func(key string, value ice.Map) { - if value = kit.GetMeta(value); name == "" || name == value[USERNAME] { - m.PushSearch(kit.SimpleKV("", value[USERROLE], value[USERNAME], value[USERNICK]), value) - } - }) -} - -func UserRoot(m *ice.Message, arg ...string) *ice.Message { // password username userrole - username := m.Option(ice.MSG_USERNAME, kit.Select(ice.Info.UserName, arg, 1)) - userrole := m.Option(ice.MSG_USERROLE, kit.Select(ROOT, arg, 2)) - if len(arg) > 0 { - _user_create(m, userrole, username, kit.Select("", arg, 0)) - ice.Info.UserName = username - } - return m -} -func UserRole(m *ice.Message, username ice.Any) (role string) { - if role = VOID; username == ice.Info.UserName { - return ROOT - } - if m.Richs(USER, nil, kit.Format(username), func(key string, value ice.Map) { - role = kit.Format(kit.GetMeta(value)[USERROLE]) - }) == nil && kit.Format(username) == m.Option(ice.MSG_USERNAME) { - return m.Option(ice.MSG_USERROLE) - } - return -} -func UserNick(m *ice.Message, username ice.Any) (nick string) { - if m.Richs(USER, nil, kit.Format(username), func(key string, value ice.Map) { - nick = kit.Format(kit.GetMeta(value)[USERNICK]) - }) == nil && kit.Format(username) == m.Option(ice.MSG_USERNAME) { - return m.Option(ice.MSG_USERNICK) - } - return -} -func UserZone(m *ice.Message, username ice.Any) (zone string) { - m.Richs(USER, nil, kit.Format(username), func(key string, value ice.Map) { - zone = kit.Format(kit.GetMeta(value)[USERZONE]) - }) - return -} -func UserLogin(m *ice.Message, username, password string) bool { - return _user_login(m, username, password) -} const ( + BACKGROUND = "background" + AVATAR = "avatar" GENDER = "gender" MOBILE = "mobile" EMAIL = "email" - BACKGROUND = "background" - CITY = "city" COUNTRY = "country" LANGUAGE = "language" @@ -114,24 +71,50 @@ const ( const USER = "user" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - USER: {Name: USER, Help: "用户", Value: kit.Data( - mdb.SHORT, USERNAME, mdb.FIELD, "time,userrole,username,usernick,userzone", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ USER: {Name: "user username auto create", Help: "用户", Actions: ice.MergeAction(ice.Actions{ mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { - if arg[0] == USER { - _user_search(m, arg[1], kit.Select("", arg, 2)) - } + mdb.HashSelectSearch(m, arg) }}, - mdb.CREATE: {Name: "create userrole=void,tech username password", Help: "创建", Hand: func(m *ice.Message, arg ...string) { - if !_user_exists(m, m.Option(USERNAME)) { - _user_create(m, m.Option(USERROLE), m.Option(USERNAME), m.Option(PASSWORD)) - } + mdb.CREATE: {Name: "create username password userrole=void,tech", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + _user_create(m, m.Option(USERNAME), m.Option(PASSWORD), m.OptionSimple(USERROLE)...) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelect(m, arg...) - }}, - }}) + LOGIN: {Name: "login username password", Help: "登录", Hand: func(m *ice.Message, arg ...string) { + _user_login(m, m.Option(USERNAME), m.Option(PASSWORD)) + }}, + }, mdb.HashAction(mdb.SHORT, USERNAME, mdb.FIELD, "time,userrole,username,usernick,userzone"))}, + }) +} + +func UserRoot(m *ice.Message, arg ...string) *ice.Message { // password username userrole + username := m.Option(ice.MSG_USERNAME, kit.Select(ice.Info.UserName, arg, 1)) + userrole := m.Option(ice.MSG_USERROLE, kit.Select(ROOT, arg, 2)) + if len(arg) > 0 { + m.Cmd(USER, mdb.CREATE, username, kit.Select("", arg, 0), userrole) + ice.Info.UserName = username + } + return m +} +func UserRole(m *ice.Message, username ice.Any) (role string) { + if role = VOID; username == ice.Info.UserName { + return ROOT + } + return UserInfo(m, username, USERROLE, ice.MSG_USERROLE) +} +func UserNick(m *ice.Message, username ice.Any) (nick string) { + return UserInfo(m, username, USERNICK, ice.MSG_USERNICK) +} +func UserZone(m *ice.Message, username ice.Any) (zone string) { + return UserInfo(m, username, USERZONE, ice.MSG_USERZONE) +} +func UserInfo(m *ice.Message, name ice.Any, key, meta string) (value string) { + if m.Cmd(USER, name).Tables(func(val ice.Maps) { + value = val[key] + }).Length() == 0 && kit.Format(name) == m.Option(ice.MSG_USERNAME) { + return m.Option(meta) + } + return +} +func UserLogin(m *ice.Message, username, password string) bool { + return m.Cmdy(USER, LOGIN, username, password).Option(ice.MSG_USERNAME) != "" } diff --git a/base/cli/daemon.go b/base/cli/daemon.go index f50e296b..e35776e2 100644 --- a/base/cli/daemon.go +++ b/base/cli/daemon.go @@ -6,63 +6,67 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" - "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" ) func _daemon_exec(m *ice.Message, cmd *exec.Cmd) { if r, ok := m.Optionv(CMD_INPUT).(io.Reader); ok { - cmd.Stdin = r + cmd.Stdin = r // 输入流 } if w := _system_out(m, CMD_OUTPUT); w != nil { - cmd.Stdout = w - cmd.Stderr = w + cmd.Stdout, cmd.Stderr = w, w } if w := _system_out(m, CMD_ERRPUT); w != nil { cmd.Stderr = w } - // 启动进程 + h := mdb.HashCreate(m, + STATUS, START, ice.CMD, kit.Join(cmd.Args, ice.SP), + DIR, cmd.Dir, ENV, kit.Select("", cmd.Env), + m.OptionSimple(CMD_OUTPUT, CMD_ERRPUT, mdb.CACHE_CLEAR_ON_EXIT), + ).Result() + + // 启动服务 if e := cmd.Start(); m.Warn(e, ice.ErrNotStart, cmd.Args) { + mdb.HashModify(m, h, STATUS, ERROR, ERROR, e) return // 启动失败 } + mdb.HashSelectUpdate(m, h, func(value ice.Map) { value[PID] = cmd.Process.Pid }) m.Echo("%d", cmd.Process.Pid) - m.Go(func() { - h := m.Cmdx(mdb.INSERT, DAEMON, "", mdb.HASH, - STATUS, START, ice.CMD, kit.Join(cmd.Args, ice.SP), - PID, cmd.Process.Pid, DIR, cmd.Dir, ENV, kit.Select("", cmd.Env), - m.OptionSimple(CMD_OUTPUT, CMD_ERRPUT, mdb.CACHE_CLEAR_ON_EXIT), - ) - + m.Go(func() { // 等待结果 if e := cmd.Wait(); !m.Warn(e, ice.ErrNotStart, cmd.Args) && cmd.ProcessState.ExitCode() == 0 { m.Cost(CODE, cmd.ProcessState.ExitCode(), ctx.ARGS, cmd.Args) - m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, mdb.HASH, h, STATUS, STOP) + mdb.HashModify(m, mdb.HASH, h, STATUS, STOP) } else { - if m.Conf(DAEMON, kit.Keys(mdb.HASH, h, kit.Keym(STATUS))) == START { - m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, mdb.HASH, h, STATUS, ERROR, ERROR, e) - } + mdb.HashSelectUpdate(m, h, func(value ice.Map) { + if value[STATUS] == START { + value[STATUS], value[ERROR] = ERROR, e + } + }) } + status := mdb.HashSelectFields(m, h, STATUS) switch m.Sleep300ms(); cb := m.OptionCB(DAEMON).(type) { case func(string) bool: - if !cb(m.Conf(DAEMON, kit.Keys(mdb.HASH, h, kit.Keym(STATUS)))) { + if !cb(status) { // 拉起服务 m.Cmdy(DAEMON, cmd.Path, cmd.Args) } case func(string): - cb(m.Conf(DAEMON, kit.Keys(mdb.HASH, h, kit.Keym(STATUS)))) + cb(status) case func(): cb() + case nil: default: - m.Error(true, ice.ErrNotImplement) + m.ErrorNotImplement(cb) } for _, p := range kit.Simple(CMD_INPUT, CMD_OUTPUT, CMD_ERRPUT) { kit.Close(m.Optionv(p)) } }) - m.Sleep("100ms") } const ( @@ -87,10 +91,10 @@ const ( RELOAD = "reload" RESTART = "restart" - START = "start" - STOP = "stop" OPEN = "open" CLOSE = "close" + START = "start" + STOP = "stop" BEGIN = "begin" END = "end" @@ -99,61 +103,51 @@ const ( BACK = "back" FROM = "from" MAIN = "main" - KILL = "kill" ) const DAEMON = "daemon" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - DAEMON: {Name: DAEMON, Help: "守护进程", Value: kit.Data( - nfs.PATH, ice.USR_LOCAL_DAEMON, mdb.FIELD, "time,hash,status,pid,cmd,dir,env", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ DAEMON: {Name: "daemon hash auto start prunes", Help: "守护进程", Actions: ice.MergeAction(ice.Actions{ ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(mdb.PRUNES, DAEMON, "", mdb.HASH, mdb.CACHE_CLEAR_ON_EXIT, ice.TRUE) + mdb.HashPrunesValue(m, mdb.CACHE_CLEAR_ON_EXIT, ice.TRUE) }}, mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { - m.OptionFields(m.Config(mdb.FIELD)) - m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, STATUS, STOP) - m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, STATUS, ERROR) + mdb.HashPrunesValue(m, STATUS, ERROR) + mdb.HashPrunesValue(m, STATUS, STOP) }}, START: {Name: "start cmd env dir", Help: "添加", Hand: func(m *ice.Message, arg ...string) { m.Option(CMD_DIR, m.Option(DIR)) m.Option(CMD_ENV, kit.Split(m.Option(ENV), " =")) - m.Cmdy(DAEMON, kit.Split(m.Option(ice.CMD))) + _daemon_exec(m, _system_cmd(m, kit.Split(m.Option(ice.CMD))...)) }}, RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(DAEMON, STOP).Sleep3s().Cmdy(DAEMON, START) + m.Cmdy("", STOP).Sleep3s().Cmdy("", START) }}, STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { m.OptionFields(m.Config(mdb.FIELD)) - m.Cmd(mdb.SELECT, DAEMON, "", mdb.HASH, m.OptionSimple(mdb.HASH)).Tables(func(value ice.Maps) { - m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, m.OptionSimple(mdb.HASH), STATUS, STOP) - m.Cmdy(SYSTEM, KILL, value[PID]) + mdb.HashSelect(m, m.Option(mdb.HASH)).Tables(func(value ice.Maps) { + mdb.HashModify(m, m.OptionSimple(mdb.HASH), STATUS, STOP) + m.Cmd(gdb.SIGNAL, gdb.KILL, value[PID]) }) - if IsSuccess(m) { - m.SetAppend() - } }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelect(m, arg...).Set(ctx.ACTION).Tables(func(value ice.Maps) { + }, mdb.HashAction(mdb.FIELD, "time,hash,status,pid,cmd,dir,env")), Hand: func(m *ice.Message, arg ...string) { + if mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) { switch value[STATUS] { case START: m.PushButton(RESTART, STOP) default: m.PushButton(mdb.REMOVE) } - }) - - if len(arg) == 0 || m.Length() > 0 { + }); len(arg) == 0 || m.Length() > 0 { return } + if len(arg) == 1 { arg = kit.Split(arg[0]) } _daemon_exec(m, _system_cmd(m, arg...)) }}, - }}) + }) } diff --git a/base/cli/forever.go b/base/cli/forever.go index a4a92945..b9a60734 100644 --- a/base/cli/forever.go +++ b/base/cli/forever.go @@ -5,18 +5,12 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" + "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) -func _forever_kill(m *ice.Message, s string) { - if p := m.Cmdx(nfs.CAT, m.Conf("gdb.signal", kit.Keym(nfs.PATH))); p != "" { - if s != "" { - m.Cmd(SYSTEM, "kill", "-s", s, p) - } - m.Echo(p) - } -} func BinPath(arg ...string) string { return kit.Join(kit.Simple(arg, kit.Path(ice.BIN), kit.Path(ice.USR_LOCAL_BIN), kit.Path(ice.USR_LOCAL_GO_BIN), kit.Env(PATH)), ice.DF) } @@ -24,16 +18,11 @@ func BinPath(arg ...string) string { const FOREVER = "forever" func init() { - const SERVE = "serve" - const RESTART = "restart" - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ FOREVER: {Name: "forever auto", Help: "启动", Actions: ice.Actions{ - RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) { - _forever_kill(m, "INT") - }}, - SERVE: {Name: "serve", Help: "服务", Hand: func(m *ice.Message, arg ...string) { + gdb.START: {Name: "start", Help: "服务", Hand: func(m *ice.Message, arg ...string) { env := []string{PATH, BinPath(), HOME, kit.Select(kit.Path(""), os.Getenv(HOME))} - for _, k := range []string{TERM, SHELL, CTX_SHY, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER, CTX_DAEMON} { + for _, k := range ENV_LIST { if kit.Env(k) != "" { env = append(env, k, kit.Env(k)) } @@ -49,24 +38,27 @@ func init() { m.Cmd(FOREVER, STOP) m.Cmdy(FOREVER, kit.Select(os.Args[0], nfs.PWD+ice.BIN_ICE_BIN, kit.FileExists(ice.BIN_ICE_BIN)), - SERVE, START, ice.DEV, "", aaa.USERNAME, aaa.ROOT, aaa.PASSWORD, aaa.ROOT, arg) + "serve", START, ice.DEV, "", aaa.USERNAME, aaa.ROOT, aaa.PASSWORD, aaa.ROOT, arg) }}, - STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { - _forever_kill(m, "QUIT") + gdb.RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) { + m.Cmd(gdb.SIGNAL, gdb.RESTART) + }}, + gdb.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { + m.Cmd(gdb.SIGNAL, gdb.STOP) }}, }, Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { - _forever_kill(m, "") + m.Cmdy(RUNTIME, BOOTINFO) return } for { - println(kit.Format("%s run %s", kit.Now(), kit.Join(arg, ice.SP))) + logs.Println("run %s", kit.Join(arg, ice.SP)) if m.Sleep("1s"); IsSuccess(m.Cmd(SYSTEM, arg)) { - println(kit.Format("%s exit", kit.Now())) - return + logs.Println("exit") + break } } - }}}, + }}, }) } diff --git a/base/cli/mirrors.go b/base/cli/mirrors.go index af1f0ef8..cf4ed3ab 100644 --- a/base/cli/mirrors.go +++ b/base/cli/mirrors.go @@ -1,6 +1,7 @@ package cli import ( + "runtime" "strings" ice "shylinux.com/x/icebergs" @@ -8,18 +9,9 @@ import ( kit "shylinux.com/x/toolkits" ) -func IsAlpine(m *ice.Message, arg ...string) bool { - if strings.Contains(m.Conf(RUNTIME, "host.OSID"), ALPINE) { - if len(arg) > 0 { - m.Cmd(MIRRORS, mdb.CREATE, "cli", arg[0], "cmd", arg[1]) - } - return true - } - return false -} - const ( - OSID = "OSID" + CMD = "cmd" + OSID = "osid" ALPINE = "alpine" CENTOS = "centos" UBUNTU = "ubuntu" @@ -28,31 +20,49 @@ const ( const MIRRORS = "mirrors" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ MIRRORS: {Name: "mirrors cli auto", Help: "软件镜像", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Go(func() { - m.Sleep("1s") - IsAlpine(m, "curl", "system apk add curl") - IsAlpine(m, "make", "system apk add make") - IsAlpine(m, "gcc", "system apk add gcc") - IsAlpine(m, "vim", "system apk add vim") - IsAlpine(m, "tmux", "system apk add tmux") + m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH), "") + IsAlpine(m, "curl") + IsAlpine(m, "make") + IsAlpine(m, "gcc") + IsAlpine(m, "vim") + IsAlpine(m, "tmux") - if IsAlpine(m, "git", "system apk add git"); !IsAlpine(m, "go", "system apk add git go") { - m.Cmd(MIRRORS, mdb.CREATE, kit.SimpleKV("cli,cmd", "go", "install download https://golang.google.cn/dl/go1.15.5.linux-amd64.tar.gz usr/local")) + IsAlpine(m, "git") + mdb.ZoneInsert(m, CLI, "go", CMD, kit.Format("install download https://golang.google.cn/dl/go1.15.5.%s-%s.tar.gz usr/local", runtime.GOOS, runtime.GOARCH)) + + IsAlpine(m, "node", "nodejs") + IsAlpine(m, "java", "openjdk8") + IsAlpine(m, "javac", "openjdk8") + IsAlpine(m, "mvn", "openjdk8 maven") + IsAlpine(m, "python", "python2") + IsAlpine(m, "python2") + IsAlpine(m, "python3") + }}, + mdb.INSERT: {Name: "insert cli osid cmd", Help: "添加"}, + CMD: {Name: "cmd cli osid", Help: "安装", Hand: func(m *ice.Message, arg ...string) { + osid := kit.Select(m.Conf(RUNTIME, kit.Keys(HOST, OSID)), m.Option(OSID)) + mdb.ZoneSelectCB(m, m.Option(CLI), func(value ice.Map) { + if osid != "" && strings.Contains(osid, kit.Format(value[OSID])) { + m.Cmdy(kit.Split(kit.Format(value[CMD]))) } - - IsAlpine(m, "node", "system apk add nodejs") - IsAlpine(m, "python", "system apk add python2") - IsAlpine(m, "python2", "system apk add python2") - IsAlpine(m, "python3", "system apk add python3") - IsAlpine(m, "mvn", "system apk add openjdk8 maven") - IsAlpine(m, "javac", "system apk add openjdk8") - IsAlpine(m, "java", "system apk add openjdk8") }) }}, - mdb.CREATE: {Name: "create cli cmd", Help: "创建"}, - }, mdb.HashAction(mdb.SHORT, "cli", mdb.FIELD, "time,cli,cmd"))}, - }}) + ALPINE: {Name: "alpine cli cmd", Help: "安装", Hand: func(m *ice.Message, arg ...string) { + IsAlpine(m, arg...) + }}, + }, mdb.ZoneAction(mdb.SHORT, CLI, mdb.FIELD, "time,id,osid,cmd"))}, + }) +} + +func IsAlpine(m *ice.Message, arg ...string) bool { + if strings.Contains(m.Conf(RUNTIME, kit.Keys(HOST, OSID)), ALPINE) { + if len(arg) > 0 { + mdb.ZoneInsert(m, CLI, arg[0], OSID, ALPINE, CMD, "system apk add "+kit.Select(arg[0], arg, 1)) + } + return true + } + return false } diff --git a/base/cli/qrcode.go b/base/cli/qrcode.go index e1096654..c8f5b21b 100644 --- a/base/cli/qrcode.go +++ b/base/cli/qrcode.go @@ -31,6 +31,7 @@ func _parse_color(str string) color.Color { for k := range _trans_web { list = append(list, k) } + kit.Sort(list) str = list[rand.Intn(len(list))] } if strings.HasPrefix(str, "#") { @@ -93,24 +94,12 @@ func _qrcode_web(m *ice.Message, text string) { } } -func Color(m *ice.Message, c string, str ice.Any) string { - wrap, color := `%v`, c - if m.IsCliUA() { - wrap, color = "\033[3%sm%v\033[0m", _parse_cli_color(c) - } - return fmt.Sprintf(wrap, color, str) -} -func ColorRed(m *ice.Message, str ice.Any) string { return Color(m, RED, str) } -func ColorGreen(m *ice.Message, str ice.Any) string { return Color(m, GREEN, str) } -func ColorYellow(m *ice.Message, str ice.Any) string { return Color(m, YELLOW, str) } - const ( - FG = "fg" - BG = "bg" - SIZE = "size" - + FG = "fg" + BG = "bg" DARK = 255 LIGHT = 127 + SIZE = "size" ) const ( COLOR = "color" @@ -129,7 +118,7 @@ const ( const QRCODE = "qrcode" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ QRCODE: {Name: "qrcode text@key fg@key bg@key size auto", Help: "二维码", Actions: ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.AddRender(ice.RENDER_QRCODE, func(m *ice.Message, cmd string, args ...ice.Any) string { @@ -138,26 +127,32 @@ func init() { }}, mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { switch arg[0] { - case "text": - m.Push("text", "hi") - m.Push("text", "hello") - m.Push("text", "world") - case "fg", "bg": - m.Push("color", "red") - m.Push("color", "green") - m.Push("color", "blue") + case mdb.TEXT: + m.Push(arg[0], "hi", "hello", "world") + case FG, BG: + m.Push(arg[0], RED, GREEN, BLUE) } }}, }, Hand: func(m *ice.Message, arg ...string) { m.Option(SIZE, kit.Select("240", arg, 3)) m.Option(BG, kit.Select(WHITE, arg, 2)) m.Option(FG, kit.Select(BLUE, arg, 1)) - if m.IsCliUA() { - _qrcode_cli(m, kit.Select(ice.Info.Domain, arg, 0)) + _qrcode_cli(m, kit.Select(kit.Select(ice.Info.Make.Domain, ice.Info.Domain), arg, 0)) } else { _qrcode_web(m, kit.Select(m.Option(ice.MSG_USERWEB), arg, 0)) } }}, - }}) + }) } + +func Color(m *ice.Message, c string, str ice.Any) string { + wrap, color := `%v`, c + if m.IsCliUA() { + wrap, color = "\033[3%sm%v\033[0m", _parse_cli_color(c) + } + return fmt.Sprintf(wrap, color, str) +} +func ColorRed(m *ice.Message, str ice.Any) string { return Color(m, RED, str) } +func ColorGreen(m *ice.Message, str ice.Any) string { return Color(m, GREEN, str) } +func ColorYellow(m *ice.Message, str ice.Any) string { return Color(m, YELLOW, str) } diff --git a/base/cli/runtime.go b/base/cli/runtime.go index 49226f83..6eefdc6c 100644 --- a/base/cli/runtime.go +++ b/base/cli/runtime.go @@ -9,6 +9,7 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" @@ -25,42 +26,49 @@ func _runtime_init(m *ice.Message) { m.Conf(RUNTIME, kit.Keys(HOST, GOOS), runtime.GOOS) m.Conf(RUNTIME, kit.Keys(HOST, PID), os.Getpid()) m.Conf(RUNTIME, kit.Keys(HOST, HOME), kit.Env(HOME)) + m.Conf(RUNTIME, kit.Keys(HOST, MAXPROCS), runtime.GOMAXPROCS(0)) - // 启动信息 boot - if name, e := os.Hostname(); e == nil { - m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Select(name, kit.Env("HOSTNAME"))) + // 启动目录 boot + m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Env("HOSTNAME")) + if name, e := os.Hostname(); e == nil && name != "" { + m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), name) } - if name, e := os.Getwd(); e == nil { - name = path.Base(kit.Select(name, kit.Env("PWD"))) - name = kit.Slice(strings.Split(name, ice.PS), -1)[0] - name = kit.Slice(strings.Split(name, "\\"), -1)[0] - m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), name) + m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(kit.Env("PWD"))) + if name, e := os.Getwd(); e == nil && name != "" { + m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), path.Base(name)) } - m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(kit.UserName(), kit.Select(kit.Env("WORKSPACE_GIT_USERNAME"), kit.Env(CTX_USER)))) ice.Info.HostName = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME)) ice.Info.PathName = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME)) ice.Info.UserName = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME)) aaa.UserRoot(ice.Pulse) - // 启动次数 boot + // 启动程序 boot m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT), kit.Int(m.Conf(RUNTIME, kit.Keys(BOOT, mdb.COUNT)))+1) bin := _system_find(m, os.Args[0]) m.Conf(RUNTIME, kit.Keys(BOOT, ice.BIN), bin) if s, e := os.Stat(bin); e == nil { - m.Conf(RUNTIME, kit.Keys(BOOT, "size"), kit.FmtSize(s.Size())) + m.Conf(RUNTIME, kit.Keys(BOOT, nfs.SIZE), kit.FmtSize(s.Size())) if f, e := os.Open(bin); e == nil { defer f.Close() - m.Conf(RUNTIME, kit.Keys(BOOT, "hash"), kit.Hashs(f)) + m.Conf(RUNTIME, kit.Keys(BOOT, mdb.HASH), kit.Hashs(f)) } } // 环境变量 conf - for _, k := range []string{CTX_SHY, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER, CTX_DAEMON} { - m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k)) + for _, k := range ENV_LIST { + switch m.Conf(RUNTIME, kit.Keys(CONF, k), kit.Env(k)); k { + case CTX_PID: + ice.Info.PidPath = kit.Select("var/run/ice.pid", kit.Env(k)) + case CTX_SHARE: + ice.Info.CtxShare = kit.Env(k) + case CTX_RIVER: + ice.Info.CtxRiver = kit.Env(k) + } } - osid := "" + // 系统版本 osid + osid := runtime.GOOS m.Cmd(nfs.CAT, "/etc/os-release", func(text string) { if ls := kit.Split(text, "="); len(ls) > 1 { switch ls[0] { @@ -119,11 +127,11 @@ const ( WINDOWS = "windows" ) const ( - SHELL = "SHELL" - TERM = "TERM" - USER = "USER" - HOME = "HOME" PATH = "PATH" + HOME = "HOME" + USER = "USER" + TERM = "TERM" + SHELL = "SHELL" ) const ( CTX_SHY = "ctx_shy" @@ -131,9 +139,9 @@ const ( CTX_OPS = "ctx_ops" CTX_POD = "ctx_pod" CTX_ARG = "ctx_arg" + CTX_PID = "ctx_pid" + CTX_LOG = "ctx_log" - CTX_PID = "ctx_pid" - CTX_LOG = "ctx_log" CTX_USER = "ctx_user" CTX_SHARE = "ctx_share" CTX_RIVER = "ctx_river" @@ -141,37 +149,37 @@ const ( MAKE_DOMAIN = "make.domain" ) + +var ENV_LIST = []string{ + TERM, SHELL, CTX_SHY, CTX_DEV, CTX_OPS, CTX_ARG, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER, CTX_DAEMON, +} + const ( HOSTNAME = "hostname" PATHNAME = "pathname" USERNAME = "username" ) const ( - MAXPROCS = "maxprocs" IFCONFIG = "ifconfig" HOSTINFO = "hostinfo" USERINFO = "userinfo" PROCINFO = "procinfo" PROCKILL = "prockill" - BOOTINFO = "bootinfo" DISKINFO = "diskinfo" + BOOTINFO = "bootinfo" + MAXPROCS = "maxprocs" ) const RUNTIME = "runtime" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - RUNTIME: {Name: RUNTIME, Help: "运行环境", Value: kit.Dict()}, - }, Commands: ice.Commands{ - RUNTIME: {Name: "runtime info=ifconfig,hostinfo,hostname,userinfo,procinfo,bootinfo,diskinfo,env,file,route auto", Help: "运行环境", Actions: ice.Actions{ + Index.MergeCommands(ice.Commands{ + RUNTIME: {Name: "runtime info=ifconfig,hostinfo,hostname,userinfo,procinfo,diskinfo,bootinfo,api,cli,cmd,env auto", Help: "运行环境", Actions: ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(RUNTIME, MAXPROCS, "1") - _runtime_init(m) - }}, - MAXPROCS: {Name: "maxprocs", Help: "最大并发", Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 0 { - runtime.GOMAXPROCS(kit.Int(m.Conf(RUNTIME, kit.Keys(HOST, "GOMAXPROCS"), kit.Select("1", arg, 0)))) + cs := m.Target().Configs + if _, ok := cs[RUNTIME]; !ok { + cs[RUNTIME] = &ice.Config{Value: kit.Dict()} } - m.Echo("%d", runtime.GOMAXPROCS(0)) + _runtime_init(m) }}, IFCONFIG: {Name: "ifconfig", Help: "网卡配置", Hand: func(m *ice.Message, arg ...string) { m.Cmdy("tcp.host") @@ -193,13 +201,37 @@ func init() { m.StatusTimeCount() }}, PROCKILL: {Name: "prockill", Help: "结束进程", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SYSTEM, KILL, m.Option("PID")) + m.Cmdy(gdb.SIGNAL, gdb.STOP, m.Option("PID")) m.ProcessRefresh30ms() }}, DISKINFO: {Name: "diskinfo", Help: "磁盘信息", Hand: func(m *ice.Message, arg ...string) { _runtime_diskinfo(m) }}, - "env": {Name: "env", Help: "环境变量", Hand: func(m *ice.Message, arg ...string) { + MAXPROCS: {Name: "maxprocs", Help: "最大并发", Hand: func(m *ice.Message, arg ...string) { + if len(arg) > 0 { + runtime.GOMAXPROCS(kit.Int(m.Conf(RUNTIME, kit.Keys(HOST, MAXPROCS), kit.Select("1", arg, 0)))) + } + m.Echo("%d", runtime.GOMAXPROCS(0)) + }}, + API: {Name: "api", Help: "接口命令", Hand: func(m *ice.Message, arg ...string) { + for k, v := range ice.Info.Route { + m.Push(nfs.PATH, k) + m.Push(nfs.FILE, v) + } + m.Sort(nfs.PATH).StatusTimeCount() + }}, + CLI: {Name: "cli", Help: "文件模块", Hand: func(m *ice.Message, arg ...string) { + for k, v := range ice.Info.File { + m.Push(nfs.FILE, k) + m.Push(mdb.NAME, v) + } + m.Sort(nfs.FILE).StatusTimeCount() + }}, + CMD: {Name: "cmd", Help: "模块命令", Hand: func(m *ice.Message, arg ...string) { + m.OptionFields(ctx.INDEX, mdb.NAME, mdb.HELP) + m.Cmdy(ctx.COMMAND, mdb.SEARCH, ctx.COMMAND).StatusTimeCount() + }}, + ENV: {Name: "env", Help: "环境变量", Hand: func(m *ice.Message, arg ...string) { for _, v := range os.Environ() { ls := strings.SplitN(v, "=", 2) m.Push(mdb.NAME, ls[0]) @@ -207,22 +239,6 @@ func init() { } m.StatusTimeCount() }}, - "file": {Name: "file", Help: "模块文件", Hand: func(m *ice.Message, arg ...string) { - for k, v := range ice.Info.File { - m.Push(nfs.FILE, k) - m.Push(mdb.NAME, v) - } - m.Sort(nfs.FILE) - m.StatusTimeCount() - }}, - "route": {Name: "route", Help: "接口命令", Hand: func(m *ice.Message, arg ...string) { - for k, v := range ice.Info.Route { - m.Push(nfs.PATH, k) - m.Push(nfs.FILE, v) - } - m.Sort(nfs.PATH) - m.StatusTimeCount() - }}, MAKE_DOMAIN: {Name: "make.domain", Help: "编译主机", Hand: func(m *ice.Message, arg ...string) { if os.Getenv(CTX_DEV) == "" || os.Getenv(CTX_POD) == "" { m.Echo(m.Conf(RUNTIME, MAKE_DOMAIN)) @@ -234,8 +250,7 @@ func init() { if len(arg) > 0 && arg[0] == BOOTINFO { arg = arg[1:] } - m.Cmdy(ctx.CONFIG, RUNTIME, arg) - m.DisplayStoryJSON() + m.Cmdy(ctx.CONFIG, RUNTIME, arg).DisplayStoryJSON() }}, - }}) + }) } diff --git a/base/cli/system.go b/base/cli/system.go index a2ac4cd8..1addc0c8 100644 --- a/base/cli/system.go +++ b/base/cli/system.go @@ -12,43 +12,38 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/file" ) func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd { - // 定制目录 if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 { if file := _system_find(m, arg[0], strings.Split(text, ice.NL)...); file != "" { - m.Debug("cmd: %v", file) - arg[0] = file + m.Log_SELECT("etc path cmd", file) + arg[0] = file // 配置目录 } } - // 环境变量 env := kit.Simple(m.Optionv(CMD_ENV)) for i := 0; i < len(env)-1; i += 2 { if env[i] == PATH { if file := _system_find(m, arg[0], strings.Split(env[i+1], ice.DF)...); file != "" { - m.Debug("cmd: %v", file) - arg[0] = file + m.Log_SELECT("env path cmd", file) + arg[0] = file // 环境变量 } } } - // 自动安装 if _system_find(m, arg[0]) == "" { - if cmds := m.Cmd(MIRRORS, arg[0]).Append("cmd"); cmds != "" { - m.Cmd(kit.Split(cmds)) - if file := _system_find(m, arg[0]); file != "" { - m.Debug("cmd: %v", file) - arg[0] = file - } + m.Cmd(MIRRORS, CMD, arg[0]) + if file := _system_find(m, arg[0]); file != "" { + m.Log_SELECT("mirrors cmd", file) + arg[0] = file // 软件镜像 } } - cmd := exec.Command(arg[0], arg[1:]...) // 运行目录 if cmd.Dir = m.Option(CMD_DIR); len(cmd.Dir) > 0 { if m.Log_EXPORT(CMD_DIR, cmd.Dir); !kit.FileExists(cmd.Dir) { - nfs.MkdirAll(m, cmd.Dir) + file.MkdirAll(cmd.Dir, ice.MOD_DIR) } } // 环境变量 @@ -61,13 +56,11 @@ func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd { return cmd } func _system_out(m *ice.Message, out string) io.Writer { - defer func() { m.Warn(recover(), "output", out) }() - if w, ok := m.Optionv(out).(io.Writer); ok { return w } else if m.Option(out) == "" { return nil - } else if f, p, e := kit.Create(m.Option(out)); m.Assert(e) { + } else if f, p, e := file.CreateFile(m.Option(out)); m.Assert(e) { m.Log_EXPORT(out, p) m.Optionv(out, f) return f @@ -95,20 +88,18 @@ func _system_find(m *ice.Message, bin string, dir ...string) string { return "" } func _system_exec(m *ice.Message, cmd *exec.Cmd) { - // 输入流 if r, ok := m.Optionv(CMD_INPUT).(io.Reader); ok { - cmd.Stdin = r + cmd.Stdin = r // 输入流 } - - // 输出流 if w := _system_out(m, CMD_OUTPUT); w != nil { - cmd.Stdout, cmd.Stderr = w, w + cmd.Stdout, cmd.Stderr = w, w // 输出流 if w := _system_out(m, CMD_ERRPUT); w != nil { cmd.Stderr = w } } else { out := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS)) err := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS)) + cmd.Stdout, cmd.Stderr = out, err defer func() { m.Push(CMD_OUT, out.String()) m.Push(CMD_ERR, err.String()) @@ -116,7 +107,6 @@ func _system_exec(m *ice.Message, cmd *exec.Cmd) { m.SetAppend() } }() - cmd.Stdout, cmd.Stderr = out, err } // 执行命令 @@ -126,16 +116,6 @@ func _system_exec(m *ice.Message, cmd *exec.Cmd) { m.Push(mdb.TIME, m.Time()).Push(CODE, int(cmd.ProcessState.ExitCode())) } -func IsSuccess(m *ice.Message) bool { - return m.Append(CODE) == "0" || m.Append(CODE) == "" -} -func SystemFind(m *ice.Message, bin string, dir ...string) string { - if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 { - dir = append(dir, strings.Split(text, ice.NL)...) - } - dir = append(dir, strings.Split(kit.Env(PATH), ice.DF)...) - return _system_find(m, bin, dir...) -} const ( CMD_DIR = "cmd_dir" @@ -145,16 +125,14 @@ const ( CMD_OUTPUT = "cmd_output" CMD_ERRPUT = "cmd_errput" - CMD_OUT = "cmd_out" CMD_ERR = "cmd_err" + CMD_OUT = "cmd_out" ) const SYSTEM = "system" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SYSTEM: {Name: SYSTEM, Help: "系统命令", Value: kit.Data(mdb.FIELD, "time,id,cmd")}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SYSTEM: {Name: "system cmd run", Help: "系统命令", Actions: ice.Actions{ nfs.FIND: {Name: "find", Help: "查找", Hand: func(m *ice.Message, arg ...string) { m.Echo(_system_find(m, arg[0], arg[1:]...)) @@ -168,37 +146,28 @@ func init() { m.Cmdy(nfs.CAT, ice.ETC_PATH) }}, }, Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 { - mdb.ListSelect(m, arg...) - return - } - // m.Grow(SYSTEM, "", kit.Dict(mdb.TIME, m.Time(), ice.CMD, kit.Join(arg, ice.SP))) - if len(arg) == 1 { arg = kit.Split(arg[0]) } - if kit.Ext(arg[0]) == nfs.SH && arg[0] != nfs.SH && kit.FileExists(path.Join(ice.SRC, arg[0])) { - arg = []string{nfs.SH, path.Join(ice.SRC, arg[0])} - } _system_exec(m, _system_cmd(m, arg...)) }}, - }}) + }) } -type buffer struct { - m *ice.Message - n string -} - -func (b *buffer) Write(buf []byte) (int, error) { - if b.m.IsCliUA() { - print(string(buf)) - } else { - b.m.PushNoticeGrow(string(buf)) - } - return len(buf), nil -} -func (b *buffer) Close() error { return nil } func PushStream(m *ice.Message) { - m.Option(CMD_OUTPUT, &buffer{m: m, n: m.Option(ice.MSG_DAEMON)}) + m.Option(CMD_OUTPUT, file.NewWriteCloser(func(buf []byte) (int, error) { + m.PushNoticeGrow(string(buf)) + return len(buf), nil + }, func() error { m.PushNoticeToast("done"); return nil })) +} + +func IsSuccess(m *ice.Message) bool { + return m.Append(CODE) == "0" || m.Append(CODE) == "" +} +func SystemFind(m *ice.Message, bin string, dir ...string) string { + if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 { + dir = append(dir, strings.Split(text, ice.NL)...) + } + dir = append(dir, strings.Split(kit.Env(PATH), ice.DF)...) + return _system_find(m, bin, dir...) } diff --git a/base/ctx/command.go b/base/ctx/command.go index 9efdb3d3..99756fa9 100644 --- a/base/ctx/command.go +++ b/base/ctx/command.go @@ -12,7 +12,7 @@ import ( ) func _command_list(m *ice.Message, name string) { - if kit.FileExists(path.Join(ice.SRC, name)) { + if nfs.ExistsFile(m, path.Join(ice.SRC, name)) { switch kit.Ext(name) { case nfs.JS: m.Push(DISPLAY, ice.FileURI(name)) @@ -22,8 +22,8 @@ func _command_list(m *ice.Message, name string) { name = ice.GetFileCmd(name) default: - if file, msg := name, m.Cmd(mdb.RENDER, kit.Ext(name)); msg.Length() > 0 { - m.Push(ARGS, kit.Format(kit.List(file))) + if msg := m.Cmd(mdb.RENDER, kit.Ext(name)); msg.Length() > 0 { + m.Push(ARGS, kit.Format(kit.List(name))) name = kit.Keys(msg.Append(mdb.TEXT), msg.Append(mdb.NAME)) } } @@ -68,10 +68,45 @@ func _command_search(m *ice.Message, kind, name, text string) { kit.SimpleKV("", s.Cap(ice.CTX_FOLLOW), cmd.Name, cmd.Help), CONTEXT, s.Cap(ice.CTX_FOLLOW), COMMAND, key, INDEX, kit.Keys(s.Cap(ice.CTX_FOLLOW), key), + mdb.HELP, cmd.Help, ) }) } +const ( + INDEX = "index" + ARGS = "args" + STYLE = "style" + DISPLAY = "display" + ACTION = "action" + + CAN_PLUGIN = "can.plugin" +) +const COMMAND = "command" + +func init() { + Index.MergeCommands(ice.Commands{ + COMMAND: {Name: "command key auto", Help: "命令", Actions: ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, m.Prefix(COMMAND)) + m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, COMMAND) + }}, + mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { + if arg[0] == m.CommandKey() || len(arg) > 1 && arg[1] != "" { + _command_search(m, arg[0], kit.Select("", arg, 1), kit.Select("", arg, 2)) + } + }}, + }, Hand: func(m *ice.Message, arg ...string) { + if len(arg) == 0 { + arg = append(arg, "") + } + for _, key := range arg { + _command_list(m, key) + } + }}, + }) +} + func CmdAction(args ...ice.Any) ice.Actions { return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(args...), COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) { @@ -90,37 +125,3 @@ func CmdAction(args ...ice.Any) ice.Actions { }}, } } - -const ( - INDEX = "index" - ARGS = "args" - STYLE = "style" - DISPLAY = "display" - ACTION = "action" - - CAN_PLUGIN = "can.plugin" -) -const COMMAND = "command" - -func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ - COMMAND: {Name: "command key auto", Help: "命令", Actions: ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, m.Prefix(COMMAND)) - m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, COMMAND) - }}, - mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { - if arg[0] == m.CommandKey() || len(arg) > 1 && arg[1] != "" { - _command_search(m, arg[0], kit.Select("", arg, 1), kit.Select("", arg, 2)) - } - }}, - }, Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 { - arg = append(arg, "") - } - for _, key := range arg { - _command_list(m, key) - } - }}, - }}) -} diff --git a/base/ctx/config.go b/base/ctx/config.go index bf3d7868..5056b160 100644 --- a/base/ctx/config.go +++ b/base/ctx/config.go @@ -2,7 +2,6 @@ package ctx import ( "encoding/json" - "os" "path" "strings" @@ -10,23 +9,12 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/miss" ) -func _config_list(m *ice.Message) { - for k, v := range m.Source().Configs { - if k[0] == '/' || k[0] == '_' { - continue // 内部配置 - } - - m.Push(mdb.KEY, k) - m.Push(mdb.NAME, v.Name) - m.Push(mdb.VALUE, kit.Format(v.Value)) - } - m.Sort(mdb.KEY) -} func _config_save(m *ice.Message, name string, arg ...string) { - name = path.Join(m.Config(nfs.PATH), name) - if f, p, e := kit.Create(name); m.Assert(e) { + name = path.Join(ice.VAR_CONF, name) + if f, p, e := miss.CreateFile(name); m.Assert(e) { defer f.Close() msg := m.Spawn(m.Source()) @@ -39,16 +27,16 @@ func _config_save(m *ice.Message, name string, arg ...string) { // 保存配置 if s, e := json.MarshalIndent(data, "", " "); m.Assert(e) { - if n, e := f.Write(s); m.Assert(e) { - m.Log_EXPORT(CONFIG, name, nfs.FILE, p, nfs.SIZE, n) + if _, e := f.Write(s); m.Assert(e) { + // m.Log_EXPORT(CONFIG, name, nfs.FILE, p, nfs.SIZE, n) } } m.Echo(p) } } func _config_load(m *ice.Message, name string, arg ...string) { - name = path.Join(m.Config(nfs.PATH), name) - if f, e := os.Open(name); e == nil { + name = path.Join(ice.VAR_CONF, name) + if f, e := miss.OpenFile(name); e == nil { defer f.Close() msg := m.Spawn(m.Source()) @@ -58,7 +46,7 @@ func _config_load(m *ice.Message, name string, arg ...string) { // 加载配置 for k, v := range data { msg.Search(k, func(p *ice.Context, s *ice.Context, key string) { - m.Log_IMPORT(CONFIG, kit.Keys(s.Name, key), nfs.FILE, name) + // m.Log_IMPORT(CONFIG, kit.Keys(s.Name, key), nfs.FILE, name) if s.Configs[key] == nil { s.Configs[key] = &ice.Config{} } @@ -83,11 +71,17 @@ func _config_make(m *ice.Message, key string, arg ...string) { m.Echo(kit.Formats(msg.Confv(key))) } } -func _config_rich(m *ice.Message, key string, sub string, arg ...string) { - m.Rich(key, sub, kit.Data(arg)) -} -func _config_grow(m *ice.Message, key string, sub string, arg ...string) { - m.Grow(key, sub, kit.Dict(arg)) +func _config_list(m *ice.Message) { + for k, v := range m.Source().Configs { + if k[0] == '/' || k[0] == '_' { + continue // 内部配置 + } + + m.Push(mdb.KEY, k) + m.Push(mdb.NAME, v.Name) + m.Push(mdb.VALUE, kit.Format(v.Value)) + } + m.Sort(mdb.KEY) } const ( @@ -99,9 +93,7 @@ const ( const CONFIG = "config" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - CONFIG: {Name: CONFIG, Help: "配置", Value: kit.Data(nfs.PATH, ice.VAR_CONF)}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ CONFIG: {Name: "config key auto reset", Help: "配置", Actions: ice.Actions{ SAVE: {Name: "save", Help: "保存", Hand: func(m *ice.Message, arg ...string) { _config_save(m, arg[0], arg[1:]...) @@ -110,10 +102,10 @@ func init() { _config_load(m, arg[0], arg[1:]...) }}, RICH: {Name: "rich", Help: "富有", Hand: func(m *ice.Message, arg ...string) { - _config_rich(m, arg[0], arg[1], arg[2:]...) + m.Cmdy(mdb.INSERT, arg[0], arg[1], mdb.HASH, arg[2:]) }}, GROW: {Name: "grow", Help: "成长", Hand: func(m *ice.Message, arg ...string) { - _config_grow(m, arg[0], arg[1], arg[2:]...) + m.Cmdy(mdb.INSERT, arg[0], arg[1], mdb.LIST, arg[2:]) }}, "list": {Name: "list", Help: "列表", Hand: func(m *ice.Message, arg ...string) { list := []ice.Any{} @@ -134,5 +126,5 @@ func init() { _config_make(m, arg[0], arg[1:]...) m.DisplayStoryJSON() }}, - }}) + }) } diff --git a/base/ctx/context.go b/base/ctx/context.go index e5345ebb..c7494222 100644 --- a/base/ctx/context.go +++ b/base/ctx/context.go @@ -5,6 +5,7 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" ) @@ -19,35 +20,20 @@ func _context_list(m *ice.Message, sub *ice.Context, name string) { m.Push(mdb.HELP, s.Help) }) } -func Inputs(m *ice.Message, field string) bool { - switch strings.TrimPrefix(field, "extra.") { - case ice.POD: - m.Cmdy("route") - case ice.CTX: - m.Cmdy(CONTEXT) - case ice.CMD: - m.Cmdy(CONTEXT, kit.Select(m.Option(ice.CTX), m.Option(kit.Keys(mdb.EXTRA, ice.CTX))), COMMAND) - case ice.ARG: - - default: - return false - } - return true -} const CONTEXT = "context" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ CONTEXT: {Name: "context name=web action=context,command,config key auto spide", Help: "模块", Actions: ice.MergeAction(ice.Actions{ "spide": {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 || arg[1] == CONTEXT { // 模块列表 m.Cmdy(CONTEXT, kit.Select(ice.ICE, arg, 0), CONTEXT) - m.Display("/plugin/story/spide.js?prefix=spide", "root", kit.Select(ice.ICE, arg, 0), "split", ice.PT) + m.DisplayStorySpide("prefix", m.ActionKey(), nfs.ROOT, kit.Select(ice.ICE, arg, 0), "split", ice.PT) } else if index := kit.Keys(arg[1]); strings.HasSuffix(index, arg[2]) { // 命令列表 m.Cmdy(CONTEXT, index, COMMAND).Tables(func(value ice.Maps) { - m.Push("file", arg[1]) + m.Push(nfs.FILE, arg[1]) }) } else { // 命令详情 @@ -72,5 +58,20 @@ func init() { } }) }}, - }}) + }) +} +func Inputs(m *ice.Message, field string) bool { + switch strings.TrimPrefix(field, "extra.") { + case ice.POD: + m.Cmdy("route") + case ice.CTX: + m.Cmdy(CONTEXT) + case ice.CMD: + m.Cmdy(CONTEXT, kit.Select(m.Option(ice.CTX), m.Option(kit.Keys(mdb.EXTRA, ice.CTX))), COMMAND) + case ice.ARG: + + default: + return false + } + return true } diff --git a/base/ctx/message.go b/base/ctx/message.go index ef312d9b..7c70aa48 100644 --- a/base/ctx/message.go +++ b/base/ctx/message.go @@ -12,7 +12,7 @@ import ( const MESSAGE = "message" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ MESSAGE: {Name: "message", Help: "消息", Hand: func(m *ice.Message, arg ...string) { t := reflect.TypeOf(m) for i := 0; i < t.NumMethod(); i++ { @@ -22,5 +22,5 @@ func init() { m.Push(mdb.TEXT, strings.Split(p, ice.ICEBERGS+"/")[1]) } }}, - }}) + }) } diff --git a/base/gdb/event.go b/base/gdb/event.go index cda2a7f5..2501dba6 100644 --- a/base/gdb/event.go +++ b/base/gdb/event.go @@ -6,33 +6,19 @@ import ( kit "shylinux.com/x/toolkits" ) -func _event_listen(m *ice.Message, event string, cmd string) { - m.Cmdy(mdb.INSERT, EVENT, "", mdb.HASH, EVENT, event) - m.Cmdy(mdb.INSERT, EVENT, "", mdb.ZONE, event, ice.CMD, cmd) -} -func _event_action(m *ice.Message, event string, arg ...string) { - mdb.ZoneSelect(m, event).Tables(func(value ice.Maps) { - m.Cmd(kit.Split(value[ice.CMD]), event, arg).Cost(EVENT, event, ice.ARG, arg) - }) -} - const EVENT = "event" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - EVENT: {Name: EVENT, Help: "事件流", Value: kit.Data(mdb.SHORT, EVENT, mdb.FIELD, "time,id,cmd")}, - }, Commands: ice.Commands{ - EVENT: {Name: "event event id auto listen", Help: "事件流", Actions: ice.MergeAction(ice.Actions{ + Index.MergeCommands(ice.Commands{ + EVENT: {Name: "event event id auto listen happen", Help: "事件流", Actions: ice.MergeAction(ice.Actions{ LISTEN: {Name: "listen event cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) { - _event_listen(m, m.Option(EVENT), m.Option(ice.CMD)) + mdb.ZoneInsert(m, m.OptionSimple(EVENT, ice.CMD)) }}, HAPPEN: {Name: "happen event arg", Help: "触发", Hand: func(m *ice.Message, arg ...string) { - _event_action(m, m.Option(EVENT), arg[2:]...) + mdb.ZoneSelect(m, m.Option(EVENT)).Tables(func(value ice.Maps) { + m.Cmd(kit.Split(value[ice.CMD]), m.Option(EVENT), arg[2:]).Cost() + }) }}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { - if mdb.ZoneSelect(m, arg...); len(arg) == 0 { - m.PushAction(HAPPEN, mdb.REMOVE) - } - }}, - }}) + }, mdb.ZoneAction(mdb.SHORT, EVENT, mdb.FIELD, "time,id,cmd"))}, + }) } diff --git a/base/gdb/gdb.go b/base/gdb/gdb.go index 899037d3..0a4927b9 100644 --- a/base/gdb/gdb.go +++ b/base/gdb/gdb.go @@ -2,6 +2,7 @@ package gdb import ( "os" + "strings" "time" ice "shylinux.com/x/icebergs" @@ -10,48 +11,56 @@ import ( type Frame struct { s chan os.Signal - t time.Duration - e chan bool } func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { return &Frame{} } func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { + list := []string{} + for k := range ice.Info.File { + if strings.HasPrefix(k, ice.Info.Make.Path+ice.PS) { + list = append(list, k) + } + } + for _, k := range list { + ice.Info.File["/require/"+strings.TrimPrefix(k, ice.Info.Make.Path+ice.PS)] = ice.Info.File[k] + delete(ice.Info.File, k) + } + f.s = make(chan os.Signal, ice.MOD_CHAN) - f.e = make(chan bool, 1) return f } func (f *Frame) Start(m *ice.Message, arg ...string) bool { - f.t = kit.Duration(m.Conf(TIMER, kit.Keym(TICK))) + t := kit.Duration(m.Conf(TIMER, kit.Keym(TICK))) + enable := m.Conf(TIMER, kit.Keym("enable")) == ice.TRUE + for { select { - case <-f.e: - return true + case <-time.Tick(t): + if enable { + m.Cmd(TIMER, HAPPEN) + } - // case <-time.Tick(f.t): - // // m.Cmd(TIMER, ACTION) - - case s := <-f.s: + case s, ok := <-f.s: + if !ok { + return true + } m.Cmd(SIGNAL, HAPPEN, SIGNAL, s) } } return true } func (f *Frame) Close(m *ice.Message, arg ...string) bool { - f.e <- true + close(f.s) return true } const GDB = "gdb" var Index = &ice.Context{Name: GDB, Help: "事件模块", Commands: ice.Commands{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Load(TIMER) - }}, - ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { - m.Save(TIMER) - }}, + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Load(TIMER, ROUTINE) }}, + ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { m.Save(TIMER, ROUTINE) }}, }} -func init() { ice.Index.Register(Index, &Frame{}, ROUTINE, SIGNAL, EVENT, TIMER) } +func init() { ice.Index.Register(Index, &Frame{}, SIGNAL, TIMER, EVENT, ROUTINE) } diff --git a/base/gdb/routine.go b/base/gdb/routine.go index af0acd44..45deafbc 100644 --- a/base/gdb/routine.go +++ b/base/gdb/routine.go @@ -4,31 +4,43 @@ import ( "path" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) const ROUTINE = "routine" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - ROUTINE: {Name: ROUTINE, Help: "协程池", Value: kit.Data(mdb.SHORT, "time,hash,status,fileline")}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ ROUTINE: {Name: "routine hash auto prunes", Help: "协程池", Actions: ice.MergeAction(ice.Actions{ - mdb.CREATE: {Name: "create fileline status", Help: "创建"}, - mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { - m.OptionFields(m.Config(mdb.SHORT)) - m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, cli.STATUS, cli.STOP) - m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, cli.STATUS, cli.ERROR) + mdb.CREATE: {Name: "create name", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + m.Go(func() { + cb := m.OptionCB(ROUTINE) + h := mdb.HashCreate(m, m.OptionSimple(mdb.NAME), mdb.STATUS, START, ice.CMD, logs.FileLine(cb, 100)).Result() + defer func() { + if e := recover(); e == nil { + mdb.HashModify(m, mdb.HASH, h, mdb.STATUS, STOP) + } else { + mdb.HashModify(m, mdb.HASH, h, mdb.STATUS, ERROR, ERROR, e) + } + }() + switch cb := cb.(type) { + case []string: + m.Cmd(kit.Split(kit.Join(cb))) + case string: + m.Cmd(kit.Split(cb)) + case func(): + cb() + default: + m.ErrorNotImplement(cb) + } + }) }}, "inner": {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) { - ls := kit.Split(m.Option("fileline"), ":") + ls := kit.Split(m.Option(ice.CMD), ":") m.ProcessCommand("inner", []string{path.Dir(ls[0]), path.Base(ls[0]), ls[1]}, arg...) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelect(m, arg...) - m.PushAction("inner", mdb.REMOVE) - }}, - }}) + }, mdb.HashActionStatus(mdb.FIELD, "time,hash,name,status,cmd", mdb.ACTION, "inner"))}, + }) } diff --git a/base/gdb/signal.go b/base/gdb/signal.go index 829f58ef..40fd4493 100644 --- a/base/gdb/signal.go +++ b/base/gdb/signal.go @@ -1,23 +1,22 @@ package gdb import ( + "fmt" "os" "os/signal" - "path" "syscall" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" - log "shylinux.com/x/toolkits/logs" + "shylinux.com/x/toolkits/logs" ) func _signal_listen(m *ice.Message, s int, arg ...string) { if f, ok := m.Target().Server().(*Frame); ok { - m.Cmdy(mdb.INSERT, SIGNAL, "", mdb.HASH, arg) signal.Notify(f.s, syscall.Signal(s)) + mdb.HashCreate(m, SIGNAL, s, arg) } } func _signal_action(m *ice.Message, arg ...string) { @@ -25,6 +24,65 @@ func _signal_action(m *ice.Message, arg ...string) { m.Cmdy(kit.Split(value[ice.CMD])) }) } +func _signal_process(m *ice.Message, p string, s os.Signal) { + if p == "" { + p = m.Cmdx(nfs.CAT, ice.Info.PidPath) + } + if p == "" { + p = kit.Format(os.Getpid()) + } + if p, e := os.FindProcess(kit.Int(p)); e == nil { + p.Signal(s) + } +} + +const ( + PID = "pid" +) +const ( + LISTEN = ice.LISTEN + HAPPEN = ice.HAPPEN + + START = ice.START + RESTART = ice.RESTART + STOP = ice.STOP + ERROR = ice.ERROR + KILL = "kill" +) +const SIGNAL = "signal" + +func init() { + Index.MergeCommands(ice.Commands{ + SIGNAL: {Name: "signal signal auto listen", Help: "信号器", Actions: ice.MergeAction(ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + _signal_listen(m, 2, mdb.NAME, "重启", ice.CMD, "exit 1") + _signal_listen(m, 3, mdb.NAME, "退出", ice.CMD, "exit 0") + if f, p, e := logs.CreateFile(ice.Info.PidPath); !m.Warn(e) { + defer f.Close() + fmt.Fprint(f, os.Getpid()) + m.Log_CREATE(nfs.FILE, p) + } + }}, + LISTEN: {Name: "listen signal name cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) { + _signal_listen(m, kit.Int(m.Option(SIGNAL)), arg...) + }}, + HAPPEN: {Name: "happen signal", Help: "触发", Hand: func(m *ice.Message, arg ...string) { + _signal_action(m, m.Option(SIGNAL)) + }}, + RESTART: {Name: "restart pid", Help: "触发", Hand: func(m *ice.Message, arg ...string) { + _signal_process(m, m.Option(PID), syscall.SIGINT) + }}, + STOP: {Name: "stop pid", Help: "触发", Hand: func(m *ice.Message, arg ...string) { + _signal_process(m, m.Option(PID), syscall.SIGQUIT) + }}, + KILL: {Name: "kill pid signal", Help: "触发", Hand: func(m *ice.Message, arg ...string) { + _signal_process(m, m.Option(PID), syscall.Signal(kit.Int(kit.Select("9", m.Option(SIGNAL))))) + }}, + }, mdb.HashAction(mdb.SHORT, SIGNAL, mdb.FIELD, "time,signal,name,cmd", mdb.ACTION, HAPPEN)), Hand: func(m *ice.Message, arg ...string) { + mdb.HashSelect(m, arg...).Sort(SIGNAL) + }}, + }) +} func SignalNotify(m *ice.Message, sig int, cb func()) { ch := make(chan os.Signal) @@ -37,39 +95,3 @@ func SignalNotify(m *ice.Message, sig int, cb func()) { } }) } - -const ( - LISTEN = ice.LISTEN - HAPPEN = ice.HAPPEN -) -const SIGNAL = "signal" - -func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SIGNAL: {Name: SIGNAL, Help: "信号器", Value: kit.Data( - mdb.SHORT, SIGNAL, mdb.FIELD, "time,signal,name,cmd", nfs.PATH, path.Join(ice.VAR_RUN, "ice.pid"), - )}, - }, Commands: ice.Commands{ - SIGNAL: {Name: "signal signal auto listen", Help: "信号器", Actions: ice.MergeAction(ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - if log.LogDisable { - return // 禁用日志 - } - m.Cmd(nfs.SAVE, kit.Select(m.Config(nfs.PATH), m.Conf(cli.RUNTIME, kit.Keys(cli.CONF, cli.CTX_PID))), - m.Conf(cli.RUNTIME, kit.Keys(cli.HOST, cli.PID))) - - m.Cmd(SIGNAL, LISTEN, SIGNAL, "3", mdb.NAME, "退出", ice.CMD, "exit 0") - m.Cmd(SIGNAL, LISTEN, SIGNAL, "2", mdb.NAME, "重启", ice.CMD, "exit 1") - }}, - LISTEN: {Name: "listen signal name cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) { - _signal_listen(m, kit.Int(m.Option(SIGNAL)), arg...) - }}, - HAPPEN: {Name: "happen signal", Help: "触发", Hand: func(m *ice.Message, arg ...string) { - _signal_action(m, m.Option(SIGNAL)) - }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelect(m, arg...).Sort(SIGNAL) - m.PushAction(HAPPEN, mdb.REMOVE) - }}, - }}) -} diff --git a/base/gdb/timer.go b/base/gdb/timer.go index 493d8d80..e2aa64ff 100644 --- a/base/gdb/timer.go +++ b/base/gdb/timer.go @@ -4,62 +4,43 @@ import ( "time" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" ) -func _timer_action(m *ice.Message, arg ...string) { - now := time.Now().UnixNano() - m.OptionFields(m.Config(mdb.FIELD)) - - m.Richs(TIMER, "", mdb.FOREACH, func(key string, value ice.Map) { - if value = kit.GetMeta(value); value[cli.STATUS] == cli.STOP { +func _timer_action(m *ice.Message, now time.Time, arg ...string) { + mdb.HashSelects(m).Tables(func(value ice.Maps) { + if value[mdb.COUNT] == "0" { return } - - order := kit.Int(value[ORDER]) - if n := kit.Time(kit.Format(value[NEXT])); now > n && order > 0 { - m.Logs(TIMER, mdb.KEY, key, ORDER, order) - - msg := m.Cmd(value[ice.CMD]) - m.Grow(TIMER, kit.Keys(mdb.HASH, key), kit.Dict(ice.RES, msg.Result())) - if value[ORDER] = kit.Format(order - 1); order > 1 { - value[NEXT] = msg.Time(value[INTERVAL]) - } + if kit.Time(value[mdb.TIME]) > kit.Int64(now) { + return } + m.Cmd(ROUTINE, mdb.CREATE, mdb.NAME, "some", kit.Keycb(ROUTINE), value[ice.CMD]) + mdb.HashModify(m, mdb.HASH, value[mdb.HASH], mdb.COUNT, kit.Int(value[mdb.COUNT])-1, mdb.TIME, m.Time(value[INTERVAL])) }) } const ( DELAY = "delay" INTERVAL = "interval" - ORDER = "order" - NEXT = "next" TICK = "tick" ) const TIMER = "timer" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - TIMER: {Name: TIMER, Help: "定时器", Value: kit.Data( - mdb.FIELD, "time,hash,delay,interval,order,next,cmd", TICK, "1s", - )}, - }, Commands: ice.Commands{ - TIMER: {Name: "timer hash id auto create action prunes", Help: "定时器", Actions: ice.MergeAction(ice.Actions{ - mdb.CREATE: {Name: "create delay=10ms interval=10s order=3 cmd=runtime", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.INSERT, TIMER, "", mdb.HASH, DELAY, "10ms", INTERVAL, "10m", ORDER, 1, NEXT, m.Time(m.Option(DELAY)), arg) - }}, + Index.MergeCommands(ice.Commands{ + TIMER: {Name: "timer hash auto create prunes", Help: "定时器", Actions: ice.MergeAction(ice.Actions{ + mdb.CREATE: {Name: "create name=hi delay=10ms interval=10s count=3 cmd=runtime", Help: "创建"}, mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { - m.OptionFields(m.Config(mdb.FIELD)) - m.Cmdy(mdb.PRUNES, TIMER, "", mdb.HASH, ORDER, 0) + mdb.HashPrunesValue(m, mdb.COUNT, "0") }}, HAPPEN: {Name: "happen", Help: "执行", Hand: func(m *ice.Message, arg ...string) { - _timer_action(m, arg...) + _timer_action(m, time.Now(), arg...) }}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { - m.Fields(len(arg), m.Config(mdb.FIELD), "time,id,res") - mdb.ZoneSelect(m, arg...) - }}, - }}) + RESTART: {Name: "restart count=3", Help: "重启", Hand: func(m *ice.Message, arg ...string) { + mdb.HashModify(m, m.OptionSimple(mdb.HashShort(m)), arg) + }}, + }, mdb.HashAction(mdb.FIELD, "time,hash,name,delay,interval,count,cmd", TICK, "10s"))}, + }) } diff --git a/base/lex/matrix.go b/base/lex/matrix.go index 7a66c443..3b81cb4b 100644 --- a/base/lex/matrix.go +++ b/base/lex/matrix.go @@ -385,9 +385,7 @@ const ( const MATRIX = "matrix" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - MATRIX: {Name: MATRIX, Help: "魔方矩阵", Value: kit.Data()}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ MATRIX: {Name: "matrix hash npage text auto", Help: "魔方矩阵", Actions: ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { // _lex_load(m.Load()) @@ -399,7 +397,7 @@ func init() { case func(string, *Matrix): cb(h, mat) default: - m.Error(true, ice.ErrNotImplement) + m.ErrorNotImplement(cb) } m.Echo(h) }}, @@ -538,5 +536,5 @@ func init() { m.Push("word", string(word)) }) }}, - }}) + }) } diff --git a/base/lex/regexp.go b/base/lex/regexp.go index 2fb1c441..983e24fb 100644 --- a/base/lex/regexp.go +++ b/base/lex/regexp.go @@ -1,3 +1,4 @@ package lex const REGEXP = "regexp" +const PREFIX = "prefix" diff --git a/base/lex/split.go b/base/lex/split.go index c24c6fbc..289d9c70 100644 --- a/base/lex/split.go +++ b/base/lex/split.go @@ -4,6 +4,7 @@ import ( "strings" ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" ) @@ -34,18 +35,17 @@ func _split_deep(stack []int, text string) ([]int, int) { func _split_list(m *ice.Message, file string, arg ...string) ice.Map { const DEEP = "_deep" stack, deep := []int{}, 0 - list := kit.List(kit.Data(DEEP, -1)) - line := "" + list, line := kit.List(kit.Data(DEEP, -1)), "" m.Cmd(nfs.CAT, file, func(text string) { - if strings.HasPrefix(strings.TrimSpace(text), "# ") { - return // 注释 - } if strings.TrimSpace(text) == "" { return // 空行 } if line += text; strings.Count(text, "`")%2 == 1 { return // 多行 } + if strings.HasPrefix(strings.TrimSpace(text), "# ") { + return // 注释 + } stack, deep = _split_deep(stack, text) data := kit.Data(DEEP, deep) @@ -61,8 +61,9 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map { ls = cb(ls, data) case func([]string): cb(ls) + case nil: default: - m.Error(true, ice.ErrNotImplement) + m.ErrorNotImplement(cb) } // 参数字段 @@ -80,7 +81,7 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map { // 查找节点 for i := len(list) - 1; i >= 0; i-- { if deep > kit.Int(kit.Value(list[i], kit.Keym(DEEP))) { - kit.Value(list[i], "list.-2", data) + kit.Value(list[i], kit.Keys(mdb.LIST, "-2"), data) list = append(list, data) break } @@ -90,9 +91,6 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map { }) return list[0].(ice.Map) } -func Split(m *ice.Message, arg ...string) ice.Map { - return kit.Value(_split_list(m, arg[0], arg[1:]...), "list.0").(ice.Map) -} const ( SPLIT_SPACE = "split.space" @@ -103,17 +101,17 @@ const ( const SPLIT = "split" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SPLIT: {Name: "split", Help: "解析", Value: kit.Data()}, - }, Commands: ice.Commands{ - SPLIT: {Name: "split path key auto", Help: "解析", Hand: func(m *ice.Message, arg ...string) { + Index.MergeCommands(ice.Commands{ + SPLIT: {Name: "split path key auto", Help: "分词", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) { m.Cmdy(nfs.DIR, arg) return } - - m.Echo(kit.Format(_split_list(m, arg[0], kit.Split(kit.Join(arg[1:]))...))) - m.DisplayStoryJSON() + m.Echo(kit.Format(_split_list(m, arg[0], kit.Split(kit.Join(arg[1:]))...))).DisplayStoryJSON() }}, - }}) + }) +} + +func Split(m *ice.Message, arg ...string) ice.Map { + return kit.Value(_split_list(m, arg[0], arg[1:]...), kit.Keys(mdb.LIST, "0")).(ice.Map) } diff --git a/base/log/log.go b/base/log/log.go index d2f9cc68..68fa68f6 100644 --- a/base/log/log.go +++ b/base/log/log.go @@ -2,6 +2,7 @@ package log import ( "bufio" + "os" "path" "strings" @@ -9,7 +10,7 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" - log "shylinux.com/x/toolkits/logs" + "shylinux.com/x/toolkits/logs" ) type Log struct { @@ -25,6 +26,13 @@ func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server return &Frame{} } func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { + switch strings.Split(os.Getenv("TERM"), "-")[0] { + case "xterm", "screen": + ice.Info.Colors = true + default: + ice.Info.Colors = false + } + f.p = make(chan *Log, ice.MOD_BUFS) ice.Info.Log = func(msg *ice.Message, p, l, s string) { f.p <- &Log{m: msg, p: p, l: l, s: s} @@ -36,7 +44,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { select { case l, ok := <-f.p: if !ok { - break + return true } file := kit.Select(BENCH, m.Conf(SHOW, kit.Keys(l.l, FILE))) @@ -124,9 +132,6 @@ var Index = &ice.Context{Name: "log", Help: "日志模块", Configs: ice.Configs SHOW: {Name: SHOW, Help: "日志分流", Value: kit.Dict()}, }, Commands: ice.Commands{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - if log.LogDisable { - return // 禁用日志 - } if !strings.Contains(ice.Getenv("ctx_daemon"), "log") { return // 没有日志 } @@ -140,7 +145,7 @@ var Index = &ice.Context{Name: "log", Help: "日志模块", Configs: ice.Configs m.Conf(SHOW, kit.Keys(k, FILE), key) }) // 日志文件 - if f, p, e := kit.Create(kit.Format(value[nfs.PATH])); m.Assert(e) { + if f, p, e := logs.CreateFile(kit.Format(value[nfs.PATH])); m.Assert(e) { m.Cap(ice.CTX_STREAM, path.Base(p)) value[FILE] = bufio.NewWriter(f) m.Log_CREATE(nfs.FILE, p) diff --git a/base/mdb/engine.go b/base/mdb/engine.go index 722cf75c..a55f50dc 100644 --- a/base/mdb/engine.go +++ b/base/mdb/engine.go @@ -2,31 +2,10 @@ package mdb import ( ice "shylinux.com/x/icebergs" - kit "shylinux.com/x/toolkits" ) const ENGINE = "engine" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - ENGINE: {Name: ENGINE, Help: "引擎", Value: kit.Data(SHORT, TYPE, FIELD, "time,type,name,text")}, - }, Commands: ice.Commands{ - ENGINE: {Name: "engine type name text auto", Help: "引擎", Actions: ice.MergeAction(ice.Actions{ - CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) { - m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME))) - m.Option(TYPE, kit.Ext(m.Option(TYPE))) - m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text")) - }}, - }, HashAction()), Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 1 { - m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg, func(value ice.Map) { - m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), arg[0], arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3)) - }) - return - } - if HashSelect(m, arg...); len(arg) == 0 { - m.Sort(TYPE) - } - }}, - }}) + Index.MergeCommands(ice.Commands{ENGINE: {Name: "engine type name text auto", Help: "引擎", Actions: RenderAction()}}) } diff --git a/base/mdb/hash.go b/base/mdb/hash.go index 4ce26d1f..36bd0419 100644 --- a/base/mdb/hash.go +++ b/base/mdb/hash.go @@ -2,27 +2,34 @@ package mdb import ( "encoding/json" - "os" "path" - "strings" ice "shylinux.com/x/icebergs" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/miss" ) func _hash_fields(m *ice.Message) []string { - return kit.Split(kit.Select("time,hash,type,name,text", m.OptionFields())) + return kit.Split(kit.Select(HASH_FIELD, m.OptionFields())) +} +func _hash_select_fields(m *ice.Message, prefix, chain string, key string, field string) (value string) { + defer m.RLock(prefix, chain)() + m.Richs(prefix, chain, key, func(h string, v Map) { + if field == HASH { + value = h + } else { + value = kit.Format(v[field]) + } + }) + return } func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) { defer m.RLock(prefix, chain)() list := map[string]int{} - m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) { - if val = kit.GetMeta(val); kit.Format(val[COUNT]) != "" { - list[kit.Format(val[field])] = kit.Int(val[COUNT]) - } else { - list[kit.Format(val[field])]++ - } + m.Richs(prefix, chain, FOREACH, func(val Map) { + val = kit.GetMeta(val) + list[kit.Format(val[field])] += kit.Int(kit.Select("1", val[COUNT])) }) for k, i := range list { m.Push(field, k) @@ -30,18 +37,30 @@ func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) { } m.SortIntR(COUNT) } -func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) { +func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) string { defer m.Lock(prefix, chain)() - if m.Option(ice.MSG_DOMAIN) != "" { - m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT)), m.Conf(prefix, kit.Keym(SHORT))) + if value := m.Confm(prefix, kit.Keys(HASH, arg[1])); value != nil { + value = kit.GetMeta(value) + for i := 2; i < len(arg)-1; i += 2 { + kit.Value(value, arg[i], arg[i+1]) + } + return arg[1] } + m.Log_INSERT(KEY, path.Join(prefix, chain), arg[0], arg[1]) if expire := m.Conf(prefix, kit.Keys(chain, kit.Keym(EXPIRE))); expire != "" { arg = kit.Simple(TIME, m.Time(expire), arg) } - - m.Echo(m.Rich(prefix, chain, kit.Data(arg))) + if m.Option(ice.MSG_DOMAIN) != "" { + m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT)), m.Conf(prefix, kit.Keym(SHORT))) + } + if m.Optionv(TARGET) != nil { + m.Echo(m.Rich(prefix, chain, kit.Data(arg, TARGET, m.Optionv(TARGET)))) + } else { + m.Echo(m.Rich(prefix, chain, kit.Data(arg))) + } + return m.Result() } func _hash_delete(m *ice.Message, prefix, chain, field, value string) { defer m.Lock(prefix, chain)() @@ -49,7 +68,7 @@ func _hash_delete(m *ice.Message, prefix, chain, field, value string) { if field != HASH { field, value = HASH, kit.Select(kit.Hashs(value), m.Option(HASH)) } - m.Richs(prefix, chain, value, func(key string, val ice.Map) { + m.Richs(prefix, chain, value, func(key string, val Map) { m.Log_DELETE(KEY, path.Join(prefix, chain), field, value, VALUE, kit.Format(val)) m.Conf(prefix, kit.Keys(chain, HASH, key), "") }) @@ -57,15 +76,9 @@ func _hash_delete(m *ice.Message, prefix, chain, field, value string) { func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) { defer m.Lock(prefix, chain)() - m.Richs(prefix, chain, value, func(key string, val ice.Map) { - val = kit.GetMeta(val) + m.Richs(prefix, chain, value, func(key string, val Map) { m.Log_MODIFY(KEY, path.Join(prefix, chain), field, value, arg) - for i := 0; i < len(arg); i += 2 { - if arg[i] == field { - continue - } - kit.Value(val, arg[i], kit.Select("", arg, i+1)) - } + _mdb_modify(m, val, field, arg...) }) } func _hash_select(m *ice.Message, prefix, chain, field, value string) { @@ -75,19 +88,8 @@ func _hash_select(m *ice.Message, prefix, chain, field, value string) { value = RANDOMS } fields := _hash_fields(m) - m.Richs(prefix, chain, value, func(key string, val ice.Map) { - switch val = kit.GetMeta(val); cb := m.OptionCB(SELECT).(type) { - case func(fields []string, value ice.Map): - cb(fields, val) - case func(value ice.Map): - cb(val) - default: - if m.OptionFields() == DETAIL { - m.Push(DETAIL, val) - } else { - m.Push(key, val, fields) - } - } + m.Richs(prefix, chain, value, func(key string, value Map) { + _mdb_select(m, key, value, fields, nil) }) if !m.FieldsIsDetail() { m.SortTimeR(TIME) @@ -97,9 +99,9 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) { defer m.RLock(prefix, chain)() fields := _hash_fields(m) - m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) { + m.Richs(prefix, chain, FOREACH, func(key string, val Map) { switch val = kit.GetMeta(val); cb := m.OptionCB(PRUNES).(type) { - case func(string, ice.Map) bool: + case func(string, Map) bool: if !cb(key, val) { return } @@ -116,7 +118,7 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) { func _hash_export(m *ice.Message, prefix, chain, file string) { defer m.Lock(prefix, chain)() - f, p, e := kit.Create(kit.Keys(file, JSON)) + f, p, e := miss.CreateFile(kit.Keys(file, JSON)) m.Assert(e) defer f.Close() @@ -131,13 +133,11 @@ func _hash_export(m *ice.Message, prefix, chain, file string) { func _hash_import(m *ice.Message, prefix, chain, file string) { defer m.Lock(prefix, chain)() - f, e := os.Open(kit.Keys(file, JSON)) - if m.Warn(e) { - return - } + f, e := miss.OpenFile(kit.Keys(file, JSON)) + m.Assert(e) defer f.Close() - list := ice.Map{} + list := Map{} m.Assert(json.NewDecoder(f).Decode(&list)) count := 0 @@ -157,41 +157,12 @@ func _hash_import(m *ice.Message, prefix, chain, file string) { m.Echo("%d", count) } +const ( + HASH_FIELD = "time,hash,type,name,text" +) const HASH = "hash" -func AutoConfig(args ...ice.Any) *ice.Action { - return &ice.Action{Hand: func(m *ice.Message, arg ...string) { - if cs := m.Target().Configs; cs[m.CommandKey()] == nil && len(args) > 0 { - cs[m.CommandKey()] = &ice.Config{Value: kit.Data(args...)} - m.Load(m.CommandKey()) - } - - inputs := []ice.Any{} - kit.Fetch(kit.Split(m.Config(FIELD)), func(i int, k string) { - switch k { - case TIME, HASH, ID: - return - } - inputs = append(inputs, k) - }) - - cs := m.Target().Commands - if cs[m.CommandKey()] == nil { - return - } - - if cs[m.CommandKey()].Actions[INSERT] != nil { - if cs[m.CommandKey()].Meta[INSERT] == nil { - m.Design(INSERT, "添加", append([]ice.Any{ZONE}, inputs...)...) - } - } else if cs[m.CommandKey()].Actions[CREATE] != nil { - if cs[m.CommandKey()].Meta[CREATE] == nil { - m.Design(CREATE, "创建", inputs...) - } - } - }} -} -func HashAction(args ...ice.Any) ice.Actions { +func HashAction(args ...Any) ice.Actions { return ice.Actions{ice.CTX_INIT: AutoConfig(args...), INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { HashInputs(m, arg) }}, CREATE: {Name: "create", Help: "创建", Hand: func(m *ice.Message, arg ...string) { HashCreate(m, arg) }}, @@ -203,93 +174,149 @@ func HashAction(args ...ice.Any) ice.Actions { IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { HashImport(m, arg) }}, } } -func HashActionStatus(args ...ice.Any) ice.Actions { +func HashActionStatus(args ...Any) ice.Actions { list := HashAction(args...) list[PRUNES] = &ice.Action{Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { m.OptionFields(m.Config(FIELD)) - m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, "error") - m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, "close") + m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.ERROR) + m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.CLOSE) + m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.STOP) + m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, ice.END) + m.Tables(func(value ice.Maps) { HashRemove(m, HASH, value[HASH]) }) }} return list } -func HashInputs(m *ice.Message, arg ...ice.Any) *ice.Message { - return m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, kit.Simple(arg...)) +func HashShort(m *ice.Message) string { + return kit.Select(HASH, m.Config(SHORT), m.Config(SHORT) != UNIQ) } -func HashCreate(m *ice.Message, arg ...ice.Any) *ice.Message { - field := m.Config(FIELD) - args := kit.Simple(arg...) - for i := 0; i < len(args); i += 2 { - if !strings.Contains(field, args[i]) { - args[i] = kit.Keys("extra", args[i]) - } - } - return m.Cmdy(INSERT, m.PrefixKey(), "", HASH, args) +func HashField(m *ice.Message) string { return kit.Select(HASH_FIELD, m.Config(FIELD)) } +func HashArgs(m *ice.Message, arg ...Any) []string { + return _mdb_args(m, HashField(m), arg...) } -func HashRemove(m *ice.Message, arg ...ice.Any) *ice.Message { - m.OptionFields(m.Config(FIELD)) - defer m.Event(kit.Keys(m.CommandKey(), REMOVE), m.CommandKey(), m.Option(m.Config(SHORT))) - return m.Cmd(DELETE, m.PrefixKey(), "", HASH, kit.Simple(arg...)) +func HashInputs(m *ice.Message, arg ...Any) *ice.Message { + return m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, HashArgs(m, arg)) } -func HashModify(m *ice.Message, arg ...ice.Any) *ice.Message { - field := m.Config(FIELD) - args := kit.Simple(arg...) - for i := 0; i < len(args); i += 2 { - if !strings.Contains(field, args[i]) { - args[i] = kit.Keys("extra", args[i]) - } - } - return m.Cmd(MODIFY, m.PrefixKey(), "", HASH, args) +func HashCreate(m *ice.Message, arg ...Any) *ice.Message { + return m.Cmdy(INSERT, m.PrefixKey(), "", HASH, HashArgs(m, arg...)) +} +func HashRemove(m *ice.Message, arg ...Any) *ice.Message { + return m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(HashShort(m)), arg) +} +func HashModify(m *ice.Message, arg ...Any) *ice.Message { + return m.Cmd(MODIFY, m.PrefixKey(), "", HASH, m.OptionSimple(HashShort(m)), HashArgs(m, arg...)) } func HashSelect(m *ice.Message, arg ...string) *ice.Message { - m.Fields(len(arg), m.Config(FIELD)) - m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg) - m.PushAction(m.Config("action"), REMOVE) - m.StatusTimeCount() - return m -} -func HashPrunes(m *ice.Message, cb func(ice.Maps) bool) *ice.Message { - _key := func(m *ice.Message) string { - if m.Config(HASH) == UNIQ { - return HASH - } - if m.Config(SHORT) == UNIQ { - return HASH - } - return kit.Select(HASH, m.Config(SHORT)) + m.Fields(len(kit.Slice(arg, 0, 1)), HashField(m)) + m.Cmdy(SELECT, m.PrefixKey(), "", HASH, HashShort(m), arg) + if m.PushAction(m.Config(ACTION), REMOVE); !m.FieldsIsDetail() { + return m.StatusTimeCount() + } else { + return m.StatusTime() } +} +func HashPrunes(m *ice.Message, cb func(Maps) bool) *ice.Message { expire := kit.Time(kit.Select(m.Time("-72h"), m.Option(EXPIRE))) - m.Cmd(m.CommandKey()).Tables(func(value ice.Maps) { - if kit.Time(value[TIME]) > expire { - return + m.Cmd(m.CommandKey()).Tables(func(value Maps) { + if cb != nil && !cb(value) || kit.Time(value[TIME]) < expire { + HashRemove(m, HashShort(m), value[HashShort(m)]) } - if cb != nil && cb(value) { - return - } - m.OptionFields(m.Config(FIELD)) - m.Cmdy(DELETE, m.PrefixKey(), "", HASH, _key(m), value[_key(m)]) }) return m } -func HashExport(m *ice.Message, arg ...ice.Any) *ice.Message { - m.OptionFields(m.Config(FIELD)) - return m.Cmd(EXPORT, m.PrefixKey(), "", HASH, kit.Simple(arg...)) +func HashExport(m *ice.Message, arg ...Any) *ice.Message { + return m.Cmdy(EXPORT, m.PrefixKey(), "", HASH, arg) } -func HashImport(m *ice.Message, arg ...ice.Any) *ice.Message { - return m.Cmd(IMPORT, m.PrefixKey(), "", HASH, kit.Simple(arg...)) +func HashImport(m *ice.Message, arg ...Any) *ice.Message { + return m.Cmdy(IMPORT, m.PrefixKey(), "", HASH, arg) } -func HashCache(m *ice.Message, h string, add func() ice.Any) ice.Any { +func HashTarget(m *ice.Message, h string, add func() Any) Any { defer m.Lock()() - p := m.Confv(m.PrefixKey(), kit.Keys(HASH, h, "_cache")) - if pp, ok := p.(ice.Map); ok && len(pp) == 0 { + p := m.Confv(m.PrefixKey(), kit.Keys(HASH, h, TARGET)) + if pp, ok := p.(Map); ok && len(pp) == 0 { p = nil } - if add != nil && p == nil { + if p == nil && add != nil { p = add() - m.Confv(m.PrefixKey(), kit.Keys(HASH, h, "_cache"), p) // 添加 + m.Confv(m.PrefixKey(), kit.Keys(HASH, h, TARGET), p) } return p } +func HashPrunesValue(m *ice.Message, field, value string) { + m.OptionFields(m.Config(FIELD)) + m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, field, value) +} +func HashSelectFields(m *ice.Message, key string, field string) (value string) { + HashSelectDetail(m, key, func(h string, val ice.Map) { + if field == HASH { + value = h + } else { + value = kit.Format(val[field]) + } + }) + return +} +func HashSelectDetail(m *ice.Message, key string, cb Any) bool { + defer m.RLock(m.PrefixKey(), "")() + has := false + m.Richs(m.PrefixKey(), nil, key, func(key string, value Map) { + hashSelect(m, key, value, cb) + has = true + }) + return has +} +func HashSelectUpdate(m *ice.Message, key string, cb Any) *ice.Message { + defer m.Lock(m.PrefixKey(), "")() + m.Richs(m.PrefixKey(), nil, key, func(key string, value Map) { + hashSelect(m, key, value, cb) + }) + return m +} +func HashSelectSearch(m *ice.Message, args []string, keys ...string) *ice.Message { + if len(keys) == 0 { + ls := kit.Split(m.Config(FIELD)) + for _, k := range ls { + switch k { + case TIME, HASH: + default: + keys = append(keys, k) + } + } + } + if args[0] == m.CommandKey() { + HashSelectValue(m, func(value ice.Map) { + if args[1] == "" || args[1] == value[keys[1]] { + m.PushSearch(kit.SimpleKV("", value[keys[0]], value[keys[1]], value[keys[2]]), value) + } + }) + } + return m +} +func HashSelectValue(m *ice.Message, cb Any) *ice.Message { + defer m.RLock(m.PrefixKey(), "")() + m.Richs(m.PrefixKey(), nil, FOREACH, func(key string, value Map) { + hashSelect(m, key, value, cb) + }) + return m +} +func HashSelects(m *ice.Message, arg ...string) *ice.Message { + m.OptionFields(m.Config(FIELD)) + return HashSelect(m, arg...) +} +func hashSelect(m *ice.Message, key string, value Map, cb Any) *ice.Message { + switch value = kit.GetMeta(value); cb := cb.(type) { + case func(string, Map): + cb(key, value) + case func(Map): + cb(value) + case func(Any): + cb(value[TARGET]) + case nil: + default: + m.ErrorNotImplement(cb) + } + return m +} diff --git a/base/mdb/list.go b/base/mdb/list.go index 98a30e92..6491e168 100644 --- a/base/mdb/list.go +++ b/base/mdb/list.go @@ -2,24 +2,23 @@ package mdb import ( "encoding/csv" - "os" "path" ice "shylinux.com/x/icebergs" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/miss" ) func _list_fields(m *ice.Message) []string { - return kit.Split(kit.Select("time,id,type,name,text", m.OptionFields())) + return kit.Split(kit.Select(LIST_FIELD, m.OptionFields())) } func _list_inputs(m *ice.Message, prefix, chain string, field, value string) { + defer m.RLock(prefix, chain)() + list := map[string]int{} - m.Grows(prefix, chain, "", "", func(index int, val ice.Map) { - if val = kit.GetMeta(val); kit.Format(val[COUNT]) != "" { - list[kit.Format(val[field])] = kit.Int(val[COUNT]) - } else { - list[kit.Format(val[field])]++ - } + m.Grows(prefix, chain, "", "", func(val ice.Map) { + val = kit.GetMeta(val) + list[kit.Format(val[field])] += kit.Int(kit.Select("1", val[COUNT])) }) for k, i := range list { m.Push(field, k) @@ -28,43 +27,34 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) { m.SortIntR(COUNT) } func _list_insert(m *ice.Message, prefix, chain string, arg ...string) { + defer m.Lock(prefix, chain)() + m.Log_INSERT(KEY, path.Join(prefix, chain), arg[0], arg[1]) m.Echo("%d", m.Grow(prefix, chain, kit.Dict(arg))) } -func _list_delete(m *ice.Message, prefix, chain, field, value string) { -} func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) { + defer m.Lock(prefix, chain)() + m.Grows(prefix, chain, field, value, func(index int, val ice.Map) { - val = kit.GetMeta(val) m.Log_MODIFY(KEY, path.Join(prefix, chain), field, value, arg) - for i := 0; i < len(arg); i += 2 { - if arg[i] == field { - continue - } - kit.Value(val, arg[i], kit.Select("", arg, i+1)) - } + _mdb_modify(m, val, field, arg...) }) } func _list_select(m *ice.Message, prefix, chain, field, value string) { + defer m.RLock(prefix, chain)() + if value == "" { field = "" } fields := _list_fields(m) - m.Grows(prefix, chain, kit.Select(m.Option(ice.CACHE_FIELD), field), kit.Select(m.Option(ice.CACHE_VALUE), value), func(index int, val ice.Map) { - switch val = kit.GetMeta(val); cb := m.OptionCB(SELECT).(type) { - case func(fields []string, value ice.Map): - cb(fields, val) - default: - if m.OptionFields() == DETAIL { - m.Push(DETAIL, val) - } else { - m.Push("", val, fields) - } - } + m.Grows(prefix, chain, kit.Select(m.Option(ice.CACHE_FIELD), field), kit.Select(m.Option(ice.CACHE_VALUE), value), func(value ice.Map) { + _mdb_select(m, "", value, fields, nil) }) } func _list_export(m *ice.Message, prefix, chain, file string) { - f, p, e := kit.Create(kit.Keys(file, CSV)) + defer m.RLock(prefix, chain)() + + f, p, e := miss.CreateFile(kit.Keys(file, CSV)) m.Assert(e) defer f.Close() @@ -72,7 +62,7 @@ func _list_export(m *ice.Message, prefix, chain, file string) { defer w.Flush() count := 0 - head := kit.Split(m.OptionFields()) + head := kit.Split(m.Config(FIELD)) m.Grows(prefix, chain, "", "", func(index int, val ice.Map) { if val = kit.GetMeta(val); index == 0 { if len(head) == 0 || head[0] == ice.CACHE_DETAIL { // 默认表头 @@ -98,7 +88,9 @@ func _list_export(m *ice.Message, prefix, chain, file string) { m.Echo(p) } func _list_import(m *ice.Message, prefix, chain, file string) { - f, e := os.Open(kit.Keys(file, CSV)) + defer m.RLock(prefix, chain)() + + f, e := miss.OpenFile(kit.Keys(file, CSV)) m.Assert(e) defer f.Close() @@ -128,55 +120,102 @@ func _list_import(m *ice.Message, prefix, chain, file string) { m.Log_IMPORT(KEY, kit.Keys(prefix, chain), COUNT, count) m.Echo("%d", count) } -func _list_prunes(m *ice.Message, prefix, chain string, arg ...string) { -} +const ( + LIST_FIELD = "time,id,type,name,text" +) const LIST = "list" func ListAction(args ...ice.Any) ice.Actions { return ice.Actions{ice.CTX_INIT: AutoConfig(args...), INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(INPUTS, m.PrefixKey(), "", LIST, arg) + m.Cmdy(INPUTS, m.PrefixKey(), "", LIST, ListArgs(m, arg)) }}, - INSERT: {Name: "insert type=go name=hi text=hello", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(INSERT, m.PrefixKey(), "", LIST, arg) + INSERT: {Name: "insert", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(INSERT, m.PrefixKey(), "", LIST, ListArgs(m, arg)) }}, DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(DELETE, m.PrefixKey(), "", LIST, m.OptionSimple(ID), arg) }}, MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(MODIFY, m.PrefixKey(), "", LIST, m.OptionSimple(ID), arg) + m.Cmdy(MODIFY, m.PrefixKey(), "", LIST, m.OptionSimple(ID), ListArgs(m, arg)) }}, - EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { - m.Option(ice.CACHE_LIMIT, "-1") - m.OptionFields(m.Config(FIELD)) - m.Cmdy(EXPORT, m.PrefixKey(), "", LIST) - m.Conf(m.PrefixKey(), LIST, "") - m.Config(COUNT, 0) - }}, - IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(IMPORT, m.PrefixKey(), "", LIST, arg) + SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) { + ListSelect(m, arg...) }}, PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(PRUNES, m.PrefixKey(), "", LIST, arg) }}, + EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(EXPORT, m.PrefixKey(), "", LIST, arg) + }}, + IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(IMPORT, m.PrefixKey(), "", LIST, arg) + }}, PREV: {Name: "prev", Help: "上一页", Hand: func(m *ice.Message, arg ...string) { PrevPage(m, m.Config(COUNT), kit.Slice(arg, 1)...) }}, NEXT: {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) { - NextPage(m, m.Config(COUNT), kit.Slice(arg, 1)...) - }}, - SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) { - ListSelect(m, arg...) + NextPageLimit(m, m.Config(COUNT), kit.Slice(arg, 1)...) }}, } } +func ListField(m *ice.Message) string { return kit.Select(LIST_FIELD, m.Config(FIELD)) } +func ListArgs(m *ice.Message, arg ...ice.Any) []string { + return _mdb_args(m, ListField(m), arg...) +} func ListSelect(m *ice.Message, arg ...string) *ice.Message { m.OptionPage(kit.Slice(arg, 1)...) - m.Fields(len(kit.Slice(arg, 0, 1)), m.Config(FIELD)) - m.Cmdy(SELECT, m.PrefixKey(), "", LIST, ID, arg) - if !m.FieldsIsDetail() { + m.Fields(len(kit.Slice(arg, 0, 1)), ListField(m)) + if m.Cmdy(SELECT, m.PrefixKey(), "", LIST, ID, arg); !m.FieldsIsDetail() { m.StatusTimeCountTotal(m.Config(COUNT)) + } else { + m.StatusTime() } return m } +func PrevPageLimit(m *ice.Message, total string, arg ...string) { + if kit.Int(kit.Select("0", arg, 1)) > 0 { + PrevPage(m, total, arg...) + } else { + m.Toast("已经是最前一页啦!") + m.ProcessHold() + } +} +func PrevPage(m *ice.Message, total string, arg ...string) { + limit, offend := kit.Select("10", arg, 0), kit.Select("0", arg, 1) + offends := kit.Int(offend) - kit.Int(limit) + if total != "0" && (offends <= -kit.Int(total) || offends >= kit.Int(total)) { + m.Toast("已经是最前一页啦!") + m.ProcessHold() + return + } + if offends == 0 { + m.ProcessRewrite("offend", "") + } else { + m.ProcessRewrite("offend", offends) + } + +} +func NextPage(m *ice.Message, total string, arg ...string) { + limit, offend := kit.Select("10", arg, 0), kit.Select("0", arg, 1) + offends := kit.Int(offend) + kit.Int(limit) + if total != "0" && (offends <= -kit.Int(total) || offends >= kit.Int(total)) { + m.Toast("已经是最后一页啦!") + m.ProcessHold() + return + } + if offends == 0 { + m.ProcessRewrite("offend", "") + } else { + m.ProcessRewrite("offend", offends) + } +} +func NextPageLimit(m *ice.Message, total string, arg ...string) { + if kit.Int(kit.Select("0", arg, 1)) < 0 { + NextPage(m, total, arg...) + } else { + m.Toast("已经是最后一页啦!") + m.ProcessHold() + } +} diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index 1048be94..2165f111 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -8,26 +8,73 @@ import ( kit "shylinux.com/x/toolkits" ) +type Any = interface{} +type Map = map[string]Any +type Maps = map[string]string + +func _domain_chain(m *ice.Message, chain string) string { + return kit.Keys(m.Option(ice.MSG_DOMAIN), chain) +} func _file_name(m *ice.Message, arg ...string) string { if len(arg) > 3 && strings.Contains(arg[3], ice.PS) { return arg[3] } return path.Join(ice.USR_LOCAL_EXPORT, m.Option(ice.MSG_DOMAIN), path.Join(arg[:2]...), arg[2]) - return kit.Select(path.Join(ice.USR_LOCAL_EXPORT, m.Option(ice.MSG_DOMAIN), path.Join(arg[:2]...), arg[2]), arg, 3) } -func _domain_chain(m *ice.Message, chain string) string { - return kit.Keys(m.Option(ice.MSG_DOMAIN), chain) +func _mdb_args(m *ice.Message, field string, arg ...Any) []string { + args := kit.Simple(arg...) + for i := 0; i < len(args); i += 2 { + if !strings.Contains(field, args[i]) && !strings.HasPrefix(args[i], EXTRA) { + args[i] = kit.Keys(EXTRA, args[i]) + } + } + return args +} +func _mdb_modify(m *ice.Message, val ice.Map, field string, arg ...string) { + val = kit.GetMeta(val) + for i := 0; i < len(arg); i += 2 { + if arg[i] == field { + continue + } + kit.Value(val, arg[i], kit.Select("", arg, i+1)) + } +} +func _mdb_select(m *ice.Message, key string, value ice.Map, fields []string, val ice.Map) { + switch value = kit.GetMeta(value); cb := m.OptionCB(SELECT).(type) { + case func(string, []string, ice.Map, ice.Map): + cb(key, fields, value, val) + case func([]string, ice.Map): + cb(fields, value) + case func(string, ice.Map, ice.Map): + cb(key, value, val) + case func(string, ice.Map): + cb(key, value) + case func(ice.Map): + cb(value) + case func(Any): + cb(value[TARGET]) + case func(ice.Maps): + res := ice.Maps{} + for k, v := range value { + res[k] = kit.Format(v) + } + cb(res) + case nil: + if m.FieldsIsDetail() { + m.Push(ice.CACHE_DETAIL, value) + } else { + m.Push(key, value, fields, val) + } + default: + m.ErrorNotImplement(cb) + } } -const ( - CSV = "csv" - JSON = "json" -) const ( DICT = kit.MDB_DICT META = kit.MDB_META - UNIQ = kit.MDB_UNIQ + UNIQ = kit.MDB_UNIQ FOREACH = kit.MDB_FOREACH RANDOMS = kit.MDB_RANDOMS ) @@ -36,7 +83,6 @@ const ( ID = kit.MDB_ID KEY = kit.MDB_KEY TIME = kit.MDB_TIME - // ZONE = kit.MDB_ZONE TYPE = kit.MDB_TYPE NAME = kit.MDB_NAME TEXT = kit.MDB_TEXT @@ -71,6 +117,7 @@ const ( const ( DETAIL = "detail" RANDOM = "random" + ACTION = "action" INPUTS = "inputs" CREATE = "create" @@ -91,103 +138,70 @@ const ( PREV = "prev" PAGE = "page" OFFEND = "offend" + + JSON = "json" + CSV = "csv" ) const ( CACHE_CLEAR_ON_EXIT = "cache.clear.on.exit" + + SOURCE = "_source" + TARGET = "_target" ) -func PrevPageLimit(m *ice.Message, total string, arg ...string) { - if kit.Int(kit.Select("0", arg, 1)) > 0 { - PrevPage(m, total, arg...) - } else { - m.Toast("已经是最前一页啦!") - m.ProcessHold() - } -} -func PrevPage(m *ice.Message, total string, arg ...string) { - limit, offend := kit.Select("10", arg, 0), kit.Select("0", arg, 1) - offends := kit.Int(offend) - kit.Int(limit) - if total != "0" && (offends <= -kit.Int(total) || offends >= kit.Int(total)) { - m.Toast("已经是最前一页啦!") - m.ProcessHold() - return - } - if offends == 0 { - m.ProcessRewrite("offend", "") - } else { - m.ProcessRewrite("offend", offends) - } - -} -func NextPage(m *ice.Message, total string, arg ...string) { - limit, offend := kit.Select("10", arg, 0), kit.Select("0", arg, 1) - offends := kit.Int(offend) + kit.Int(limit) - if total != "0" && (offends <= -kit.Int(total) || offends >= kit.Int(total)) { - m.Toast("已经是最后一页啦!") - m.ProcessHold() - return - } - if offends == 0 { - m.ProcessRewrite("offend", "") - } else { - m.ProcessRewrite("offend", offends) - } -} -func NextPageLimit(m *ice.Message, total string, arg ...string) { - if kit.Int(kit.Select("0", arg, 1)) < 0 { - NextPage(m, total, arg...) - } else { - m.Toast("已经是最后一页啦!") - m.ProcessHold() - } -} - const MDB = "mdb" var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {}}, ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) {}}, INPUTS: {Name: "inputs key sub type field value", Help: "补全", Hand: func(m *ice.Message, arg ...string) { - switch arg[3] { + switch arg[3] = strings.TrimPrefix(arg[3], "extra."); arg[3] { + case ice.POD: + m.Cmdy("route") + case ice.CTX: + m.Cmdy("context") + case ice.CMD: + m.Cmdy("context", kit.Select(m.Option(ice.CTX), m.Option(kit.Keys(EXTRA, ice.CTX))), "command") case "index": - m.OptionFields(arg[3]) - m.Cmdy("command", "search", "command", "", "") - } - switch arg[2] { - case ZONE: // inputs key sub type zone field value - _list_inputs(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), kit.Select(NAME, arg, 4), kit.Select("", arg, 5)) - case HASH: - _hash_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4)) - case LIST: - _list_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4)) + m.OptionFields(arg[0]) + m.Cmdy("command", SEARCH, "command", kit.Select("", arg, 1)) + default: + switch arg[2] { + case ZONE: // inputs key sub type zone field value + _zone_inputs(m, arg[0], _domain_chain(m, arg[1]), arg[3], kit.Select(NAME, arg, 4), kit.Select("", arg, 5)) + case HASH: + _hash_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4)) + case LIST: + _list_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select(NAME, arg, 3), kit.Select("", arg, 4)) + } } }}, INSERT: {Name: "insert key sub type arg...", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + defer m.ProcessRefresh3ms() switch arg[2] { case ZONE: // insert key sub type zone arg... - _list_insert(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4:]...) + _zone_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4:]...) case HASH: _hash_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) case LIST: _list_insert(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) } - m.ProcessRefresh3ms() }}, DELETE: {Name: "delete key sub type field value", Help: "删除", Hand: func(m *ice.Message, arg ...string) { + defer m.ProcessRefresh3ms() switch arg[2] { case ZONE: // delete key sub type zone field value - _list_delete(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4], arg[5]) + // _list_delete(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4], arg[5]) case HASH: _hash_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4]) case LIST: - _list_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4]) + // _list_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4]) } - m.ProcessRefresh3ms() }}, MODIFY: {Name: "modify key sub type field value arg...", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { switch arg[2] { case ZONE: // modify key sub type zone id field value - _list_modify(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), ID, arg[4], arg[5:]...) + _zone_modify(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4], arg[5:]...) case HASH: _hash_modify(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4], arg[5:]...) case LIST: @@ -207,14 +221,12 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands PRUNES: {Name: "prunes key sub type [field value]...", Help: "清理", Hand: func(m *ice.Message, arg ...string) { switch arg[2] { case ZONE: // prunes key sub type zone field value - _list_prunes(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4:]...) + // _list_prunes(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4:]...) case HASH: _hash_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) - m.Tables(func(value ice.Maps) { - _hash_delete(m, arg[0], _domain_chain(m, arg[1]), HASH, value[HASH]) - }) + m.Tables(func(value ice.Maps) { _hash_delete(m, arg[0], _domain_chain(m, arg[1]), HASH, value[HASH]) }) case LIST: - _list_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) + // _list_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) } }}, EXPORT: {Name: "export key sub type file", Help: "导出", Hand: func(m *ice.Message, arg ...string) { @@ -223,10 +235,12 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands } switch file := _file_name(m, arg...); arg[2] { case ZONE: + m.OptionFields(ZoneShort(m), m.Config(FIELD)) _zone_export(m, arg[0], _domain_chain(m, arg[1]), file) case HASH: _hash_export(m, arg[0], _domain_chain(m, arg[1]), file) case LIST: + m.OptionFields(m.Config(FIELD)) _list_export(m, arg[0], _domain_chain(m, arg[1]), file) } }}, @@ -249,3 +263,35 @@ func init() { SEARCH, ENGINE, PLUGIN, RENDER, ) } +func AutoConfig(args ...ice.Any) *ice.Action { + return &ice.Action{Hand: func(m *ice.Message, arg ...string) { + if cs := m.Target().Configs; cs[m.CommandKey()] == nil && len(args) > 0 { + cs[m.CommandKey()] = &ice.Config{Value: kit.Data(args...)} + m.Load(m.CommandKey()) + } + + inputs := []ice.Any{} + kit.Fetch(kit.Split(m.Config(FIELD)), func(i int, k string) { + switch k { + case TIME, HASH, ID: + return + } + inputs = append(inputs, k) + }) + + cs := m.Target().Commands + if cs[m.CommandKey()] == nil { + return + } + + if cs[m.CommandKey()].Actions[INSERT] != nil { + if cs[m.CommandKey()].Meta[INSERT] == nil { + m.Design(INSERT, "添加", append([]ice.Any{ZONE}, inputs...)...) + } + } else if cs[m.CommandKey()].Actions[CREATE] != nil { + if cs[m.CommandKey()].Meta[CREATE] == nil { + m.Design(CREATE, "创建", inputs...) + } + } + }} +} diff --git a/base/mdb/plugin.go b/base/mdb/plugin.go index 4edfc307..6186e673 100644 --- a/base/mdb/plugin.go +++ b/base/mdb/plugin.go @@ -2,34 +2,10 @@ package mdb import ( ice "shylinux.com/x/icebergs" - kit "shylinux.com/x/toolkits" ) const PLUGIN = "plugin" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - PLUGIN: {Name: PLUGIN, Help: "插件", Value: kit.Data(SHORT, TYPE, FIELD, "time,type,name,text")}, - }, Commands: ice.Commands{ - PLUGIN: {Name: "plugin type name text auto", Help: "插件", Actions: ice.Actions{ - CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) { - m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME))) - m.Option(TYPE, kit.Ext(m.Option(TYPE))) - m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text")) - }}, - }, Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 1 { - m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg, func(value ice.Map) { - m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), arg[0], arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3)) - }) - return - } - if HashSelect(m, arg...); len(arg) == 0 { - m.Sort(TYPE) - } else if len(arg) == 1 { - m.DisplayStoryJSON() - m.Echo(kit.Formats(m.Confv(m.Append(NAME), "meta.plug"))) - } - }}, - }}) + Index.MergeCommands(ice.Commands{PLUGIN: {Name: "plugin type name text auto", Help: "插件", Actions: RenderAction()}}) } diff --git a/base/mdb/render.go b/base/mdb/render.go index 87a2425e..c4c0f102 100644 --- a/base/mdb/render.go +++ b/base/mdb/render.go @@ -8,28 +8,31 @@ import ( const RENDER = "render" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - RENDER: {Name: RENDER, Help: "渲染", Value: kit.Data(SHORT, TYPE, FIELD, "time,type,name,text")}, - }, Commands: ice.Commands{ - RENDER: {Name: "render type name text auto", Help: "渲染", Actions: ice.Actions{ - CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) { - m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME))) - m.Option(TYPE, kit.Ext(m.Option(TYPE))) - m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text")) - }}, - }, Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 1 { - m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg, func(value ice.Map) { - m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), arg[0], arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3)) - }) - return - } - if HashSelect(m, arg...); len(arg) == 0 { - m.Sort(TYPE) - } else if len(arg) == 1 { - m.DisplayStoryJSON() - m.Echo(kit.Formats(m.Confv(m.Append(NAME), "meta.plug"))) + Index.MergeCommands(ice.Commands{RENDER: {Name: "render type name text auto", Help: "渲染", Actions: RenderAction()}}) +} + +func RenderAction(args ...ice.Any) ice.Actions { + return ice.MergeAction(ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + if cs := m.Target().Configs; cs[m.CommandKey()] == nil { + cs[m.CommandKey()] = &ice.Config{Value: kit.Data(SHORT, TYPE)} } }}, - }}) + CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + m.Option(TYPE, kit.Ext(m.Option(TYPE))) + m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME))) + m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text")) + }}, + SELECT: {Name: "select type name text auto", Help: "渲染", Hand: func(m *ice.Message, arg ...string) { + if len(arg) > 1 { + for _, k := range kit.Split(arg[0]) { + HashSelect(m.Spawn(ice.OptionFields("")), k).Tables(func(value ice.Maps) { + m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), k, arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3)) + }) + } + return + } + HashSelect(m, arg...) + }}, + }) } diff --git a/base/mdb/search.go b/base/mdb/search.go index aba1ef2c..33dc9322 100644 --- a/base/mdb/search.go +++ b/base/mdb/search.go @@ -2,32 +2,10 @@ package mdb import ( ice "shylinux.com/x/icebergs" - kit "shylinux.com/x/toolkits" ) const SEARCH = "search" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SEARCH: {Name: SEARCH, Help: "搜索", Value: kit.Data(SHORT, TYPE, FIELD, "time,type,name,text")}, - }, Commands: ice.Commands{ - SEARCH: {Name: "search type name text auto", Help: "搜索", Actions: ice.Actions{ - CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) { - m.Option(NAME, kit.Select(m.Option(TYPE), m.Option(NAME))) - m.Option(TYPE, kit.Ext(m.Option(TYPE))) - m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple("type,name,text")) - }}, - }, Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 1 { - m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), kit.Slice(arg, 0, 1), func(value ice.Map) { - m.OptionFields(kit.Select("ctx,cmd,type,name,text", kit.Select(m.OptionFields()))) - m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), arg[0], arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3)) - }) - return - } - if HashSelect(m, arg...); len(arg) == 0 { - m.Sort(TYPE) - } - }}, - }}) + Index.MergeCommands(ice.Commands{SEARCH: {Name: "search type name text auto", Help: "搜索", Actions: RenderAction()}}) } diff --git a/base/mdb/zone.go b/base/mdb/zone.go index 2039aef8..60a3e26f 100644 --- a/base/mdb/zone.go +++ b/base/mdb/zone.go @@ -2,63 +2,62 @@ package mdb import ( "encoding/csv" - "os" "path" - "sort" - "strings" ice "shylinux.com/x/icebergs" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" + "shylinux.com/x/toolkits/miss" ) func _zone_fields(m *ice.Message) []string { - return kit.Split(kit.Select("zone,id,time,type,name,text", m.OptionFields())) + return kit.Split(kit.Select(ZONE_FIELD, m.OptionFields())) +} +func _zone_inputs(m *ice.Message, prefix, chain, zone string, field, value string) { + if field == m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT))) { + _hash_inputs(m, prefix, chain, field, value) + return + } + h := _hash_select_fields(m, prefix, chain, zone, HASH) + defer m.RLock(prefix, chain)() + _list_inputs(m, prefix, _domain_chain(m, kit.Keys(chain, HASH, h)), field, value) +} +func _zone_insert(m *ice.Message, prefix, chain, zone string, arg ...string) { + h := _hash_select_fields(m, prefix, chain, zone, HASH) + if h == "" { + h = _hash_insert(m, prefix, chain, m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT))), zone) + } + m.Assert(h != "") + defer m.Lock(prefix, chain)() + _list_insert(m, prefix, _domain_chain(m, kit.Keys(chain, HASH, h)), arg...) +} +func _zone_modify(m *ice.Message, prefix, chain, zone, id string, arg ...string) { + h := _hash_select_fields(m, prefix, chain, zone, HASH) + m.Assert(h != "") + defer m.RLock(prefix, chain)() + _list_modify(m, prefix, _domain_chain(m, kit.Keys(chain, HASH, h)), ID, id, arg...) } func _zone_select(m *ice.Message, prefix, chain, zone string, id string) { + if zone == "" { + _hash_select(m, prefix, chain, HASH, FOREACH) + return + } if zone == RANDOM { zone = RANDOMS } fields := _zone_fields(m) - cb := m.OptionCB(SELECT) - m.Richs(prefix, chain, kit.Select(FOREACH, zone), func(key string, val ice.Map) { - if val = kit.GetMeta(val); zone == "" { - if m.OptionFields() == DETAIL { - m.Push(DETAIL, val) - } else { - m.Push(key, val, fields) - } - return - } - - m.Grows(prefix, kit.Keys(chain, HASH, key), ID, id, func(index int, value ice.Map) { - switch value = kit.GetMeta(value); cb := cb.(type) { - case func(string, []string, ice.Map, ice.Map): - cb(key, fields, value, val) - case func(string, ice.Map, ice.Map): - cb(key, value, val) - case func(string, ice.Map): - cb(key, value) - case func(ice.Map): - cb(value) - case func(ice.Maps): - res := ice.Maps{} - for k, v := range value { - res[k] = kit.Format(v) - } - cb(res) - default: - if m.FieldsIsDetail() { - m.Push(DETAIL, value) - } else { - m.Push(key, value, fields, val) - } - } + defer m.RLock(prefix, chain)() + m.Richs(prefix, chain, kit.Select(FOREACH, zone), func(key string, val Map) { + chain := kit.Keys(chain, HASH, key) + defer m.RLock(prefix, chain)() + m.Grows(prefix, chain, ID, id, func(value ice.Map) { + _mdb_select(m, key, value, fields, val) }) }) } func _zone_export(m *ice.Message, prefix, chain, file string) { - f, p, e := kit.Create(kit.Keys(file, CSV)) + f, p, e := miss.CreateFile(kit.Keys(file, CSV)) m.Assert(e) defer f.Close() @@ -66,21 +65,24 @@ func _zone_export(m *ice.Message, prefix, chain, file string) { defer w.Flush() fields := _zone_fields(m) - fields = append(fields, EXTRA) + if kit.IndexOf(fields, EXTRA) == -1 { + fields = append(fields, EXTRA) + } w.Write(fields) keys := []string{} - m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) { - keys = append(keys, key) - }) - sort.Strings(keys) + m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) { keys = append(keys, key) }) + kit.Sort(keys) count := 0 + defer m.Lock(prefix, chain)() for _, key := range keys { m.Richs(prefix, chain, key, func(key string, val ice.Map) { val = kit.GetMeta(val) - m.Grows(prefix, kit.Keys(chain, HASH, key), "", "", func(index int, value ice.Map) { + chain := kit.Keys(chain, HASH, key) + defer m.RLock(prefix, chain)() + m.Grows(prefix, chain, "", "", func(value ice.Map) { value = kit.GetMeta(value) list := []string{} @@ -98,10 +100,8 @@ func _zone_export(m *ice.Message, prefix, chain, file string) { m.Echo(p) } func _zone_import(m *ice.Message, prefix, chain, file string) { - f, e := os.Open(kit.Keys(file, CSV)) - if m.Warn(e) { - return - } + f, e := miss.OpenFile(kit.Keys(file, CSV)) + m.Assert(e) defer f.Close() r := csv.NewReader(f) @@ -111,6 +111,7 @@ func _zone_import(m *ice.Message, prefix, chain, file string) { list := ice.Maps{} zkey := kit.Select(head[0], m.OptionFields()) + defer m.Lock(prefix, chain)() for { line, e := r.Read() if e != nil { @@ -135,7 +136,11 @@ func _zone_import(m *ice.Message, prefix, chain, file string) { list[zone] = m.Rich(prefix, chain, kit.Data(zkey, zone)) } - m.Grow(prefix, kit.Keys(chain, HASH, list[zone]), data) + func() { + chain := kit.Keys(chain, HASH, list[zone]) + defer m.Lock(prefix, chain)() + m.Grow(prefix, chain, data) + }() count++ } @@ -143,61 +148,36 @@ func _zone_import(m *ice.Message, prefix, chain, file string) { m.Echo("%d", count) } +const ( + ZONE_FIELD = "zone,id,time,type,name,text" +) const ZONE = "zone" func ZoneAction(args ...ice.Any) ice.Actions { - _zone := func(m *ice.Message) string { return kit.Select(ZONE, m.Config(SHORT)) } - return ice.Actions{ice.CTX_INIT: AutoConfig(args...), INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { - arg[0] = strings.TrimPrefix(arg[0], "extra.") - arg[0] = kit.Select(arg[0], m.Config(kit.Keys(ALIAS, arg[0]))) - switch arg[0] { - case ice.POD: - m.Cmdy("route") - case ice.CTX: - m.Cmdy("context") - case ice.CMD: - m.Cmdy("context", kit.Select(m.Option(ice.CTX), m.Option(kit.Keys(EXTRA, ice.CTX))), "command") - case ice.ARG: - - case "index": - m.OptionFields(arg[0]) - m.Cmdy("command", SEARCH, "command", kit.Select("", arg, 1)) - - case _zone(m): - m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, arg) - default: - m.Cmdy(INPUTS, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), arg) - } + ZoneInputs(m, arg) }}, CREATE: {Name: "create zone", Help: "创建", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(INSERT, m.PrefixKey(), "", HASH, arg) + ZoneCreate(m, arg) }}, REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(_zone(m)), arg) + ZoneRemove(m, arg) }}, INSERT: {Name: "insert", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 { - arg = m.OptionSimple(_zone(m), m.Config(FIELD)) - } - m.Cmdy(INSERT, m.PrefixKey(), "", HASH, _zone(m), arg[1]) - m.Cmdy(INSERT, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), arg[2:]) + ZoneInsert(m, arg) }}, MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), m.Option(ID), arg) + ZoneModify(m, arg) }}, - PLUGIN: {Name: "plugin extra.pod extra.ctx extra.cmd extra.arg", Help: "插件", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(_zone(m)), m.Option(ID), arg) + SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) { + ZoneSelect(m, arg...) }}, EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { - m.Option(ice.CACHE_LIMIT, "-1") - m.OptionFields(_zone(m), m.Config(FIELD)) - m.Cmdy(EXPORT, m.PrefixKey(), "", ZONE) + ZoneExport(m, arg) }}, IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { - m.OptionFields(_zone(m)) - m.Cmdy(IMPORT, m.PrefixKey(), "", ZONE) + ZoneImport(m, arg) }}, PREV: {Name: "prev", Help: "上一页", Hand: func(m *ice.Message, arg ...string) { PrevPage(m, arg[0], arg[1:]...) @@ -205,28 +185,56 @@ func ZoneAction(args ...ice.Any) ice.Actions { NEXT: {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) { NextPageLimit(m, arg[0], arg[1:]...) }}, - SELECT: {Name: "select", Help: "列表", Hand: func(m *ice.Message, arg ...string) { - ZoneSelect(m, arg...) - }}, } } +func ZoneShort(m *ice.Message) string { + return kit.Select(ZONE, m.Config(SHORT), m.Config(SHORT) != UNIQ) +} +func ZoneField(m *ice.Message) string { return kit.Select(ZONE_FIELD, m.Config(FIELD)) } +func ZoneArgs(m *ice.Message, arg ...Any) []string { + return _mdb_args(m, ZoneField(m), arg...) +} + +func ZoneInputs(m *ice.Message, arg ...Any) { + m.Cmdy(INPUTS, m.PrefixKey(), "", ZONE, ZoneArgs(m, arg...)) +} +func ZoneCreate(m *ice.Message, arg ...Any) { + m.Cmdy(INSERT, m.PrefixKey(), "", HASH, arg) +} +func ZoneRemove(m *ice.Message, arg ...Any) { + m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(ZoneShort(m)), arg) +} +func ZoneInsert(m *ice.Message, arg ...Any) { + args := kit.Simple(arg...) + m.Cmdy(INSERT, m.PrefixKey(), "", ZONE, args[1], ZoneArgs(m, args[2:])) +} +func ZoneModify(m *ice.Message, arg ...Any) { + m.Cmdy(MODIFY, m.PrefixKey(), "", ZONE, m.Option(ZoneShort(m)), m.Option(ID), ZoneArgs(m, arg...)) +} func ZoneSelect(m *ice.Message, arg ...string) *ice.Message { arg = kit.Slice(arg, 0, 2) m.Fields(len(arg), kit.Fields(TIME, m.Config(SHORT), COUNT), m.Config(FIELD)) - if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg); kit.Select("", arg, 0) == "" { + if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(logs.FileLine(-1, 3))); len(arg) == 0 { if m.Config(SHORT) != "" { m.Sort(m.Config(SHORT)) } - m.PushAction(REMOVE) - } - if len(arg) == 0 { + m.PushAction(m.Config(ACTION), REMOVE) m.StatusTimeCount() - } - if len(arg) == 1 { - m.StatusTimeCountTotal(m.Conf(m.PrefixKey(), kit.Keys(HASH, kit.Hashs(arg[0]), kit.Keym("count")))) + } else if len(arg) == 1 { + m.StatusTimeCountTotal(m.Conf("", kit.Keys(HASH, HashSelectFields(m, arg[0], HASH), kit.Keym(COUNT)))) } return m } +func ZoneExport(m *ice.Message, arg ...Any) { + m.Cmdy(EXPORT, m.PrefixKey(), "", ZONE, arg) +} +func ZoneImport(m *ice.Message, arg ...Any) { + m.Cmdy(IMPORT, m.PrefixKey(), "", ZONE, arg) +} +func ZoneSelectPage(m *ice.Message, arg ...string) *ice.Message { + m.OptionPages(kit.Slice(arg, 2)...) + return ZoneSelect(m, arg...) +} func ZoneSelectAll(m *ice.Message, arg ...string) *ice.Message { m.Option(ice.CACHE_LIMIT, "-1") return ZoneSelect(m, arg...) diff --git a/base/nfs/cat.go b/base/nfs/cat.go index bf58c891..8bd460b6 100644 --- a/base/nfs/cat.go +++ b/base/nfs/cat.go @@ -4,78 +4,41 @@ import ( "bufio" "bytes" "io" - "os" "path" "strings" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/aaa" - "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" ) -type ReadCloser struct { - r io.Reader -} - -func (r *ReadCloser) Read(buf []byte) (int, error) { - return r.r.Read(buf) -} -func (r *ReadCloser) Close() error { - if c, ok := r.r.(io.Closer); ok { - return c.Close() - } - return nil -} -func NewReadCloser(r io.Reader) *ReadCloser { - return &ReadCloser{r: r} -} - -var rewriteList = []ice.Any{} - -func AddRewrite(cb ice.Any) { rewriteList = append(rewriteList, cb) } - -func _cat_right(m *ice.Message, name string) bool { - return aaa.RoleRight(m, m.Option(ice.MSG_USERROLE), strings.Split(name, ice.PS)...) -} -func _cat_find(m *ice.Message, name string) io.ReadCloser { +func _cat_find(m *ice.Message, name string) (io.ReadCloser, error) { if m.Option(CAT_CONTENT) != "" { - return NewReadCloser(bytes.NewBufferString(m.Option(CAT_CONTENT))) + return NewReadCloser(bytes.NewBufferString(m.Option(CAT_CONTENT))), nil } - - // 模块回调 - for _, h := range rewriteList { - switch h := h.(type) { - case func(m *ice.Message, name string) io.ReadCloser: - if r := h(m, name); r != nil { - return r - } - case func(m *ice.Message, name string) []byte: - if b := h(m, name); b != nil { - return NewReadCloser(bytes.NewBuffer(b)) - } - case func(m *ice.Message, name string) string: - if s := h(m, name); s != "" { - return NewReadCloser(bytes.NewBufferString(s)) - } - default: - m.Error(true, ice.ErrNotImplement) + return OpenFile(m, path.Join(m.Option(DIR_ROOT), name)) +} +func _cat_size(m *ice.Message, p string) (nline int) { + if f, e := OpenFile(m, p); m.Warn(e) { + defer f.Close() + for bio := bufio.NewScanner(f); bio.Scan(); nline++ { + bio.Text() } } - - // 本地文件 - if f, e := os.Open(path.Join(m.Option(DIR_ROOT), name)); e == nil { - return f + return nline +} +func _cat_hash(m *ice.Message, p string) string { + if f, e := OpenFile(m, p); !m.Warn(e) { + defer f.Close() + return kit.Hashs(f) } - return nil + return "" } func _cat_list(m *ice.Message, name string) { - if m.Warn(!_cat_right(m, name), ice.ErrNotRight) { + if !m.Right(m, name) { return // 没有权限 } - - f := _cat_find(m, name) - if m.Warn(f == nil, ice.ErrNotFound, name) { + f, e := _cat_find(m, name) + if m.Warn(e, ice.ErrNotFound, name) { return // 没有文件 } defer f.Close() @@ -97,15 +60,15 @@ func _cat_list(m *ice.Message, name string) { for bio := bufio.NewScanner(f); bio.Scan(); { cb(bio.Text()) } + case func([]string, string): for bio := bufio.NewScanner(f); bio.Scan(); { cb(kit.Split(bio.Text()), bio.Text()) } - - default: - buf := make([]byte, ice.MOD_BUFS) - for begin := 0; true; { - if n, e := f.Read(buf[begin:]); !m.Warn(e, ice.ErrNotFound, name) { + case nil: + buf, begin := make([]byte, ice.MOD_BUFS), 0 + for { + if n, e := f.Read(buf[begin:]); !m.Warn(e, ice.ErrNotValid, name) { m.Log_IMPORT(FILE, name, SIZE, n) if begin += n; begin < len(buf) { buf = buf[:begin] @@ -117,6 +80,8 @@ func _cat_list(m *ice.Message, name string) { } } m.Echo(string(buf)) + default: + m.ErrorNotImplement(cb) } } @@ -125,6 +90,7 @@ const ( TEMPLATE = "template" WEBSITE = "website" + STDIO = "stdio" SOURCE = "source" SCRIPT = "script" BINARY = "binary" @@ -155,15 +121,15 @@ const ( YML = "yml" ZML = "zml" + PNG = "png" + JPG = "jpg" + MP4 = "mp4" + PWD = "./" + PS = ice.PS + PT = ice.PT ) -const ( - PATH = "path" - FILE = "file" - LINE = "line" - SIZE = "size" -) const CAT = "cat" func init() { @@ -177,20 +143,13 @@ func init() { ), )}, }, Commands: ice.Commands{ - CAT: {Name: "cat path auto", Help: "文件", Actions: ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(mdb.RENDER, mdb.CREATE, m.CommandKey(), m.PrefixKey()) - }}, - mdb.RENDER: {Name: "render type name text", Help: "渲染", Hand: func(m *ice.Message, arg ...string) { - _cat_list(m, path.Join(arg[2], arg[1])) - }}, - }, Hand: func(m *ice.Message, arg ...string) { + CAT: {Name: "cat path auto", Help: "文件", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) { m.Cmdy(DIR, arg) return } if m.Option(DIR_ROOT) != "" { - m.Info("dir_root: %v", m.Option(DIR_ROOT)) + m.Log_SELECT(DIR_ROOT, m.Option(DIR_ROOT)) } _cat_list(m, arg[0]) }}, diff --git a/base/nfs/dir.go b/base/nfs/dir.go index c0c8fd10..251fee41 100644 --- a/base/nfs/dir.go +++ b/base/nfs/dir.go @@ -1,9 +1,6 @@ package nfs import ( - "bufio" - "crypto/sha1" - "io/ioutil" "os" "path" "regexp" @@ -15,57 +12,38 @@ import ( kit "shylinux.com/x/toolkits" ) +func _dir_size(m *ice.Message, p string) int { + if ls, e := ReadDir(m, p); !m.Warn(e) { + return len(ls) + } + return 0 +} +func _dir_hash(m *ice.Message, p string) string { + if ls, e := ReadDir(m, p); !m.Warn(e) { + meta := []string{} + for _, s := range ls { + meta = append(meta, kit.Format("%s%d%s", s.Name(), s.Size(), s.ModTime())) + } + return kit.Hashs(meta) + } + return "" +} func _dir_list(m *ice.Message, root string, name string, level int, deep bool, dir_type string, dir_reg *regexp.Regexp, fields []string) *ice.Message { - if !_cat_right(m, path.Join(root, name)) { + if !m.Right(m, path.Join(root, name)) { return m // 没有权限 } - if len(ice.Info.Pack) > 0 && m.Option(DIR_PACK) == ice.TRUE { - for k, b := range ice.Info.Pack { - p := strings.TrimPrefix(k, root) - if !strings.HasPrefix(p, name) { - if p = strings.TrimPrefix(k, root+ice.PS); !strings.HasPrefix(p, name) { - if p = strings.TrimPrefix(k, ice.PS); !strings.HasPrefix(p, name) { - continue - } - } - } - - m.Debug("dir binpack %s", p) - for _, field := range fields { - switch field { - case PATH: - m.Push(field, p) - case SIZE: - m.Push(field, len(b)) - default: - m.Push(field, "") - } - } - } - return m // 打包文件 - } - - list, e := ioutil.ReadDir(path.Join(root, name)) + list, e := ReadDir(m, path.Join(root, name)) if e != nil { // 单个文件 - ls, _ := ioutil.ReadDir(path.Dir(path.Join(root, name))) - for _, k := range ls { - if k.Name() == path.Base(name) { - list = append(list, k) + ls, _ := ReadDir(m, path.Dir(path.Join(root, name))) + for _, s := range ls { + if s.Name() == path.Base(name) { + list = append(list, s) } } name = path.Dir(name) } - // 文件排序 - for i := 0; i < len(list)-1; i++ { - for j := i + 1; j < len(list); j++ { - if list[i].Name() > list[j].Name() { - list[i], list[j] = list[j], list[i] - } - } - } - for _, f := range list { if f.Name() == ice.PT || f.Name() == ".." { continue @@ -74,7 +52,7 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d continue } - p := path.Join(root, name, f.Name()) + p, pp := path.Join(root, name, f.Name()), path.Join(name, f.Name()) isDir := f.IsDir() || kit.IsDir(p) if !(dir_type == TYPE_CAT && isDir || dir_type == TYPE_DIR && !isDir) && (dir_reg == nil || dir_reg.MatchString(f.Name())) { switch cb := m.OptionCB(DIR).(type) { @@ -86,7 +64,7 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d continue case nil: default: - m.Error(true, "what: %v: %v", ice.ErrNotImplement, cb) + m.ErrorNotImplement(cb) } for _, field := range fields { @@ -96,78 +74,54 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d case mdb.TYPE: m.Push(field, kit.Select(CAT, DIR, isDir)) - case "tree": + case TREE: if level == 0 { m.Push(field, f.Name()) } else { m.Push(field, strings.Repeat("| ", level-1)+"|-"+f.Name()) } - case "full": - m.Push(field, path.Join(root, name, f.Name())+kit.Select("", ice.PS, isDir)) + case FULL: + m.Push(field, p+kit.Select("", ice.PS, isDir)) case PATH: - m.Push(field, path.Join(name, f.Name())+kit.Select("", ice.PS, isDir)) + m.Push(field, pp+kit.Select("", ice.PS, isDir)) case FILE: m.Push(field, f.Name()+kit.Select("", ice.PS, isDir)) - case mdb.NAME: + case NAME: m.Push(field, f.Name()) case SIZE: if isDir { - if ls, e := ioutil.ReadDir(path.Join(root, name, f.Name())); e == nil { - m.Push(field, len(ls)) - } else { - m.Push(field, 0) - } + m.Push(field, _dir_size(m, p)) } else { m.Push(field, kit.FmtSize(f.Size())) } case LINE: if isDir { - if ls, e := ioutil.ReadDir(path.Join(root, name, f.Name())); e == nil { - m.Push(field, len(ls)) - } else { - m.Push(field, 0) - } + m.Push(field, _dir_size(m, p)) } else { - nline := 0 - if f, e := os.Open(p); m.Assert(e) { - defer f.Close() - for bio := bufio.NewScanner(f); bio.Scan(); nline++ { - bio.Text() - } - } - m.Push(field, nline) + m.Push(field, _cat_size(m, p)) } case mdb.HASH, "hashs": - var h [20]byte + h := "" if isDir { - if d, e := ioutil.ReadDir(p); m.Assert(e) { - meta := []string{} - for _, v := range d { - meta = append(meta, kit.Format("%s%d%s", v.Name(), v.Size(), v.ModTime())) - } - kit.Sort(meta) - h = sha1.Sum([]byte(strings.Join(meta, ""))) - } + h = _dir_hash(m, p) } else { - if f, e := ioutil.ReadFile(path.Join(name, f.Name())); m.Assert(e) { - h = sha1.Sum(f) - } + h = _cat_hash(m, p) } - - m.Push(mdb.HASH, kit.Select(kit.Format(h[:6]), kit.Format(h[:]), field == mdb.HASH)) + m.Debug("what %v %v", h, p) + m.Push(mdb.HASH, kit.Select(h[:6], h[:], field == mdb.HASH)) case mdb.LINK: - m.PushDownload(mdb.LINK, kit.Select("", f.Name(), !isDir), path.Join(root, name, f.Name())) + m.PushDownload(mdb.LINK, kit.Select("", f.Name(), !isDir), p) case mdb.SHOW: - switch p := m.MergeURL2("/share/local/"+path.Join(name, f.Name()), ice.POD, m.Option(ice.MSG_USERPOD)); kit.Ext(f.Name()) { - case "png", "jpg": + switch p := m.MergeURL2("/share/local/"+p, ice.POD, m.Option(ice.MSG_USERPOD)); kit.Ext(f.Name()) { + case PNG, JPG: m.PushImages(field, p) - case "mp4": + case MP4: m.PushVideos(field, p) default: m.Push(field, "") } - case "action": + case mdb.ACTION: if m.IsCliUA() || m.Option(ice.MSG_USERROLE) == aaa.VOID { break } @@ -178,27 +132,65 @@ func _dir_list(m *ice.Message, root string, name string, level int, deep bool, d } } - switch f.Name() { - case "node_modules", "pluged", "target", "trash": - continue - } - if deep && isDir { - _dir_list(m, root, path.Join(name, f.Name()), level+1, deep, dir_type, dir_reg, fields) + switch f.Name() { + case "node_modules", "pluged", "target", "trash": + continue // 禁用递归 + } + + _dir_list(m, root, pp, level+1, deep, dir_type, dir_reg, fields) } } return m } -func _dir_search(m *ice.Message, kind, name string) { - msg := _dir_list(m.Spawn(), PWD, "", 0, true, TYPE_BOTH, nil, kit.Split("time,type,name")) - msg.Tables(func(value ice.Maps) { - if !strings.Contains(value[mdb.NAME], name) { - return - } - if value[mdb.TYPE] == CAT { - value[mdb.TYPE] = kit.Ext(value[mdb.NAME]) - } - m.PushSearch(value) + +const ( + TYPE_ALL = "all" + TYPE_CAT = "cat" + TYPE_DIR = "dir" + TYPE_BOTH = "both" +) +const ( + DIR_ROOT = "dir_root" + DIR_TYPE = "dir_type" + DIR_DEEP = "dir_deep" + DIR_REG = "dir_reg" + + DIR_DEF_FIELDS = "time,path,size,action" + DIR_WEB_FIELDS = "time,size,path,action,link" + DIR_CLI_FIELDS = "path,size,time" +) +const ( + ROOT = "root" + TREE = "tree" + FULL = "full" + PATH = "path" + FILE = "file" + NAME = "name" + SIZE = "size" + LINE = "line" +) +const DIR = "dir" + +func init() { + Index.MergeCommands(ice.Commands{ + DIR: {Name: "dir path field auto upload", Help: "目录", Actions: ice.Actions{ + mdb.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { + m.Upload(m.Option(PATH)) + }}, + TRASH: {Name: "trash", Help: "删除", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(TRASH, m.Option(PATH)) + }}, + }, Hand: func(m *ice.Message, arg ...string) { + if m.Option(DIR_ROOT) != "" { + m.Log_SELECT(DIR_ROOT, m.Option(DIR_ROOT)) + } + _dir_list(m, kit.Select(PWD, m.Option(DIR_ROOT)), kit.Select(PWD, arg, 0), + 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), kit.Regexp(m.Option(DIR_REG)), + kit.Split(kit.Select(kit.Select(DIR_DEF_FIELDS, m.OptionFields()), kit.Join(kit.Slice(arg, 1))))) + m.SortTimeR(mdb.TIME) + m.StatusTimeCount() + }}, }) } @@ -210,66 +202,3 @@ func Dir(m *ice.Message, sort string) *ice.Message { m.Copy(m.Cmd(DIR, PWD).Sort(sort)) return m } -func MkdirAll(m *ice.Message, p string) error { - m.Log_EXPORT("mkdir", "dir", p) - return os.MkdirAll(p, ice.MOD_DIR) -} - -const ( - TYPE_ALL = "all" - TYPE_CAT = "cat" - TYPE_DIR = "dir" - TYPE_BOTH = "both" -) -const ( - DIR_PACK = "dir_pack" - DIR_ROOT = "dir_root" - DIR_TYPE = "dir_type" - DIR_DEEP = "dir_deep" - DIR_REG = "dir_reg" - - DIR_DEF_FIELDS = "time,path,size,action" - DIR_WEB_FIELDS = "time,size,path,action,link" - DIR_CLI_FIELDS = "path,size,time" -) -const DIR = "dir" - -func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - DIR: {Name: DIR, Help: "目录", Value: kit.Data()}, - }, Commands: ice.Commands{ - DIR: {Name: "dir path field... auto upload", Help: "目录", Actions: ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(mdb.RENDER, mdb.CREATE, m.CommandKey(), m.PrefixKey()) - }}, - mdb.SEARCH: {Name: "search type name", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { - if arg[0] == mdb.FOREACH { - return - } - _dir_search(m, arg[0], arg[1]) - }}, - mdb.RENDER: {Name: "render type name text", Help: "渲染", Hand: func(m *ice.Message, arg ...string) { - _dir_list(m, arg[2], arg[1], 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), - nil, kit.Split(kit.Select("time,size,type,path", m.OptionFields()))) - }}, - mdb.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { - m.Upload(m.Option(PATH)) - }}, - mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - os.Remove(m.Option(PATH)) - }}, - TRASH: {Name: "trash", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(TRASH, m.Option(PATH)) - }}, - }, Hand: func(m *ice.Message, arg ...string) { - if m.Option(DIR_ROOT) != "" { - m.Info("dir_root: %v", m.Option(DIR_ROOT)) - } - _dir_list(m, kit.Select(PWD, m.Option(DIR_ROOT)), kit.Select(PWD, arg, 0), - 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), kit.Regexp(m.Option(DIR_REG)), - kit.Split(kit.Select(kit.Select(DIR_DEF_FIELDS, m.OptionFields()), kit.Join(kit.Slice(arg, 1))))) - m.SortTimeR(mdb.TIME) - m.StatusTimeCount() - }}, - }}) -} diff --git a/base/nfs/find.go b/base/nfs/find.go index b3ce0bab..b31beda4 100644 --- a/base/nfs/find.go +++ b/base/nfs/find.go @@ -9,11 +9,11 @@ import ( const FIND = "find" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ FIND: {Name: "find path word auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { for _, file := range strings.Split(m.Cmdx("cli.system", FIND, PWD, "-name", arg[1]), ice.NL) { m.Push(FILE, strings.TrimPrefix(file, PWD)) } }}, - }}) + }) } diff --git a/base/nfs/grep.go b/base/nfs/grep.go index 9b5d647e..b872f8fd 100644 --- a/base/nfs/grep.go +++ b/base/nfs/grep.go @@ -5,10 +5,10 @@ import ice "shylinux.com/x/icebergs" const GREP = "grep" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ GREP: {Name: "grep path word auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { m.Option("cmd_dir", arg[0]) m.Split(m.Cmdx("cli.system", GREP, "--exclude=.[a-z]*", "--exclude-dir=.[a-z]*", "-rni", arg[1]), "file:line:text", ":") }}, - }}) + }) } diff --git a/base/nfs/nfs.go b/base/nfs/nfs.go index 0500d67b..173c51a8 100644 --- a/base/nfs/nfs.go +++ b/base/nfs/nfs.go @@ -1,9 +1,107 @@ package nfs -import ice "shylinux.com/x/icebergs" +import ( + "io" + "io/ioutil" + "os" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/toolkits/file" +) var Index = &ice.Context{Name: "nfs", Help: "存储模块"} func init() { ice.Index.Register(Index, nil, TAR, CAT, DIR, DEFS, SAVE, PUSH, COPY, LINK, TAIL, TRASH, GREP) } + +var DiskFile = file.NewDiskFile() +var PackFile = file.NewPackFile() + +func init() { file.Init(ice.Pulse.OptionFiles(DiskFile, PackFile)) } + +func StatFile(m *ice.Message, p string) (os.FileInfo, error) { + file := m.OptionFiles() + return file.StatFile(p) +} +func OpenFile(m *ice.Message, p string) (io.ReadCloser, error) { + file := m.OptionFiles() + return file.OpenFile(p) +} +func CreateFile(m *ice.Message, p string) (io.WriteCloser, string, error) { + file := m.OptionFiles() + return file.CreateFile(p) +} +func AppendFile(m *ice.Message, p string) (io.ReadWriteCloser, string, error) { + file := m.OptionFiles() + w, e := file.AppendFile(p) + return w, p, e +} +func WriteFile(m *ice.Message, p string, b []byte) error { + file := m.OptionFiles() + return file.WriteFile(p, b) +} + +func ReadDir(m *ice.Message, p string) ([]os.FileInfo, error) { + file := m.OptionFiles() + list, e := file.ReadDir(p) + for i := 0; i < len(list)-1; i++ { + for j := i + 1; j < len(list); j++ { + if list[i].Name() > list[j].Name() { + list[i], list[j] = list[j], list[i] + } + } + } + return list, e +} +func MkdirAll(m *ice.Message, p string) error { + file := m.OptionFiles() + return file.MkdirAll(p, ice.MOD_DIR) +} +func RemoveAll(m *ice.Message, p string) error { + file := m.OptionFiles() + return file.RemoveAll(p) +} +func Remove(m *ice.Message, p string) error { + file := m.OptionFiles() + return file.Remove(p) +} +func Rename(m *ice.Message, oldname string, newname string) error { + file := m.OptionFiles() + return file.Rename(oldname, newname) +} +func Symlink(m *ice.Message, oldname string, newname string) error { + file := m.OptionFiles() + return file.Symlink(oldname, newname) +} +func Link(m *ice.Message, oldname string, newname string) error { + file := m.OptionFiles() + return file.Link(oldname, newname) +} +func Close(m *ice.Message) { + file := m.OptionFiles() + file.Close() +} + +func ExistsFile(m *ice.Message, p string) bool { + file := m.OptionFiles() + if _, e := file.StatFile(p); e == nil { + return true + } + return false +} +func ReadFile(m *ice.Message, p string) ([]byte, error) { + file := m.OptionFiles() + if f, e := file.OpenFile(p); e == nil { + return ioutil.ReadAll(f) + } else { + return nil, e + } +} + +func NewWriteCloser(w func([]byte) (int, error), c func() error) io.WriteCloser { + return file.NewWriteCloser(w, c) +} +func NewReadCloser(r io.Reader) io.ReadCloser { + return file.NewReadCloser(r) +} diff --git a/base/nfs/pack.go b/base/nfs/pack.go new file mode 100644 index 00000000..36262808 --- /dev/null +++ b/base/nfs/pack.go @@ -0,0 +1,63 @@ +package nfs + +import ( + "io" + "io/ioutil" + "path" + "strings" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" + kit "shylinux.com/x/toolkits" +) + +const PACK = "pack" + +func init() { + pack := PackFile + Index.MergeCommands(ice.Commands{ + PACK: {Name: "pack path auto upload create", Help: "文件系统", Actions: ice.Actions{ + mdb.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { + if b, h, e := m.R.FormFile(mdb.UPLOAD); m.Assert(e) { + defer b.Close() + if f, p, e := pack.CreateFile(path.Join(m.Option(PATH), h.Filename)); m.Assert(e) { + defer f.Close() + if n, e := io.Copy(f, b); e == nil { + m.Log_IMPORT(FILE, p, SIZE, n) + } + } + } + }}, + mdb.CREATE: {Name: "create path=h1/h2/hi.txt text=hello", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + if f, _, e := pack.CreateFile(m.Option(PATH)); e == nil { + defer f.Close() + f.Write([]byte(m.Option(mdb.TEXT))) + } + }}, + mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { + pack.Remove(path.Clean(m.Option(PATH))) + }}, + }, Hand: func(m *ice.Message, arg ...string) { + p := kit.Select("", arg, 0) + if p != "" && !strings.HasSuffix(p, PS) { + if f, e := pack.OpenFile(p); e == nil { + defer f.Close() + if b, e := ioutil.ReadAll(f); e == nil { + m.Echo(string(b)) + } + } + return + } + + ls, _ := pack.ReadDir(p) + for _, f := range ls { + m.Push(mdb.TIME, f.ModTime().Format(ice.MOD_TIME)) + m.Push(PATH, path.Join(p, f.Name())+kit.Select("", PS, f.IsDir())) + m.Push(SIZE, f.Size()) + } + m.Sort("time,path") + m.PushAction(mdb.REMOVE) + m.StatusTimeCount() + }}, + }) +} diff --git a/base/nfs/save.go b/base/nfs/save.go index c97a1a88..cd52f049 100644 --- a/base/nfs/save.go +++ b/base/nfs/save.go @@ -1,17 +1,16 @@ package nfs import ( + "fmt" "io" - "os" "path" - "strings" ice "shylinux.com/x/icebergs" kit "shylinux.com/x/toolkits" ) func _defs_file(m *ice.Message, name string, text ...string) { - if kit.FileExists(path.Join(m.Option(DIR_ROOT), name)) { + if ExistsFile(m, path.Join(m.Option(DIR_ROOT), name)) { return } for i, v := range text { @@ -21,11 +20,11 @@ func _defs_file(m *ice.Message, name string, text ...string) { _save_file(m, name, text...) } func _save_file(m *ice.Message, name string, text ...string) { - if f, p, e := kit.Create(path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) { + if f, p, e := CreateFile(m, path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) { defer f.Close() for _, v := range text { - if n, e := f.WriteString(v); m.Assert(e) { + if n, e := fmt.Fprint(f, v); m.Assert(e) { m.Log_EXPORT(FILE, p, SIZE, n) } } @@ -33,16 +32,11 @@ func _save_file(m *ice.Message, name string, text ...string) { } } func _push_file(m *ice.Message, name string, text ...string) { - p := path.Join(m.Option(DIR_ROOT), name) - if strings.Contains(p, ice.PS) { - MkdirAll(m, path.Dir(p)) - } - - if f, e := os.OpenFile(p, os.O_WRONLY|os.O_APPEND|os.O_CREATE, ice.MOD_FILE); m.Assert(e) { + if f, p, e := AppendFile(m, path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) { defer f.Close() for _, k := range text { - if n, e := f.WriteString(k); m.Assert(e) { + if n, e := fmt.Fprint(f, k); m.Assert(e) { m.Log_EXPORT(FILE, p, SIZE, n) } } @@ -50,11 +44,11 @@ func _push_file(m *ice.Message, name string, text ...string) { } } func _copy_file(m *ice.Message, name string, from ...string) { - if f, p, e := kit.Create(path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) { + if f, p, e := CreateFile(m, path.Join(m.Option(DIR_ROOT), name)); m.Assert(e) { defer f.Close() for _, v := range from { - if s, e := os.Open(v); !m.Warn(e, ice.ErrNotFound, name) { + if s, e := OpenFile(m, path.Join(m.Option(DIR_ROOT), v)); !m.Warn(e, ice.ErrNotFound, name) { defer s.Close() if n, e := io.Copy(f, s); !m.Warn(e, ice.ErrNotFound, name) { @@ -67,23 +61,28 @@ func _copy_file(m *ice.Message, name string, from ...string) { } } func _link_file(m *ice.Message, name string, from string) { - if from == "" || m.Warn(!kit.FileExists(from), ice.ErrNotFound, from) { + if m.Warn(from == "", ice.ErrNotValid, from) { return } - os.Remove(name) + name = path.Join(m.Option(DIR_ROOT), name) + from = path.Join(m.Option(DIR_ROOT), from) + if m.Warn(!ExistsFile(m, from), ice.ErrNotFound, from) { + return + } + Remove(m, name) MkdirAll(m, path.Dir(name)) - if e := os.Link(from, name); e != nil { - if m.Warn(os.Symlink(from, name), ice.ErrWarn, from) { + if m.Warn(Link(m, from, name)) { + if m.Warn(Symlink(m, from, name), ice.ErrWarn, from) { return } } - m.Log_EXPORT(name, "from", from) + m.Log_EXPORT(FILE, name, FROM, from) m.Echo(name) - } const ( CONTENT = "content" + FROM = "from" ) const DEFS = "defs" const SAVE = "save" @@ -92,7 +91,7 @@ const COPY = "copy" const LINK = "link" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ DEFS: {Name: "defs file text...", Help: "默认", Hand: func(m *ice.Message, arg ...string) { _defs_file(m, arg[0], arg[1:]...) }}, @@ -119,5 +118,5 @@ func init() { LINK: {Name: "link file from", Help: "链接", Hand: func(m *ice.Message, arg ...string) { _link_file(m, arg[0], arg[1]) }}, - }}) + }) } diff --git a/base/nfs/tail.go b/base/nfs/tail.go index 53dd1b29..5252663b 100644 --- a/base/nfs/tail.go +++ b/base/nfs/tail.go @@ -36,11 +36,7 @@ func _tail_count(m *ice.Message, name string) string { const TAIL = "tail" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - TAIL: {Name: TAIL, Help: "日志流", Value: kit.Data( - mdb.SHORT, mdb.NAME, mdb.FIELD, "time,id,file,text", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TAIL: {Name: "tail name id auto page filter:text create", Help: "日志流", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Richs(TAIL, "", mdb.FOREACH, func(key string, value ice.Map) { @@ -62,7 +58,7 @@ func init() { mdb.CREATE: {Name: "create file name", Help: "创建", Hand: func(m *ice.Message, arg ...string) { _tail_create(m, arg...) }}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,id,file,text")), Hand: func(m *ice.Message, arg ...string) { m.Fields(len(kit.Slice(arg, 0, 2)), "time,name,count,file", m.Config(mdb.FIELD)) m.OptionPage(kit.Slice(arg, 2)...) @@ -76,5 +72,5 @@ func init() { m.StatusTimeCountTotal(_tail_count(m, arg[0])) } }}, - }}) + }) } diff --git a/base/nfs/tar.go b/base/nfs/tar.go index ffd7f164..bfd5c773 100644 --- a/base/nfs/tar.go +++ b/base/nfs/tar.go @@ -15,7 +15,7 @@ import ( const TAR = "tar" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TAR: {Name: "tar file path auto", Help: "打包", Actions: ice.Actions{ mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 1 { @@ -63,18 +63,18 @@ func init() { } header.Name = strings.TrimPrefix(p, dir_root+ice.PS) - if err = t.WriteHeader(header); m.Warn(err != nil, "err: %v", err) { + if err = t.WriteHeader(header); m.Warn(err) { return } file, err := os.Open(p) - if m.Warn(err != nil, "err: %v", err) { + if m.Warn(err) { return } defer file.Close() m.PushNoticeGrow(kit.Format("%v %v %v\n", header.Name, kit.FmtSize(f.Size()), kit.FmtSize(total))) - if _, err = io.Copy(t, file); m.Warn(err != nil, "err: %v", err) { + if _, err = io.Copy(t, file); m.Warn(err) { return } @@ -84,5 +84,5 @@ func init() { } m.StatusTimeCountTotal(kit.FmtSize(total)) }}, - }}) + }) } diff --git a/base/nfs/trash.go b/base/nfs/trash.go index 6eb10f24..8c291eac 100644 --- a/base/nfs/trash.go +++ b/base/nfs/trash.go @@ -1,7 +1,6 @@ package nfs import ( - "os" "path" ice "shylinux.com/x/icebergs" @@ -10,61 +9,59 @@ import ( ) func _trash_create(m *ice.Message, name string) { - if s, e := os.Stat(name); m.Assert(e) { - p := path.Join(ice.VAR_TRASH, path.Base(name)) - if !s.IsDir() { - if f, e := os.Open(name); m.Assert(e) { - defer f.Close() - p = path.Join(ice.VAR_TRASH, kit.HashsPath(f)) - } + if m.Warn(name == "", ice.ErrNotValid, name) { + return + } + s, e := StatFile(m, name) + if m.Warn(e, ice.ErrNotFound, name) { + return + } + p := path.Join(ice.VAR_TRASH, path.Base(name)) + if !s.IsDir() { + if f, e := OpenFile(m, name); m.Assert(e) { + defer f.Close() + p = path.Join(ice.VAR_TRASH, kit.HashsPath(f)) } + } - MkdirAll(m, path.Dir(p)) - if os.RemoveAll(p); !m.Warn(os.Rename(name, p)) { - m.Cmd(mdb.INSERT, TRASH, "", mdb.HASH, FILE, p, FROM, name) - } + MkdirAll(m, path.Dir(p)) + if RemoveAll(m, p); !m.Warn(Rename(m, name, p)) { + mdb.HashCreate(m, FROM, name, FILE, p) } } -const ( - FROM = "from" -) const TRASH = "trash" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - TRASH: {Name: TRASH, Help: "回收站", Value: kit.Data( - mdb.SHORT, FROM, mdb.FIELD, "time,hash,file,from", PATH, ice.VAR_TRASH, - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TRASH: {Name: "trash hash auto prunes", Help: "回收站", Actions: ice.MergeAction(ice.Actions{ mdb.REVERT: {Name: "revert", Help: "恢复", Hand: func(m *ice.Message, arg ...string) { - os.Rename(m.Option(FILE), m.Option(FROM)) - m.Cmd(mdb.DELETE, TRASH, "", mdb.HASH, m.OptionSimple(mdb.HASH)) + Rename(m, m.Option(FILE), m.Option(FROM)) + mdb.HashRemove(m, m.OptionSimple(mdb.HASH)) }}, mdb.CREATE: {Name: "create path", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - p := path.Join(m.Config(PATH), path.Base(m.Option(PATH))) - os.RemoveAll(p) - if os.MkdirAll(path.Dir(p), ice.MOD_DIR); !m.Warn(os.Rename(m.Option(PATH), p)) { + p := path.Join(ice.VAR_TRASH, path.Base(m.Option(PATH))) + RemoveAll(m, p) + if MkdirAll(m, path.Dir(p)); !m.Warn(Rename(m, m.Option(PATH), p)) { m.Echo(p) } }}, mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - os.Remove(m.Option(FILE)) - m.Cmd(mdb.DELETE, TRASH, "", mdb.HASH, m.OptionSimple(mdb.HASH)) + Remove(m, m.Option(FILE)) + mdb.HashRemove(m, m.OptionSimple(mdb.HASH)) }}, mdb.PRUNES: {Name: "prunes before@date", Help: "清理", Hand: func(m *ice.Message, arg ...string) { mdb.HashPrunes(m, func(value ice.Maps) bool { - os.Remove(value[FILE]) + Remove(m, value[FILE]) return false }) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { - if mdb.HashSelect(m, arg...); len(arg) == 0 || !kit.FileExists(arg[0]) { + }, mdb.HashAction(mdb.SHORT, FROM, mdb.FIELD, "time,hash,file,from")), Hand: func(m *ice.Message, arg ...string) { + if mdb.HashSelect(m, arg...); len(arg) == 0 || !ExistsFile(m, arg[0]) { m.PushAction(mdb.REVERT, mdb.REMOVE) return } _trash_create(m, arg[0]) }}, - }}) + }) } diff --git a/base/ssh/scripts.go b/base/ssh/scripts.go index 26b1fed5..a42a2c0c 100644 --- a/base/ssh/scripts.go +++ b/base/ssh/scripts.go @@ -13,21 +13,21 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" ) -func Render(msg *ice.Message, cmd string, args ...ice.Any) (res string) { - switch arg := kit.Simple(args...); cmd { +func Render(msg *ice.Message, cmd string, arg ...ice.Any) (res string) { + switch args := kit.Simple(arg...); cmd { case ice.RENDER_VOID: return res case ice.RENDER_RESULT: - if len(arg) > 0 { - msg.Resultv(arg) + if len(args) > 0 { + msg.Resultv(args) } res = msg.Result() - default: if res = msg.Result(); res == "" { res = msg.Table().Result() @@ -110,22 +110,18 @@ func (f *Frame) alias(m *ice.Message, ls []string) []string { return ls } func (f *Frame) parse(m *ice.Message, line string) string { - // for _, one := range kit.Split(line, ";", ";", ";") { - for _, one := range kit.Simple(line) { - msg := m.Spawn(f.target) - ls := f.change(msg, f.alias(msg, kit.Split(strings.TrimSpace(one)))) - if len(ls) == 0 { - continue - } - - msg.Render("", kit.List()) - if msg.Cmdy(ls[0], ls[1:]); msg.IsErrNotFound() { - msg.SetResult().Cmdy(cli.SYSTEM, ls) - } - - f.res = Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]ice.Any)...) + msg := m.Spawn(f.target) + ls := f.change(msg, f.alias(msg, kit.Split(strings.TrimSpace(line)))) + if len(ls) == 0 { + return "" } - m.Sleep("10ms") + + msg.Render("", kit.List()) + if msg.Cmdy(ls); msg.IsErrNotFound() { + msg.SetResult().Cmdy(cli.SYSTEM, ls) + } + + f.res = Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]ice.Any)...) return "" } func (f *Frame) scan(m *ice.Message, h, line string) *Frame { @@ -142,22 +138,14 @@ func (f *Frame) scan(m *ice.Message, h, line string) *Frame { m.I, m.O = f.stdin, f.stdout bio := bufio.NewScanner(f.stdin) - for f.prompt(m, ps...); bio.Scan() && f.stdin != nil; f.prompt(m, ps...) { - if h == STDIO { - if len(bio.Text()) == 0 { - continue // 空行 - } - m.Cmdx(mdb.INSERT, SOURCE, kit.Keys(mdb.HASH, h), mdb.LIST, mdb.TEXT, bio.Text()) + for f.prompt(m, ps...); f.stdin != nil && bio.Scan(); f.prompt(m, ps...) { + if len(bio.Text()) == 0 && h == STDIO { + continue // 空行 } f.count++ + mdb.ZoneInsert(m.Spawn(), mdb.HASH, h, mdb.TEXT, bio.Text()) - if len(bio.Text()) == 0 { - if strings.Count(line, "`")%2 == 1 { - line += ice.NL - } - continue // 空行 - } if strings.HasSuffix(bio.Text(), "\\") { line += bio.Text()[:len(bio.Text())-1] ps = f.ps2 @@ -170,11 +158,8 @@ func (f *Frame) scan(m *ice.Message, h, line string) *Frame { } if strings.HasPrefix(strings.TrimSpace(line), "#") { line = "" - continue + continue // 注释 } - // if line = strings.Split(line, " # ")[0]; len(line) == 0 { - // continue // 注释 - // } if ps = f.ps1; f.stdout == os.Stdout { if ice.Info.Colors { f.printf(m, "\033[0m") // 清空格式 @@ -195,27 +180,28 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { m.Optionv(FRAME, f) switch f.source = kit.Select(STDIO, arg, 0); f.source { case STDIO: // 终端交互 - m.Cap(ice.CTX_STREAM, f.source) - if f.target == nil { + if m.Cap(ice.CTX_STREAM, f.source); f.target == nil { f.target = m.Target() } r, w, _ := os.Pipe() - m.Go(func() { io.Copy(w, os.Stdin) }) - f.stdin, f.stdout = r, os.Stdout - f.pipe = w + go func() { io.Copy(w, os.Stdin) }() + f.pipe, f.stdin, f.stdout = w, r, os.Stdout m.Option(ice.MSG_OPTS, ice.MSG_USERNAME) - m.Conf(SOURCE, kit.Keys(mdb.HASH, STDIO, kit.Keym(mdb.NAME)), STDIO) m.Conf(SOURCE, kit.Keys(mdb.HASH, STDIO, kit.Keym(mdb.TIME)), m.Time()) - f.count = kit.Int(m.Conf(SOURCE, kit.Keys(mdb.HASH, STDIO, kit.Keym(mdb.COUNT)))) + 1 f.scan(m, STDIO, "") default: // 脚本文件 - if strings.Contains(m.Option(ice.MSG_SCRIPT), ice.PS) { - f.source = path.Join(path.Dir(m.Option(ice.MSG_SCRIPT)), f.source) + if m.Option(ice.MSG_SCRIPT) != "" { + ls := kit.Split(m.Option(ice.MSG_SCRIPT), ice.PS) + for i := len(ls) - 1; i > 0; i-- { + if p := path.Join(path.Join(ls[:i]...), f.source); nfs.ExistsFile(m, p) { + f.source = p + } + } } m.Option(ice.MSG_SCRIPT, f.source) f.target = m.Source() @@ -224,13 +210,12 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { return true // 查找失败 } else { buf := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS)) + f.stdin, f.stdout = bytes.NewBufferString(msg.Result()), buf defer func() { m.Echo(buf.String()) }() - - f.stdin, f.stdout = bytes.NewBuffer([]byte(msg.Result())), buf } f.count = 1 - f.scan(m, m.Cmdx(mdb.INSERT, SOURCE, "", mdb.HASH, mdb.NAME, f.source), "") + f.scan(m, mdb.HashCreate(m.Spawn(), mdb.NAME, f.source).Result(), "") } return true } @@ -266,16 +251,14 @@ func init() { PS2, []ice.Any{mdb.COUNT, " ", TARGET, "> "}, )}, }, Commands: ice.Commands{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {}}, SOURCE: {Name: "source file", Help: "脚本解析", Actions: ice.MergeAction(ice.Actions{ - "repeat": {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) { + gdb.RESTART: {Name: "restart", Help: "执行", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(SCREEN, m.Option(mdb.TEXT)) m.ProcessInner() }}, }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { - if len(arg) > 0 && kit.Ext(arg[0]) == ice.SHY { - (&Frame{}).Start(m, arg...) - return // 脚本解析 + if f, ok := m.Target().Server().(*Frame); ok { + f.Spawn(m, m.Target()).Start(m, arg...) } }}, TARGET: {Name: "target name run", Help: "当前模块", Hand: func(m *ice.Message, arg ...string) { @@ -284,26 +267,30 @@ func init() { f.prompt(m) }}, PROMPT: {Name: "prompt arg run", Help: "命令提示", Hand: func(m *ice.Message, arg ...string) { - f := m.Optionv(FRAME).(*Frame) - f.ps1 = arg - f.prompt(m) + if f, ok := m.Optionv(FRAME).(*Frame); ok { + f.ps1 = arg + f.prompt(m) + } }}, PRINTF: {Name: "printf run text", Help: "输出显示", Hand: func(m *ice.Message, arg ...string) { - f := m.Optionv(FRAME).(*Frame) - f.printf(m, arg[0]) + if f, ok := m.Optionv(FRAME).(*Frame); ok { + f.printf(m, arg[0]) + } }}, SCREEN: {Name: "screen run text", Help: "输出命令", Hand: func(m *ice.Message, arg ...string) { - f := m.Optionv(FRAME).(*Frame) - for _, line := range kit.Split(arg[0], ice.NL, ice.NL) { - fmt.Fprintf(f.pipe, line+ice.NL) - f.printf(m, line+ice.NL) - m.Sleep300ms() + if f, ok := m.Optionv(FRAME).(*Frame); ok { + for _, line := range kit.Split(arg[0], ice.NL, ice.NL) { + fmt.Fprintf(f.pipe, line+ice.NL) + f.printf(m, line+ice.NL) + m.Sleep300ms() + } + m.Echo(f.res) } - m.Echo(f.res) }}, RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, arg ...string) { - f := m.Optionv(FRAME).(*Frame) - f.Close(m, arg...) + if f, ok := m.Optionv(FRAME).(*Frame); ok { + f.Close(m, arg...) + } }}, }}) } diff --git a/base/tcp/client.go b/base/tcp/client.go index 12b20db4..8d65700d 100644 --- a/base/tcp/client.go +++ b/base/tcp/client.go @@ -36,7 +36,6 @@ func (c *Conn) Close() error { func _client_dial(m *ice.Message, arg ...string) { c, e := net.Dial(TCP, m.Option(HOST)+ice.DF+m.Option(PORT)) - c = &Conn{m: m, s: &Stat{}, Conn: c} if e == nil { defer c.Close() @@ -57,8 +56,10 @@ func _client_dial(m *ice.Message, arg ...string) { break } } - default: + case nil: c.Write([]byte("hello world\n")) + default: + m.ErrorNotImplement(cb) } } @@ -77,25 +78,18 @@ const ( const CLIENT = "client" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - CLIENT: {Name: CLIENT, Help: "客户端", Value: kit.Data( - mdb.FIELD, "time,hash,status,type,name,host,port,error,nread,nwrite", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ CLIENT: {Name: "client hash auto prunes", Help: "客户端", Actions: ice.MergeAction(ice.Actions{ ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { - m.Richs(CLIENT, "", mdb.FOREACH, func(key string, value ice.Map) { - kit.Value(value, kit.Keym(STATUS), CLOSE) - }) - m.Cmdy(SERVER, mdb.PRUNES) + m.Conf(m.PrefixKey(), "", "") }}, DIAL: {Name: "dial type name port=9010 host=", Help: "连接", Hand: func(m *ice.Message, arg ...string) { _client_dial(m, arg...) }}, - }, mdb.HashActionStatus()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashActionStatus(mdb.FIELD, "time,hash,status,type,name,host,port,error,nread,nwrite")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) { m.PushButton(kit.Select("", mdb.REMOVE, value[STATUS] == OPEN)) }) }}, - }}) + }) } diff --git a/base/tcp/host.go b/base/tcp/host.go index 15562e9a..cd6ac8a0 100644 --- a/base/tcp/host.go +++ b/base/tcp/host.go @@ -59,13 +59,6 @@ func _islocalhost(m *ice.Message, ip string) (ok bool) { } return false } -func IsLocalHost(m *ice.Message, ip string) bool { return _islocalhost(m, ip) } -func ReplaceLocalhost(m *ice.Message, url string) string { - if strings.Contains(url, "://"+LOCALHOST) { - url = strings.Replace(url, "://"+LOCALHOST, "://"+m.Cmd(HOST).Append(aaa.IP), 1) - } - return url -} const ( LOCALHOST = "localhost" @@ -73,16 +66,10 @@ const ( const HOST = "host" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - HOST: {Name: HOST, Help: "主机", Value: kit.Data( - aaa.BLACK, kit.Data(mdb.SHORT, mdb.TEXT), aaa.WHITE, kit.Data(mdb.SHORT, mdb.TEXT), - )}, - }, Commands: ice.Commands{ - HOST: {Name: "host name auto", Help: "主机", Actions: ice.Actions{ + Index.MergeCommands(ice.Commands{ + HOST: {Name: "host name auto", Help: "主机", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(HOST).Tables(func(value ice.Maps) { - m.Cmd(HOST, aaa.WHITE, value[aaa.IP]) - }) + m.Cmd(HOST).Tables(func(value ice.Maps) { m.Cmd(HOST, aaa.WHITE, value[aaa.IP]) }) }}, aaa.BLACK: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) { m.Log_CREATE(aaa.BLACK, arg[0]) @@ -92,8 +79,16 @@ func init() { m.Log_CREATE(aaa.WHITE, arg[0]) m.Rich(HOST, kit.Keym(aaa.WHITE), kit.Dict(mdb.TEXT, arg[0])) }}, - }, Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(aaa.BLACK, kit.Data(mdb.SHORT, mdb.TEXT), aaa.WHITE, kit.Data(mdb.SHORT, mdb.TEXT))), Hand: func(m *ice.Message, arg ...string) { _host_list(m, kit.Select("", arg, 0)) }}, - }}) + }) +} + +func IsLocalHost(m *ice.Message, ip string) bool { return _islocalhost(m, ip) } +func ReplaceLocalhost(m *ice.Message, url string) string { + if strings.Contains(url, "://"+LOCALHOST) { + url = strings.Replace(url, "://"+LOCALHOST, "://"+m.Cmd(HOST).Append(aaa.IP), 1) + } + return url } diff --git a/base/tcp/port.go b/base/tcp/port.go index 314ee475..e52cbf88 100644 --- a/base/tcp/port.go +++ b/base/tcp/port.go @@ -6,7 +6,6 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" - "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" @@ -25,12 +24,12 @@ func _port_right(m *ice.Message, arg ...string) string { c.Close() continue } - p := path.Join(m.Conf(cli.DAEMON, kit.Keym(nfs.PATH)), kit.Format(i)) - if kit.FileExists(p) { + p := path.Join(ice.USR_LOCAL_DAEMON, kit.Format(i)) + if nfs.ExistsFile(m, p) { continue } - nfs.MkdirAll(m, p) + nfs.MkdirAll(m, p) m.Log_SELECT(PORT, i) return m.Config(CURRENT, i) } @@ -46,10 +45,8 @@ const ( const PORT = "port" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - PORT: {Name: PORT, Help: "端口", Value: kit.Data(BEGIN, 10000, CURRENT, 10000, END, 20000)}, - }, Commands: ice.Commands{ - PORT: {Name: "port port path auto", Help: "端口", Actions: ice.Actions{ + Index.MergeCommands(ice.Commands{ + PORT: {Name: "port port path auto", Help: "端口", Actions: ice.MergeAction(ice.Actions{ aaa.RIGHT: {Name: "right", Help: "分配", Hand: func(m *ice.Message, arg ...string) { m.Echo(_port_right(m, arg...)) }}, @@ -58,33 +55,33 @@ func init() { m.Cmd(nfs.TRASH, path.Join(ice.USR_LOCAL_DAEMON, m.Option(PORT))) } }}, - }, Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 { - current := kit.Int(m.Config(BEGIN)) - m.Option(nfs.DIR_ROOT, ice.USR_LOCAL_DAEMON) - m.Cmd(nfs.DIR, nfs.PWD, nfs.DIR_CLI_FIELDS).Tables(func(value ice.Maps) { - bin := m.Cmd(nfs.DIR, path.Join(value[nfs.PATH], ice.BIN), nfs.DIR_CLI_FIELDS).Append(nfs.PATH) - if bin == "" { - bin = m.Cmd(nfs.DIR, path.Join(value[nfs.PATH], "sbin"), nfs.DIR_CLI_FIELDS).Append(nfs.PATH) - } - port := kit.Int(path.Base(value[nfs.PATH])) - if port > current { - current = port - } - - m.Push(mdb.TIME, value[mdb.TIME]) - m.Push(PORT, port) - m.Push(nfs.SIZE, value[nfs.SIZE]) - m.Push(ice.BIN, bin) - }) - m.SortInt(PORT) - m.PushAction(nfs.TRASH) - m.Config(CURRENT, current) - m.StatusTimeCount(m.ConfigSimple(BEGIN, CURRENT, END)) + }, mdb.HashAction(BEGIN, 10000, CURRENT, 10000, END, 20000)), Hand: func(m *ice.Message, arg ...string) { + if len(arg) > 0 { + m.Cmdy(nfs.DIR, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_DAEMON, arg[0]))) return } - m.Option(nfs.DIR_ROOT, path.Join(m.Conf(cli.DAEMON, kit.Keym(nfs.PATH)), arg[0])) - m.Cmdy(nfs.DIR, arg[1:]) + + current := kit.Int(m.Config(BEGIN)) + m.Option(nfs.DIR_ROOT, ice.USR_LOCAL_DAEMON) + m.Cmd(nfs.DIR, nfs.PWD, nfs.DIR_CLI_FIELDS).Tables(func(value ice.Maps) { + bin := m.Cmd(nfs.DIR, path.Join(value[nfs.PATH], ice.BIN), nfs.DIR_CLI_FIELDS).Append(nfs.PATH) + if bin == "" { + bin = m.Cmd(nfs.DIR, path.Join(value[nfs.PATH], "sbin"), nfs.DIR_CLI_FIELDS).Append(nfs.PATH) + } + port := kit.Int(path.Base(value[nfs.PATH])) + if port > current { + current = port + } + + m.Push(mdb.TIME, value[mdb.TIME]) + m.Push(PORT, port) + m.Push(nfs.SIZE, value[nfs.SIZE]) + m.Push(ice.BIN, bin) + }) + m.SortInt(PORT) + m.PushAction(nfs.TRASH) + m.Config(CURRENT, current) + m.StatusTimeCount(m.ConfigSimple(BEGIN, CURRENT, END)) }}, - }}) + }) } diff --git a/base/tcp/server.go b/base/tcp/server.go index 9bd7566a..1030b122 100644 --- a/base/tcp/server.go +++ b/base/tcp/server.go @@ -19,7 +19,7 @@ type Listener struct { func (l Listener) Accept() (net.Conn, error) { c, e := l.Listener.Accept() l.s.nc += 1 - return &Conn{m: l.m, h: "", s: &Stat{}, Conn: c}, e + return &Conn{m: l.m, s: &Stat{}, Conn: c}, e } func (l Listener) Close() error { l.m.Cmd(mdb.MODIFY, SERVER, "", mdb.HASH, mdb.HASH, l.h, STATUS, CLOSE) @@ -28,10 +28,8 @@ func (l Listener) Close() error { func _server_listen(m *ice.Message, arg ...string) { l, e := net.Listen(TCP, m.Option(HOST)+":"+m.Option(PORT)) - h := m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH, arg, - STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e)) - - l = &Listener{m: m, h: h, s: &Stat{}, Listener: l} + l = &Listener{m: m, h: m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH, + arg, STATUS, kit.Select(ERROR, OPEN, e == nil), ERROR, kit.Format(e), kit.Dict(mdb.TARGET, l)), s: &Stat{}, Listener: l} if e == nil { defer l.Close() } @@ -85,25 +83,28 @@ const ( const SERVER = "server" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SERVER: {Name: SERVER, Help: "服务器", Value: kit.Data( - mdb.FIELD, "time,hash,status,type,name,host,port,error,nconn", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SERVER: {Name: "server hash auto prunes", Help: "服务器", Actions: ice.MergeAction(ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + m.Conf("", mdb.HASH, "") + }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { - m.Richs(SERVER, "", mdb.FOREACH, func(key string, value ice.Map) { - kit.Value(value, kit.Keym(STATUS), CLOSE) + mdb.HashSelectValue(m, func(target ice.Any) { + if l, ok := target.(net.Listener); ok { + l.Close() + } + if l, ok := target.(*Listener); ok { + l.Close() + } }) - m.Cmdy(SERVER, mdb.PRUNES) }}, LISTEN: {Name: "LISTEN type name port=9030 host=", Help: "监听", Hand: func(m *ice.Message, arg ...string) { _server_listen(m, arg...) }}, - }, mdb.HashActionStatus()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashActionStatus(mdb.FIELD, "time,hash,status,type,name,host,port,error,nconn")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) { m.PushButton(kit.Select("", mdb.REMOVE, value[STATUS] == CLOSE)) }) }}, - }}) + }) } diff --git a/base/web/story.go b/base/web/_story.go similarity index 99% rename from base/web/story.go rename to base/web/_story.go index 98c76ba7..7b75cd79 100644 --- a/base/web/story.go +++ b/base/web/_story.go @@ -426,5 +426,4 @@ func _story_commit(m *ice.Message, arg ...string) { value["list"] = list } m.Echo(list) - } diff --git a/base/web/broad.go b/base/web/broad.go index 729cb8b5..21fa678d 100644 --- a/base/web/broad.go +++ b/base/web/broad.go @@ -5,85 +5,86 @@ import ( "strings" ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" ) -func _udp_addr(m *ice.Message, host, port string) *net.UDPAddr { +func _broad_addr(m *ice.Message, host, port string) *net.UDPAddr { addr, err := net.ResolveUDPAddr("udp4", kit.Format("%s:%s", host, port)) m.Assert(err) return addr } -func _udp_broad(m *ice.Message, host, port string, remote_host, remote_port string) { - if s, e := net.DialUDP("udp", nil, _udp_addr(m, remote_host, remote_port)); m.Assert(e) { +func _broad_send(m *ice.Message, host, port string, remote_host, remote_port string) { + if s, e := net.DialUDP("udp", nil, _broad_addr(m, remote_host, remote_port)); m.Assert(e) { defer s.Close() msg := m.Spawn(kit.Dict(tcp.HOST, host, tcp.PORT, port)) - m.Debug("broad %v to %v:%v", msg.FormatMeta(), remote_host, remote_port) + m.Log_EXPORT(BROAD, msg.FormatMeta(), "to", remote_host+ice.DF+remote_port) s.Write([]byte(msg.FormatMeta())) } } -func _serve_udp(m *ice.Message, host, port string) { - m.Cmd(BROAD, mdb.CREATE, tcp.HOST, host, tcp.PORT, port) - _udp_broad(m, host, port, "255.255.255.255", "9020") - - if s, e := net.ListenUDP("udp", _udp_addr(m, "0.0.0.0", port)); m.Assert(e) { +func _broad_serve(m *ice.Message, host, port string) { + _broad_send(m, host, port, "255.255.255.255", "9020") + if s, e := net.ListenUDP("udp", _broad_addr(m, "0.0.0.0", port)); m.Assert(e) { defer s.Close() - m.Debug("listen %v %v", host, port) + m.Cmd(BROAD, mdb.CREATE, tcp.HOST, host, tcp.PORT, port, kit.Dict(mdb.TARGET, s)) - buf := make([]byte, 1024) + buf := make([]byte, ice.MOD_BUFS) for { n, addr, err := s.ReadFromUDP(buf[:]) if err != nil { - m.Debug("what %v", err) - continue + break } - m.Debug("recv %v %v", string(buf[:n]), addr) + m.Log_IMPORT(BROAD, string(buf[:n]), "from", addr) msg := m.Spawn(buf[:n]) if m.Cmd(BROAD, kit.Format("%s,%s", msg.Option(tcp.HOST), msg.Option(tcp.PORT))).Length() > 0 { continue } - if remote, err := net.ResolveUDPAddr("udp4", kit.Format("%s:%s", msg.Option(tcp.HOST), msg.Option(tcp.PORT))); err == nil { + if remote, err := net.ResolveUDPAddr("udp4", kit.Format("%s:%s", msg.Option(tcp.HOST), msg.Option(tcp.PORT))); !m.Warn(err) { m.Cmd(BROAD).Tables(func(value ice.Maps) { - m.Debug("broad %v to %v", kit.Format(value), kit.Format(remote)) + m.Log_EXPORT(BROAD, kit.Format(value), "to", kit.Format(remote)) s.WriteToUDP([]byte(m.Spawn(value).FormatMeta()), remote) }) m.Cmd(BROAD, mdb.CREATE, msg.OptionSimple(tcp.HOST, tcp.PORT)) - } else { - m.Debug("what %v", err) } } } } func _broad_search(m *ice.Message, kind, name, text string, arg ...string) { - m.Richs(BROAD, nil, mdb.FOREACH, func(key string, value ice.Map) { - if value = kit.GetMeta(value); !strings.Contains(kit.Format(value[tcp.HOST]), name) { + mdb.HashSelectValue(m, func(value ice.Map) { + if !strings.Contains(kit.Format(value[tcp.HOST]), name) { return } - m.PushSearch(mdb.TYPE, "friend", mdb.TEXT, kit.Format("http://%s:%s", value[tcp.HOST], value[tcp.PORT]), value) + m.PushSearch(mdb.TYPE, FRIEND, mdb.TEXT, kit.Format("http://%s:%s", value[tcp.HOST], value[tcp.PORT]), value) }) } const BROAD = "broad" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ - BROAD: {Name: "broad hash auto", Help: "广播", Actions: ice.MergeAction(ice.Actions{ + Index.MergeCommands(ice.Commands{ + BROAD: {Name: "broad hash auto serve", Help: "广播", Actions: ice.MergeAction(ice.Actions{ + ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { + mdb.HashSelectValue(m, func(target ice.Any) { + if c, ok := target.(*net.UDPConn); ok { + c.Close() + } + }) + }}, + mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { + _broad_search(m, arg[0], arg[1], kit.Select("", arg, 2)) + }}, SERVE: {Name: "broad port=9020", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { - _serve_udp(m, m.Cmd(tcp.HOST).Append("ip"), m.Option(tcp.PORT)) + _broad_serve(m, m.Cmd(tcp.HOST).Append(aaa.IP), m.Option(tcp.PORT)) }}, SPACE: {Name: "space dev", Help: "连接", Hand: func(m *ice.Message, arg ...string) { m.Cmd(SPIDE, mdb.CREATE, mdb.NAME, m.Option(ice.DEV), ADDRESS, kit.Format("http://%s:%s", m.Option(tcp.HOST), m.Option(tcp.PORT))) m.Cmd(SPACE, tcp.DIAL, m.OptionSimple(ice.DEV)) }}, - }, mdb.HashAction( - mdb.SHORT, "host,port", mdb.FIELD, "time,hash,host,port", - )), Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelect(m, arg...) - m.PushAction(SPACE, mdb.REMOVE) - }}, - }}) + }, mdb.HashAction(mdb.SHORT, "host,port", mdb.FIELD, "time,hash,host,port", mdb.ACTION, "space"))}, + }) } diff --git a/base/web/cache.go b/base/web/cache.go index 0fed59d7..2bc4bfc4 100644 --- a/base/web/cache.go +++ b/base/web/cache.go @@ -10,16 +10,17 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/miss" ) func _cache_name(m *ice.Message, h string) string { - return path.Join(m.Config(nfs.PATH), h[:2], h) + return path.Join(ice.VAR_FILE, h[:2], h) } func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { // file size if name == "" { return } - if len(text) > 512 || kind == "go" { // 存入文件 + if len(text) > 512 || kind == nfs.GO { // 存入文件 p := m.Cmdx(nfs.SAVE, _cache_name(m, kit.Hashs(text)), text) text, arg = p, kit.Simple(p, len(text)) } @@ -28,7 +29,7 @@ func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { // fi size := kit.Int(kit.Select(kit.Format(len(text)), arg, 1)) file := kit.Select("", arg, 0) text = kit.Select(file, text) - h := m.Cmdx(mdb.INSERT, CACHE, "", mdb.HASH, kit.SimpleKV("", kind, name, text), nfs.FILE, file, nfs.SIZE, size) + h := mdb.HashCreate(m, kit.SimpleKV("", kind, name, text), nfs.FILE, file, nfs.SIZE, size).Result() // 返回结果 m.Push(mdb.TIME, m.Time()) @@ -50,26 +51,26 @@ func _cache_watch(m *ice.Message, key, file string) { }) } func _cache_catch(m *ice.Message, name string) (file, size string) { - if f, e := os.Open(name); m.Assert(e) { + if f, e := nfs.OpenFile(m, name); m.Assert(e) { defer f.Close() - if s, e := f.Stat(); m.Assert(e) { + if s, e := nfs.StatFile(m, name); 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); e == nil { - defer buf.Close() + if b, h, e := r.FormFile(UPLOAD); e == nil { + defer b.Close() // 创建文件 - if f, p, e := kit.Create(_cache_name(m, kit.Hashs(buf))); m.Assert(e) { + if f, p, e := miss.CreateFile(_cache_name(m, kit.Hashs(b))); m.Assert(e) { defer f.Close() // 导入数据 - buf.Seek(0, os.SEEK_SET) - if n, e := io.Copy(f, buf); m.Assert(e) { + b.Seek(0, os.SEEK_SET) + if n, e := io.Copy(f, b); m.Assert(e) { m.Log_IMPORT(nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(n))) return h.Header.Get(ContentType), h.Filename, p, kit.Format(n) } @@ -80,12 +81,14 @@ func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size stri func _cache_download(m *ice.Message, r *http.Response) (file, size string) { defer r.Body.Close() - if f, p, e := kit.Create(path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ))); m.Assert(e) { - step, total := 0, kit.Int(kit.Select("1", r.Header.Get(ContentLength))) + if f, p, e := miss.CreateFile(path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ))); m.Assert(e) { + defer f.Close() + + step, total := 0, kit.Int(kit.Select("100", r.Header.Get(ContentLength))) size, buf := 0, make([]byte, ice.MOD_BUFS) for { - if n, _ := r.Body.Read(buf); n > 0 { + if n, e := r.Body.Read(buf); n > 0 && e == nil { size += n f.Write(buf[0:n]) s := size * 100 / total @@ -95,31 +98,16 @@ func _cache_download(m *ice.Message, r *http.Response) (file, size string) { cb(size, total, s) case func(int, int): cb(size, total) - case []string: - m.Richs(cb[0], cb[1], cb[2], func(key string, value ice.Map) { - value = kit.GetMeta(value) - value[mdb.COUNT], value[mdb.TOTAL], value[mdb.VALUE] = size, total, kit.Format(s) - }) default: if s != step && s%10 == 0 { m.Log_IMPORT(nfs.FILE, p, mdb.VALUE, s, mdb.COUNT, kit.FmtSize(int64(size)), mdb.TOTAL, kit.FmtSize(int64(total))) } } + step = s continue } - - f.Close() - break - } - - if f, e := os.Open(p); m.Assert(e) { - defer f.Close() - - m.Log_IMPORT(nfs.FILE, p, nfs.SIZE, kit.FmtSize(int64(size))) - c := _cache_name(m, kit.Hashs(f)) - m.Cmd(nfs.LINK, c, p) - return c, kit.Format(size) + return p, kit.Format(size) } } return "", "0" @@ -135,22 +123,7 @@ const ( const CACHE = "cache" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - CACHE: {Name: CACHE, Help: "缓存池", Value: kit.Data( - mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text", - mdb.STORE, ice.VAR_DATA, nfs.PATH, ice.VAR_FILE, mdb.FSIZE, "200000", - mdb.LIMIT, "50", mdb.LEAST, "30", - )}, - }, Commands: ice.Commands{ - "/cache/": {Name: "/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) { - m.Richs(CACHE, nil, arg[0], func(key string, value ice.Map) { - if kit.Format(value[nfs.FILE]) == "" { - m.RenderResult(value[mdb.TEXT]) - } else { - m.RenderDownload(value[nfs.FILE]) - } - }) - }}, + Index.MergeCommands(ice.Commands{ CACHE: {Name: "cache hash auto", Help: "缓存池", Actions: ice.MergeAction(ice.Actions{ WATCH: {Name: "watch key file", Help: "释放", Hand: func(m *ice.Message, arg ...string) { _cache_watch(m, arg[0], arg[1]) @@ -169,19 +142,28 @@ func init() { 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) + file, size = _cache_catch(m, file) _cache_save(m, arg[0], arg[1], "", file, size) } }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text,file")), Hand: func(m *ice.Message, arg ...string) { if mdb.HashSelect(m, arg...); len(arg) == 0 { return } - if m.Append(nfs.FILE) == "" { m.PushScript("inner", m.Append(mdb.TEXT)) } else { - m.PushDownload(m.Append(mdb.NAME), m.MergeURL2("/share/cache/"+arg[0])) + m.PushDownload(m.Append(mdb.NAME), m.MergeURL2(SHARE_CACHE+arg[0])) } }}, - }}) + PP(CACHE): {Name: "/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) { + mdb.HashSelectDetail(m, arg[0], func(value ice.Map) { + if kit.Format(value[nfs.FILE]) == "" { + m.RenderResult(value[mdb.TEXT]) + } else { + m.RenderDownload(value[nfs.FILE]) + } + }) + }}, + }) } diff --git a/base/web/dream.go b/base/web/dream.go index e28d092d..e12021b5 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -7,44 +7,65 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/cli" - "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/file" ) func _dream_list(m *ice.Message) *ice.Message { - return m.Cmdy(nfs.DIR, m.Config(nfs.PATH), "time,size,name").Tables(func(value ice.Maps) { - if m.Richs(SPACE, nil, value[mdb.NAME], func(key string, val ice.Map) { - m.Push(mdb.TYPE, val[mdb.TYPE]) + list := m.CmdMap(SPACE, mdb.NAME) + m.Cmdy(nfs.DIR, ice.USR_LOCAL_WORK, "time,size,name").Tables(func(value ice.Maps) { + if dream, ok := list[value[mdb.NAME]]; ok { + m.Push(mdb.TYPE, dream[mdb.TYPE]) m.Push(cli.STATUS, cli.START) m.PushButton("vimer", "xterm", cli.OPEN, cli.STOP) m.PushAnchor(strings.Split(m.MergePod(value[mdb.NAME]), "?")[0]) - }) == nil { + text := []string{} + for _, line := range kit.Split(m.Cmdx(SPACE, value[mdb.NAME], cli.SYSTEM, "git", "diff", "--shortstat"), ice.FS, ice.FS) { + if list := kit.Split(line); strings.Contains(line, "file") { + text = append(text, list[0]+" file") + } else if strings.Contains(line, "ins") { + text = append(text, list[0]+" +++") + } else if strings.Contains(line, "dele") { + text = append(text, list[0]+" ---") + } + } + m.Push(mdb.TEXT, strings.Join(text, ", ")) + } else { m.Push(mdb.TYPE, WORKER) m.Push(cli.STATUS, cli.STOP) m.PushButton(cli.START, nfs.TRASH) m.PushAnchor("") + m.Push(mdb.TEXT, "") } }) + return m.Sort("status,type,name").StatusTimeCount(cli.START, len(list)) } + func _dream_show(m *ice.Message, name string) { if !strings.Contains(name, "-") || !strings.HasPrefix(name, "20") { name = m.Time("20060102-") + kit.ReplaceAll(name, "-", "_") } - defer m.ProcessOpen(m.MergePod(m.Option(mdb.NAME, name))) + // defer m.ProcessOpen(m.MergePod(m.Option(mdb.NAME, name))) defer m.Echo(m.MergePod(m.Option(mdb.NAME, name))) - // 任务目录 - p := path.Join(m.Config(nfs.PATH), name) + p := path.Join(ice.USR_LOCAL_WORK, name) + if pid := m.Cmdx(nfs.CAT, path.Join(p, ice.Info.PidPath)); pid != "" && kit.FileExists("/proc/"+pid) { + m.Info("already exists %v", pid) + return // 已经启动 + } else if m.Cmd(SPACE, name).Length() > 0 { + return // 已经启动 + } + if m.Option(nfs.REPOS) != "" { // 下载源码 m.Cmd("web.code.git.repos", mdb.CREATE, m.OptionSimple(nfs.REPOS), nfs.PATH, p) } else { // 创建目录 - nfs.MkdirAll(m, p) + file.MkdirAll(p, ice.MOD_DIR) } - // 任务模板 + // 目录文件 if m.Option(nfs.TEMPLATE) != "" { for _, file := range []string{ ice.ETC_MISS_SH, ice.SRC_MAIN_SHY, ice.SRC_MAIN_GO, @@ -53,7 +74,7 @@ func _dream_show(m *ice.Message, name string) { if kit.FileExists(path.Join(p, file)) { continue } - switch m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(m.Config(nfs.PATH), m.Option(nfs.TEMPLATE), file)); file { + switch m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(ice.USR_LOCAL_WORK, m.Option(nfs.TEMPLATE), file)); file { case ice.GO_MOD: kit.Rewrite(path.Join(p, file), func(line string) string { return kit.Select(line, "module "+name, strings.HasPrefix(line, "module")) @@ -61,37 +82,26 @@ func _dream_show(m *ice.Message, name string) { } } } - - // 任务脚本 m.Cmd(nfs.DEFS, path.Join(p, ice.ETC_MISS_SH), m.Config("miss")) - defer m.Cmdy(nfs.DIR, p) - if pid := m.Cmdx(nfs.CAT, path.Join(p, m.Conf(gdb.SIGNAL, kit.Keym(nfs.PATH)))); pid != "" && kit.FileExists("/proc/"+pid) { - m.Info("already exists %v", pid) - return // 已经启动 - } else if m.Cmd(SPACE, name).Length() > 0 { - return // 已经启动 - } - - defer m.ToastProcess()() - - m.Optionv(cli.CMD_DIR, p) + // 环境变量 + m.Optionv(cli.CMD_DIR, kit.Path(p)) m.Optionv(cli.CMD_ENV, kit.Simple( cli.CTX_OPS, "http://:"+m.Cmd(SERVE, ice.OptionFields("")).Append(tcp.PORT), cli.PATH, cli.BinPath(kit.Path(p, ice.BIN)), cli.HOME, kit.Env(cli.HOME), - cli.SHELL, kit.Env(cli.SHELL), cli.TERM, kit.Env(cli.TERM), + cli.TERM, kit.Env(cli.TERM), cli.SHELL, kit.Env(cli.SHELL), cli.USER, ice.Info.UserName, m.Configv(cli.ENV), )) m.Optionv(cli.CMD_OUTPUT, path.Join(p, ice.BIN_BOOT_LOG)) - // 启动任务 + defer m.ToastProcess()() bin := kit.Select(os.Args[0], cli.SystemFind(m, ice.ICE_BIN, kit.Path(path.Join(p, ice.BIN)), kit.Path(ice.BIN))) m.Cmd(cli.DAEMON, bin, SPACE, tcp.DIAL, ice.DEV, ice.OPS, m.OptionSimple(mdb.NAME, RIVER)) m.Sleep3s() m.Option(cli.CMD_ENV, "") m.Option(cli.CMD_OUTPUT, "") - m.Event(DREAM_CREATE, kit.SimpleKV("", m.Option(mdb.TYPE), name)...) + m.Event(DREAM_CREATE, m.OptionSimple(mdb.TYPE, mdb.NAME)...) } const ( @@ -102,8 +112,8 @@ const ( const DREAM = "dream" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ - DREAM: {Name: "dream name path auto start", Help: "梦想家", Actions: ice.Actions{ + Index.MergeCommands(ice.Commands{ + DREAM: {Name: "dream name path auto start", Help: "梦想家", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Config("miss", _dream_miss) }}, @@ -129,10 +139,10 @@ func init() { cli.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { m.Cmd(SPACE, mdb.MODIFY, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP) m.Cmd(SPACE, m.Option(mdb.NAME), ice.EXIT) - m.ProcessRefresh("100ms") + m.ProcessRefresh30ms() }}, DREAM_STOP: {Name: "dream.stop type name", Help: "停止", Hand: func(m *ice.Message, arg ...string) { - if m.Cmd(SPACE, m.Option(mdb.NAME)).Append(mdb.STATUS) == cli.STOP { + if m.CmdAppend(SPACE, m.Option(mdb.NAME), mdb.STATUS) == cli.STOP { m.Cmd(mdb.DELETE, m.Prefix(SPACE), "", mdb.HASH, m.OptionSimple(mdb.NAME)) } else { m.Cmd(mdb.DELETE, m.Prefix(SPACE), "", mdb.HASH, m.OptionSimple(mdb.NAME)) @@ -140,42 +150,19 @@ func init() { } }}, nfs.TRASH: {Name: "trash", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmd(nfs.TRASH, mdb.CREATE, path.Join(m.Config(nfs.PATH), m.Option(mdb.NAME))) + m.Cmd(nfs.TRASH, mdb.CREATE, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME))) m.ProcessRefresh30ms() }}, - }, Hand: func(m *ice.Message, arg ...string) { - if start := 0; len(arg) == 0 { - _dream_list(m).SetAppend(mdb.TEXT) - m.Tables(func(value ice.Maps) { - if value[cli.STATUS] != cli.START { - m.Push(mdb.TEXT, "") - return - } - start++ - text := []string{} - for _, line := range kit.Split(m.Cmdx(SPACE, value[mdb.NAME], cli.SYSTEM, "git", "diff", "--shortstat"), ice.FS, ice.FS) { - if list := kit.Split(line); strings.Contains(line, "file") { - text = append(text, list[0]+" file") - } else if strings.Contains(line, "ins") { - text = append(text, list[0]+" +++") - } else if strings.Contains(line, "dele") { - text = append(text, list[0]+" ---") - } - } - m.Push(mdb.TEXT, strings.Join(text, ", ")) - }).Sort("status,type,name").StatusTimeCount(cli.START, start) - if !m.IsMobileUA() { + }, mdb.HashAction("miss", _dream_miss)), Hand: func(m *ice.Message, arg ...string) { + if len(arg) == 0 { + if _dream_list(m); !m.IsMobileUA() { m.Display("/plugin/table.js?style=card") } return } - - m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), arg[0])) - m.Cmdy(nfs.CAT, arg[1:]) + m.Cmdy(nfs.CAT, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_WORK, arg[0]))) }}, - }, Configs: ice.Configs{ - DREAM: {Name: DREAM, Help: "梦想家", Value: kit.Data(nfs.PATH, ice.USR_LOCAL_WORK, "miss", _dream_miss)}, - }}) + }) } var _dream_miss = `#! /bin/sh diff --git a/base/web/render.go b/base/web/render.go index 1462cede..8088e529 100644 --- a/base/web/render.go +++ b/base/web/render.go @@ -2,6 +2,7 @@ package web import ( "fmt" + "io" "net/http" "path" "strings" @@ -9,13 +10,15 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" + "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" ) const ( - STATUS = "status" COOKIE = "cookie" + STATUS = "status" ) func Render(msg *ice.Message, cmd string, args ...ice.Any) { @@ -27,30 +30,34 @@ func Render(msg *ice.Message, cmd string, args ...ice.Any) { case COOKIE: // value [name [path [expire]]] RenderCookie(msg, arg[0], arg[1:]...) + case STATUS, ice.RENDER_STATUS: // [code [text]] + RenderStatus(msg, kit.Int(kit.Select("200", arg, 0)), kit.Select("", arg, 1)) + + case ice.RENDER_REDIRECT: // url [arg...] + RenderRedirect(msg, arg...) + case ice.RENDER_DOWNLOAD: // file [type [name]] - if strings.HasPrefix(arg[0], "http") { + if strings.HasPrefix(arg[0], ice.HTTP) { http.Redirect(msg.W, msg.R, arg[0], http.StatusSeeOther) break } msg.W.Header().Set("Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(path.Base(kit.Select(arg[0], msg.Option("filename"))), arg, 2))) - if RenderType(msg.W, arg[0], kit.Select("", arg, 1)); !ice.Info.Dump(msg.W, arg[0], nil) { + RenderType(msg.W, arg[0], kit.Select("", arg, 1)) + if _, e := nfs.DiskFile.StatFile(arg[0]); e == nil { http.ServeFile(msg.W, msg.R, kit.Path(arg[0])) + } else if f, e := nfs.PackFile.OpenFile(arg[0]); e == nil { + defer f.Close() + io.Copy(msg.W, f) } - case ice.RENDER_REDIRECT: // url [arg...] - RenderRedirect(msg, arg...) - case ice.RENDER_RESULT: if len(arg) > 0 { // [str [arg...]] msg.W.Write([]byte(kit.Format(arg[0], args[1:]...))) } else { - args = append(args, "length:", len(msg.Result())) + args = append(args, nfs.SIZE, len(msg.Result())) msg.W.Write([]byte(msg.Result())) } - case STATUS, ice.RENDER_STATUS: // [code [text]] - RenderStatus(msg, kit.Int(kit.Select("200", arg, 0)), kit.Select("", arg, 1)) - case ice.RENDER_JSON: msg.W.Header().Set("Content-Type", "application/json") msg.W.Write([]byte(arg[0])) @@ -73,26 +80,33 @@ func Render(msg *ice.Message, cmd string, args ...ice.Any) { msg.Echo(kit.Format(cmd, args...)) } msg.W.Header().Set(ContentType, ContentJSON) - fmt.Fprint(msg.W, msg.FormatsMeta()) + fmt.Fprint(msg.W, msg.FormatMeta()) + } +} +func RenderType(w http.ResponseWriter, name, mime string) { + if mime != "" { + w.Header().Set(ContentType, mime) + return + } + + switch kit.Ext(name) { + case nfs.CSS: + w.Header().Set(ContentType, "text/css; charset=utf-8") + case "pdf": + w.Header().Set(ContentType, "application/pdf") } } func RenderHeader(msg *ice.Message, key, value string) { msg.W.Header().Set(key, value) } -func RenderStatus(msg *ice.Message, code int, text string) { - msg.W.WriteHeader(code) - msg.W.Write([]byte(text)) -} -func CookieName(url string) string { - return ice.MSG_SESSID + "_" + kit.ReplaceAll(kit.ParseURLMap(url)[tcp.HOST], ".", "_", ":", "_") -} func RenderCookie(msg *ice.Message, value string, arg ...string) { // name path expire - expire := time.Now().Add(kit.Duration(kit.Select(msg.Conf(aaa.SESS, kit.Keym(aaa.EXPIRE)), arg, 2))) + expire := time.Now().Add(kit.Duration(kit.Select(msg.Conf(aaa.SESS, kit.Keym(mdb.EXPIRE)), arg, 2))) http.SetCookie(msg.W, &http.Cookie{Value: value, Name: kit.Select(CookieName(msg.Option(ice.MSG_USERWEB)), arg, 0), Path: kit.Select(ice.PS, arg, 1), Expires: expire}) } -func RenderRedirect(msg *ice.Message, arg ...string) { - http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusTemporaryRedirect) +func RenderStatus(msg *ice.Message, code int, text string) { + msg.W.WriteHeader(code) + msg.W.Write([]byte(text)) } func RenderRefresh(msg *ice.Message, arg ...string) { // url text delay msg.Render(ice.RENDER_VOID) @@ -107,27 +121,18 @@ func RenderRefresh(msg *ice.Message, arg ...string) { // url text delay `, kit.Select("3", arg, 2), kit.Select(msg.Option(ice.MSG_USERWEB), arg, 0), kit.Select("loading...", arg, 1))) } -func RenderType(w http.ResponseWriter, name, mime string) { - if mime != "" { - w.Header().Set(ContentType, mime) - return - } - - switch kit.Ext(name) { - case "css": - w.Header().Set(ContentType, "text/css; charset=utf-8") - case "pdf": - w.Header().Set(ContentType, "application/pdf") - default: - } -} -func RenderResult(msg *ice.Message, arg ...ice.Any) { - Render(msg, ice.RENDER_RESULT, arg...) +func RenderRedirect(msg *ice.Message, arg ...string) { + http.Redirect(msg.W, msg.R, kit.MergeURL(arg[0], arg[1:]), http.StatusTemporaryRedirect) } func RenderDownload(msg *ice.Message, arg ...ice.Any) { Render(msg, ice.RENDER_DOWNLOAD, arg...) } - +func RenderResult(msg *ice.Message, arg ...ice.Any) { + Render(msg, ice.RENDER_RESULT, arg...) +} +func CookieName(url string) string { + return ice.MSG_SESSID + "_" + kit.ReplaceAll(kit.ParseURLMap(url)[tcp.HOST], ".", "_", ":", "_") +} func Format(tag string, arg ...ice.Any) string { return kit.Format("<%s>%s", tag, strings.Join(kit.Simple(arg), ""), tag) } diff --git a/base/web/route.go b/base/web/route.go index 700a6f30..e4604790 100644 --- a/base/web/route.go +++ b/base/web/route.go @@ -12,7 +12,7 @@ import ( ) func _route_travel(m *ice.Message, route string) { - m.Richs(SPACE, nil, mdb.FOREACH, func(key string, val ice.Map) { + m.Cmd(SPACE).Tables(func(val ice.Maps) { switch val[mdb.TYPE] { case SERVER: // 远程查询 if val[mdb.NAME] == ice.Info.NodeName { @@ -31,13 +31,12 @@ func _route_travel(m *ice.Message, route string) { } }) } -func _route_list(m *ice.Message) { +func _route_list(m *ice.Message) *ice.Message { m.Tables(func(value ice.Maps) { m.PushAnchor(value[ROUTE], m.MergePod(value[ROUTE])) - switch value[mdb.TYPE] { case SERVER: - m.PushButton(tcp.START) + m.PushButton(tcp.START, aaa.INVITE) case WORKER: fallthrough default: @@ -59,22 +58,19 @@ func _route_list(m *ice.Message) { m.Push(ROUTE, ice.Info.NodeName) m.PushAnchor(tcp.LOCALHOST, kit.Format("%s://%s:%s", u.Scheme, tcp.LOCALHOST, u.Port())) m.PushButton(tcp.START) + return m } const ROUTE = "route" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - ROUTE: {Name: ROUTE, Help: "路由器", Value: kit.Data(mdb.SHORT, ROUTE)}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ ROUTE: {Name: "route route ctx cmd auto invite spide", Help: "路由器", Actions: ice.Actions{ aaa.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPACE, m.Option(ROUTE), SPACE, aaa.INVITE, arg) - m.ProcessInner() + m.Cmdy(SPACE, m.Option(ROUTE), SPACE, aaa.INVITE, arg).ProcessInner() }}, cli.START: {Name: "start name repos template", Help: "启动", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPACE, m.Option(ROUTE), DREAM, tcp.START, arg) - m.ProcessInner() + m.Cmdy(SPACE, m.Option(ROUTE), DREAM, tcp.START, arg).ProcessInner() }}, ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(SPACE, m.Option(ROUTE), kit.Keys(m.Option(ice.CTX), m.Option(ice.CMD)), arg) @@ -85,7 +81,7 @@ func init() { SPIDE: {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) { if m.Option(ROUTE) == "" { // 路由列表 route m.Cmdy(ROUTE).Cut(ROUTE) - m.Display("/plugin/story/spide.js?prefix=spide", lex.SPLIT, ice.PT) + m.DisplayStorySpide("prefix", "spide", lex.SPLIT, ice.PT) } else if m.Option(ctx.CONTEXT) == "" { // 模块列表 context m.Cmdy(SPACE, m.Option(ROUTE), ctx.CONTEXT, ice.ICE, ctx.CONTEXT).Cut(mdb.NAME).RenameAppend(mdb.NAME, ctx.CONTEXT) @@ -101,8 +97,7 @@ func init() { }, Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 || arg[0] == "" { // 路由列表 if _route_travel(m, kit.Select("", arg, 0)); m.W != nil { - _route_list(m) - m.Sort("type,route") + _route_list(m).Sort("type,route") } } else if len(arg) == 1 || arg[1] == "" { // 模块列表 @@ -122,5 +117,5 @@ func init() { m.ProcessField(ctx.ACTION, ctx.COMMAND) } }}, - }}) + }) } diff --git a/base/web/serve.go b/base/web/serve.go index d7fe6963..5647e20d 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -2,6 +2,7 @@ package web import ( "encoding/json" + "io" "net/http" "net/url" "os" @@ -17,12 +18,48 @@ import ( "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) var rewriteList = []ice.Any{} func AddRewrite(cb ice.Any) { rewriteList = append(rewriteList, cb) } +func _serve_rewrite(m *ice.Message) { + AddRewrite(func(w http.ResponseWriter, r *http.Request) bool { + msg, repos := m.Spawn(SERVE, w, r), kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get("User-Agent"), "Mozilla/5.0")) + if r.Method == SPIDE_GET { + switch r.URL.Path { + case ice.PS: + if repos == ice.VOLCANOS { + if s := msg.Cmdx("web.chat.website", lex.PARSE, ice.INDEX_IML, "Header", "", "River", "", "Footer", ""); s != "" { + Render(msg, ice.RENDER_RESULT, s) + return true // 定制主页 + } + } + Render(msg, ice.RENDER_DOWNLOAD, path.Join(msg.Config(kit.Keys(repos, nfs.PATH)), msg.Config(kit.Keys(repos, INDEX)))) + return true // 默认主页 + + case PP(ice.HELP): + r.URL.Path = P(ice.HELP, ice.TUTOR_SHY) + } + p := path.Join(ice.USR, repos, r.URL.Path) + m.Debug("what %v", p) + if _, e := nfs.DiskFile.StatFile(p); e == nil { + m.Debug("what %v", p) + http.ServeFile(w, r, kit.Path(p)) + return true + } else if f, e := nfs.PackFile.OpenFile(p); e == nil { + defer f.Close() + m.Debug("what %v", p) + RenderType(w, p, "") + io.Copy(w, f) + return true + } + } + return false + }) +} func _serve_domain(m *ice.Message) string { if p := m.Config(DOMAIN); p != "" { return p @@ -41,6 +78,36 @@ func _serve_domain(m *ice.Message) string { return kit.Format("https://%s", m.R.Host) } } +func _serve_spide(m *ice.Message, prefix string, c *ice.Context) { + for k := range c.Commands { + if strings.HasPrefix(k, ice.PS) { + m.Push(nfs.PATH, path.Join(prefix, k)+kit.Select("", ice.PS, strings.HasSuffix(k, ice.PS))) + } + } + for k, v := range c.Contexts { + _serve_spide(m, path.Join(prefix, k), v) + } +} +func _serve_start(m *ice.Message) { + ice.Info.Domain = kit.Select(kit.Format("%s://%s:%s", m.Option(tcp.PROTO), kit.Select(m.Cmd(tcp.HOST).Append(aaa.IP), m.Option(tcp.HOST)), m.Option(tcp.PORT)), ice.Info.Domain) + if cli.NodeInfo(m, SERVER, kit.Select(ice.Info.HostName, m.Option("nodename"))); m.Option(tcp.PORT) == tcp.RANDOM { + m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) + } + + if m.Option("staffname") != "" { + m.Config("staffname", m.Option(aaa.USERNAME, m.Option("staffname"))) + } + aaa.UserRoot(m, m.Option(aaa.PASSWORD), m.Option(aaa.USERNAME), m.Option(aaa.USERROLE)) + + m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...) + m.Go(func() { m.Cmd(BROAD, SERVE) }) + m.Sleep300ms() + + for _, k := range kit.Split(m.Option(ice.DEV)) { + m.Cmd(SPACE, tcp.DIAL, ice.DEV, k, mdb.NAME, ice.Info.NodeName) + } +} + func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { if r.Header.Get("Index-Module") == "" { r.Header.Set("Index-Module", m.Prefix()) @@ -60,19 +127,20 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { } else { r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, ":")[0]) } - m.Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL) + meta := logs.FileLineMeta("") + m.Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL, meta) // 参数日志 if m.Config(LOGHEADERS) == ice.TRUE { for k, v := range r.Header { - m.Info("%s: %v", k, kit.Format(v)) + m.Info("%s: %v", k, kit.Format(v), meta) } - m.Info("") + m.Info("", meta) defer func() { - m.Info("") + m.Info("", meta) for k, v := range w.Header() { - m.Info("%s: %v", k, kit.Format(v)) + m.Info("%s: %v", k, kit.Format(v), meta) } }() } @@ -80,7 +148,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { // 模块回调 for _, h := range rewriteList { if m.Config(LOGHEADERS) == ice.TRUE { - m.Info("%s: %v", r.URL.Path, kit.FileLine(h, 3)) + m.Info("%s: %v", r.URL.Path, kit.FileLine(h, 3), meta) } switch h := h.(type) { case func(w http.ResponseWriter, r *http.Request) func(): @@ -95,7 +163,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { return false } default: - m.Error(true, ice.ErrNotImplement) + m.ErrorNotImplement(h) } } return true @@ -131,7 +199,7 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon } _serve_params(msg, r.URL.Path) - // 请求参数 + // 解析参数 switch r.Header.Get(ContentType) { case ContentJSON: defer r.Body.Close() @@ -145,11 +213,12 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon default: r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength)))) if r.ParseForm(); len(r.PostForm) > 0 { + meta := logs.FileLineMeta("") for k, v := range r.PostForm { if len(v) > 1 { - msg.Logs("form", k, len(v), kit.Join(v, ice.SP)) + msg.Logs("form", k, len(v), kit.Join(v, ice.SP), meta) } else { - msg.Logs("form", k, v) + msg.Logs("form", k, v, meta) } } } @@ -163,16 +232,11 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon v[i], _ = url.QueryUnescape(p) } } - if msg.Optionv(k, v); k == ice.MSG_SESSID { - msg.Option(ice.MSG_SESSID, v[0]) - RenderCookie(msg, v[0]) - } + msg.Optionv(k, v) } for k, v := range r.PostForm { msg.Optionv(k, v) } - - // 会话参数 for _, v := range r.Cookies() { msg.Option(v.Name, v.Value) } @@ -181,7 +245,7 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon msg.Option(ice.MSG_USERWEB, _serve_domain(msg)) msg.Option(ice.MSG_USERADDR, kit.Select(r.RemoteAddr, r.Header.Get(ice.MSG_USERADDR))) msg.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP)) - msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent")) + msg.Option(ice.MSG_USERUA, r.Header.Get(UserAgent)) if msg.Option(ice.POD) != "" { msg.Option(ice.MSG_USERPOD, msg.Option(ice.POD)) } @@ -240,10 +304,8 @@ func _serve_login(msg *ice.Message, key string, cmds []string, w http.ResponseWr return cmds, msg.Result(0) != ice.ErrWarn && msg.Result(0) != ice.FALSE } - if ls := strings.Split(r.URL.Path, ice.PS); msg.Config(kit.Keys(aaa.BLACK, ls[1])) == ice.TRUE { - return cmds, false // 黑名单 - } else if msg.Config(kit.Keys(aaa.WHITE, ls[1])) == ice.TRUE { - return cmds, true // 白名单 + if msg.Right(key, cmds) { + return cmds, true } if msg.Warn(msg.Option(ice.MSG_USERNAME) == "", ice.ErrNotLogin, r.URL.Path) { @@ -255,16 +317,6 @@ func _serve_login(msg *ice.Message, key string, cmds []string, w http.ResponseWr } return cmds, true } -func _serve_spide(m *ice.Message, prefix string, c *ice.Context) { - for k := range c.Commands { - if strings.HasPrefix(k, ice.PS) { - m.Push(nfs.PATH, path.Join(prefix, k)+kit.Select("", ice.PS, strings.HasSuffix(k, ice.PS))) - } - } - for k, v := range c.Contexts { - _serve_spide(m, path.Join(prefix, k), v) - } -} const ( WEB_LOGIN = "_login" @@ -279,120 +331,58 @@ func init() { Index.Merge(&ice.Context{Configs: ice.Configs{ SERVE: {Name: SERVE, Help: "服务器", Value: kit.Data( mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,port,dev", - tcp.LOCALHOST, ice.TRUE, aaa.BLACK, kit.Dict(), aaa.WHITE, kit.Dict( - LOGIN, ice.TRUE, SHARE, ice.TRUE, SPACE, ice.TRUE, - ice.VOLCANOS, ice.TRUE, ice.PUBLISH, ice.TRUE, - ice.INTSHELL, ice.TRUE, ice.REQUIRE, ice.TRUE, - "cmd", ice.TRUE, ice.HELP, ice.TRUE, - ), LOGHEADERS, ice.FALSE, - - DOMAIN, "", nfs.PATH, kit.Dict(ice.PS, ice.USR_VOLCANOS), + DOMAIN, "", tcp.LOCALHOST, ice.TRUE, LOGHEADERS, ice.FALSE, + nfs.PATH, kit.Dict(ice.PS, ice.USR_VOLCANOS), ice.VOLCANOS, kit.Dict(nfs.PATH, ice.USR_VOLCANOS, INDEX, "page/index.html", nfs.REPOS, "https://shylinux.com/x/volcanos", nfs.BRANCH, nfs.MASTER, - ), ice.PUBLISH, ice.USR_PUBLISH, - + ), ice.INTSHELL, kit.Dict(nfs.PATH, ice.USR_INTSHELL, INDEX, ice.INDEX_SH, nfs.REPOS, "https://shylinux.com/x/intshell", nfs.BRANCH, nfs.MASTER, - ), ice.REQUIRE, ".ish/pluged", + ), )}, }, Commands: ice.Commands{ SERVE: {Name: "serve name auto start spide", Help: "服务器", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { cli.NodeInfo(m, WORKER, ice.Info.PathName) - AddRewrite(func(w http.ResponseWriter, r *http.Request) bool { - w.Header().Add("Access-Control-Allow-Origin", "*") - if r.Method == SPIDE_GET { - switch r.URL.Path { - case ice.PS: - msg := m.Spawn(SERVE, w, r) - repos := kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get("User-Agent"), "Mozilla/5.0")) - if repos == ice.VOLCANOS { - if s := msg.Cmdx("web.chat.website", lex.PARSE, "index.iml", "Header", "", "River", "", "Footer", ""); s != "" { - Render(msg, ice.RENDER_RESULT, s) - return true // 定制主页 - } - } - Render(msg, ice.RENDER_DOWNLOAD, path.Join(msg.Config(kit.Keys(repos, nfs.PATH)), msg.Config(kit.Keys(repos, INDEX)))) - return true // 默认主页 - - case "/help/": - r.URL.Path = "/help/tutor.shy" - } - } - return false - }) - }}, - ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { - m.Cmd(SERVE).Tables(func(value ice.Maps) { - m.Done(value[cli.STATUS] == tcp.START) - }) + for _, p := range []string{LOGIN, SHARE, SPACE, ice.VOLCANOS, ice.INTSHELL, ice.PUBLISH, ice.REQUIRE, ice.HELP, ice.CMD} { + m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, p) + } + _serve_rewrite(m) }}, DOMAIN: {Name: "domain", Help: "域名", Hand: func(m *ice.Message, arg ...string) { ice.Info.Domain = m.Conf(SHARE, kit.Keym(DOMAIN, m.Config(DOMAIN, arg[0]))) }}, - "list_broad": {Name: "list_broad", Help: "服务发现", Hand: func(m *ice.Message, arg ...string) { - m.Go(func() { _serve_udp(m, m.Cmd(tcp.HOST).Append(aaa.IP), m.Option(tcp.PORT)) }) - }}, - aaa.BLACK: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) { - for _, k := range arg { - m.Log_CREATE(aaa.BLACK, k) - m.Config(kit.Keys(aaa.BLACK, k), ice.TRUE) - } - }}, - aaa.WHITE: {Name: "white", Help: "白名单", Hand: func(m *ice.Message, arg ...string) { - for _, k := range arg { - m.Log_CREATE(aaa.WHITE, k) - m.Config(kit.Keys(aaa.WHITE, k), ice.TRUE) - } - }}, cli.START: {Name: "start dev proto=http host port=9020 nodename password username userrole staffname", Help: "启动", Hand: func(m *ice.Message, arg ...string) { - ice.Info.Domain = kit.Select(kit.Format("%s://%s:%s", m.Option(tcp.PROTO), kit.Select(m.Cmd(tcp.HOST).Append(aaa.IP), m.Option(tcp.HOST)), m.Option(tcp.PORT)), ice.Info.Domain) - if cli.NodeInfo(m, SERVER, kit.Select(ice.Info.HostName, m.Option("nodename"))); m.Option(tcp.PORT) == tcp.RANDOM { - m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) - } - if m.Option("staffname") != "" { - m.Config("staffname", m.Option(aaa.USERNAME, m.Option("staffname"))) - } - aaa.UserRoot(m, m.Option(aaa.PASSWORD), m.Option(aaa.USERNAME), m.Option(aaa.USERROLE)) - - m.Go(func() { m.Cmd(BROAD, SERVE) }) - m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...) - m.Sleep300ms() - - for _, k := range kit.Split(m.Option(ice.DEV)) { - m.Cmd(SPACE, tcp.DIAL, ice.DEV, k, mdb.NAME, ice.Info.NodeName) - } + _serve_start(m) }}, - "spide": {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) { + SPIDE: {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { // 模块列表 - m.Display("/plugin/story/spide.js", "root", ice.ICE, "prefix", "spide") _serve_spide(m, ice.PS, m.Target()) - m.StatusTimeCount() - return + m.DisplayStorySpide(lex.PREFIX, m.ActionKey(), nfs.ROOT, m.MergeLink(ice.PS)) } }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelect(m, arg...) - }}, + }, mdb.HashAction())}, - "/intshell/": {Name: "/intshell/", Help: "命令行", Hand: func(m *ice.Message, arg ...string) { + PP(ice.INTSHELL): {Name: "/intshell/", Help: "命令行", Hand: func(m *ice.Message, arg ...string) { m.RenderIndex(SERVE, ice.INTSHELL, arg...) }}, - "/volcanos/": {Name: "/volcanos/", Help: "浏览器", Hand: func(m *ice.Message, arg ...string) { + PP(ice.VOLCANOS): {Name: "/volcanos/", Help: "浏览器", Hand: func(m *ice.Message, arg ...string) { m.RenderIndex(SERVE, ice.VOLCANOS, arg...) }}, - "/require/src/": {Name: "/require/src/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { - if p := path.Join(ice.SRC, path.Join(arg...)); m.Option(ice.POD) != "" { - m.RenderResult(m.Cmdx(SPACE, m.Option(ice.POD), nfs.CAT, p)) - } else { - m.RenderDownload(p) - } + PP(ice.PUBLISH): {Name: "/publish/", Help: "定制化", Hand: func(m *ice.Message, arg ...string) { + _share_local(aaa.UserRoot(m), ice.USR_PUBLISH, path.Join(arg...)) }}, - "/require/usr/": {Name: "/require/usr/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { - m.RenderDownload(path.Join(ice.USR, path.Join(arg...))) + PP(ice.REQUIRE): {Name: "/require/shylinux.com/x/volcanos/proto.js", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { + _share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...) }}, - "/require/node_modules/": {Name: "/require/node_modules/", Help: "依赖库", Hand: func(m *ice.Message, arg ...string) { - p := path.Join(ice.USR_VOLCANOS, "node_modules", path.Join(arg...)) + PP(ice.REQUIRE, ice.SRC): {Name: "/require/src/", Help: "源代码", Hand: func(m *ice.Message, arg ...string) { + _share_local(aaa.UserRoot(m), ice.SRC, path.Join(arg...)) + }}, + PP(ice.REQUIRE, ice.USR): {Name: "/require/usr/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { + _share_local(aaa.UserRoot(m), ice.USR, path.Join(arg...)) + }}, + PP(ice.REQUIRE, ice.NODE_MODULES): {Name: "/require/node_modules/", Help: "依赖库", Hand: func(m *ice.Message, arg ...string) { + p := path.Join(ice.USR_VOLCANOS, ice.NODE_MODULES, path.Join(arg...)) if b, ok := ice.Info.Pack[p]; ok && len(b) > 0 { } else if _, e := os.Stat(p); e != nil { @@ -400,18 +390,7 @@ func init() { } m.RenderDownload(p) }}, - "/require/": {Name: "/require/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { - _share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...) - }}, - "/publish/": {Name: "/publish/", Help: "定制化", Hand: func(m *ice.Message, arg ...string) { - if strings.HasPrefix(arg[0], "ice.") && m.Option(ice.POD) != "" { - _share_local(aaa.UserRoot(m), path.Join(ice.USR_PUBLISH, arg[0])) - // _share_local(aaa.UserRoot(m), ice.BIN_ICE_BIN) - return - } - _share_local(m, m.Conf(SERVE, kit.Keym(ice.PUBLISH)), path.Join(arg...)) - }}, - "/help/": {Name: "/help/", Help: "帮助", Hand: func(m *ice.Message, arg ...string) { + PP(ice.HELP): {Name: "/help/", Help: "帮助", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { arg = append(arg, "tutor.shy") } diff --git a/base/web/share.go b/base/web/share.go index 40493464..001dc06b 100644 --- a/base/web/share.go +++ b/base/web/share.go @@ -3,7 +3,6 @@ package web import ( "fmt" "net/http" - "os" "path" "strings" "time" @@ -16,33 +15,27 @@ import ( "shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/file" ) -func _share_link(m *ice.Message, p string, arg ...ice.Any) string { - p = kit.Select("", "/share/local/", !strings.HasPrefix(p, ice.PS)) + p - return tcp.ReplaceLocalhost(m, m.MergeURL2(p, arg...)) -} -func _share_repos(m *ice.Message, repos string, arg ...string) { - if repos == ice.Info.Make.Module && kit.FileExists(path.Join(arg...)) { - m.RenderDownload(path.Join(arg...)) - return - } - prefix := kit.Path(m.Conf(SERVE, kit.Keym(ice.REQUIRE))) - if !kit.FileExists(path.Join(prefix, repos)) { // 克隆代码 - m.Cmd("web.code.git.repos", mdb.CREATE, nfs.REPOS, "https://"+repos, nfs.PATH, path.Join(prefix, repos)) - } - m.RenderDownload(path.Join(prefix, repos, path.Join(arg...))) -} -func _share_proxy(m *ice.Message) { - switch p := path.Join(ice.VAR_PROXY, m.Option(ice.POD), m.Option(nfs.PATH)); m.R.Method { - case http.MethodGet: // 下发文件 - m.RenderDownload(path.Join(p, m.Option(mdb.NAME))) +func _share_render(m *ice.Message, arg ...string) { + ice.AddRender(ice.RENDER_DOWNLOAD, func(msg *ice.Message, cmd string, args ...ice.Any) string { + list := []string{} + if msg.Option(ice.MSG_USERPOD) != "" { + list = append(list, ice.POD, msg.Option(ice.MSG_USERPOD)) + } - case http.MethodPost: // 上传文件 - m.Cmdy(CACHE, UPLOAD) - m.Cmdy(CACHE, WATCH, m.Option(mdb.DATA), p) - m.RenderResult(m.Option(nfs.PATH)) - } + arg := kit.Simple(args...) + if len(arg) > 1 { + list = append(list, "filename", arg[0]) + } + return fmt.Sprintf(`%s`, + _share_link(msg, kit.Select(arg[0], arg, 1), list), path.Base(arg[0]), arg[0]) + }) +} +func _share_link(m *ice.Message, p string, arg ...ice.Any) string { + p = kit.Select("", SHARE_LOCAL, !strings.HasPrefix(p, ice.PS)) + p + return tcp.ReplaceLocalhost(m, m.MergeURL2(p, arg...)) } func _share_cache(m *ice.Message, arg ...string) { if pod := m.Option(ice.POD); m.PodCmd(CACHE, arg[0]) { @@ -52,10 +45,10 @@ func _share_cache(m *ice.Message, arg ...string) { m.Option(ice.POD, pod) _share_local(m, m.Append(nfs.FILE)) } - return + } else { + msg := m.Cmd(CACHE, arg[0]) + m.RenderDownload(msg.Append(nfs.FILE), msg.Append(mdb.TYPE), msg.Append(mdb.NAME)) } - msg := m.Cmd(CACHE, arg[0]) - m.RenderDownload(msg.Append(nfs.FILE), msg.Append(mdb.TYPE), msg.Append(mdb.NAME)) } func _share_local(m *ice.Message, arg ...string) { p := path.Join(arg...) @@ -72,36 +65,51 @@ func _share_local(m *ice.Message, arg ...string) { } } - if m.Option(ice.POD) != "" { // 远程文件 - pp := path.Join(ice.VAR_PROXY, m.Option(ice.POD), p) - cache := time.Now().Add(-time.Hour * 240000) - var size int64 - if s, e := os.Stat(pp); e == nil { - cache = s.ModTime() - size = s.Size() - } - - // 上传文件 - if p == "bin/ice.bin" { - aaa.UserRoot(m).Cmd(SPACE, m.Option(ice.POD), SPIDE, "submit", m.MergeURL2(SHARE_PROXY, nfs.PATH, ""), m.Option(ice.POD), p, size, cache.Format(ice.MOD_TIME)) - } else { - m.Cmd(SPACE, m.Option(ice.POD), SPIDE, ice.DEV, SPIDE_RAW, m.MergeURL2(SHARE_PROXY, nfs.PATH, ""), - SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, p, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, "@"+p) - - } - - if s, e := os.Stat(pp); e == nil && !s.IsDir() { - p = pp - } + if m.Option(ice.POD) == "" { + m.RenderDownload(p) + return // 本地文件 } - if strings.HasSuffix(p, path.Join(ice.USR_PUBLISH, ice.ORDER_JS)) { - if !kit.FileExists(p) { - m.RenderResult("") - return - } + + pp := path.Join(ice.VAR_PROXY, m.Option(ice.POD), p) + cache, size := time.Now().Add(-time.Hour*240000), int64(0) + if s, e := file.StatFile(pp); e == nil { + cache, size = s.ModTime(), s.Size() } + + // 上传文件 + if p == "bin/ice.bin" { + aaa.UserRoot(m).Cmd(SPACE, m.Option(ice.POD), SPIDE, "submit", m.MergeURL2(SHARE_PROXY, nfs.PATH, ""), m.Option(ice.POD), p, size, cache.Format(ice.MOD_TIME)) + } else { + m.Cmd(SPACE, m.Option(ice.POD), SPIDE, ice.DEV, SPIDE_RAW, m.MergeURL2(SHARE_PROXY, nfs.PATH, ""), + SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, p, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, "@"+p) + } + if s, e := file.StatFile(pp); e == nil && !s.IsDir() { + p = pp + } + m.RenderDownload(p) } +func _share_proxy(m *ice.Message) { + switch p := path.Join(ice.VAR_PROXY, m.Option(ice.POD), m.Option(nfs.PATH)); m.R.Method { + case http.MethodGet: // 下发文件 + m.RenderDownload(path.Join(p, m.Option(mdb.NAME))) + + case http.MethodPost: // 上传文件 + m.Cmdy(CACHE, UPLOAD) + m.Cmdy(CACHE, WATCH, m.Option(mdb.DATA), p) + m.RenderResult(m.Option(nfs.PATH)) + } +} +func _share_repos(m *ice.Message, repos string, arg ...string) { + if repos == ice.Info.Make.Module && kit.FileExists(path.Join(arg...)) { + m.RenderDownload(path.Join(arg...)) + return + } + if !kit.FileExists(path.Join(ice.ISH_PLUGED, repos)) { // 克隆代码 + m.Cmd("web.code.git.repos", mdb.CREATE, nfs.REPOS, "https://"+repos, nfs.PATH, path.Join(ice.ISH_PLUGED, repos)) + } + m.RenderDownload(path.Join(ice.ISH_PLUGED, repos, path.Join(arg...))) +} const ( TOPIC = "topic" @@ -112,9 +120,9 @@ const ( SHARE_TOAST = "/share/toast/" SHARE_CACHE = "/share/cache/" - SHARE_REPOS = "/share/repos/" - SHARE_PROXY = "/share/proxy/" SHARE_LOCAL = "/share/local/" + SHARE_PROXY = "/share/proxy/" + SHARE_REPOS = "/share/repos/" SHARE_LOCAL_AVATAR = "/share/local/avatar/" SHARE_LOCAL_BACKGROUND = "/share/local/background/" @@ -122,26 +130,10 @@ const ( const SHARE = "share" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SHARE: {Name: SHARE, Help: "共享链", Value: kit.Data( - mdb.EXPIRE, "72h", mdb.FIELD, "time,hash,userrole,username,river,storm,type,name,text", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SHARE: {Name: "share hash auto prunes", Help: "共享链", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - ice.AddRender(ice.RENDER_DOWNLOAD, func(msg *ice.Message, cmd string, args ...ice.Any) string { - list := []string{} - if msg.Option(ice.MSG_USERPOD) != "" { - list = append(list, ice.POD, msg.Option(ice.MSG_USERPOD)) - } - - arg := kit.Simple(args...) - if len(arg) > 1 { - list = append(list, "filename", arg[0]) - } - return fmt.Sprintf(`%s`, - _share_link(msg, kit.Select(arg[0], arg, 1), list), path.Base(arg[0]), arg[0]) - }) + _share_render(m) }}, mdb.CREATE: {Name: "create type name text", Help: "创建", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, mdb.TIME, m.Time(m.Config(mdb.EXPIRE)), @@ -154,38 +146,31 @@ func init() { m.EchoQRCode(msg.Option(mdb.LINK)) m.ProcessInner() }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.FIELD, "time,hash,userrole,username,river,storm,type,name,text", mdb.EXPIRE, "72h")), Hand: func(m *ice.Message, arg ...string) { if m.PodCmd(SHARE, arg) && m.Length() > 0 { return } if mdb.HashSelect(m, arg...); len(arg) > 0 { - link := _share_link(m, "/share/"+arg[0]) + link := _share_link(m, P(SHARE, arg[0])) m.PushQRCode(cli.QRCODE, link) m.PushScript(ssh.SCRIPT, link) m.PushAnchor(link) } else { m.Action(LOGIN) } - m.PushAction(mdb.REMOVE) - m.StatusTimeCount() }}, - "/share/": {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, arg ...string) { - m.Option(SHARE, kit.Select(m.Option(SHARE), arg, 0)) - if msg := m.Cmd(SHARE, m.Option(SHARE)); kit.Int(msg.Append(mdb.TIME)) < kit.Int(msg.FormatTime()) { + PP(SHARE): {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, arg ...string) { + msg := m.Cmd(SHARE, m.Option(SHARE, kit.Select(m.Option(SHARE), arg, 0))) + if kit.Int(msg.Append(mdb.TIME)) < kit.Int(msg.FormatTime()) { m.RenderResult("共享超时") return - } else { - switch msg.Append(mdb.TYPE) { - case LOGIN: - if sessid := aaa.SessCreate(m, msg.Append(aaa.USERNAME)); m.Option(ice.MSG_USERWEB) == "" { - m.RenderRedirect(ice.PS, ice.MSG_SESSID, sessid) - } else { - RenderCookie(m, sessid) - RenderRedirect(m, ice.PS) - } - default: - m.RenderIndex(SERVE, ice.VOLCANOS) - } + } + switch msg.Append(mdb.TYPE) { + case LOGIN: + sessid := aaa.SessCreate(m, msg.Append(aaa.USERNAME)) + m.RenderRedirect(ice.PS, ice.MSG_SESSID, sessid) + default: + m.RenderIndex(SERVE, ice.VOLCANOS) } }}, @@ -195,22 +180,20 @@ func init() { SHARE_CACHE: {Name: "/share/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) { _share_cache(m, arg...) }}, - SHARE_REPOS: {Name: "/share/repos/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { - _share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...) - }}, - SHARE_PROXY: {Name: "/share/proxy/", Help: "文件流", Hand: func(m *ice.Message, arg ...string) { - _share_proxy(m) - }}, SHARE_LOCAL: {Name: "/share/local/", Help: "文件夹", Hand: func(m *ice.Message, arg ...string) { _share_local(m, arg...) }}, SHARE_LOCAL_AVATAR: {Name: "avatar", Help: "头像", Hand: func(m *ice.Message, arg ...string) { - // RenderType(m.W, "", "image/svg+xml") - // m.RenderResult(`hello`) m.RenderDownload(strings.TrimPrefix(m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME)).Append(aaa.AVATAR), SHARE_LOCAL)) }}, SHARE_LOCAL_BACKGROUND: {Name: "background", Help: "壁纸", Hand: func(m *ice.Message, arg ...string) { m.RenderDownload(strings.TrimPrefix(m.Cmd(aaa.USER, m.Option(ice.MSG_USERNAME)).Append(aaa.BACKGROUND), SHARE_LOCAL)) }}, - }}) + SHARE_PROXY: {Name: "/share/proxy/", Help: "文件流", Hand: func(m *ice.Message, arg ...string) { + _share_proxy(m) + }}, + SHARE_REPOS: {Name: "/share/repos/", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { + _share_repos(m, path.Join(arg[0], arg[1], arg[2]), arg[3:]...) + }}, + }) } diff --git a/base/web/space.go b/base/web/space.go index dfb33f14..bb979f06 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -41,109 +41,117 @@ func _space_domain(m *ice.Message) (link string) { return tcp.ReplaceLocalhost(m, link) } func _space_dial(m *ice.Message, dev, name string, arg ...string) { - if strings.HasPrefix(dev, "http") { + if strings.HasPrefix(dev, ice.HTTP) { m.Cmd(SPIDE, mdb.CREATE, ice.DEV, dev) dev = ice.DEV } - value := m.Richs(SPIDE, nil, dev, nil) - client := kit.Value(value, tcp.CLIENT).(ice.Map) - - host := kit.Format(client[tcp.HOSTNAME]) - proto := strings.Replace(kit.Format(client[tcp.PROTOCOL]), "http", "ws", 1) - uri := kit.MergeURL(proto+"://"+host+"/space/", mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, - SHARE, m.Conf(cli.RUNTIME, kit.Keys("conf.ctx_share")), RIVER, m.Conf(cli.RUNTIME, kit.Keys("conf.ctx_river")), arg) + msg := m.Cmd(SPIDE, dev) + host := msg.Append(kit.Keys(tcp.CLIENT, tcp.HOSTNAME)) + proto := strings.Replace(msg.Append(kit.Keys(tcp.CLIENT, tcp.PROTOCOL)), ice.HTTP, "ws", 1) + uri := kit.MergeURL(proto+"://"+host+PP(SPACE), mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, SHARE, ice.Info.CtxShare, RIVER, ice.Info.CtxRiver, arg) + u := kit.ParseURL(uri) m.Go(func() { - u := kit.ParseURL(uri) - redial := m.Configm(REDIAL) frame := m.Target().Server().(*Frame) - for i := 0; i >= 0 && i < kit.Int(redial["c"]); i++ { - msg := m.Spawn() - ls := strings.Split(host, ":") - msg.Cmd(tcp.CLIENT, tcp.DIAL, kit.SimpleKV("type,name,host,port", proto, dev, ls[0], kit.Select("443", ls, 1)), func(s net.Conn) { - if s, _, e := websocket.NewClient(s, u, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !msg.Warn(e) { - msg.Rich(SPACE, nil, kit.Dict(SOCKET, s, kit.SimpleKV("", MASTER, dev, host))) - msg.Log_CREATE(SPACE, dev, "retry", i, "uri", uri) - defer msg.Conf(SPACE, kit.KeyHash(name), "") + ls := strings.Split(host, ":") + args := kit.SimpleKV("type,name,host,port", proto, dev, ls[0], kit.Select("443", ls, 1)) - // 连接成功 - if i = 0; _space_handle(msg, true, frame.send, s, dev) { - i = -2 // 连接关闭 + redial := m.Configm(REDIAL) + a, b, c := kit.Int(redial["a"]), kit.Int(redial["b"]), kit.Int(redial["c"]) + for i := 0; i >= 0 && i < c; i++ { + msg := m.Spawn() + msg.Cmd(tcp.CLIENT, tcp.DIAL, args, func(s net.Conn) { + if s, _, e := websocket.NewClient(s, u, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !msg.Warn(e) { + msg.Option(mdb.TARGET, s) + msg.Log_CREATE(SPACE, dev, "retry", i, "uri", uri) + mdb.HashCreate(msg, kit.SimpleKV("", MASTER, dev, host)) + defer mdb.HashRemove(msg, mdb.NAME, name) + + if i = 0; _space_handle(msg, true, frame, s, dev) { + i = -2 // 关闭连接 } } }) // 断线重连 - sleep := time.Duration(rand.Intn(kit.Int(redial["a"])*i+2)+kit.Int(redial["b"])) * time.Millisecond + sleep := time.Duration(rand.Intn(a*(i+1))+b) * time.Millisecond msg.Cost("order", i, "sleep", sleep, "reconnect", dev) - time.Sleep(sleep) + if time.Sleep(sleep); mdb.HashSelect(msg).Length() == 0 { + break + } } }) } -func _space_handle(m *ice.Message, safe bool, send map[string]*ice.Message, c *websocket.Conn, name string) bool { - for running := true; running; { - if _, b, e := c.ReadMessage(); m.Warn(e, SPACE, name) { +func _space_handle(m *ice.Message, safe bool, frame *Frame, c *websocket.Conn, name string) bool { + for { + _, b, e := c.ReadMessage() + if m.Warn(e, SPACE, name) { break - } else { - socket, msg := c, m.Spawn(b) - target := kit.Simple(msg.Optionv(ice.MSG_TARGET)) - source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name) - msg.Log("recv", "%v->%v %s %v", source, target, msg.Detailv(), msg.FormatMeta()) + } - if len(target) == 0 { - if msg.Option(ice.MSG_HANDLE) == ice.TRUE { - msg.Debug("what %v %v", msg.FormatMeta(), msg.FormatStack(1, 100)) - continue - } - if msg.Optionv(ice.MSG_HANDLE, ice.TRUE); safe { // 下行命令 - msg.Option(ice.MSG_USERROLE, kit.Select(msg.Option(ice.MSG_USERROLE), msg.Cmd(aaa.USER, msg.Option(ice.MSG_USERNAME)).Append(aaa.USERROLE))) - if msg.Option(ice.MSG_USERROLE) == aaa.VOID && ice.Info.UserName == "demo" { - msg.Option(ice.MSG_USERROLE, aaa.TECH) - } - msg.Log_AUTH(aaa.USERROLE, msg.Option(ice.MSG_USERROLE), aaa.USERNAME, msg.Option(ice.MSG_USERNAME)) - msg.Go(func() { _space_exec(msg, source, target, c, name) }) - } else { // 上行请求 - msg.Push(mdb.LINK, kit.MergePOD(_space_domain(msg), name)) - _space_echo(msg, []string{}, kit.Revert(source)[1:], c, name) - } + socket, msg := c, m.Spawn(b) + target := kit.Simple(msg.Optionv(ice.MSG_TARGET)) + source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name) + msg.Log("recv", "%v->%v %s %v", source, target, msg.Detailv(), msg.FormatMeta()) - } else if msg.Richs(SPACE, nil, target[0], func(key string, value ice.Map) { - if s, ok := value[SOCKET].(*websocket.Conn); ok { - socket, source, target = s, source, target[1:] - _space_echo(msg, source, target, socket, kit.Select("", target)) - return // 转发报文 - } - - if msg.Warn(msg.Option(ice.MSG_HANDLE) == ice.TRUE, ice.ErrNotFound, "already handled") { - // 回复失败 - - } else { // 下发失败 - msg.Warn(true, ice.ErrNotFound, target) - source, target = []string{}, kit.Revert(source)[1:] - } - }) != nil { // 转发成功 - - } else if res, ok := send[msg.Option(ice.MSG_TARGET)]; len(target) != 1 || !ok { - if msg.Warn(msg.Option(ice.MSG_HANDLE) == ice.TRUE, ice.ErrNotFound, target) { - // 回复失败 - - } else { // 下发失败 - msg.Warn(true, ice.ErrNotFound, target) - source, target = []string{}, kit.Revert(source)[1:] - } - - } else { // 接收响应 - m.Sleep30ms() - res.Back(msg) + if len(target) == 0 { // 执行命令 + if msg.Option(ice.MSG_HANDLE) == ice.TRUE { // 异常请求 + msg.Debug("what %v %v", msg.FormatMeta(), msg.FormatStack(1, 100)) + continue } + if msg.Optionv(ice.MSG_HANDLE, ice.TRUE); safe { // 下行命令 + msg.Option(ice.MSG_USERROLE, kit.Select(msg.Option(ice.MSG_USERROLE), msg.Cmd(aaa.USER, msg.Option(ice.MSG_USERNAME)).Append(aaa.USERROLE))) + if msg.Option(ice.MSG_USERROLE) == aaa.VOID && ice.Info.UserName == "demo" { + msg.Option(ice.MSG_USERROLE, aaa.TECH) + } + msg.Log_AUTH(aaa.USERROLE, msg.Option(ice.MSG_USERROLE), aaa.USERNAME, msg.Option(ice.MSG_USERNAME)) + msg.Go(func() { _space_exec(msg, source, target, c, name) }) + continue + } + // 上行请求 + msg.Push(mdb.LINK, kit.MergePOD(_space_domain(msg), name)) + _space_echo(msg, []string{}, kit.Revert(source)[1:], c, name) + continue + } + + if mdb.HashSelectDetail(msg, target[0], func(value ice.Map) { // 转发命令 + if s, ok := value[mdb.TARGET].(*websocket.Conn); ok { + socket, source, target = s, source, target[1:] + _space_echo(msg, source, target, socket, kit.Select("", target)) + return // 转发报文 + } + + if msg.Warn(msg.Option(ice.MSG_HANDLE) == ice.TRUE, ice.ErrNotValid, "already handled") { + // 回复失败 + + } else { // 下发失败 + msg.Warn(true, ice.ErrNotFound, target) + source, target = []string{}, kit.Revert(source)[1:] + } + }) { + continue + } + + if res, ok := frame.getSend(msg.Option(ice.MSG_TARGET)); len(target) != 1 || !ok { + if msg.Warn(msg.Option(ice.MSG_HANDLE) == ice.TRUE, ice.ErrNotValid, target) { + // 回复失败 + + } else { // 下发失败 + msg.Warn(true, ice.ErrNotFound, target) + source, target = []string{}, kit.Revert(source)[1:] + } + continue + } else { // 接收响应 + m.Sleep30ms() + res.Back(msg) } } return false } func _space_exec(msg *ice.Message, source, target []string, c *websocket.Conn, name string) { - if msg.Right(msg.Detailv()) { + if msg.Right(msg.Detailv()) { // 执行命令 msg = msg.Cmd() } @@ -154,12 +162,11 @@ func _space_exec(msg *ice.Message, source, target []string, c *websocket.Conn, n func _space_echo(msg *ice.Message, source, target []string, c *websocket.Conn, name string) { msg.Optionv(ice.MSG_SOURCE, source) msg.Optionv(ice.MSG_TARGET, target) - if e := c.WriteMessage(1, []byte(msg.FormatMeta())); msg.Warn(e) { - msg.Cmd(mdb.DELETE, msg.PrefixKey(), "", mdb.HASH, mdb.NAME, name) + if e := c.WriteMessage(1, []byte(msg.FormatMeta())); msg.Warn(e) { // 回复失败 + mdb.HashRemove(msg, mdb.NAME, name) c.Close() return } - target = append([]string{name}, target...) msg.Log("send", "%v->%v %v %v", source, target, msg.Detailv(), msg.FormatMeta()) } @@ -169,77 +176,54 @@ func _space_send(m *ice.Message, space string, arg ...string) { return } - target := kit.Split(space, ice.PT, ice.PT) - m.Warn(m.Richs(SPACE, nil, target[0], func(key string, value ice.Map) { - if socket, ok := value[SOCKET].(*websocket.Conn); !m.Warn(!ok, ice.ErrNotFound, SOCKET) { - - // 复制选项 - for _, k := range kit.Simple(m.Optionv(ice.MSG_OPTS)) { - switch k { - case ice.MSG_DETAIL, ice.MSG_CMDS, ice.MSG_SESSID: - default: - m.Optionv(k, m.Optionv(k)) - } - } - m.Optionv(ice.MSG_OPTS, m.Optionv(ice.MSG_OPTS)) - m.Optionv(ice.MSG_OPTION, m.Optionv(ice.MSG_OPTS)) - - // 构造路由 - frame := m.Target().Server().(*Frame) - id := kit.Format(m.Target().ID()) - frame.send[id] = m - - // 下发命令 - _space_echo(m.Set(ice.MSG_DETAIL, arg...), []string{id}, target[1:], socket, target[0]) - - m.Option(TIMEOUT, m.Config(kit.Keys(TIMEOUT, "c"))) - m.Call(m.Option("_async") == "", func(res *ice.Message) *ice.Message { // 返回结果 - if delete(frame.send, id); res != nil && m != nil { - return m.Cost(kit.Format("[%v]->%v %v %v", id, target, arg, m.Copy(res).FormatSize())) - } - return nil - }) - } - }) == nil, ice.ErrNotFound, space) -} -func _space_search(m *ice.Message, kind, name, text string, arg ...string) { - m.Richs(SPACE, nil, mdb.FOREACH, func(key string, value ice.Map) { - if value = kit.GetMeta(value); !strings.Contains(kit.Format(value[mdb.NAME]), name) { - return - } - - switch value[mdb.TYPE] { - case CHROME: - - case MASTER: - m.PushSearch(mdb.TEXT, m.Cmd(SPIDE, value[mdb.NAME], ice.OptionFields("")).Append("client.url"), value) + // 生成参数 + for _, k := range kit.Simple(m.Optionv(ice.MSG_OPTS)) { + switch k { + case ice.MSG_DETAIL, ice.MSG_CMDS, ice.MSG_SESSID: default: - m.PushSearch(mdb.TEXT, m.MergePod(kit.Format(value[mdb.NAME])), value) + m.Optionv(k, m.Optionv(k)) } - }) - if name != "" { + } + m.Optionv(ice.MSG_OPTS, m.Optionv(ice.MSG_OPTS)) + m.Optionv(ice.MSG_OPTION, m.Optionv(ice.MSG_OPTS)) + m.Set(ice.MSG_DETAIL, arg...) + + // 发送命令 + frame := m.Target().Server().(*Frame) + target, id := kit.Split(space, ice.PT, ice.PT), "" + if m.Warn(!mdb.HashSelectDetail(m, target[0], func(value ice.Map) { + if socket, ok := value[mdb.TARGET].(*websocket.Conn); !m.Warn(!ok, ice.ErrNotFound, mdb.TARGET) { + id = frame.addSend(kit.Format(m.Target().ID()), m) + _space_echo(m, []string{id}, target[1:], socket, target[0]) + } + }), ice.ErrNotFound, space) { return } - m.Cmd(SERVE, ice.OptionFields("")).Tables(func(val ice.Maps) { - m.Cmd(tcp.HOST, ice.OptionFields("")).Tables(func(value ice.Maps) { - m.PushSearch(kit.SimpleKV("", MYSELF, value[mdb.NAME], kit.Format("http://%s:%s", value[aaa.IP], val[tcp.PORT]))) - }) + + // 返回结果 + m.Option(TIMEOUT, m.Config(kit.Keys(TIMEOUT, "c"))) + m.Call(m.Option("_async") == "", func(res *ice.Message) *ice.Message { + if frame.delSend(id); res != nil && m != nil { + return m.Cost(kit.Format("[%v]->%v %v %v", id, target, arg, m.Copy(res).FormatSize())) + } + return nil }) } func _space_fork(m *ice.Message) { - if s, e := websocket.Upgrade(m.W, m.R, nil, kit.Int(m.Config("buffer.r")), kit.Int(m.Config("buffer.w"))); m.Assert(e) { + buffer := m.Configm(BUFFER) + if s, e := websocket.Upgrade(m.W, m.R, nil, kit.Int(buffer["r"]), kit.Int(buffer["w"])); m.Assert(e) { text := kit.Select(s.RemoteAddr().String(), m.Option(ice.MSG_USERADDR)) name := strings.ToLower(m.Option(mdb.NAME, kit.ReplaceAll(kit.Select(text, m.Option(mdb.NAME)), ".", "_", ":", "_"))) kind := kit.Select(WORKER, m.Option(mdb.TYPE)) args := append([]string{mdb.TYPE, kind, mdb.NAME, name}, m.OptionSimple(SHARE, RIVER)...) m.Go(func() { - h := m.Rich(SPACE, nil, kit.Dict(SOCKET, s, mdb.TEXT, kit.Select(text, m.Option(mdb.TEXT)), args)) - m.Log_CREATE(SPACE, name, mdb.TYPE, kind) + m.Optionv(mdb.TARGET, s) + mdb.HashCreate(m, mdb.TEXT, kit.Select(text, m.Option(mdb.TEXT)), args) switch kind { case CHROME: // 交互节点 - defer m.Confv(SPACE, kit.Keys(mdb.HASH, h), "") + defer mdb.HashRemove(m, mdb.NAME, name) m.Go(func(msg *ice.Message) { switch m.Option(ice.CMD) { case cli.PWD: @@ -261,13 +245,36 @@ func _space_fork(m *ice.Message) { default: // 服务节点 m.Event(SPACE_START, args...) defer m.Event(SPACE_STOP, args...) - defer m.Cmd(mdb.DELETE, m.PrefixKey(), "", mdb.HASH, mdb.NAME, name) + defer mdb.HashRemove(m, mdb.NAME, name) } - - _space_handle(m, false, m.Target().Server().(*Frame).send, s, name) + _space_handle(m, false, m.Target().Server().(*Frame), s, name) }) } } +func _space_search(m *ice.Message, kind, name, text string, arg ...string) { + m.Cmd(SPACE, ice.OptionFields("")).Tables(func(value ice.Maps) { + if !strings.Contains(value[mdb.NAME], name) { + return + } + + switch value[mdb.TYPE] { + case CHROME: + + case MASTER: + m.PushSearch(mdb.TEXT, m.Cmd(SPIDE, value[mdb.NAME], ice.OptionFields("")).Append("client.url"), value) + default: + m.PushSearch(mdb.TEXT, m.MergePod(value[mdb.NAME]), value) + } + }) + if name != "" { + return + } + m.Cmd(SERVE, ice.OptionFields("")).Tables(func(val ice.Maps) { + m.Cmd(tcp.HOST, ice.OptionFields("")).Tables(func(value ice.Maps) { + m.PushSearch(kit.SimpleKV("", MYSELF, value[mdb.NAME], kit.Format("http://%s:%s", value[aaa.IP], val[tcp.PORT]))) + }) + }) +} const ( CHROME = "chrome" @@ -278,13 +285,12 @@ const ( WORKER = "worker" ) const ( - SPACE_START = "space.start" - SPACE_STOP = "space.stop" - - SOCKET = "socket" BUFFER = "buffer" REDIAL = "redial" TIMEOUT = "timeout" + + SPACE_START = "space.start" + SPACE_STOP = "space.stop" ) const SPACE = "space" @@ -298,16 +304,23 @@ func init() { }, Commands: ice.Commands{ SPACE: {Name: "space name cmd auto invite", Help: "空间站", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - m.Conf(SPACE, mdb.HASH, "") + m.Conf("", mdb.HASH, "") + }}, + ice.CTX_EXIT: {Hand: func(m *ice.Message, arg ...string) { + mdb.HashSelectValue(m, func(target ice.Any) { + if c, ok := target.(*websocket.Conn); ok { + c.Close() + } + }) + m.Conf("", mdb.HASH, "") }}, mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmd(SPACE, mdb.MODIFY, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP) + mdb.HashModify(m, m.OptionSimple(mdb.NAME), mdb.STATUS, cli.STOP) + defer mdb.HashRemove(m, m.OptionSimple(mdb.NAME)) m.Cmd(SPACE, m.Option(mdb.NAME), ice.EXIT) - mdb.HashRemove(m, m.OptionSimple(mdb.NAME)) }}, mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { _space_search(m, arg[0], arg[1], kit.Select("", arg, 2)) - _broad_search(m, arg[0], arg[1], kit.Select("", arg, 2)) }}, aaa.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) { for _, k := range []string{ice.MISC, ice.CORE, ice.BASE} { @@ -342,7 +355,7 @@ func init() { // 下发命令 _space_send(m, strings.ToLower(arg[0]), arg[1:]...) }}, - "/space/": {Name: "/space/ type name share river", Help: "空间站", Hand: func(m *ice.Message, arg ...string) { + PP(SPACE): {Name: "/space/ type name share river", Help: "空间站", Hand: func(m *ice.Message, arg ...string) { _space_fork(m) }}, }}) diff --git a/base/web/spide.go b/base/web/spide.go index 25b369de..fab6d81b 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -23,109 +23,100 @@ import ( ) func _spide_create(m *ice.Message, name, address string) { - if uri, e := url.Parse(address); e == nil && address != "" { - if m.Richs(SPIDE, nil, name, func(key string, value ice.Map) { - kit.Value(value, "client.hostname", uri.Host) - kit.Value(value, "client.url", address) - }) == nil { - dir, file := path.Split(uri.EscapedPath()) - m.Echo(m.Rich(SPIDE, nil, kit.Dict( - SPIDE_COOKIE, kit.Dict(), SPIDE_HEADER, kit.Dict(), SPIDE_CLIENT, kit.Dict( - mdb.NAME, name, SPIDE_METHOD, SPIDE_POST, "url", address, - tcp.PROTOCOL, uri.Scheme, tcp.HOSTNAME, uri.Host, - nfs.PATH, dir, nfs.FILE, file, "query", uri.RawQuery, - cli.TIMEOUT, "600s", LOGHEADERS, ice.FALSE, - ), - ))) - } + if uri, e := url.Parse(address); !m.Warn(e != nil || address == "") { + dir, file := path.Split(uri.EscapedPath()) + mdb.HashCreate(m, CLIENT_NAME, name) + mdb.HashSelectUpdate(m, name, func(value ice.Map) { + value[SPIDE_COOKIE] = kit.Dict() + value[SPIDE_HEADER] = kit.Dict() + value[SPIDE_CLIENT] = kit.Dict( + mdb.NAME, name, SPIDE_METHOD, SPIDE_POST, "url", address, + tcp.PROTOCOL, uri.Scheme, tcp.HOSTNAME, uri.Host, + nfs.PATH, dir, nfs.FILE, file, "query", uri.RawQuery, + cli.TIMEOUT, "600s", LOGHEADERS, ice.FALSE, + ) + }) m.Log_CREATE(SPIDE, name, ADDRESS, address) } } func _spide_list(m *ice.Message, arg ...string) { - m.Richs(SPIDE, nil, arg[0], func(key string, value ice.Map) { - // 缓存方式 - cache, save := "", "" - switch arg[1] { - case "url": - m.Echo("%v", kit.Value(value, "client.url")) - return - case SPIDE_RAW: - cache, arg = arg[1], arg[1:] - case SPIDE_MSG: - cache, arg = arg[1], arg[1:] - case SPIDE_SAVE: - cache, save, arg = arg[1], arg[2], arg[2:] - case SPIDE_CACHE: - cache, arg = arg[1], arg[1:] - } + // 缓存方法 + cache, save := "", "" + switch arg[1] { + case SPIDE_RAW: + cache, arg = arg[1], arg[1:] + case SPIDE_MSG: + cache, arg = arg[1], arg[1:] + case SPIDE_SAVE: + cache, save, arg = arg[1], arg[2], arg[2:] + case SPIDE_CACHE: + cache, arg = arg[1], arg[1:] + } - // 请求方法 - client := value[SPIDE_CLIENT].(ice.Map) - method := kit.Select(SPIDE_POST, client[SPIDE_METHOD]) - switch arg = arg[1:]; arg[0] { - case SPIDE_GET: - method, arg = SPIDE_GET, arg[1:] - case SPIDE_PUT: - method, arg = SPIDE_PUT, arg[1:] - case SPIDE_POST: - method, arg = SPIDE_POST, arg[1:] - case SPIDE_DELETE: - method, arg = SPIDE_DELETE, arg[1:] - } + // 请求方法 + msg := mdb.HashSelect(m.Spawn(), arg[0]) + method := kit.Select(SPIDE_POST, msg.Append(CLIENT_METHOD)) + switch arg = arg[1:]; arg[0] { + case SPIDE_GET: + method, arg = SPIDE_GET, arg[1:] + case SPIDE_PUT: + method, arg = SPIDE_PUT, arg[1:] + case SPIDE_POST: + method, arg = SPIDE_POST, arg[1:] + case SPIDE_DELETE: + method, arg = SPIDE_DELETE, arg[1:] + } - // 请求地址 - uri, arg := arg[0], arg[1:] + // 构造请求 + uri, arg := arg[0], arg[1:] + body, head, arg := _spide_body(m, method, arg...) + req, e := http.NewRequest(method, kit.MergeURL2(msg.Append(CLIENT_URL), uri, arg), body) + if m.Warn(e, ice.ErrNotValid, uri) { + return + } - // 请求参数 - body, head, arg := _spide_body(m, method, arg...) - - // 构造请求 - req, e := http.NewRequest(method, kit.MergeURL2(kit.Format(client["url"]), uri, arg), body) - if m.Warn(e, ice.ErrNotFound, uri) { - return - } - - // 请求配置 + // 请求变量 + mdb.HashSelectDetail(m, msg.Append(CLIENT_NAME), func(value ice.Map) { _spide_head(m, req, head, value) + }) - // 发送请求 - res, e := _spide_send(m, req, kit.Format(client[cli.TIMEOUT])) - if m.Warn(e, ice.ErrNotFound, uri) { - return + // 发送请求 + res, e := _spide_send(m, req, kit.Format(msg.Append("client.timeout"))) + if m.Warn(e, ice.ErrNotFound, uri) { + return + } + defer res.Body.Close() + + // 请求日志 + if m.Config(LOGHEADERS) == ice.TRUE { + for k, v := range res.Header { + m.Debug("%v: %v", k, v) } + } + m.Cost(cli.STATUS, res.Status, nfs.SIZE, res.Header.Get(ContentLength), mdb.TYPE, res.Header.Get(ContentType)) - if m.Config(LOGHEADERS) == ice.TRUE { - for k, v := range res.Header { - m.Debug("%v: %v", k, v) - } - } - - // 检查结果 - defer res.Body.Close() - m.Cost(cli.STATUS, res.Status, nfs.SIZE, res.Header.Get(ContentLength), mdb.TYPE, res.Header.Get(ContentType)) - - // 缓存配置 + // 响应变量 + mdb.HashSelectUpdate(m, msg.Append(CLIENT_NAME), func(value ice.Map) { for _, v := range res.Cookies() { kit.Value(value, kit.Keys(SPIDE_COOKIE, v.Name), v.Value) m.Log_IMPORT(v.Name, v.Value) } - - // 错误信息 - if m.Warn(res.StatusCode != http.StatusOK, ice.ErrNotFound, uri, "status", res.Status) { - // b, _ := ioutil.ReadAll(res.Body) - switch m.Set(ice.MSG_RESULT); res.StatusCode { - case http.StatusNotFound: - m.Warn(true, ice.ErrNotFound, uri) - return - case http.StatusUnauthorized: - m.Warn(true, ice.ErrNotRight, uri) - return - } - } - - // 解析结果 - _spide_save(m, cache, save, uri, res) }) + + // 处理异常 + if m.Warn(res.StatusCode != http.StatusOK, ice.ErrNotFound, uri, cli.STATUS, res.Status) { + switch m.Set(ice.MSG_RESULT); res.StatusCode { + case http.StatusNotFound: + m.Warn(true, ice.ErrNotFound, uri) + return + case http.StatusUnauthorized: + m.Warn(true, ice.ErrNotRight, uri) + return + } + } + + // 解析结果 + _spide_save(m, cache, save, uri, res) } func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.Maps, []string) { head := ice.Maps{} @@ -284,7 +275,7 @@ func _spide_save(m *ice.Message, cache, save, uri string, res *http.Response) { case SPIDE_CACHE: m.Optionv(RESPONSE, res) m.Cmdy(CACHE, DOWNLOAD, res.Header.Get(ContentType), uri) - m.Echo(m.Append(DATA)) + m.Echo(m.Append(mdb.DATA)) default: b, _ := ioutil.ReadAll(res.Body) @@ -302,25 +293,30 @@ func _spide_save(m *ice.Message, cache, save, uri string, res *http.Response) { } const ( + // 缓存方法 SPIDE_RAW = "raw" SPIDE_MSG = "msg" SPIDE_SAVE = "save" SPIDE_CACHE = "cache" + // 请求方法 SPIDE_GET = "GET" SPIDE_PUT = "PUT" SPIDE_POST = "POST" SPIDE_DELETE = "DELETE" + // 请求参数 SPIDE_BODY = "body" SPIDE_FORM = "form" SPIDE_PART = "part" + SPIDE_JSON = "json" SPIDE_DATA = "data" SPIDE_FILE = "file" - SPIDE_JSON = "json" + // 响应数据 SPIDE_RES = "content_data" + // 请求头 Bearer = "Bearer" Authorization = "Authorization" ContentType = "Content-Type" @@ -328,6 +324,7 @@ const ( UserAgent = "User-Agent" Accept = "Accept" + // 数据格式 ContentFORM = "application/x-www-form-urlencoded" ContentJSON = "application/json" ContentHTML = "text/html" @@ -340,30 +337,30 @@ const ( SPIDE_HEADER = "header" SPIDE_COOKIE = "cookie" + CLIENT_NAME = "client.name" + CLIENT_METHOD = "client.method" + CLIENT_URL = "client.url" + LOGHEADERS = "logheaders" + FORM = "form" ADDRESS = "address" REQUEST = "request" RESPONSE = "response" - CLIENT_NAME = "client.name" - CLIENT_URL = "client.url" - LOGHEADERS = "logheaders" - - MERGE = "merge" + MERGE = "merge" + SUBMIT = "submit" ) const SPIDE = "spide" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SPIDE: {Name: SPIDE, Help: "蜘蛛侠", Value: kit.Data(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url", LOGHEADERS, ice.FALSE)}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SPIDE: {Name: "spide client.name action=raw,msg,save,cache method=GET,PUT,POST,DELETE url format=form,part,json,data,file arg run create", Help: "蜘蛛侠", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - conf := m.Confm(cli.RUNTIME, "conf") - m.Cmd(SPIDE, mdb.CREATE, ice.OPS, kit.Select("http://127.0.0.1:9020", conf["ctx_ops"])) - m.Cmd(SPIDE, mdb.CREATE, ice.DEV, kit.Select("http://contexts.woa.com:80", conf["ctx_dev"])) - m.Cmd(SPIDE, mdb.CREATE, ice.SHY, kit.Select("https://shylinux.com:443", conf["ctx_shy"])) - m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, SPIDE, "submit") + conf := m.Confm(cli.RUNTIME, cli.CONF) + m.Cmd(SPIDE, mdb.CREATE, ice.OPS, kit.Select("http://127.0.0.1:9020", conf[cli.CTX_OPS])) + m.Cmd(SPIDE, mdb.CREATE, ice.DEV, kit.Select("http://contexts.woa.com:80", conf[cli.CTX_DEV])) + m.Cmd(SPIDE, mdb.CREATE, ice.SHY, kit.Select("https://shylinux.com:443", conf[cli.CTX_SHY])) + m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, SPIDE, SUBMIT) }}, mdb.CREATE: {Name: "create name address", Help: "添加", Hand: func(m *ice.Message, arg ...string) { _spide_create(m, m.Option(mdb.NAME), m.Option(ADDRESS)) @@ -371,38 +368,24 @@ func init() { MERGE: {Name: "merge name path", Help: "拼接", Hand: func(m *ice.Message, arg ...string) { m.Echo(kit.MergeURL2(m.Cmd(SPIDE, arg[0], ice.OptionFields("")).Append(CLIENT_URL), arg[1], arg[2:])) }}, - "submit": {Name: "submit dev pod path size cache", Help: "发布", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPIDE, ice.DEV, SPIDE_RAW, m.Option("dev"), SPIDE_PART, "pod", m.Option("pod"), nfs.PATH, "bin/ice.bin", UPLOAD, "@"+"bin/ice.bin") + SUBMIT: {Name: "submit dev pod path size cache", Help: "发布", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(SPIDE, ice.DEV, SPIDE_RAW, m.Option(ice.DEV), SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, ice.BIN_ICE_BIN, UPLOAD, "@"+ice.BIN_ICE_BIN) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url", LOGHEADERS, ice.FALSE)), Hand: func(m *ice.Message, arg ...string) { if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") { - mdb.HashSelect(m, kit.Slice(arg, 0, 1)...) - m.Sort("client.name") - return + mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Sort(CLIENT_NAME) + } else { + _spide_list(m, arg...) } - _spide_list(m, arg...) }}, - - SPIDE_GET: {Name: "GET url key value run", Help: "蜘蛛侠", Actions: ice.Actions{ - mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.DELETE, SPIDE, "", mdb.HASH, m.OptionSimple(CLIENT_NAME)) - }}, - }, Hand: func(m *ice.Message, arg ...string) { + SPIDE_GET: {Name: "GET url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) { m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_GET, arg[0], arg[1:])))) }}, - SPIDE_POST: {Name: "POST url key value run", Help: "蜘蛛侠", Actions: ice.Actions{ - mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.DELETE, SPIDE, "", mdb.HASH, m.OptionSimple(CLIENT_NAME)) - }}, - }, Hand: func(m *ice.Message, arg ...string) { + SPIDE_POST: {Name: "POST url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) { m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_POST, arg[0], arg[1:])))) }}, - SPIDE_DELETE: {Name: "DELETE url key value run", Help: "蜘蛛侠", Actions: ice.Actions{ - mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.DELETE, SPIDE, "", mdb.HASH, m.OptionSimple(CLIENT_NAME)) - }}, - }, Hand: func(m *ice.Message, arg ...string) { + SPIDE_DELETE: {Name: "DELETE url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) { m.Echo(kit.Formats(kit.UnMarshal(m.Cmdx(SPIDE, ice.DEV, SPIDE_RAW, SPIDE_DELETE, arg[0], arg[1:])))) }}, - }}) + }) } diff --git a/base/web/web.go b/base/web/web.go index eaabd428..7531793b 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -11,6 +11,8 @@ import ( "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" + "shylinux.com/x/toolkits/task" ) type Frame struct { @@ -20,21 +22,37 @@ type Frame struct { *http.ServeMux send map[string]*ice.Message + lock task.Lock } -func (web *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if _serve_main(web.Message, w, r) { - web.ServeMux.ServeHTTP(w, r) +func (frame *Frame) getSend(key string) (*ice.Message, bool) { + defer frame.lock.RLock()() + msg, ok := frame.send[key] + return msg, ok +} +func (frame *Frame) addSend(key string, msg *ice.Message) string { + defer frame.lock.Lock()() + frame.send[key] = msg + return key +} +func (frame *Frame) delSend(key string) { + defer frame.lock.Lock()() + delete(frame.send, key) +} + +func (frame *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if _serve_main(frame.Message, w, r) { + frame.ServeMux.ServeHTTP(w, r) } } -func (web *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { +func (frame *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { return &Frame{} } -func (web *Frame) Begin(m *ice.Message, arg ...string) ice.Server { - web.send = map[string]*ice.Message{} - return web +func (frame *Frame) Begin(m *ice.Message, arg ...string) ice.Server { + frame.send = map[string]*ice.Message{} + return frame } -func (web *Frame) Start(m *ice.Message, arg ...string) bool { +func (frame *Frame) Start(m *ice.Message, arg ...string) bool { list := map[*ice.Context]string{} m.Travel(func(p *ice.Context, s *ice.Context) { if frame, ok := s.Server().(*Frame); ok { @@ -42,19 +60,20 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool { return } frame.ServeMux = http.NewServeMux() + meta := logs.FileLineMeta("") // 级联路由 msg := m.Spawn(s) if pframe, ok := p.Server().(*Frame); ok && pframe.ServeMux != nil { route := ice.PS + s.Name + ice.PS - msg.Log(ROUTE, "%s <= %s", p.Name, route) + msg.Log(ROUTE, "%s <= %s", p.Name, route, meta) pframe.Handle(route, http.StripPrefix(path.Dir(route), frame)) list[s] = path.Join(list[p], route) } // 静态路由 m.Confm(SERVE, kit.Keym(nfs.PATH), func(key string, value string) { - m.Log(ROUTE, "%s <- %s <- %s", s.Name, key, value) + m.Log(ROUTE, "%s <- %s <- %s", s.Name, key, value, meta) frame.Handle(key, http.StripPrefix(key, http.FileServer(http.Dir(value)))) }) @@ -63,7 +82,7 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool { if s != sub || k[0] != '/' { return } - msg.Log(ROUTE, "%s <- %s", s.Name, k) + msg.Log(ROUTE, "%s <- %s", s.Name, k, meta) ice.Info.Route[path.Join(list[s], k)] = ice.FileCmd(kit.FileLine(x.Hand, 300)) frame.HandleFunc(k, func(frame http.ResponseWriter, r *http.Request) { m.TryCatch(msg.Spawn(), true, func(msg *ice.Message) { @@ -77,24 +96,25 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool { m.Event(SERVE_START) defer m.Event(SERVE_STOP) - web.Message, web.Server = m, &http.Server{Handler: web} + frame.Message, frame.Server = m, &http.Server{Handler: frame} switch cb := m.OptionCB(SERVE).(type) { case func(http.Handler): - cb(web) // 启动框架 + cb(frame) // 启动框架 default: m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, WEB, m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT), func(l net.Listener) { - m.Cmdy(mdb.INSERT, SERVE, "", mdb.HASH, mdb.NAME, WEB, arg, m.OptionSimple(tcp.PROTO, ice.DEV), cli.STATUS, tcp.START) + m.Cmd(mdb.INSERT, SERVE, "", mdb.HASH, mdb.NAME, WEB, arg, m.OptionSimple(tcp.PROTO, ice.DEV), cli.STATUS, tcp.START, kit.Dict(mdb.TARGET, l)) defer m.Cmd(mdb.MODIFY, SERVE, "", mdb.HASH, m.OptionSimple(mdb.NAME), cli.STATUS, tcp.STOP) - m.Warn(web.Server.Serve(l)) // 启动服务 + m.Warn(frame.Server.Serve(l)) // 启动服务 }) } return true } -func (web *Frame) Close(m *ice.Message, arg ...string) bool { - return m.Done(true) +func (frame *Frame) Close(m *ice.Message, arg ...string) bool { + return true } -func P(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) } +func P(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) } +func PP(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) + ice.PS } const ( SERVE_START = "serve.start" @@ -106,8 +126,7 @@ var Index = &ice.Context{Name: WEB, Help: "网络模块"} func init() { ice.Index.Register(Index, &Frame{}, - SERVE, SPACE, DREAM, ROUTE, - SHARE, SPIDE, CACHE, STORY, - BROAD, + BROAD, SERVE, SPACE, DREAM, + SHARE, CACHE, SPIDE, ROUTE, ) } diff --git a/base/yac/matrix.go b/base/yac/matrix.go index 982dd9f3..fe6eabc4 100644 --- a/base/yac/matrix.go +++ b/base/yac/matrix.go @@ -359,7 +359,7 @@ func init() { case func(string, *Matrix): cb(h, mat) default: - m.Error(true, ice.ErrNotImplement) + m.ErrorNotImplement(cb) } m.Echo(h) }}, @@ -400,7 +400,7 @@ func init() { case func(string, int, []string, int, *lex.Stream) (int, []string): return cb(nhash, hash, word, begin, stream) default: - m.Error(true, ice.ErrNotImplement) + m.ErrorNotImplement(cb) } return hash, word }, mat.index(m, NPAGE, m.Option(NPAGE)), stream, 1) diff --git a/base/yac/script.go b/base/yac/script.go index 826018dd..8722e6df 100644 --- a/base/yac/script.go +++ b/base/yac/script.go @@ -95,7 +95,7 @@ func _exp_true(m *ice.Message, arg string) bool { const SCRIPT = "script" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SCRIPT: {Name: "script name npage text auto create", Help: "脚本解析", Actions: ice.Actions{ mdb.CREATE: {Name: "create name=shy text=etc/yac.txt", Help: "创建", Hand: func(m *ice.Message, arg ...string) { m.Cmd(MATRIX, mdb.CREATE, m.Option(mdb.NAME)) @@ -214,5 +214,5 @@ func init() { }) m.Resultv(stack.res) }}, - }}) + }) } diff --git a/conf.go b/conf.go index 68582440..8e691f9c 100644 --- a/conf.go +++ b/conf.go @@ -17,7 +17,6 @@ const ( SUCCESS = "success" FAILURE = "failure" PROCESS = "process" - RESTART = "restart" OF = " of " INIT = "init" @@ -107,14 +106,18 @@ const ( // DIR PLUGIN_INPUT = "/plugin/input" PLUGIN_STORY = "/plugin/story" PLUGIN_LOCAL = "/plugin/local" + NODE_MODULES = "node_modules" + ISH_PLUGED = ".ish/pluged" - FAVICON = "favicon.ico" - PROTO_JS = "proto.js" - FRAME_JS = "frame.js" - INDEX_JS = "index.js" - ORDER_JS = "order.js" - ORDER_SH = "order.sh" - INDEX_SH = "index.sh" + FAVICON = "favicon.ico" + PROTO_JS = "proto.js" + FRAME_JS = "frame.js" + INDEX_JS = "index.js" + ORDER_JS = "order.js" + ORDER_SH = "order.sh" + INDEX_SH = "index.sh" + INDEX_IML = "index.iml" + TUTOR_SHY = "tutor.shy" USR_LOCAL = "usr/local" USR_LOCAL_GO = "usr/local/go" @@ -159,6 +162,8 @@ const ( // DIR ICE_BIN = "ice.bin" GO_SUM = "go.sum" GO_MOD = "go.mod" + + CTX_DAEMON = "ctx_daemon" ) const ( // MSG MSG_DETAIL = "detail" @@ -206,23 +211,26 @@ const ( // MSG MSG_STORM = "sess.storm" MSG_TOAST = "sess.toast" MSG_LOCAL = "sess.local" + + MSG_FILES = "file.system" ) const ( // RENDER - RENDER_RAW = "_raw" - RENDER_VOID = "_void" - RENDER_JSON = "_json" RENDER_STATUS = "_status" - RENDER_RESULT = "_result" - RENDER_ANCHOR = "_anchor" - RENDER_BUTTON = "_button" - RENDER_SCRIPT = "_script" - RENDER_QRCODE = "_qrcode" - RENDER_IMAGES = "_images" - RENDER_VIDEOS = "_videos" - RENDER_IFRAME = "_iframe" - RENDER_TEMPLATE = "_template" RENDER_REDIRECT = "_redirect" RENDER_DOWNLOAD = "_download" + RENDER_TEMPLATE = "_template" + RENDER_RESULT = "_result" + RENDER_JSON = "_json" + RENDER_VOID = "_void" + RENDER_RAW = "_raw" + + RENDER_ANCHOR = "_anchor" + RENDER_BUTTON = "_button" + RENDER_SCRIPT = "_script" + RENDER_QRCODE = "_qrcode" + RENDER_IMAGES = "_images" + RENDER_VIDEOS = "_videos" + RENDER_IFRAME = "_iframe" ) const ( // PROCESS PROCESS_LOCATION = "_location" @@ -369,4 +377,13 @@ const ( // gdb LISTEN = "listen" HAPPEN = "happen" FILELINE = "fileline" + + RESTART = "restart" + ERROR = "error" + OPEN = "open" + CLOSE = "close" + START = "start" + STOP = "stop" + BEGIN = "begin" + END = "end" ) diff --git a/core/chat/action.go b/core/chat/action.go index 7f23b5e9..7aab57ab 100644 --- a/core/chat/action.go +++ b/core/chat/action.go @@ -146,7 +146,7 @@ const ( const ACTION = "action" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ web.P(ACTION): {Name: "/action river storm action arg...", Help: "工作台", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { for _, cmd := range []string{ @@ -193,5 +193,5 @@ func init() { // 执行命令 _action_exec(m, arg[0], arg[1], arg[2], arg[3:]...) }}, - }}) + }) } diff --git a/core/chat/cmd.go b/core/chat/cmd.go index d749dd80..72bc4136 100644 --- a/core/chat/cmd.go +++ b/core/chat/cmd.go @@ -51,9 +51,40 @@ func _cmd_file(m *ice.Message, arg ...string) bool { const CMD = "cmd" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - CMD: {Name: CMD, Help: "命令", Value: kit.Data(mdb.SHORT, "type", nfs.PATH, nfs.PWD)}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ + CMD: {Name: "cmd path auto upload up home", Help: "命令", Actions: ice.MergeAction(ice.Actions{ + web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { + m.Upload(path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd"))) + }}, + + "home": {Name: "home", Help: "根目录", Hand: func(m *ice.Message, arg ...string) { + m.ProcessLocation("/chat/cmd/") + }}, + "up": {Name: "up", Help: "上一级", Hand: func(m *ice.Message, arg ...string) { + if strings.TrimPrefix(m.R.URL.Path, "/cmd") == ice.PS { + m.Cmdy(CMD) + } else if strings.HasSuffix(m.R.URL.Path, ice.PS) { + m.ProcessLocation("../") + } else { + m.ProcessLocation(nfs.PWD) + } + }}, + }, mdb.HashAction(mdb.SHORT, "type", nfs.PATH, nfs.PWD)), Hand: func(m *ice.Message, arg ...string) { + if _cmd_file(m, arg...) { + return + } + if msg := m.Cmd(ctx.COMMAND, arg[0]); msg.Length() > 0 { + m.RenderCmd(arg[0]) + return + } + + if len(arg) > 0 { + m.ProcessLocation(arg[0]) + return + } + m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd"))) + m.Cmdy(nfs.DIR, arg) + }}, "/cmd/": {Name: "/cmd/", Help: "命令", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Name: "_init", Help: "初始化", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(CMD, mdb.CREATE, mdb.TYPE, "shy", mdb.NAME, "web.wiki.word") @@ -84,38 +115,5 @@ func init() { m.RenderDownload(path.Join(m.Config(nfs.PATH), path.Join(arg...))) // 文件 } }}, - CMD: {Name: "cmd path auto upload up home", Help: "命令", Actions: ice.MergeAction(ice.Actions{ - web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { - m.Upload(path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd"))) - }}, - - "home": {Name: "home", Help: "根目录", Hand: func(m *ice.Message, arg ...string) { - m.ProcessLocation("/chat/cmd/") - }}, - "up": {Name: "up", Help: "上一级", Hand: func(m *ice.Message, arg ...string) { - if strings.TrimPrefix(m.R.URL.Path, "/cmd") == ice.PS { - m.Cmdy(CMD) - } else if strings.HasSuffix(m.R.URL.Path, ice.PS) { - m.ProcessLocation("../") - } else { - m.ProcessLocation(nfs.PWD) - } - }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { - if _cmd_file(m, arg...) { - return - } - if msg := m.Cmd(ctx.COMMAND, arg[0]); msg.Length() > 0 { - m.RenderCmd(arg[0]) - return - } - - if len(arg) > 0 { - m.ProcessLocation(arg[0]) - return - } - m.Option(nfs.DIR_ROOT, path.Join(m.Config(nfs.PATH), strings.TrimPrefix(path.Dir(m.R.URL.Path), "/cmd"))) - m.Cmdy(nfs.DIR, arg) - }}, - }}) + }) } diff --git a/core/chat/files.go b/core/chat/files.go index 38984539..788633c4 100644 --- a/core/chat/files.go +++ b/core/chat/files.go @@ -11,11 +11,7 @@ import ( const FILES = "files" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - FILES: {Name: FILES, Help: "文件夹", Value: kit.Data( - mdb.SHORT, mdb.DATA, mdb.FIELD, "time,hash,type,name,size,data", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ FILES: {Name: "files hash auto upload", Help: "文件夹", Actions: ice.MergeAction(ice.Actions{ web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)) @@ -25,7 +21,7 @@ func init() { } m.Cmdy(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, mdb.TYPE, kit.Ext(up[1]), mdb.NAME, up[1], nfs.SIZE, up[2], mdb.DATA, up[0]) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.DATA, mdb.FIELD, "time,hash,type,name,size,data")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...) m.Tables(func(value ice.Maps) { link := web.SHARE_CACHE + value[mdb.DATA] @@ -34,5 +30,5 @@ func init() { } }) }}, - }}) + }) } diff --git a/core/chat/grant.go b/core/chat/grant.go index ba390a6d..e746a5fc 100644 --- a/core/chat/grant.go +++ b/core/chat/grant.go @@ -10,7 +10,7 @@ import ( const GRANT = "grant" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ GRANT: {Name: "grant space id auto insert", Help: "授权", Actions: ice.MergeAction(ice.Actions{ mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { switch arg[0] { @@ -26,5 +26,5 @@ func init() { }}, mdb.INSERT: {Name: "insert space grant userrole username", Help: "添加"}, }, mdb.ZoneAction(mdb.SHORT, web.SPACE, mdb.FIELD, "time,grant,userrole,username"))}, - }}) + }) } diff --git a/core/chat/info.go b/core/chat/info.go index 7dfc1675..7ee72946 100644 --- a/core/chat/info.go +++ b/core/chat/info.go @@ -8,7 +8,7 @@ import ( const INFO = "info" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ INFO: {Name: "info auto", Help: "信息", Actions: ice.Actions{ mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.MODIFY, RIVER, "", mdb.HASH, mdb.HASH, m.Option(ice.MSG_RIVER), arg) @@ -17,5 +17,5 @@ func init() { m.OptionFields(mdb.DETAIL) m.Cmdy(mdb.SELECT, RIVER, "", mdb.HASH, mdb.HASH, m.Option(ice.MSG_RIVER)) }}, - }}) + }) } diff --git a/core/chat/location.go b/core/chat/location.go index 0337f7b6..e0fb0378 100644 --- a/core/chat/location.go +++ b/core/chat/location.go @@ -42,6 +42,9 @@ func init() { m.Echo(get(m, "place/v1/explore", m.OptionSimple("boundary,page_index"))) }}, "search": {Name: "search", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { + if arg[0] == "*" { + return + } m.Echo(get(m, "place/v1/search", m.OptionSimple("keyword,boundary,page_index"))) }}, "direction": {Name: "direction", Help: "导航", Hand: func(m *ice.Message, arg ...string) { diff --git a/core/chat/node.go b/core/chat/node.go index 8989ae28..2c7d961d 100644 --- a/core/chat/node.go +++ b/core/chat/node.go @@ -12,7 +12,7 @@ import ( const NODE = "node" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ NODE: {Name: "node pod ctx cmd auto insert invite", Help: "设备", Actions: ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Watch(web.DREAM_START, m.PrefixKey()) @@ -60,5 +60,5 @@ func init() { } m.Cmdy(web.ROUTE, arg) }}, - }}) + }) } diff --git a/core/chat/ocean.go b/core/chat/ocean.go index 0bf8fac0..b89b83b3 100644 --- a/core/chat/ocean.go +++ b/core/chat/ocean.go @@ -10,7 +10,7 @@ import ( const OCEAN = "ocean" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ OCEAN: {Name: "ocean username auto insert invite", Help: "用户", Actions: ice.Actions{ mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(aaa.USER, ice.OptionFields(aaa.USERNAME, aaa.USERNICK, aaa.USERZONE)) @@ -31,5 +31,5 @@ func init() { }) m.PushAction(mdb.DELETE) }}, - }}) + }) } diff --git a/core/chat/paste.go b/core/chat/paste.go index adaec60f..a109bf18 100644 --- a/core/chat/paste.go +++ b/core/chat/paste.go @@ -5,27 +5,22 @@ import ( "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/ssh" - kit "shylinux.com/x/toolkits" ) const PASTE = "paste" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - PASTE: {Name: PASTE, Help: "粘贴", Value: kit.Data( - mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ PASTE: {Name: "paste hash auto getClipboardData", Help: "粘贴", Actions: ice.MergeAction(ice.Actions{ "getClipboardData": {Name: "getClipboardData", Help: "粘贴", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(PASTE, mdb.CREATE, arg) }}, mdb.CREATE: {Name: "create type=text name=hi text:textarea=hi", Help: "添加"}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text")), Hand: func(m *ice.Message, arg ...string) { if mdb.HashSelect(m, arg...); len(arg) > 0 { m.PushScript(ssh.SCRIPT, m.Append(mdb.TEXT)) m.PushQRCode(cli.QRCODE, m.Append(mdb.TEXT)) } }}, - }}) + }) } diff --git a/core/chat/pod.go b/core/chat/pod.go index cbe5bf01..52638f2c 100644 --- a/core/chat/pod.go +++ b/core/chat/pod.go @@ -16,13 +16,8 @@ import ( const POD = "pod" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - POD: {Name: POD, Help: "节点", Value: kit.Data()}, - }, Commands: ice.Commands{ - "/pod/": {Name: "/pod/", Help: "节点", Actions: ice.MergeAction(ice.Actions{ - ice.CTX_INIT: {Name: "_init", Help: "初始化", Hand: func(m *ice.Message, arg ...string) { - }}, - }, ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) { + Index.MergeCommands(ice.Commands{ + "/pod/": {Name: "/pod/", Help: "节点", Actions: ctx.CmdAction(), Hand: func(m *ice.Message, arg ...string) { if strings.HasPrefix(m.R.Header.Get("User-Agent"), "curl") || strings.HasPrefix(m.R.Header.Get("User-Agent"), "Wget") { m.Option(ice.MSG_USERNAME, "root") m.Option(ice.MSG_USERROLE, "root") @@ -53,5 +48,5 @@ func init() { // m.Cmdy(web.SPACE, m.Option(ice.MSG_USERPOD), "web.chat."+ice.PS+path.Join(arg[1:]...)) } }}, - }}) + }) } diff --git a/core/chat/river.go b/core/chat/river.go index ece8c46d..20ad077e 100644 --- a/core/chat/river.go +++ b/core/chat/river.go @@ -53,7 +53,7 @@ func _river_list(m *ice.Message) { const RIVER = "river" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ RIVER: {Name: "river hash auto create", Help: "群组", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Config(nfs.TEMPLATE, _river_template) }}, mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { @@ -134,7 +134,7 @@ func init() { m.Cmdy(RIVER, arg) } }}, - }}) + }) } var _river_template = kit.Dict( diff --git a/core/chat/room.go b/core/chat/room.go index d2663fac..4cdcc22f 100644 --- a/core/chat/room.go +++ b/core/chat/room.go @@ -2,7 +2,6 @@ package chat import ( ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/web" kit "shylinux.com/x/toolkits" @@ -63,15 +62,15 @@ func init() { m.Cmdy(mdb.INSERT, m.Prefix(ROOM), "", mdb.HASH, m.OptionSimple(mdb.ZONE)) m.Cmdy(mdb.INSERT, m.Prefix(JOIN), "", mdb.HASH, m.OptionSimple(mdb.ZONE)) }}, - mdb.INSERT: {Name: "insert zone username daemon", Hand: func(m *ice.Message, arg ...string) { - m.Conf(m.Prefix(JOIN), kit.Keys(kit.KeyHash(m.Option(mdb.ZONE)), kit.Keym(mdb.SHORT)), web.SOCKET) - m.Cmdy(mdb.INSERT, m.Prefix(JOIN), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, - aaa.USERNAME, m.Option(ice.MSG_USERNAME), web.SOCKET, m.Option(ice.MSG_DAEMON), - ) - }}, - mdb.DELETE: {Name: "delete zone socket", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.DELETE, m.Prefix(JOIN), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, m.OptionSimple(web.SOCKET)) - }}, + // mdb.INSERT: {Name: "insert zone username daemon", Hand: func(m *ice.Message, arg ...string) { + // m.Conf(m.Prefix(JOIN), kit.Keys(kit.KeyHash(m.Option(mdb.ZONE)), kit.Keym(mdb.SHORT)), web.SOCKET) + // m.Cmdy(mdb.INSERT, m.Prefix(JOIN), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, + // aaa.USERNAME, m.Option(ice.MSG_USERNAME), web.SOCKET, m.Option(ice.MSG_DAEMON), + // ) + // }}, + // mdb.DELETE: {Name: "delete zone socket", Hand: func(m *ice.Message, arg ...string) { + // m.Cmdy(mdb.DELETE, m.Prefix(JOIN), kit.KeyHash(m.Option(mdb.ZONE)), mdb.HASH, m.OptionSimple(web.SOCKET)) + // }}, }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { m.Fields(len(arg), "time,space", "time,zone") if len(arg) == 0 { diff --git a/core/chat/scan.go b/core/chat/scan.go index f67e1971..82d67fc6 100644 --- a/core/chat/scan.go +++ b/core/chat/scan.go @@ -11,18 +11,14 @@ import ( const SCAN = "scan" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SCAN: {Name: SCAN, Help: "扫码", Value: kit.Data( - mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SCAN: {Name: "scan hash auto scanQRCode scanQRCode0", Help: "扫码", Meta: kit.Dict( ice.Display("scan.js"), ), Actions: ice.MergeAction(ice.Actions{ "scanQRCode0": {Name: "scan create", Help: "本机扫码"}, "scanQRCode": {Name: "scan create", Help: "扫码"}, mdb.CREATE: {Name: "create type=text name=hi text:textarea=hi", Help: "添加"}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text")), Hand: func(m *ice.Message, arg ...string) { if mdb.HashSelect(m, arg...); len(arg) > 0 { if m.Append(mdb.TYPE) == "image" { m.PushImages("image", m.Append(mdb.TEXT)) @@ -31,5 +27,5 @@ func init() { m.PushQRCode(cli.QRCODE, m.Append(mdb.TEXT)) } }}, - }}) + }) } diff --git a/core/chat/search.go b/core/chat/search.go index a4361433..b3af3c72 100644 --- a/core/chat/search.go +++ b/core/chat/search.go @@ -10,9 +10,9 @@ import ( const SEARCH = "search" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ web.P(SEARCH): {Name: "/search", Help: "搜索引擎", Actions: ctx.CmdAction(mdb.SHORT, mdb.NAME), Hand: func(m *ice.Message, arg ...string) { m.Cmdy(m.Space(m.Option(ice.POD)), mdb.SEARCH, arg).StatusTimeCount() }}, - }}) + }) } diff --git a/core/chat/sso.go b/core/chat/sso.go index 9c5b8ad7..f16e444f 100644 --- a/core/chat/sso.go +++ b/core/chat/sso.go @@ -12,16 +12,15 @@ import ( const SSO = "sso" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/sso": {Name: "/sso", Help: "登录", Hand: func(m *ice.Message, arg ...string) { if m.Option(ice.MSG_USERNAME) == "" { m.RenderIndex(web.SERVE, ice.VOLCANOS) return } sessid := m.Cmdx(web.SPACE, m.Option(web.SPACE), aaa.SESS, mdb.CREATE, - mdb.TIME, m.Time("720h"), - aaa.USERROLE, m.Option(ice.MSG_USERROLE), aaa.USERNAME, m.Option(ice.MSG_USERNAME), + aaa.USERROLE, m.Option(ice.MSG_USERROLE), aaa.USERNICK, m.Option(ice.MSG_USERNICK), ) m.RenderRedirect(kit.MergeURL(m.Option(cli.BACK), ice.MSG_SESSID, sessid)) @@ -31,5 +30,5 @@ func init() { // web.RenderCookie(m, sessid, web.CookieName(m.Option("back"))) // m.RenderRedirect(kit.MergeURL(m.Option("back"))) }}, - }}) + }) } diff --git a/core/chat/storm.go b/core/chat/storm.go index 147dff69..25212845 100644 --- a/core/chat/storm.go +++ b/core/chat/storm.go @@ -14,7 +14,7 @@ func _storm_key(m *ice.Message, key ...ice.Any) string { const STORM = "storm" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ STORM: {Name: "storm hash id auto insert create", Help: "应用", Actions: ice.Actions{ mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { if ctx.Inputs(m, arg[0]) { @@ -88,5 +88,5 @@ func init() { m.PushAction(mdb.EXPORT, mdb.IMPORT) } }}, - }}) + }) } diff --git a/core/chat/topic.go b/core/chat/topic.go index 57ce0e4b..9452d180 100644 --- a/core/chat/topic.go +++ b/core/chat/topic.go @@ -22,7 +22,7 @@ func init() { mdb.TYPE: "text", mdb.NAME: "height", mdb.VALUE: "31", }, } - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TOPIC: {Name: "topic zone id auto create insert", Help: "主题", Actions: ice.MergeAction(ice.Actions{ mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { switch arg[0] { @@ -145,5 +145,5 @@ body.{{.Option "topic"}} fieldset.panel.Header>div.output div:hover { background m.W.Header()[web.ContentType] = kit.Simple(web.ContentCSS) m.RenderResult() }}, - }}) + }) } diff --git a/core/chat/trans.go b/core/chat/trans.go index e4255eef..696732ae 100644 --- a/core/chat/trans.go +++ b/core/chat/trans.go @@ -18,7 +18,7 @@ const ( ) func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TRANS: {Name: "trans from to auto", Help: "传输", Actions: ice.MergeAction(ice.Actions{ SEND: {Name: "send", Help: "发送", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(web.SPACE, m.Option(TO), web.SPIDE, ice.DEV, web.SPIDE_SAVE, kit.Select(nfs.PWD, m.Option("to_path")), @@ -50,5 +50,5 @@ func init() { } m.DisplayLocal("") }}, - }}) + }) } diff --git a/core/code/autogen.go b/core/code/autogen.go index 053c747e..7377a0b0 100644 --- a/core/code/autogen.go +++ b/core/code/autogen.go @@ -173,7 +173,7 @@ func init() { const AUTOGEN = "autogen" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ AUTOGEN: {Name: "autogen path auto create binpack script relay", Help: "生成", Actions: ice.Actions{ mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { switch arg[0] { @@ -187,6 +187,7 @@ func init() { _defs(m, mdb.KEY, kit.Keys("web.code", m.Option(mdb.ZONE), m.Option(mdb.NAME))) m.Option(mdb.TEXT, kit.Format("`name:\"%s\" help:\"%s\"`", _defs_list(m), m.Option(mdb.HELP))) + m.OptionFiles(nfs.DiskFile) if p := path.Join(ice.SRC, m.Option(mdb.ZONE), kit.Keys(m.Option(mdb.NAME), GO)); !kit.FileExists(p) { _autogen_module(m, p) _autogen_import(m, path.Join(ice.SRC, m.Option(cli.MAIN)), m.Option(mdb.ZONE), _autogen_mod(m, ice.GO_MOD)) @@ -228,5 +229,5 @@ func init() { }, Hand: func(m *ice.Message, arg ...string) { m.Cmdy(nfs.CAT, kit.Select("version.go", arg, 0), kit.Dict(nfs.DIR_ROOT, ice.SRC)) }}, - }}) + }) } diff --git a/core/code/bench.go b/core/code/bench.go index 5aaa0366..ca6da038 100644 --- a/core/code/bench.go +++ b/core/code/bench.go @@ -37,12 +37,12 @@ func _bench_http(m *ice.Message, target string, arg ...string) { } } - var body int64 + var ndata int64 if s, e := bench.HTTP(nconn, nreqs, list, func(req *http.Request, res *http.Response) { n, _ := io.Copy(ioutil.Discard, res.Body) - atomic.AddInt64(&body, n) + atomic.AddInt64(&ndata, n) }); m.Assert(e) { - m.Echo("body: %s\n", kit.FmtSize(body)) + m.Echo("ndata: %s\n", kit.FmtSize(ndata)) m.Echo(s.Show()) m.ProcessInner() } @@ -61,7 +61,7 @@ const ( const BENCH = "bench" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ BENCH: {Name: "bench zone id auto insert", Help: "性能压测", Actions: ice.MergeAction(ice.Actions{ mdb.INSERT: {Name: "insert zone=some type=http,redis name=demo text='http://localhost:9020' nconn=3 nreqs=10", Help: "添加"}, ice.RUN: {Name: "run", Help: "执行", Hand: func(m *ice.Message, arg ...string) { @@ -75,5 +75,5 @@ func init() { }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,nconn,nreqs")), Hand: func(m *ice.Message, arg ...string) { mdb.ZoneSelect(m, arg...).PushAction(kit.Select(mdb.REMOVE, ice.RUN, len(arg) > 0)) }}, - }}) + }) } diff --git a/core/code/binpack.go b/core/code/binpack.go index 9965194b..f500ce6c 100644 --- a/core/code/binpack.go +++ b/core/code/binpack.go @@ -3,9 +3,7 @@ package code import ( "encoding/base64" "fmt" - "io" "io/ioutil" - "net/http" "os" "path" "strings" @@ -13,7 +11,6 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" - "shylinux.com/x/icebergs/base/web" kit "shylinux.com/x/toolkits" ) @@ -51,11 +48,13 @@ func _binpack_can(m *ice.Message, f *os.File, dir string) { m.Option(nfs.DIR_TYPE, nfs.CAT) for _, k := range []string{ice.FAVICON, ice.PROTO_JS, ice.FRAME_JS} { - fmt.Fprintln(f, _binpack_file(m, path.Join(dir, k), ice.PS+k)) + // fmt.Fprintln(f, _binpack_file(m, path.Join(dir, k), ice.PS+k)) + fmt.Fprintln(f, _binpack_file(m, path.Join(dir, k), path.Join(ice.USR_VOLCANOS, k))) } for _, k := range []string{LIB, PAGE, PANEL, PLUGIN, "publish/client/nodejs/"} { m.Cmd(nfs.DIR, k).Sort(nfs.PATH).Tables(func(value ice.Maps) { - fmt.Fprintln(f, _binpack_file(m, path.Join(dir, value[nfs.PATH]), ice.PS+value[nfs.PATH])) + // fmt.Fprintln(f, _binpack_file(m, path.Join(dir, value[nfs.PATH]), ice.PS+value[nfs.PATH])) + fmt.Fprintln(f, _binpack_file(m, path.Join(dir, value[nfs.PATH]), path.Join(ice.USR_VOLCANOS, value[nfs.PATH]))) }) } fmt.Fprintln(f) @@ -67,50 +66,13 @@ func _binpack_ctx(m *ice.Message, f *os.File) { const BINPACK = "binpack" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ BINPACK: {Name: "binpack path auto create remove export", Help: "打包", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { if kit.FileExists(path.Join(ice.USR_VOLCANOS, ice.PROTO_JS)) { m.Cmd(BINPACK, mdb.REMOVE) return } - - ice.Info.Dump = func(w io.Writer, name string, cb func(string)) bool { - if strings.HasPrefix(name, ice.SRC) && kit.FileExists(name) { - return false - } - for _, key := range []string{name, strings.TrimPrefix(name, ice.USR_VOLCANOS)} { - if b, ok := ice.Info.Pack[key]; ok { - if cb != nil { - cb(name) - } - w.Write(b) - return true // 读取数据 - } - } - return false - } - web.AddRewrite(func(w http.ResponseWriter, r *http.Request) bool { - if ice.Info.Dump(w, r.URL.Path, func(name string) { web.RenderType(w, name, "") }) { - return true // 输出数据 - } - return false - }) - nfs.AddRewrite(func(msg *ice.Message, name string) []byte { - if kit.FileExists(name) { - return nil - } - if strings.HasPrefix(name, ice.SRC) && kit.FileExists(name) { - return nil - } - for _, key := range []string{name, path.Join(m.Option(nfs.DIR_ROOT), name), path.Join(ice.PS, name), strings.TrimPrefix(name, ice.USR_VOLCANOS)} { - if b, ok := ice.Info.Pack[key]; ok && len(b) > 0 { - m.Logs(BINPACK, len(b), key) - return b // 读取数据 - } - } - return nil - }) }}, mdb.CREATE: {Name: "create", Help: "创建", Hand: func(m *ice.Message, arg ...string) { if f, p, e := kit.Create(ice.SRC_BINPACK_GO); m.Assert(e) { @@ -122,6 +84,7 @@ func init() { import ( "encoding/base64" ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/nfs" ) func init() { @@ -130,7 +93,9 @@ func init() { defer fmt.Fprintln(f, ` for k, v := range pack { - ice.Info.Pack[k], _ = base64.StdEncoding.DecodeString(v) + if b, e := base64.StdEncoding.DecodeString(v); e == nil { + nfs.PackFile.WriteFile(k, b) + } } `) @@ -188,5 +153,5 @@ func init() { } m.Echo(string(ice.Info.Pack[arg[0]])) }}, - }}) + }) } diff --git a/core/code/case.go b/core/code/case.go index efd5bdc4..1717ae2e 100644 --- a/core/code/case.go +++ b/core/code/case.go @@ -15,7 +15,7 @@ import ( const CASE = "case" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ CASE: {Name: "case dev zone id auto", Help: "用例", Actions: ice.MergeAction(ice.Actions{ mdb.CREATE: {Name: "create name address", Help: "创建", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(web.SPIDE, mdb.CREATE, arg) @@ -122,5 +122,5 @@ func init() { m.Option(cli.CMD_DIR, kit.Select(path.Dir(arg[0]), arg[0], strings.HasSuffix(arg[0], "/"))) m.Cmdy(cli.SYSTEM, "go", "test", nfs.PWD, "-v", "-run="+arg[1]) }}, - }}) + }) } diff --git a/core/code/favor.go b/core/code/favor.go index a2c687a1..b7962225 100644 --- a/core/code/favor.go +++ b/core/code/favor.go @@ -3,20 +3,32 @@ package code import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" ) const FAVOR = "favor" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ - FAVOR: {Name: "favor zone id auto insert", Help: "收藏夹", Actions: ice.MergeAction(ice.Actions{ + Index.MergeCommands(ice.Commands{ + FAVOR: {Name: "favor zone id auto insert test page", Help: "收藏夹", Actions: ice.MergeAction(ice.Actions{ mdb.INSERT: {Name: "insert zone=数据结构 type=go name=hi text=hello path file line", Help: "添加"}, INNER: {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) { m.ProcessCommand(INNER, m.OptionSplit("path,file,line"), arg...) }}, + "test": {Name: "test zone=hi count=10", Help: "测试", Hand: func(m *ice.Message, arg ...string) { + m.Cmd(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, m.OptionSimple(mdb.ZONE)) + for i := 0; i < kit.Int(m.Option(mdb.COUNT)); i++ { + m.Cmd(mdb.INSERT, m.PrefixKey(), "", mdb.ZONE, m.Option(mdb.ZONE), mdb.NAME, i) + } + m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH, kit.Hashs(m.Option(mdb.ZONE)), kit.Keym(mdb.LIMIT)), 20) + m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH, kit.Hashs(m.Option(mdb.ZONE)), kit.Keym(mdb.LEAST)), 10) + m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH, kit.Hashs(m.Option(mdb.ZONE)), kit.Keym(mdb.FSIZE)), 500) + m.Cmdy(nfs.DIR, "var/data/", kit.Dict(nfs.DIR_DEEP, true)) + m.Echo(kit.Formats(m.Confv(m.PrefixKey()))) + }}, }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,path,file,line")), Hand: func(m *ice.Message, arg ...string) { - mdb.ZoneSelect(m, arg...).PushAction(kit.Select(mdb.REMOVE, INNER, len(arg) > 0)) + mdb.ZoneSelectPage(m, arg...).PushAction(kit.Select(mdb.REMOVE, INNER, len(arg) > 0)) }}, - }}) + }) } diff --git a/core/code/install.go b/core/code/install.go index 15b67875..d6ae82d1 100644 --- a/core/code/install.go +++ b/core/code/install.go @@ -7,11 +7,13 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/cli" + "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/web" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/file" ) func _install_path(m *ice.Message, link string) string { @@ -22,7 +24,7 @@ func _install_path(m *ice.Message, link string) string { if p := path.Join(ice.USR_INSTALL, path.Base(link)); kit.FileExists(p) { return path.Join(ice.USR_INSTALL, strings.Split(m.Cmdx(cli.SYSTEM, "sh", "-c", kit.Format("tar tf %s| head -n1", p), ice.Option{cli.CMD_OUTPUT, ""}), ice.PS)[0]) } - m.Error(true, ice.ErrNotFound) + m.ErrorNotImplement(link) return "" } func _install_download(m *ice.Message) { @@ -99,7 +101,7 @@ func _install_spawn(m *ice.Message, arg ...string) { target := path.Join(ice.USR_LOCAL_DAEMON, m.Option(tcp.PORT)) source := _install_path(m, "") - nfs.MkdirAll(m, target) + file.MkdirAll(target, ice.MOD_DIR) defer m.Echo(target) if m.Option(INSTALL) == "" && kit.FileExists(kit.Path(source, "_install")) { @@ -119,7 +121,7 @@ func _install_start(m *ice.Message, arg ...string) { case func(string): cb(p) default: - m.Error(true, ice.ErrNotImplement) + m.ErrorNotImplement(cb) } if m.Cmdy(cli.DAEMON, arg[1:], args); cli.IsSuccess(m) { @@ -132,7 +134,7 @@ func _install_stop(m *ice.Message, arg ...string) { m.Cmd(cli.DAEMON, cli.STOP, kit.Dict(mdb.HASH, value[mdb.HASH])) } }) - m.Cmd(cli.SYSTEM, cli.KILL, m.Option(cli.PID)) + m.Cmd(gdb.SIGNAL, gdb.KILL, m.Option(cli.PID)) } func _install_service(m *ice.Message, arg ...string) { arg = kit.Split(path.Base(arg[0]), "-.")[:1] @@ -152,11 +154,7 @@ const ( const INSTALL = "install" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - INSTALL: {Name: INSTALL, Help: "安装", Value: kit.Data( - mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,path,link", nfs.PATH, ice.USR_INSTALL, - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ INSTALL: {Name: "install name port path auto download", Help: "安装", Meta: kit.Dict(), Actions: ice.MergeAction(ice.Actions{ web.DOWNLOAD: {Name: "download link path", Help: "下载", Hand: func(m *ice.Message, arg ...string) { _install_download(m) @@ -188,7 +186,7 @@ func init() { cli.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { _install_stop(m, arg...) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,path,link", nfs.PATH, ice.USR_INSTALL)), Hand: func(m *ice.Message, arg ...string) { switch len(arg) { case 0: // 源码列表 mdb.HashSelect(m, arg...) @@ -201,7 +199,7 @@ func init() { m.Cmdy(nfs.CAT, kit.Select(nfs.PWD, arg, 2)) } }}, - }}) + }) } func InstallAction(args ...ice.Any) ice.Actions { diff --git a/core/code/oauth.go b/core/code/oauth.go index b3d1fc5e..77d06c0b 100644 --- a/core/code/oauth.go +++ b/core/code/oauth.go @@ -22,9 +22,7 @@ func init() { LOGIN_OAUTH = "https://github.com/login/oauth/" API_GITHUB = "https://api.github.com/" ) - Index.Merge(&ice.Context{Configs: ice.Configs{ - OAUTH: {Name: OAUTH, Help: "授权", Value: kit.Data(mdb.FIELD, "time,hash,code,access_token,scope,token_type")}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ OAUTH: {Name: "oauth hash auto", Help: "授权", Actions: ice.MergeAction(ice.Actions{ ctx.CONFIG: {Name: "config client_id client_secret redirect_uri", Help: "配置", Hand: func(m *ice.Message, arg ...string) { m.ConfigOption(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI) @@ -60,7 +58,7 @@ func init() { m.Option(web.SPIDE_HEADER, web.Accept, web.ContentJSON, web.Authorization, "token "+m.Append(ACCESS_TOKEN)) m.Cmd(web.SPIDE_DELETE, API_GITHUB+"user/keys/"+m.Option(mdb.ID)) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.FIELD, "time,hash,code,access_token,scope,token_type")), Hand: func(m *ice.Message, arg ...string) { if mdb.HashSelect(m, arg...).PushAction("user", "public", ACCESS_TOKEN, mdb.REMOVE); len(arg) == 0 { m.Action(mdb.CREATE) m.Echo(kit.MergeURL2(LOGIN_OAUTH, "authorize", m.ConfigSimple(REDIRECT_URI, CLIENT_ID), SCOPE, "read:user read:public_key write:public_key repo")) @@ -82,5 +80,5 @@ func init() { m.RenderCmd(m.PrefixKey(), m.Cmdx(m.PrefixKey(), mdb.CREATE, m.OptionSimple(CODE))) } }}, - }}) + }) } diff --git a/core/code/pprof.go b/core/code/pprof.go index b24465ab..dfd95caf 100644 --- a/core/code/pprof.go +++ b/core/code/pprof.go @@ -24,11 +24,7 @@ const ( const PPROF = "pprof" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - PPROF: {Name: PPROF, Help: "性能分析", Value: kit.Data( - mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,text,file", PPROF, kit.List(GO, "tool", PPROF), - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ PPROF: {Name: "pprof zone id auto", Help: "性能分析", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { web.AddRewrite(func(w http.ResponseWriter, r *http.Request) bool { @@ -65,9 +61,10 @@ func init() { m.Cmd(cli.DAEMON, m.Configv(PPROF), "-http="+p, m.Option(BINNARY), m.Option(nfs.FILE)) m.Echo("http://%s/ui/top", p).ProcessInner() }}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,text,file", PPROF, kit.List(GO, "tool", PPROF))), Hand: func(m *ice.Message, arg ...string) { m.Fields(len(arg), "time,zone,count,binnary,service,seconds", m.Config(mdb.FIELD)) if mdb.ZoneSelect(m, arg...); len(arg) == 0 { + m.EchoAnchor(m.MergeLink("/code/pprof/")) m.PushAction(ice.RUN, mdb.REMOVE) m.Action(mdb.CREATE) return @@ -83,5 +80,5 @@ func init() { m.R.URL.Path = "/debug" + m.R.URL.Path http.DefaultServeMux.ServeHTTP(m.W, m.R) }}, - }}) + }) } diff --git a/core/code/template.go b/core/code/template.go index e5b389b3..f9d3b44d 100644 --- a/core/code/template.go +++ b/core/code/template.go @@ -13,7 +13,7 @@ import ( const TEMPLATE = "template" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TEMPLATE: {Name: "template name auto", Help: "模板", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { for _, _template := range _template_list { @@ -40,7 +40,7 @@ func init() { m.Action(mdb.CREATE) } m.PushAction(nfs.DEFS, mdb.REMOVE) - }}}, + }}, }) } diff --git a/core/code/vimer.go b/core/code/vimer.go index 758fb2bb..5f0c12b8 100644 --- a/core/code/vimer.go +++ b/core/code/vimer.go @@ -158,82 +158,78 @@ func _vimer_go_complete(m *ice.Message, name string, arg ...string) *ice.Message const VIMER = "vimer" func init() { - Index.Merge(&ice.Context{ - Configs: ice.Configs{ - VIMER: {Name: VIMER, Help: "编辑器", Value: kit.Data()}, - }, - Commands: ice.Commands{ - VIMER: {Name: "vimer path=src/ file=main.go line=1 list", Help: "编辑器", Meta: kit.Dict(ice.DisplayLocal("", INNER)), Actions: ice.Actions{ - nfs.SAVE: {Name: "save type file path", Help: "保存", Hand: func(m *ice.Message, arg ...string) { - m.Option(nfs.CONTENT, kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(nfs.CONTENT))) - m.Cmdy(nfs.SAVE, path.Join(m.Option(nfs.PATH), m.Option(nfs.FILE))) - }}, - nfs.TRASH: {Name: "trash path", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(nfs.TRASH, arg[0]) - }}, - AUTOGEN: {Name: "create name=hi help=示例 type=Zone,Hash,Lists,Data,Code main=main.go zone key", 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) { - if msg := m.Cmd(COMPILE, ice.SRC_MAIN_GO, ice.BIN_ICE_BIN); cli.IsSuccess(msg) { - m.Cmd(UPGRADE, cli.RESTART) - } else { - _inner_make(m, msg) - } - }}, - nfs.SCRIPT: {Name: "script file=hi/hi.js", Help: "脚本", Hand: func(m *ice.Message, arg ...string) { - m.Option(mdb.TEXT, strings.TrimSpace(kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(mdb.TEXT)))) - m.Cmdy(TEMPLATE, nfs.DEFS) - }}, - nfs.WEBSITE: {Name: "website file=hi.zml", Help: "网页", Hand: func(m *ice.Message, arg ...string) { - m.Option(mdb.TEXT, strings.TrimSpace(kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(mdb.TEXT)))) - m.Option(nfs.FILE, path.Join(nfs.WEBSITE, m.Option(nfs.FILE))) - m.Cmdy(TEMPLATE, nfs.DEFS) - }}, - web.DREAM: {Name: "dream name=hi repos", Help: "空间", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(web.DREAM, cli.START, arg) - }}, - PUBLISH: {Name: "publish", Help: "发布", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(PUBLISH, ice.CONTEXTS) - }}, - - mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { - if arg[0] == mdb.FOREACH && arg[1] == "" { - m.PushSearch(mdb.TYPE, "go", mdb.NAME, "src/main.go", mdb.TEXT, m.MergeCmd("")) - } - }}, - mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { - _vimer_inputs(m, arg...) - }}, - "complete": {Name: "complete", Help: "补全", Hand: func(m *ice.Message, arg ...string) { - _vimer_complete(m, arg...) - }}, - "listTags": {Name: "listTags", Help: "索引", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy("web.code.vim.tags", "listTags", arg) - }}, - - "unpack": {Name: "unpack", Help: "导出文件", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(BINPACK, mdb.EXPORT) - }}, - DEVPACK: {Name: "devpack", Help: "开发模式", Hand: func(m *ice.Message, arg ...string) { - m.Cmd(nfs.LINK, ice.GO_SUM, path.Join(ice.SRC_DEBUG, ice.GO_SUM)) - m.Cmd(nfs.LINK, ice.GO_MOD, path.Join(ice.SRC_DEBUG, ice.GO_MOD)) - m.Cmdy(nfs.CAT, ice.GO_MOD) - m.Cmdy(WEBPACK, mdb.REMOVE) - m.ProcessInner() - m.ToastSuccess() - }}, - BINPACK: {Name: "binpack", Help: "打包模式", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(WEBPACK, mdb.CREATE) - m.Cmdy(AUTOGEN, BINPACK) - m.ProcessInner() - m.ToastSuccess() - }}, - }, Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(INNER, arg) - m.Option("plug", m.Config("show.plug")) - m.Option("exts", m.Config("show.exts")) - m.Option("tabs", m.Config("show.tabs")) + Index.MergeCommands(ice.Commands{ + VIMER: {Name: "vimer path=src/ file=main.go line=1 list", Help: "编辑器", Meta: kit.Dict(ice.DisplayLocal("", INNER)), Actions: ice.Actions{ + nfs.SAVE: {Name: "save type file path", Help: "保存", Hand: func(m *ice.Message, arg ...string) { + m.Option(nfs.CONTENT, kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(nfs.CONTENT))) + m.Cmdy(nfs.SAVE, path.Join(m.Option(nfs.PATH), m.Option(nfs.FILE))) }}, - }}) + nfs.TRASH: {Name: "trash path", Help: "删除", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(nfs.TRASH, arg[0]) + }}, + AUTOGEN: {Name: "create name=hi help=示例 type=Zone,Hash,Data,Code main=main.go zone key", 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) { + if msg := m.Cmd(COMPILE, ice.SRC_MAIN_GO, ice.BIN_ICE_BIN); cli.IsSuccess(msg) { + m.Cmd(UPGRADE, cli.RESTART) + } else { + _inner_make(m, msg) + } + }}, + nfs.SCRIPT: {Name: "script file=hi/hi.js", Help: "脚本", Hand: func(m *ice.Message, arg ...string) { + m.Option(mdb.TEXT, strings.TrimSpace(kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(mdb.TEXT)))) + m.Cmdy(TEMPLATE, nfs.DEFS) + }}, + nfs.WEBSITE: {Name: "website file=hi.zml", Help: "网页", Hand: func(m *ice.Message, arg ...string) { + m.Option(mdb.TEXT, strings.TrimSpace(kit.Select(_vimer_defs(m, kit.Ext(m.Option(nfs.FILE))), m.Option(mdb.TEXT)))) + m.Option(nfs.FILE, path.Join(nfs.WEBSITE, m.Option(nfs.FILE))) + m.Cmdy(TEMPLATE, nfs.DEFS) + }}, + web.DREAM: {Name: "dream name=hi repos", Help: "空间", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(web.DREAM, cli.START, arg) + }}, + PUBLISH: {Name: "publish", Help: "发布", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(PUBLISH, ice.CONTEXTS) + }}, + + mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { + if arg[0] == mdb.FOREACH && arg[1] == "" { + m.PushSearch(mdb.TYPE, "go", mdb.NAME, "src/main.go", mdb.TEXT, m.MergeCmd("")) + } + }}, + mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { + _vimer_inputs(m, arg...) + }}, + "complete": {Name: "complete", Help: "补全", Hand: func(m *ice.Message, arg ...string) { + _vimer_complete(m, arg...) + }}, + "listTags": {Name: "listTags", Help: "索引", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy("web.code.vim.tags", "listTags", arg) + }}, + + "unpack": {Name: "unpack", Help: "导出文件", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(BINPACK, mdb.EXPORT) + }}, + DEVPACK: {Name: "devpack", Help: "开发模式", Hand: func(m *ice.Message, arg ...string) { + m.Cmd(nfs.LINK, ice.GO_SUM, path.Join(ice.SRC_DEBUG, ice.GO_SUM)) + m.Cmd(nfs.LINK, ice.GO_MOD, path.Join(ice.SRC_DEBUG, ice.GO_MOD)) + m.Cmdy(nfs.CAT, ice.GO_MOD) + m.Cmdy(WEBPACK, mdb.REMOVE) + m.ProcessInner() + m.ToastSuccess() + }}, + BINPACK: {Name: "binpack", Help: "打包模式", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(WEBPACK, mdb.CREATE) + m.Cmdy(AUTOGEN, BINPACK) + m.ProcessInner() + m.ToastSuccess() + }}, + }, Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(INNER, arg) + m.Option("plug", m.Config("show.plug")) + m.Option("exts", m.Config("show.exts")) + m.Option("tabs", m.Config("show.tabs")) + }}, + }) } diff --git a/core/code/webpack.go b/core/code/webpack.go index 2ee8082b..6f68d3ce 100644 --- a/core/code/webpack.go +++ b/core/code/webpack.go @@ -46,7 +46,6 @@ func _webpack_cache(m *ice.Message, dir string, write bool) { m.Option(nfs.DIR_ROOT, "") m.Option(nfs.DIR_DEEP, true) - m.Option(nfs.DIR_PACK, true) m.Option(nfs.DIR_TYPE, nfs.CAT) // m.Cmd(nfs.DIR, ice.SRC).Tables(func(value ice.Maps) { diff --git a/core/code/xterm.go b/core/code/xterm.go index 7ec46d7c..7884ac89 100644 --- a/core/code/xterm.go +++ b/core/code/xterm.go @@ -22,8 +22,7 @@ func _xterm_socket(m *ice.Message, h, t string) { m.Option(mdb.TEXT, t) } func _xterm_get(m *ice.Message, h string, must bool) (f *os.File) { - f, _ = mdb.HashCache(m, h, func() ice.Any { - m.Debug("what %v", must) + f, _ = mdb.HashTarget(m, h, func() ice.Any { if !must { return nil } @@ -49,7 +48,6 @@ func _xterm_get(m *ice.Message, h string, must bool) (f *os.File) { }) return tty }).(*os.File) - m.Debug("what %v", f) return } diff --git a/core/mall/salary.go b/core/mall/salary.go index 178edde2..74026ee2 100644 --- a/core/mall/salary.go +++ b/core/mall/salary.go @@ -14,14 +14,10 @@ const ( const SALARY = "salary" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SALARY: {Name: SALARY, Help: "工资", Value: kit.Data( - mdb.SHORT, MONTH, mdb.FIELD, "month,company,amount,income,tax", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SALARY: {Name: "salary month auto create", Help: "工资", Actions: ice.MergeAction(ice.Actions{ mdb.CREATE: {Name: "create month company amount income tax 公积金 养老保险 医疗保险 生育保险 工伤保险 失业保险 企业公积金 企业养老保险 企业医疗保险 企业生育保险 企业工伤保险 企业失业保险", Help: "添加"}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, MONTH, mdb.FIELD, "month,company,amount,income,tax")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...) amount, income, tax := 0, 0, 0 m.Tables(func(value ice.Maps) { @@ -31,5 +27,5 @@ func init() { }) m.StatusTime(AMOUNT, amount, INCOME, income, TAX, tax) }}, - }}) + }) } diff --git a/core/team/count.go b/core/team/count.go index ed933a84..ad232da3 100644 --- a/core/team/count.go +++ b/core/team/count.go @@ -12,7 +12,7 @@ import ( const COUNT = "count" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ COUNT: {Name: "count begin_time@date end_time@date auto insert", Help: "倒计时", Meta: kit.Dict( ice.Display(""), ), Actions: ice.MergeAction(ice.Actions{ @@ -44,5 +44,5 @@ func init() { ) }) }}, - }}) + }) } diff --git a/core/team/plan.go b/core/team/plan.go index 1be37b57..ddd4cc24 100644 --- a/core/team/plan.go +++ b/core/team/plan.go @@ -65,7 +65,7 @@ const ( const PLAN = "plan" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ PLAN: {Name: "plan scale=week,day,week,month,year,long begin_time@date list", Help: "计划", Meta: kit.Dict( ice.Display("/plugin/local/team/plan.js"), ), Actions: ice.MergeAction(ice.Actions{ @@ -95,5 +95,5 @@ func init() { _plan_list(m, begin_time, end_time) m.PushPodCmd(m.CommandKey(), arg...) }}, - }}) + }) } diff --git a/core/team/task.go b/core/team/task.go index 6bf7d4d2..c97421a2 100644 --- a/core/team/task.go +++ b/core/team/task.go @@ -56,11 +56,7 @@ const ( const TASK = "task" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - TASK: {Name: TASK, Help: "任务", Value: kit.Data( - mdb.SHORT, mdb.ZONE, mdb.FIELD, "begin_time,id,status,level,score,type,name,text", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TASK: {Name: "task zone id auto insert export import", Help: "任务", Actions: ice.MergeAction(ice.Actions{ 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) { m.Cmdy(mdb.INSERT, m.Prefix(TASK), "", mdb.HASH, m.OptionSimple(mdb.ZONE)) @@ -93,7 +89,7 @@ func init() { END: {Name: "end", Help: "完成", Hand: func(m *ice.Message, arg ...string) { _task_modify(m, STATUS, FINISH) }}, - }, mdb.ZoneAction(), ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "begin_time,id,status,level,score,type,name,text"), ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) { if mdb.ZoneSelect(m, arg...); len(arg) > 0 { status := map[string]int{} m.Tables(func(value ice.Maps) { @@ -103,5 +99,5 @@ func init() { m.Status(status) } }}, - }}) + }) } diff --git a/core/wiki/word.go b/core/wiki/word.go index 2c33e1fe..ae620086 100644 --- a/core/wiki/word.go +++ b/core/wiki/word.go @@ -10,7 +10,6 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/ssh" - "shylinux.com/x/icebergs/base/web" kit "shylinux.com/x/toolkits" ) @@ -76,7 +75,7 @@ func init() { m.Cmdy(nfs.DIR, "src/", kit.Dict(nfs.DIR_DEEP, ice.TRUE, nfs.DIR_REG, ".*\\.shy"), nfs.DIR_CLI_FIELDS) m.Cmdy(nfs.DIR, "src/help/", kit.Dict(nfs.DIR_DEEP, ice.TRUE, nfs.DIR_REG, ".*\\.shy"), nfs.DIR_CLI_FIELDS) }}, - web.STORY: {Name: "story", Help: "运行", Hand: func(m *ice.Message, arg ...string) { + "story": {Name: "story", Help: "运行", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(arg[0], ctx.ACTION, ice.RUN, arg[2:]) }}, ice.PLAY: {Name: "play", Help: "演示"}, diff --git a/data.go b/data.go index b18bd5b6..5168faa9 100644 --- a/data.go +++ b/data.go @@ -1,6 +1,7 @@ package ice import ( + "path" "strings" "sync" @@ -94,7 +95,7 @@ func (m *Message) Richs(prefix string, chain Any, raw Any, cb Any) (res Map) { case func(*sync.Mutex, string, Map): wg, mu := &sync.WaitGroup{}, &sync.Mutex{} defer wg.Wait() - res = miss.Richs(kit.Keys(prefix, chain), cache, raw, func(key string, value Map) { + res = miss.Richs(path.Join(prefix, kit.Keys(chain)), cache, raw, func(key string, value Map) { wg.Add(1) m.Go(func() { defer wg.Done() @@ -102,7 +103,7 @@ func (m *Message) Richs(prefix string, chain Any, raw Any, cb Any) (res Map) { }) }) default: - res = miss.Richs(kit.Keys(prefix, chain), cache, raw, cb) + res = miss.Richs(path.Join(prefix, kit.Keys(chain)), cache, raw, cb) } return res @@ -113,7 +114,7 @@ func (m *Message) Rich(prefix string, chain Any, data Any) string { cache = kit.Data() m.Confv(prefix, chain, cache) } - return miss.Rich(kit.Keys(prefix, chain), cache, data) + return miss.Rich(path.Join(prefix, kit.Keys(chain)), cache, data) } func (m *Message) Grow(prefix string, chain Any, data Any) int { cache := m.Confm(prefix, chain) @@ -121,7 +122,7 @@ func (m *Message) Grow(prefix string, chain Any, data Any) int { cache = kit.Data() m.Confv(prefix, chain, cache) } - return miss.Grow(kit.Keys(prefix, chain), cache, data) + return miss.Grow(path.Join(prefix, kit.Keys(chain)), cache, data) } func (m *Message) Grows(prefix string, chain Any, match string, value string, cb Any) Map { cache := m.Confm(prefix, chain) @@ -139,7 +140,7 @@ func (m *Message) Grows(prefix string, chain Any, match string, value string, cb } } - return miss.Grows(kit.Keys(prefix, chain), cache, + return miss.Grows(path.Join(prefix, kit.Keys(chain)), cache, 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 5357c146..22b07277 100644 --- a/exec.go +++ b/exec.go @@ -3,6 +3,7 @@ package ice import ( "errors" "io" + "path" "strings" "time" @@ -61,29 +62,6 @@ func (m *Message) Sleep300ms(arg ...Any) *Message { return m.Sleep("300ms", arg. func (m *Message) Sleep30ms(arg ...Any) *Message { return m.Sleep("30ms", arg...) } func (m *Message) Sleep3s(arg ...Any) *Message { return m.Sleep("3s", arg...) } func (m *Message) Sleep30s(arg ...Any) *Message { return m.Sleep("30s", arg...) } -func (m *Message) Hold(n int) *Message { - for ctx := m.target; ctx != nil; ctx = ctx.context { - if ctx.wg != nil { - ctx.wg.Add(n) - break - } - } - return m -} -func (m *Message) Done(ok bool) bool { - if !ok { - return false - } - defer func() { recover() }() - - for ctx := m.target; ctx != nil; ctx = ctx.context { - if ctx.wg != nil { - ctx.wg.Done() - break - } - } - return ok -} func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message { wait := make(chan bool, 2) @@ -117,8 +95,9 @@ func (m *Message) Back(res *Message) *Message { } return m } -func (m *Message) Go(cb Any) *Message { - task.Put(kit.FileLine(cb, 3), func(task *task.Task) error { + +func (m *Message) Go(cb Any, arg ...string) *Message { + task.Put(kit.Select(kit.FileLine(cb, 3), arg, 0), func(task *task.Task) error { m.TryCatch(m, true, func(m *Message) { switch cb := cb.(type) { case func(*Message): @@ -126,7 +105,7 @@ func (m *Message) Go(cb Any) *Message { case func(): cb() default: - m.Error(true, ErrNotImplement) + m.ErrorNotImplement(cb) } }) return nil @@ -146,7 +125,8 @@ func (m *Message) Event(key string, arg ...string) *Message { return m } func (m *Message) Right(arg ...Any) bool { - key := strings.ReplaceAll(kit.Keys(arg...), PS, PT) + key := path.Join(strings.ReplaceAll(kit.Keys(arg...), PT, PS)) + key = strings.TrimPrefix(strings.TrimSuffix(strings.ReplaceAll(key, PS, PT), PT), PT) return m.Option(MSG_USERROLE) == ROOT || !m.Warn(m.Cmdx(ROLE, RIGHT, m.Option(MSG_USERROLE), key) != OK, ErrNotRight, kit.Join(kit.Simple(arg), PT), USERROLE, m.Option(MSG_USERROLE), FILELINE, kit.FileLine(2, 3)) } diff --git a/info.go b/info.go index 365b859d..cc7f188a 100644 --- a/info.go +++ b/info.go @@ -1,7 +1,6 @@ package ice import ( - "io" "os" "path" "strings" @@ -36,6 +35,7 @@ var Info = struct { NodeName string CtxShare string CtxRiver string + PidPath string Help string cans string @@ -45,7 +45,6 @@ var Info = struct { names Map render map[string]func(*Message, string, ...Any) string - Dump func(w io.Writer, name string, cb func(string)) bool Log func(m *Message, p, l, s string) }{ Help: ` @@ -73,7 +72,6 @@ source: https://shylinux.com/x/icebergs names: Map{}, render: map[string]func(*Message, string, ...Any) string{}, - Dump: func(w io.Writer, name string, cb func(string)) bool { return false }, Log: func(m *Message, p, l, s string) {}, } diff --git a/init.go b/init.go index 4419cae8..bc9bd290 100644 --- a/init.go +++ b/init.go @@ -3,11 +3,11 @@ package ice import ( "os" "strings" - "sync" "time" kit "shylinux.com/x/toolkits" - log "shylinux.com/x/toolkits/logs" + "shylinux.com/x/toolkits/conf" + "shylinux.com/x/toolkits/logs" ) type Frame struct{} @@ -16,8 +16,6 @@ func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server { return &Frame{} } func (f *Frame) Begin(m *Message, arg ...string) Server { - defer m.Cost(LOG_BEGIN, ICE) - list := map[*Context]*Message{m.target: m} m.Travel(func(p *Context, s *Context) { s.root = m.target @@ -29,20 +27,17 @@ func (f *Frame) Begin(m *Message, arg ...string) Server { return f } func (f *Frame) Start(m *Message, arg ...string) bool { - defer m.Cost(LOG_START, ICE) - m.Cap(CTX_STREAM, strings.Split(m.Time(), SP)[1]) + m.Cmdy("mdb._init") m.Cmdy(INIT, arg) - for _, k := range kit.Split(Getenv("ctx_daemon")) { + for _, k := range kit.Split(Getenv(CTX_DAEMON)) { m.Start(k) } m.Cmd(arg) return true } func (f *Frame) Close(m *Message, arg ...string) bool { - defer m.Cost(LOG_CLOSE, ICE) - list := map[*Context]*Message{m.target: m} m.Travel(func(p *Context, s *Context) { if msg, ok := list[p]; ok && msg != nil { @@ -50,6 +45,7 @@ func (f *Frame) Close(m *Message, arg ...string) bool { s.Close(list[s], arg...) } }) + conf.Close() return true } @@ -57,7 +53,6 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: map[string]*Confi HELP: {Value: kit.Data(INDEX, Info.Help)}, }, Commands: map[string]*Command{ CTX_INIT: {Hand: func(m *Message, 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._command(m.Spawn(c), cmd, CTX_INIT, arg...) @@ -72,16 +67,12 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: map[string]*Confi m.Echo(m.Config(INDEX)) }}, EXIT: {Name: "exit", Help: "结束", Hand: func(m *Message, arg ...string) { - m.root.Option(EXIT, kit.Select("0", arg, 0)) defer m.Target().Close(m.root.Spawn(), arg...) - + m.root.Option(EXIT, kit.Select("0", arg, 0)) m.Cmd(SOURCE, ETC_EXIT_SHY) m.root.Cmd(CTX_EXIT) }}, CTX_EXIT: {Hand: func(m *Message, arg ...string) { - defer m.Cost(CTX_EXIT) - m.Option("cmd_dir", "") - m.Option("dir_root", "") 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) { @@ -89,59 +80,35 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: map[string]*Confi }) } }) - _exit <- kit.Int(m.Option(EXIT)) }}, -}, server: &Frame{}, wg: &sync.WaitGroup{}} +}, server: &Frame{}} var Pulse = &Message{time: time.Now(), code: 0, meta: map[string][]string{}, data: Map{}, source: Index, target: Index, Hand: true, } -var _exit = make(chan int, 1) - func init() { Index.root, Pulse.root = Index, Pulse } func Run(arg ...string) string { - list := []string{} - for k := range Info.File { - if strings.HasPrefix(k, Info.Make.Path+PS) { - list = append(list, k) - } - } - for _, k := range list { - Info.File["/require/"+strings.TrimPrefix(k, Info.Make.Path+PS)] = Info.File[k] - delete(Info.File, k) - } - if len(arg) == 0 { // 进程参数 - if arg = append(arg, os.Args[1:]...); kit.Env("ctx_arg") != "" { - arg = append(arg, kit.Split(kit.Env("ctx_arg"))...) - } + arg = kit.Simple(arg, os.Args[1:], kit.Split(kit.Env("ctx_arg"))) } Pulse.meta[MSG_DETAIL] = arg switch Index.Merge(Index).Begin(Pulse.Spawn(), arg...); kit.Select("", arg, 0) { case SERVE, SPACE: // 启动服务 - switch strings.Split(os.Getenv("TERM"), "-")[0] { - case "xterm", "screen": - Info.Colors = true - default: - Info.Colors = false - } - if log.LogDisable = false; Index.Start(Pulse, arg...) { - Pulse.TryCatch(Pulse, true, func(Pulse *Message) { Index.wg.Wait() }) - os.Exit(<-_exit) + if Index.Start(Pulse, arg...) { + conf.Wait() + os.Exit(kit.Int(Pulse.Option(EXIT))) } default: // 执行命令 - if len(arg) == 0 { + if logs.Disable(true); len(arg) == 0 { arg = append(arg, HELP) } - Pulse.Cmd(INIT) if Pulse.Cmdy(arg); strings.TrimSpace(Pulse.Result()) == "" { Pulse.Table() } - Pulse.Sleep30ms() } if !strings.HasSuffix(Pulse.Result(), NL) { diff --git a/logs.go b/logs.go index dff5733f..21d0314d 100644 --- a/logs.go +++ b/logs.go @@ -7,15 +7,13 @@ import ( "time" kit "shylinux.com/x/toolkits" - log "shylinux.com/x/toolkits/logs" + "shylinux.com/x/toolkits/logs" ) func (m *Message) log(level string, str string, arg ...Any) *Message { - if log.LogDisable { - return m // 禁用日志 - } - if str = strings.TrimSpace(kit.Format(str, arg...)); Info.Log != nil { - Info.Log(m, m.FormatPrefix(), level, str) // 日志分流 + _source := logs.FileLineMeta(logs.FileLine(3, 3)) + if Info.Log != nil { + Info.Log(m, m.FormatPrefix(), level, logs.Format(str, append(arg, _source)...)) // 日志分流 } // 日志颜色 @@ -33,14 +31,6 @@ func (m *Message) log(level string, str string, arg ...Any) *Message { } } - // 文件行号 - switch level { - case LOG_INFO, LOG_CMDS, "refer", "form": - case LOG_BEGIN: - default: - suffix += SP + kit.FileLine(3, 3) - } - // 长度截断 switch level { case LOG_INFO, LOG_SEND, LOG_RECV: @@ -50,21 +40,31 @@ func (m *Message) log(level string, str string, arg ...Any) *Message { } // 输出日志 - log.Info(kit.Format("%02d %9s %s%s %s%s", m.code, - kit.Format("%4s->%-4s", m.source.Name, m.target.Name), prefix, level, str, suffix)) + logs.Infof(str, append(arg, logs.PrefixMeta(kit.Format("%02d %4s->%-4s %s%s ", m.code, m.source.Name, m.target.Name, prefix, level)), logs.SuffixMeta(suffix), _source)...) return m } -func (m *Message) join(arg ...Any) string { - args := kit.Simple(arg...) - list := []string{} - for i := 0; i < len(args); i += 2 { - if i == len(args)-1 { - list = append(list, args[i]) +func (m *Message) join(arg ...Any) (string, []Any) { + list, meta := []string{}, []Any{} + for i := 0; i < len(arg); i += 2 { + switch v := arg[i].(type) { + case logs.Meta: + i-- + meta = append(meta, v) + continue + } + if key := strings.TrimSpace(kit.Format(arg[i])); i == len(arg)-1 { + list = append(list, key) } else { - list = append(list, strings.TrimSpace(args[i])+kit.Select("", DF, !strings.HasSuffix(strings.TrimSpace(args[i]), DF)), kit.Format(args[i+1])) + switch v := arg[i+1].(type) { + case logs.Meta: + list = append(list, key) + meta = append(meta, v) + continue + } + list = append(list, key+kit.Select("", DF, !strings.HasSuffix(key, DF)), kit.Format(kit.Select("", kit.Simple(arg[i+1]), 0))) } } - return kit.Join(list, SP) + return kit.Join(list, SP), meta } func (m *Message) Log(level string, str string, arg ...Any) *Message { @@ -73,10 +73,6 @@ func (m *Message) Log(level string, str string, arg ...Any) *Message { func (m *Message) Info(str string, arg ...Any) *Message { return m.log(LOG_INFO, str, arg...) } -func (m *Message) Cost(arg ...Any) *Message { - list := []string{m.FormatCost(), m.join(arg...)} - return m.log(LOG_COST, kit.Join(list, SP)) -} func (m *Message) Warn(err Any, arg ...Any) bool { switch err := err.(type) { case error: @@ -91,21 +87,30 @@ func (m *Message) Warn(err Any, arg ...Any) bool { case nil: return false } - m.log(LOG_WARN, m.join(kit.Simple(arg...))) + str, meta := m.join(arg...) + m.log(LOG_WARN, str, meta...) + m.error(arg...) + return true +} +func (m *Message) error(arg ...Any) { if len(arg) == 0 { arg = append(arg, "", "") } else if len(arg) == 1 { arg = append(arg, "") } - m.meta[MSG_RESULT] = kit.Simple(ErrWarn, arg[0], arg[1], SP, m.join(kit.Simple(arg[2:]...))) - return true + str, meta := m.join(arg[2:]...) + m.meta[MSG_RESULT] = kit.Simple(ErrWarn, arg[0], arg[1], str, meta) } -func (m *Message) Error(err bool, str string, arg ...Any) bool { +func (m *Message) ErrorNotImplement(arg ...Any) { + m.Error(true, append(kit.List(ErrNotImplement), arg...)...) +} +func (m *Message) Error(err bool, arg ...Any) bool { if err { - m.Echo(ErrWarn).Echo(str, arg...) + m.error(arg...) m.log(LOG_ERROR, m.FormatStack(1, 100)) - m.log(LOG_ERROR, str, arg...) + str, meta := m.join(arg...) + m.log(LOG_ERROR, str, meta) m.log(LOG_ERROR, m.FormatChain()) return true } @@ -117,43 +122,62 @@ func (m *Message) Debug(str string, arg ...Any) { } m.log(LOG_DEBUG, str, arg...) } +func (m *Message) Cost(arg ...Any) *Message { + str, meta := m.join(arg...) + if len(arg) == 0 { + str = kit.Join(m.meta[MSG_DETAIL], SP) + } + list := []string{m.FormatCost(), str} + return m.log(LOG_COST, kit.Join(list, SP), meta...) +} func (m *Message) Logs(level string, arg ...Any) *Message { - return m.log(level, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(level, str, meta...) } func (m *Message) Log_AUTH(arg ...Any) *Message { - return m.log(LOG_AUTH, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_AUTH, str, meta...) } func (m *Message) Log_SEND(arg ...Any) *Message { - return m.log(LOG_AUTH, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_AUTH, str, meta...) } func (m *Message) Log_CREATE(arg ...Any) *Message { - return m.log(LOG_CREATE, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_CREATE, str, meta...) } func (m *Message) Log_REMOVE(arg ...Any) *Message { - return m.log(LOG_REMOVE, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_REMOVE, str, meta...) } func (m *Message) Log_INSERT(arg ...Any) *Message { - return m.log(LOG_INSERT, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_INSERT, str, meta...) } func (m *Message) Log_DELETE(arg ...Any) *Message { - return m.log(LOG_DELETE, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_DELETE, str, meta...) } func (m *Message) Log_MODIFY(arg ...Any) *Message { - return m.log(LOG_MODIFY, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_MODIFY, str, meta...) } func (m *Message) Log_SELECT(arg ...Any) *Message { - return m.log(LOG_SELECT, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_SELECT, str, meta...) } func (m *Message) Log_EXPORT(arg ...Any) *Message { - return m.log(LOG_EXPORT, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_EXPORT, str, meta...) } func (m *Message) Log_IMPORT(arg ...Any) *Message { - return m.log(LOG_IMPORT, m.join(arg...)) + str, meta := m.join(arg...) + return m.log(LOG_IMPORT, str, meta...) } func (m *Message) FormatPrefix() string { - return kit.Format("%s %d %s->%s", m.Time(), m.code, m.source.Name, m.target.Name) + return kit.Format("%s %d %s->%s", logs.FmtTime(logs.Now()), m.code, m.source.Name, m.target.Name) } func (m *Message) FormatTime() string { return m.Time() @@ -187,7 +211,7 @@ func (m *Message) FormatStack(s, n int) string { case "reflect", "runtime", "http", "task", "icebergs": default: switch kit.Select("", ls, 1) { - case "(*Frame)": + // case "(*Frame)": default: list = append(list, kit.Format("%s:%d\t%s", file, frame.Line, name)) } diff --git a/meta.go b/meta.go index e324c349..19273eb1 100644 --- a/meta.go +++ b/meta.go @@ -136,12 +136,23 @@ func (m *Message) Push(key string, value Any, arg ...Any) *Message { } fallthrough default: - if v = value[k]; v == nil { - if v = kit.Value(value, k); v == nil { - if v = val[k]; v == nil { - v = kit.Value(val, k) - } - } + if v = value[k]; v != nil { + break + } + if v = kit.Value(value, k); v != nil { + break + } + if v = kit.Value(value, kit.Keys("extra", k)); v != nil { + break + } + if v = val[k]; v != nil { + break + } + if v = kit.Value(val, k); v != nil { + break + } + if v = kit.Value(val, kit.Keys("extra", k)); v != nil { + break } } @@ -165,14 +176,14 @@ func (m *Message) Push(key string, value Any, arg ...Any) *Message { } default: - if m.FieldsIsDetail() { - if key != KEY || key != VALUE { - m.Add(MSG_APPEND, KEY, key) - m.Add(MSG_APPEND, VALUE, kit.Format(value)) - break + for _, v := range kit.Simple(value, arg) { + if m.FieldsIsDetail() { + if key != KEY || key != VALUE { + m.Add(MSG_APPEND, KEY, key) + m.Add(MSG_APPEND, VALUE, kit.Format(value)) + continue + } } - } - for _, v := range kit.Simple(value) { m.Add(MSG_APPEND, key, v) } } @@ -344,11 +355,13 @@ func (m *Message) Sort(key string, arg ...string) *Message { } }) compare := func(i, j int, op string) bool { - for k := range ls[1:] { + for k := range ls { + if k == 0 { + continue + } if table[i][ls[k]] == table[j][ls[k]] { continue } - if op == ">" && table[i][ls[k]] > table[j][ls[k]] { return true } @@ -363,29 +376,29 @@ func (m *Message) Sort(key string, arg ...string) *Message { // 排序数据 for i := 0; i < len(table)-1; i++ { for j := i + 1; j < len(table); j++ { - result := false + swap := false switch cmp { case "", "str": if table[i][key] > table[j][key] { - result = true + swap = true } else if table[i][key] == table[j][key] && compare(i, j, ">") { - result = true + swap = true } case "str_r": if table[i][key] < table[j][key] { - result = true + swap = true } else if table[i][key] == table[j][key] && compare(i, j, "<") { - result = true + swap = true } default: if number[i] > number[j] { - result = true + swap = true } else if table[i][key] == table[j][key] && compare(i, j, ">") { - result = true + swap = true } } - if result { + if swap { table[i], table[j] = table[j], table[i] number[i], number[j] = number[j], number[i] } diff --git a/misc.go b/misc.go index 39fb4912..dfac6785 100644 --- a/misc.go +++ b/misc.go @@ -7,6 +7,8 @@ import ( "strings" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/file" + "shylinux.com/x/toolkits/logs" ) func (m *Message) CSV(text string, head ...string) *Message { @@ -106,6 +108,14 @@ func (m *Message) RenameAppend(arg ...string) *Message { // [from to]... } return m } +func (m *Message) OptionFiles(f ...file.File) file.File { + if len(f) > 1 { + m.Optionv(MSG_FILES, file.NewMultiFile(f...)) + } else if len(f) > 0 { + m.Optionv(MSG_FILES, f[0]) + } + return m.Optionv(MSG_FILES).(file.File) +} func (m *Message) AppendSimple(key ...string) (res []string) { if len(key) == 0 { if m.FieldsIsDetail() { @@ -159,7 +169,7 @@ func (m *Message) Design(action Any, help string, input ...Any) { list = append(list, kit.Dict(NAME, k, TYPE, "text", VALUE, v)) }) default: - m.Error(true, ErrNotImplement) + m.ErrorNotImplement(input) } } k := kit.Format(action) @@ -173,8 +183,13 @@ func (m *Message) _command(arg ...Any) *Message { var cbs Any // 解析参数 + _source := logs.FileLine(3, 3) for _, v := range arg { switch val := v.(type) { + case logs.Meta: + if val.Key == "fileline" { + _source = val.Value + } case Option: opts[val.Name] = val.Value case *Option: @@ -223,6 +238,7 @@ func (m *Message) _command(arg ...Any) *Message { } // 执行命令 + msg._source = _source key = kit.Slice(strings.Split(key, PT), -1)[0] m.TryCatch(msg, true, func(msg *Message) { m = ctx._command(msg, cmd, key, arg...) }) } @@ -260,8 +276,9 @@ func (c *Context) _command(m *Message, cmd *Command, key string, arg ...string) } } - m.Log(LOG_CMDS, "%s.%s %d %v %s", c.Name, key, len(arg), arg, - kit.Select(kit.FileLine(cmd.Hand, 3), kit.FileLine(9, 3), m.target.Name == MDB)) + m._target = kit.FileLine(cmd.Hand, 3) + m.Log(LOG_CMDS, "%s.%s %d %v", c.Name, key, len(arg), arg, + logs.FileLineMeta(kit.Select(m._target, m._source, m.target.Name == MDB))) if cmd.Hand != nil { cmd.Hand(m, arg...) @@ -298,7 +315,9 @@ func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *A } } - m.Log(LOG_CMDS, "%s.%s %s %d %v %s", c.Name, key, sub, len(arg), arg, kit.FileLine(h.Hand, 3)) + m._target = kit.FileLine(cmd.Hand, 3) + m.Log(LOG_CMDS, "%s.%s %s %d %v", c.Name, key, sub, len(arg), arg, + logs.FileLineMeta(kit.Select(m._target, m._source, m.target.Name == MDB))) h.Hand(m, arg...) return m } @@ -411,7 +430,7 @@ func MergeAction(list ...Any) map[string]*Action { }) }} default: - Pulse.Error(true, ErrNotImplement) + Pulse.ErrorNotImplement(from) } } return base diff --git a/misc/bash/configs.go b/misc/bash/configs.go index 1b3a1e1a..2e16c205 100644 --- a/misc/bash/configs.go +++ b/misc/bash/configs.go @@ -8,7 +8,7 @@ import ( ) func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/configs": {Name: "/configs", Help: "配置", Hand: func(m *ice.Message, arg ...string) { m.Cmd("web.code.git.configs").Tables(func(value ice.Maps) { if strings.HasPrefix(value[mdb.NAME], "url") { @@ -17,5 +17,5 @@ func init() { } }) }}, - }}) + }) } diff --git a/misc/bash/download.go b/misc/bash/download.go index 8458d7d8..cac97c3b 100644 --- a/misc/bash/download.go +++ b/misc/bash/download.go @@ -10,7 +10,7 @@ import ( ) func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/download": {Name: "/download", Help: "下载", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 || arg[0] == "" { m.Cmdy(chat.FILES).Table() @@ -27,5 +27,5 @@ func init() { m.Echo("%s: %s\n", k, msg.Append(k)) } }}, - }}) + }) } diff --git a/misc/bash/favor.go b/misc/bash/favor.go index 7b74a006..465d584e 100644 --- a/misc/bash/favor.go +++ b/misc/bash/favor.go @@ -10,11 +10,7 @@ import ( const FAVOR = "favor" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - FAVOR: {Name: FAVOR, Help: "收藏夹", Value: kit.Data( - mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,pwd,username,hostname", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/favor": {Name: "/favor", Help: "收藏", Actions: ice.Actions{ mdb.EXPORT: {Name: "export zone name", Help: "导出", Hand: func(m *ice.Message, arg ...string) { m.Echo("#!/bin/sh\n\n") @@ -34,7 +30,7 @@ func init() { m.ProcessCommand(cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)), arg...) m.ProcessCommandOpt(arg, cli.PWD) }}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) { if mdb.ZoneSelect(m, arg...); len(arg) == 0 { m.Action(mdb.CREATE, mdb.EXPORT, mdb.IMPORT) } else { @@ -42,5 +38,5 @@ func init() { m.StatusTimeCount() } }}, - }}) + }) } diff --git a/misc/bash/grant.go b/misc/bash/grant.go index 50cc7789..b7f89ac1 100644 --- a/misc/bash/grant.go +++ b/misc/bash/grant.go @@ -8,7 +8,7 @@ import ( const GRANT = "grant" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "grant": {Name: "grant hash auto", Help: "授权", Actions: ice.MergeAction(ice.Actions{ "confirm": {Name: "confirm", Help: "同意", Hand: func(m *ice.Message, arg ...string) { m.Cmd(SESS, mdb.MODIFY, GRANT, m.Option(ice.MSG_USERNAME), ice.Option{mdb.HASH, m.Option("hash")}) @@ -31,5 +31,5 @@ func init() { } }) }}, - }}) + }) } diff --git a/misc/bash/input.go b/misc/bash/input.go index a0185010..3b7bf344 100644 --- a/misc/bash/input.go +++ b/misc/bash/input.go @@ -9,7 +9,7 @@ import ( ) func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/input": {Name: "/input", Help: "补全", Hand: func(m *ice.Message, arg ...string) { list := kit.Split(m.Option("line"), m.Option("break")) word := list[kit.Int(m.Option("index"))] @@ -97,5 +97,5 @@ func init() { } m.Info("trans: %v", m.Result()) }}, - }}) + }) } diff --git a/misc/bash/run.go b/misc/bash/run.go index 04c0d793..f5656501 100644 --- a/misc/bash/run.go +++ b/misc/bash/run.go @@ -70,7 +70,7 @@ ish_sys_dev_run_action() { const RUN = "run" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/run/": {Name: "/run/", Help: "执行", Actions: ice.MergeAction(ice.Actions{ ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) { m.Search(arg[0], func(_ *ice.Context, s *ice.Context, key string, cmd *ice.Command) { @@ -94,5 +94,5 @@ func init() { } }}, }, ctx.CmdAction())}, - }}) + }) } diff --git a/misc/bash/sess.go b/misc/bash/sess.go index 820b1708..2da012f8 100644 --- a/misc/bash/sess.go +++ b/misc/bash/sess.go @@ -10,7 +10,6 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/web" - kit "shylinux.com/x/toolkits" ) const ( @@ -21,11 +20,7 @@ const ( const SESS = "sess" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SESS: {Name: SESS, Help: "会话流", Value: kit.Data( - mdb.FIELD, "time,hash,status,username,hostname,pid,pwd,grant", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ web.WEB_LOGIN: {Hand: func(m *ice.Message, arg ...string) { if f, _, e := m.R.FormFile(SUB); e == nil { defer f.Close() @@ -72,8 +67,8 @@ func init() { m.OptionFields(m.Config(mdb.FIELD)) m.Cmdy(mdb.PRUNES, m.PrefixKey(), "", mdb.HASH, mdb.STATUS, aaa.LOGOUT) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.FIELD, "time,hash,status,username,hostname,pid,pwd,grant")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...) }}, - }}) + }) } diff --git a/misc/bash/sync.go b/misc/bash/sync.go index 91bacd81..b9e544ad 100644 --- a/misc/bash/sync.go +++ b/misc/bash/sync.go @@ -14,11 +14,7 @@ import ( const SYNC = "sync" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SYNC: {Name: SYNC, Help: "同步流", Value: kit.Data( - mdb.FIELD, "time,id,type,name,text,pwd,username,hostname", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/sync": {Name: "/sync", Help: "同步", Actions: ice.Actions{ "history": {Name: "history", Help: "历史", Hand: func(m *ice.Message, arg ...string) { ls := strings.SplitN(strings.TrimSpace(m.Option(ARG)), ice.SP, 4) @@ -41,11 +37,11 @@ func init() { FAVOR: {Name: "favor zone=some@key type name text pwd", Help: "收藏", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(FAVOR, mdb.INSERT) }}, - }, mdb.ListAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ListAction(mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) { m.OptionPage(kit.Slice(arg, 1)...) mdb.ListSelect(m, kit.Slice(arg, 0, 1)...) m.PushAction(cli.SYSTEM, FAVOR) m.StatusTimeCountTotal(m.Config(mdb.COUNT)) }}, - }}) + }) } diff --git a/misc/bash/trash.go b/misc/bash/trash.go index 5ffcf81f..69791227 100644 --- a/misc/bash/trash.go +++ b/misc/bash/trash.go @@ -9,7 +9,6 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" - kit "shylinux.com/x/toolkits" ) const ( @@ -19,11 +18,7 @@ const ( const TRASH = "trash" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - TRASH: {Name: TRASH, Help: "回收站", Value: kit.Data( - mdb.FIELD, "time,hash,username,hostname,size,from,to", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/trash": {Name: "/trash", Help: "回收", Actions: ice.Actions{ mdb.INSERT: {Name: "insert from to", Help: "添加", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(TRASH, mdb.INSERT, arg) @@ -52,9 +47,9 @@ func init() { m.ProcessCommand(nfs.CAT, []string{}, arg...) m.ProcessCommandOpt(arg, TO) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.FIELD, "time,hash,username,hostname,size,from,to")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...) m.PushAction(nfs.CAT, mdb.REVERT, mdb.REMOVE) }}, - }}) + }) } diff --git a/misc/bash/zsh.go b/misc/bash/zsh.go index f42967b1..df935658 100644 --- a/misc/bash/zsh.go +++ b/misc/bash/zsh.go @@ -5,23 +5,18 @@ import ( "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/core/code" - kit "shylinux.com/x/toolkits" ) const ZSH = "zsh" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - ZSH: {Name: ZSH, Help: "命令行", Value: kit.Data( - nfs.SOURCE, "https://nchc.dl.sourceforge.net/project/zsh/zsh/5.8/zsh-5.8.tar.xz", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ ZSH: {Name: "zsh path auto order build download", Help: "命令行", Actions: ice.MergeAction(ice.Actions{ cli.ORDER: {Name: "order", Help: "加载", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/bin") }}, - }, code.InstallAction()), Hand: func(m *ice.Message, arg ...string) { + }, code.InstallAction(nfs.SOURCE, "https://nchc.dl.sourceforge.net/project/zsh/zsh/5.8/zsh-5.8.tar.xz")), Hand: func(m *ice.Message, arg ...string) { m.Cmdy(code.INSTALL, nfs.SOURCE, m.Config(nfs.SOURCE), arg) }}, - }}) + }) } diff --git a/misc/chrome/cache.go b/misc/chrome/cache.go index 9d050722..13db7d48 100644 --- a/misc/chrome/cache.go +++ b/misc/chrome/cache.go @@ -24,8 +24,8 @@ func (c cache) Create(m *ice.Message, arg ...string) *ice.Message { if c.Hash.List(m, m.Option(mdb.LINK)); m.Length() > 0 { return m // 已经下载 } - - m.Option(mdb.HASH, c.Hash.Create(m.Spawn(), m.OptionSimple("show,type,name,link")...).Result()) + // h = c.Hash.Create(m.Spawn(), m.OptionSimple("show,type,name,link")...).Result() + // m.Option(mdb.HASH, h) msg := m.Cmd("web.spide", ice.DEV, web.SPIDE_CACHE, web.SPIDE_GET, m.Option(mdb.LINK), func(count, total, value int) { c.Hash.Modify(m, kit.Simple(mdb.COUNT, count, mdb.TOTAL, total, mdb.VALUE, kit.Format(value))...) }) diff --git a/misc/git/count.go b/misc/git/count.go index 2b1b0a6b..55a6581b 100644 --- a/misc/git/count.go +++ b/misc/git/count.go @@ -13,7 +13,7 @@ import ( const COUNT = "count" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ COUNT: {Name: "count path auto count", Help: "代码行", Actions: ice.Actions{ COUNT: {Name: "count", Help: "计数", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 || arg[0] == "usr/" { @@ -66,5 +66,5 @@ func init() { }, Hand: func(m *ice.Message, arg ...string) { m.Cmdy(nfs.DIR, arg) }}, - }}) + }) } diff --git a/misc/git/server.go b/misc/git/server.go index eb85b616..7b0b2a3b 100644 --- a/misc/git/server.go +++ b/misc/git/server.go @@ -113,7 +113,7 @@ func _server_repos(m *ice.Message, arg ...string) error { const SERVER = "server" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ web.WEB_LOGIN: {Hand: func(m *ice.Message, arg ...string) { m.Render(ice.RENDER_VOID) }}, @@ -204,5 +204,5 @@ func init() { } m.Cmdy("_sum", path.Join(m.Option(nfs.DIR_ROOT), arg[0])) }}, - }}) + }) } diff --git a/misc/git/spide.go b/misc/git/spide.go index 7f388a6f..4d20113c 100644 --- a/misc/git/spide.go +++ b/misc/git/spide.go @@ -60,7 +60,7 @@ func _spide_c(m *ice.Message, file string) { const SPIDE = "spide" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SPIDE: {Name: "spide repos auto", Help: "构架图", Actions: ice.MergeAction(ice.Actions{ code.INNER: {Name: "web.code.inner"}, "depend": {Name: "depend path=icebergs/base", Help: "依赖", Hand: func(m *ice.Message, arg ...string) { @@ -136,5 +136,5 @@ func init() { } m.SortInt(nfs.LINE) }}, - }}) + }) } diff --git a/misc/git/status.go b/misc/git/status.go index ed3f3384..d774aebc 100644 --- a/misc/git/status.go +++ b/misc/git/status.go @@ -199,7 +199,7 @@ const ( const STATUS = "status" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ STATUS: {Name: "status repos auto", Help: "状态机", Actions: ice.Actions{ mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { switch arg[0] { @@ -334,5 +334,5 @@ func init() { m.Status("files", files, "adds", adds, "dels", dels) m.Toast3s(kit.Format("files: %d, adds: %d, dels: %d", files, adds, dels), arg[0]) }}, - }}) + }) } diff --git a/misc/git/trend.go b/misc/git/trend.go index fbb09fd0..c6814435 100644 --- a/misc/git/trend.go +++ b/misc/git/trend.go @@ -11,7 +11,7 @@ import ( const TREND = "trend" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TREND: {Name: "trend repos@key begin_time@date auto", Help: "趋势图", Meta: kit.Dict( ice.DisplayStory("trend.js"), ), Actions: ice.MergeAction(ice.Actions{ @@ -26,5 +26,5 @@ func init() { arg[0] = kit.Replace(arg[0], "src", "contexts") m.Cmdy(TOTAL, kit.Slice(arg, 0, 2)) }}, - }}) + }) } diff --git a/misc/lark/company.go b/misc/lark/company.go index 889b4eb6..ca0a652e 100644 --- a/misc/lark/company.go +++ b/misc/lark/company.go @@ -39,7 +39,7 @@ func _company_members(m *ice.Message, appid string, ship_id string) { const COMPANY = "company" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ COMPANY: {Name: "company appid ship_id open_id text auto", Help: "组织", Hand: func(m *ice.Message, arg ...string) { switch len(arg) { case 0: // 应用列表 @@ -58,5 +58,5 @@ func init() { m.Cmdy(SEND, arg[0], OPEN_ID, arg[2], arg[3:]) } }}, - }}) + }) } diff --git a/misc/lark/duty.go b/misc/lark/duty.go index 8d470bd1..1d7bad2d 100644 --- a/misc/lark/duty.go +++ b/misc/lark/duty.go @@ -7,10 +7,10 @@ import ( const DUTY = "duty" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ DUTY: {Name: "duty [title] text run", Help: "通告", Hand: func(m *ice.Message, arg ...string) { msg := m.Cmd(APP, m.Option(APP_ID)) m.Cmdy(SEND, msg.Append(APPID), msg.Append(DUTY), arg) }}, - }}) + }) } diff --git a/misc/lark/employee.go b/misc/lark/employee.go index c37cdd75..ebdced00 100644 --- a/misc/lark/employee.go +++ b/misc/lark/employee.go @@ -31,7 +31,7 @@ func _employee_openid(m *ice.Message, appid string, arg ...string) { const EMPLOYEE = "employee" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ EMPLOYEE: {Name: "employee appid open_id|mobile|email auto", Help: "员工", Hand: func(m *ice.Message, arg ...string) { if len(arg) < 2 { return @@ -42,5 +42,5 @@ func init() { _employee_openid(m, arg[0], arg[1:]...) } }}, - }}) + }) } diff --git a/misc/lark/event.go b/misc/lark/event.go index a1eed238..00097741 100644 --- a/misc/lark/event.go +++ b/misc/lark/event.go @@ -17,7 +17,7 @@ const ( const EVENT = "event" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ EVENT: {Name: "event", Help: "事件", Actions: ice.Actions{ P2P_CHAT_CREATE: {Name: "", Help: "", Hand: func(m *ice.Message, arg ...string) { if m.Option(OPEN_CHAT_ID) != "" { @@ -36,5 +36,5 @@ func init() { }, Hand: func(m *ice.Message, arg ...string) { m.Cmdy(MSG, m.Option(MSG_TYPE)) }}, - }}) + }) } diff --git a/misc/lark/form.go b/misc/lark/form.go index de3fed70..93ca9d87 100644 --- a/misc/lark/form.go +++ b/misc/lark/form.go @@ -10,7 +10,7 @@ import ( const FORM = "form" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ FORM: {Name: "form [chat_id|open_id|user_id|email] target title text [confirm|value|url arg...]...", Help: "消息", Hand: func(m *ice.Message, arg ...string) { var form = kit.Dict() switch arg[0] { @@ -75,5 +75,5 @@ func init() { msg := _lark_post(m, m.Option(APP_ID), "/open-apis/message/v4/send/", web.SPIDE_DATA, kit.Formats(form)) m.Debug("%v", msg.Optionv(web.SPIDE_RES)) }}, - }}) + }) } diff --git a/misc/lark/group.go b/misc/lark/group.go index c3f232d1..0f808baa 100644 --- a/misc/lark/group.go +++ b/misc/lark/group.go @@ -34,7 +34,7 @@ func _group_members(m *ice.Message, appid string, chat_id string) { const GROUP = "group" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ GROUP: {Name: "group appid chat_id open_id text auto", Help: "群组", Hand: func(m *ice.Message, arg ...string) { switch len(arg) { case 0: // 应用列表 @@ -53,5 +53,5 @@ func init() { m.Cmdy(SEND, arg[0], OPEN_ID, arg[2], arg[3:]) } }}, - }}) + }) } diff --git a/misc/lark/home.go b/misc/lark/home.go index 999a137c..4f52f65a 100644 --- a/misc/lark/home.go +++ b/misc/lark/home.go @@ -11,7 +11,7 @@ import ( const HOME = "home" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ HOME: {Name: "home river storm title content", Help: "首页", Hand: func(m *ice.Message, arg ...string) { name := kit.Select(m.Option(ice.MSG_USERNAME), m.Option(ice.MSG_USERNICK)) if len(name) > 10 { @@ -37,5 +37,5 @@ func init() { } m.Cmd(FORM, CHAT_ID, m.Option(OPEN_CHAT_ID), name, text, "打开网页", "url", link, list) }}, - }}) + }) } diff --git a/misc/lark/msg.go b/misc/lark/msg.go index 0ec92e34..c10c65e3 100644 --- a/misc/lark/msg.go +++ b/misc/lark/msg.go @@ -59,7 +59,7 @@ const ( const MSG = "msg" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ web.WEB_LOGIN: {Hand: func(m *ice.Message, arg ...string) { m.Option(ice.MSG_USERZONE, LARK) }}, @@ -100,5 +100,5 @@ func init() { m.Cmdy(TALK, strings.TrimSpace(m.Option("text_without_at_bot"))) } }}, - }}) + }) } diff --git a/misc/lark/rand.go b/misc/lark/rand.go index bd87f0da..4f62fb6b 100644 --- a/misc/lark/rand.go +++ b/misc/lark/rand.go @@ -11,7 +11,7 @@ import ( const RAND = "rand" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ RAND: {Name: "rand", Help: "随机", Hand: func(m *ice.Message, arg ...string) { msg := m.Cmd(GROUP, m.Option(APP_ID), EMPLOYEE, m.Option(OPEN_CHAT_ID)) list := msg.Appendv(mdb.NAME) @@ -21,5 +21,5 @@ func init() { } m.Echo(list[rand.Intn(len(list))]) }}, - }}) + }) } diff --git a/misc/lark/send.go b/misc/lark/send.go index e8401e44..26ad1c4d 100644 --- a/misc/lark/send.go +++ b/misc/lark/send.go @@ -48,7 +48,7 @@ const ( const SEND = "send" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SEND: {Name: "send appid [chat_id|open_id|user_id|email] target [title] text", Help: "消息", Hand: func(m *ice.Message, arg ...string) { form := kit.Dict(CONTENT, kit.Dict()) appid, arg := arg[0], arg[1:] @@ -65,5 +65,5 @@ func init() { m.Push("message_id", msg.Append("data.message_id")) } }}, - }}) + }) } diff --git a/misc/lark/sso.go b/misc/lark/sso.go index 17730f44..84156115 100644 --- a/misc/lark/sso.go +++ b/misc/lark/sso.go @@ -12,7 +12,7 @@ import ( const SSO = "sso" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/sso": {Name: "/sso", Help: "网页", Hand: func(m *ice.Message, arg ...string) { if m.Option(ice.MSG_USERNAME) != "" { // 默认主页 m.RenderIndex(web.SERVE, ice.VOLCANOS) @@ -48,5 +48,5 @@ func init() { // web.RenderCookie(m, aaa.SessCreate(m, m.Option(aaa.USERNAME)), web.CookieName(m.Option(cli.BACK))) m.RenderRedirect(kit.MergeURL(kit.Select(home, m.Option(cli.BACK)), "sessid", aaa.SessCreate(m, m.Option(aaa.USERNAME)))) }}, - }}) + }) } diff --git a/misc/lark/talk.go b/misc/lark/talk.go index e07177b6..d99e7a5b 100644 --- a/misc/lark/talk.go +++ b/misc/lark/talk.go @@ -13,7 +13,7 @@ import ( const TALK = "talk" func init() { - Index.Merge(&ice.Context{Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ TALK: {Name: "talk text", Help: "聊天", Hand: func(m *ice.Message, arg ...string) { cmds := kit.Split(strings.Join(arg, " ")) if aaa.UserLogin(m, m.Option(OPEN_ID), ""); !m.Right(cmds) { @@ -55,5 +55,5 @@ func init() { )), )) }}, - }}) + }) } diff --git a/misc/ssh/channel.go b/misc/ssh/channel.go index 7f33efc7..0bcfdd8c 100644 --- a/misc/ssh/channel.go +++ b/misc/ssh/channel.go @@ -67,11 +67,7 @@ func _ssh_watch(m *ice.Message, meta ice.Maps, h string, input io.Reader, output const CHANNEL = "channel" func init() { - psh.Index.Merge(&ice.Context{Configs: ice.Configs{ - CHANNEL: {Name: "channel", Help: "通道", Value: kit.Data( - mdb.FIELD, "time,hash,status,username,hostport,tty,count", - )}, - }, Commands: ice.Commands{ + psh.Index.MergeCommands(ice.Commands{ CHANNEL: {Name: "channel hash id auto", Help: "通道", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Richs(CHANNEL, "", mdb.FOREACH, func(key string, value ice.Map) { @@ -96,7 +92,7 @@ func init() { }) m.ProcessRefresh300ms() }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.FIELD, "time,hash,status,username,hostport,tty,count")), Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { // 通道列表 m.Action(mdb.PRUNES) mdb.HashSelect(m, arg...) @@ -113,5 +109,5 @@ func init() { mdb.ZoneSelect(m, arg...) m.PushAction(mdb.REPEAT) }}, - }}) + }) } diff --git a/misc/ssh/connect.go b/misc/ssh/connect.go index 45f6b6d8..e79f7138 100644 --- a/misc/ssh/connect.go +++ b/misc/ssh/connect.go @@ -155,9 +155,7 @@ const SSH = "ssh" const CONNECT = "connect" func init() { - psh.Index.Merge(&ice.Context{Configs: ice.Configs{ - CONNECT: {Name: CONNECT, Help: "连接", Value: kit.Data(mdb.SHORT, "name", mdb.FIELD, "time,name,status,username,host,port")}, - }, Commands: ice.Commands{ + psh.Index.MergeCommands(ice.Commands{ CONNECT: {Name: "connect name auto", Help: "连接", Actions: ice.MergeAction(ice.Actions{ 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) { aaa.UserRoot(m) @@ -203,7 +201,7 @@ func init() { } }) }}, - }, mdb.HashActionStatus()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashActionStatus(mdb.SHORT, "name", mdb.FIELD, "time,name,status,username,host,port")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) { m.PushButton(kit.Select("", "command,session", value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE) }) @@ -211,5 +209,5 @@ func init() { m.Action(tcp.DIAL) } }}, - }}) + }) } diff --git a/misc/ssh/rsa.go b/misc/ssh/rsa.go index 106c7ec9..59908855 100644 --- a/misc/ssh/rsa.go +++ b/misc/ssh/rsa.go @@ -22,9 +22,7 @@ const ( const RSA = "rsa" func init() { - aaa.Index.Merge(&ice.Context{Configs: ice.Configs{ - RSA: {Name: RSA, Help: "角色", Value: kit.Data(mdb.SHORT, mdb.HASH, mdb.FIELD, "time,hash,title,public,private")}, - }, Commands: ice.Commands{ + aaa.Index.MergeCommands(ice.Commands{ RSA: {Name: "rsa hash auto", Help: "公钥", Actions: ice.MergeAction(ice.Actions{ mdb.IMPORT: {Name: "import key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Help: "导入", Hand: func(m *ice.Message, arg ...string) { m.Conf(m.PrefixKey(), kit.Keys(mdb.HASH, path.Base(m.Option("key"))), kit.Data(mdb.TIME, m.Time(), @@ -48,10 +46,10 @@ func init() { } } }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.HASH, mdb.FIELD, "time,hash,title,public,private")), Hand: func(m *ice.Message, arg ...string) { if mdb.HashSelect(m, arg...).PushAction(mdb.EXPORT, mdb.REMOVE); len(arg) == 0 { m.Action(mdb.CREATE, mdb.IMPORT) } }}, - }}) + }) } diff --git a/misc/ssh/session.go b/misc/ssh/session.go index f54e5a9c..c5305d82 100644 --- a/misc/ssh/session.go +++ b/misc/ssh/session.go @@ -58,9 +58,7 @@ const ( const SESSION = "session" func init() { - psh.Index.Merge(&ice.Context{Configs: ice.Configs{ - SESSION: {Name: SESSION, Help: "会话", Value: kit.Data(mdb.SHORT, "name", mdb.FIELD, "time,name,status,count,connect")}, - }, Commands: ice.Commands{ + psh.Index.MergeCommands(ice.Commands{ SESSION: {Name: "session name id auto", Help: "会话", Actions: ice.MergeAction(ice.Actions{ mdb.REPEAT: {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(SESSION, ctx.ACTION, ctx.COMMAND, CMD, m.Option(mdb.TEXT)) @@ -74,7 +72,7 @@ func init() { }) m.ProcessRefresh300ms() }}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction(mdb.SHORT, "name", mdb.FIELD, "time,name,status,count,connect")), Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) { m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE) @@ -89,5 +87,5 @@ func init() { m.PushButton(kit.Select("", mdb.REPEAT, value[mdb.TYPE] == CMD)) }) }}, - }}) + }) } diff --git a/misc/tmux/buffer.go b/misc/tmux/buffer.go index 74e35cfb..61c7df22 100644 --- a/misc/tmux/buffer.go +++ b/misc/tmux/buffer.go @@ -16,9 +16,7 @@ const ( ) func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - BUFFER: {Name: BUFFER, Help: "缓存", Value: kit.Data()}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ BUFFER: {Name: "buffer name value auto export import", Help: "缓存", Actions: ice.Actions{ mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { switch arg[0] { @@ -94,5 +92,5 @@ func init() { m.EchoScript(text) } }}, - }}) + }) } diff --git a/misc/tmux/script.go b/misc/tmux/script.go index af4e955b..2e6fddd9 100644 --- a/misc/tmux/script.go +++ b/misc/tmux/script.go @@ -3,21 +3,16 @@ package tmux import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" - kit "shylinux.com/x/toolkits" ) const SCRIPT = "script" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SCRIPT: {Name: SCRIPT, Help: "脚本", Value: kit.Data( - mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ SCRIPT: {Name: "script name auto create export import", Help: "脚本", Actions: ice.MergeAction(ice.Actions{ mdb.CREATE: {Name: "create type=shell,tmux,vim name=hi text:textarea=pwd", Help: "添加"}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...) }}, - }}) + }) } diff --git a/misc/tmux/session.go b/misc/tmux/session.go index f3af4311..f526042c 100644 --- a/misc/tmux/session.go +++ b/misc/tmux/session.go @@ -8,7 +8,6 @@ import ( "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/mdb" - "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/web" kit "shylinux.com/x/toolkits" ) @@ -79,7 +78,7 @@ func init() { m.Cmdy(cli.SYSTEM, TMUX, "new-window", "-t", m.Option(SESSION), "-dn", m.Option(mdb.NAME)) } else { // 创建会话 - m.Option(cli.CMD_DIR, path.Join(m.Conf(web.DREAM, kit.Keym(nfs.PATH)), m.Option(mdb.NAME))) + m.Option(cli.CMD_DIR, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME))) ls := kit.Split(m.Option(mdb.NAME), "-_") name := ls[len(ls)-1] diff --git a/misc/vim/favor.go b/misc/vim/favor.go index 318efc86..c12c4c5b 100644 --- a/misc/vim/favor.go +++ b/misc/vim/favor.go @@ -8,17 +8,12 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/core/code" - kit "shylinux.com/x/toolkits" ) const FAVOR = "favor" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - FAVOR: {Name: FAVOR, Help: "收藏夹", Value: kit.Data( - mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,file,line,pwd", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/favor": {Name: "/favor", Help: "收藏", Actions: ice.Actions{ mdb.SELECT: {Name: "select", Help: "主题", Hand: func(m *ice.Message, arg ...string) { m.Cmd(FAVOR).Tables(func(value ice.Maps) { @@ -40,7 +35,9 @@ func init() { p := path.Join(m.Option(cli.PWD), m.Option(nfs.FILE)) m.ProcessCommand(code.INNER, []string{path.Dir(p) + ice.PS, path.Base(p), m.Option(nfs.LINE)}, arg...) }}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction( + mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,file,line,pwd", + )), Hand: func(m *ice.Message, arg ...string) { if mdb.ZoneSelect(m, arg...); len(arg) == 0 { m.Action(mdb.CREATE, mdb.EXPORT, mdb.IMPORT) } else { @@ -48,5 +45,5 @@ func init() { m.StatusTimeCount() } }}, - }}) + }) } diff --git a/misc/vim/input.go b/misc/vim/input.go index 1ad1f263..c0d297a9 100644 --- a/misc/vim/input.go +++ b/misc/vim/input.go @@ -13,9 +13,7 @@ import ( const INPUT = "input" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - INPUT: {Name: INPUT, Help: "输入法", Value: kit.Data(mdb.FIELD, "time,id,type,name,text")}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/input": {Name: "/input", Help: "输入法", Hand: func(m *ice.Message, arg ...string) { if m.Cmdy(TAGS, ctx.ACTION, INPUT, arg[0], m.Option("pre")); m.Length() > 0 { m.Cmd(m.PrefixKey(), mdb.INSERT, kit.SimpleKV("", "tags", arg[0], m.Result())) @@ -40,6 +38,6 @@ func init() { return // 本地命令 } }}, - INPUT: {Name: "input id auto export import", Help: "输入法", Actions: mdb.ListAction()}, - }}) + INPUT: {Name: "input id auto export import", Help: "输入法", Actions: mdb.ListAction(mdb.FIELD, "time,id,type,name,text")}, + }) } diff --git a/misc/vim/sess.go b/misc/vim/sess.go index 60ed04a7..72c07eca 100644 --- a/misc/vim/sess.go +++ b/misc/vim/sess.go @@ -10,7 +10,6 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/web" - kit "shylinux.com/x/toolkits" ) const ( @@ -24,11 +23,7 @@ const ( const SESS = "sess" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SESS: {Name: SESS, Help: "会话流", Value: kit.Data( - mdb.FIELD, "time,hash,status,username,hostname,pid,pwd", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ web.WEB_LOGIN: {Hand: func(m *ice.Message, arg ...string) { if f, _, e := m.R.FormFile(SUB); e == nil { defer f.Close() @@ -68,8 +63,8 @@ func init() { m.OptionFields(m.Config(mdb.FIELD)) m.Cmdy(mdb.PRUNES, m.PrefixKey(), "", mdb.HASH, mdb.STATUS, aaa.LOGOUT) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.FIELD, "time,hash,status,username,hostname,pid,pwd")), Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...) }}, - }}) + }) } diff --git a/misc/vim/sync.go b/misc/vim/sync.go index ec215434..67c2736d 100644 --- a/misc/vim/sync.go +++ b/misc/vim/sync.go @@ -15,11 +15,7 @@ import ( const SYNC = "sync" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - SYNC: {Name: SYNC, Help: "同步流", Value: kit.Data( - mdb.FIELD, "time,id,type,name,text,pwd,buf,row,col", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/sync": {Name: "/sync", Help: "同步", Hand: func(m *ice.Message, arg ...string) { switch m.Option(ARG) { case "wq", "q", "qa": @@ -41,11 +37,11 @@ func init() { m.Cmdy(FAVOR, mdb.INSERT, m.OptionSimple(mdb.ZONE, "type,name,text,pwd"), nfs.FILE, m.Option(BUF), nfs.LINE, m.Option(ROW)) }}, - }, mdb.ListAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ListAction(mdb.FIELD, "time,id,type,name,text,pwd,buf,row,col")), Hand: func(m *ice.Message, arg ...string) { m.OptionPage(kit.Slice(arg, 1)...) mdb.ListSelect(m, kit.Slice(arg, 0, 1)...) m.PushAction(code.INNER, FAVOR) m.StatusTimeCountTotal(m.Config(mdb.COUNT)) }}, - }}) + }) } diff --git a/misc/vim/tags.go b/misc/vim/tags.go index 031b95ee..9ceca274 100644 --- a/misc/vim/tags.go +++ b/misc/vim/tags.go @@ -26,11 +26,7 @@ func init() { func_pattern = "4\n%s\n/\\<%s: \\(shy\\|func\\)/\n" libs_pattern = "4\nusr/volcanos/lib/%s.js\n/\\<%s: \\(shy\\|func\\)/\n" ) - Index.Merge(&ice.Context{Configs: ice.Configs{ - TAGS: {Name: TAGS, Help: "索引", Value: kit.Data( - mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,path,file,line", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/tags": {Name: "/tags", Help: "跳转", Hand: func(m *ice.Message, arg ...string) { switch m.Option(MODULE) { case ONIMPORT, ONACTION, ONEXPORT: @@ -82,12 +78,12 @@ func init() { m.Echo("%s: %s"+ice.NL, value[mdb.NAME], strings.Split(value[mdb.TEXT], ice.NL)[0]) }) }}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,path,file,line")), Hand: func(m *ice.Message, arg ...string) { if mdb.ZoneSelectAll(m, arg...); len(arg) == 0 { m.Action("listTags", mdb.CREATE, mdb.EXPORT, mdb.IMPORT) } else { m.Action(mdb.INSERT).PushAction(code.INNER).StatusTimeCount() } }}, - }}) + }) } diff --git a/misc/wework/bot.go b/misc/wework/bot.go index 8c37f1a4..de1bdcce 100644 --- a/misc/wework/bot.go +++ b/misc/wework/bot.go @@ -16,11 +16,7 @@ import ( const BOT = "bot" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - BOT: {Name: "bot", Help: "机器人", Value: kit.Data( - mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,token,ekey,hook", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ web.WEB_LOGIN: {Hand: func(m *ice.Message, arg ...string) {}}, "/bot/": {Name: "/bot/", Help: "机器人", Hand: func(m *ice.Message, arg ...string) { msg := m.Cmd(BOT, arg[0]) @@ -52,7 +48,7 @@ func init() { m.Cmd(web.SPIDE, mdb.CREATE, m.Option("name"), m.Option("hook")) m.Cmdy(mdb.INSERT, m.PrefixKey(), "", mdb.HASH, arg) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,token,ekey,hook")), Hand: func(m *ice.Message, arg ...string) { if mdb.HashSelect(m, arg...); len(arg) > 2 { m.Cmdy(web.SPIDE, arg[0], "", kit.Format(kit.Dict( "chatid", arg[1], "msgtype", "text", "text.content", arg[2], @@ -61,5 +57,5 @@ func init() { m.PushAction(mdb.REMOVE) } }}, - }}) + }) } diff --git a/misc/wx/access.go b/misc/wx/access.go index 285f568f..8ac27b1a 100644 --- a/misc/wx/access.go +++ b/misc/wx/access.go @@ -56,11 +56,7 @@ const ( const ACCESS = "access" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - ACCESS: {Name: ACCESS, Help: "认证", Value: kit.Data( - tcp.SERVER, "https://api.weixin.qq.com", ssh.SCRIPT, "/plugin/local/chat/wx.js", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ ACCESS: {Name: "access appid auto config ticket tokens login", Help: "认证", Actions: ice.MergeAction(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Cmd(web.SPIDE, mdb.CREATE, WX, m.Config(tcp.SERVER)) @@ -102,8 +98,8 @@ func init() { CHECK: {Name: "check", Help: "检验", Hand: func(m *ice.Message, arg ...string) { _wx_check(m) }}, - }, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.HashAction(tcp.SERVER, "https://api.weixin.qq.com", ssh.SCRIPT, "/plugin/local/chat/wx.js")), Hand: func(m *ice.Message, arg ...string) { m.Echo(m.Config(APPID)) }}, - }}) + }) } diff --git a/misc/wx/event.go b/misc/wx/event.go index 21121049..bf6a6694 100644 --- a/misc/wx/event.go +++ b/misc/wx/event.go @@ -2,15 +2,12 @@ package wx import ( ice "shylinux.com/x/icebergs" - kit "shylinux.com/x/toolkits" ) const EVENT = "event" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - EVENT: {Name: EVENT, Help: "事件", Value: kit.Data()}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ EVENT: {Name: "event", Help: "事件", Actions: ice.Actions{ "subscribe": {Name: "subscribe", Help: "订阅", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(MENU, "home") @@ -18,5 +15,5 @@ func init() { "unsubscribe": {Name: "unsubscribe", Help: "取关", Hand: func(m *ice.Message, arg ...string) { }}, }}, - }}) + }) } diff --git a/misc/wx/login.go b/misc/wx/login.go index 893a6849..1feacb36 100644 --- a/misc/wx/login.go +++ b/misc/wx/login.go @@ -63,9 +63,7 @@ func _wx_parse(m *ice.Message) { const LOGIN = "login" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - LOGIN: {Name: LOGIN, Help: "登录", Value: kit.Data()}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ "/login/": {Name: "/login/", Help: "认证", Hand: func(m *ice.Message, arg ...string) { if m.Cmdx(ACCESS, CHECK) == "" { return // 验签失败 @@ -108,5 +106,5 @@ func init() { }}, }, Hand: func(m *ice.Message, arg ...string) { }}, - }}) + }) } diff --git a/misc/wx/menu.go b/misc/wx/menu.go index 9f72b5d8..0fdf28d6 100644 --- a/misc/wx/menu.go +++ b/misc/wx/menu.go @@ -44,17 +44,13 @@ func _wx_action(m *ice.Message) { const MENU = "menu" func init() { - Index.Merge(&ice.Context{Configs: ice.Configs{ - MENU: {Name: MENU, Help: "菜单", Value: kit.Data( - mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,title,refer,image", - )}, - }, Commands: ice.Commands{ + Index.MergeCommands(ice.Commands{ MENU: {Name: "menu zone id auto insert", Help: "菜单", Actions: ice.MergeAction(ice.Actions{ mdb.INSERT: {Name: "insert zone=home title=hi refer=hello image", Help: "添加"}, - }, mdb.ZoneAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,title,refer,image")), Hand: func(m *ice.Message, arg ...string) { if mdb.ZoneSelect(m, arg...); len(arg) > 0 { _wx_action(m) } }}, - }}) + }) } diff --git a/option.go b/option.go index c4cac671..5dde2ba5 100644 --- a/option.go +++ b/option.go @@ -145,11 +145,13 @@ func (m *Message) Status(arg ...Any) { } m.Option(MSG_STATUS, kit.Format(list)) } -func (m *Message) StatusTime(arg ...Any) { +func (m *Message) StatusTime(arg ...Any) *Message { m.Status(TIME, m.Time(), arg, kit.MDB_COST, m.FormatCost()) + return m } -func (m *Message) StatusTimeCount(arg ...Any) { +func (m *Message) StatusTimeCount(arg ...Any) *Message { m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], arg, kit.MDB_COST, m.FormatCost()) + return m } func (m *Message) StatusTimeCountTotal(arg ...Any) { m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], kit.MDB_TOTAL, arg, kit.MDB_COST, m.FormatCost()) diff --git a/render.go b/render.go index 8402c54d..13049d14 100644 --- a/render.go +++ b/render.go @@ -275,6 +275,9 @@ func (m *Message) Display(file string, arg ...Any) *Message { // repos local fil func (m *Message) DisplayStoryJSON(arg ...Any) *Message { // /plugin/story/json.js return m.DisplayStory("json", arg...) } +func (m *Message) DisplayStorySpide(arg ...Any) *Message { // /plugin/story/json.js + return m.DisplayStory("spide", arg...).StatusTimeCount() +} func DisplayBase(file string, arg ...string) Maps { return Maps{DISPLAY: file, STYLE: kit.Join(arg, SP)} diff --git a/type.go b/type.go index 318226cd..75563c08 100644 --- a/type.go +++ b/type.go @@ -7,11 +7,11 @@ import ( "net/http" "path" "strings" - "sync" "sync/atomic" "time" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) type Any = interface{} @@ -69,7 +69,6 @@ type Context struct { begin *Message start *Message - wg *sync.WaitGroup id int32 } @@ -243,7 +242,7 @@ func (c *Context) Begin(m *Message, arg ...string) *Context { c.Caches[CTX_FOLLOW] = &Cache{Name: CTX_FOLLOW, Value: follow} c.Caches[CTX_STATUS] = &Cache{Name: CTX_STATUS, Value: CTX_BEGIN} c.Caches[CTX_STREAM] = &Cache{Name: CTX_STREAM, Value: ""} - m.Log(LOG_BEGIN, c.Cap(CTX_FOLLOW)) + // m.Log(LOG_BEGIN, c.Cap(CTX_FOLLOW)) if c.begin = m; c.server != nil { c.server.Begin(m, arg...) @@ -254,9 +253,11 @@ func (c *Context) Start(m *Message, arg ...string) bool { wait := make(chan bool, 1) defer func() { <-wait }() - m.Hold(1) + _source := m.target.Name + if c.server != nil { + _source = logs.FileLine(c.server.Start, 3) + } m.Go(func() { - defer m.Done(true) m.Log(LOG_START, c.Cap(CTX_FOLLOW)) c.Cap(CTX_STATUS, CTX_START) @@ -265,7 +266,7 @@ func (c *Context) Start(m *Message, arg ...string) bool { if c.start = m; c.server != nil { c.server.Start(m, arg...) } - }) + }, _source) return true } func (c *Context) Close(m *Message, arg ...string) bool { @@ -289,11 +290,13 @@ type Message struct { message *Message root *Message - source *Context - target *Context - _cmd *Command - _key string - _sub string + _source string + _target string + source *Context + target *Context + _cmd *Command + _key string + _sub string cb func(*Message) *Message W http.ResponseWriter @@ -334,6 +337,7 @@ func (m *Message) Spawn(arg ...Any) *Message { time: time.Now(), code: int(m.target.root.ID()), meta: map[string][]string{}, data: Map{}, + _source: m._source, message: m, root: m.root, source: m.target, target: m.target, _cmd: m._cmd, _key: m._key, _sub: m._sub, W: m.W, R: m.R, O: m.O, I: m.I, @@ -392,7 +396,7 @@ func (m *Message) Travel(cb Any) *Message { } m.target = target default: - m.Error(true, ErrNotImplement) + m.ErrorNotImplement(cb) } for _, k := range kit.SortedKey(list[i].Contexts) { // 遍历递进 @@ -429,7 +433,8 @@ func (m *Message) Search(key string, cb Any) *Message { break } } - if m.Warn(p == nil, ErrNotFound, key) { + // if m.Warn(p == nil, ErrNotFound, key) { + if p == nil { return m } key = ls[len(ls)-1] @@ -489,11 +494,22 @@ func (m *Message) Search(key string, cb Any) *Message { case func(p *Context, s *Context): cb(p.context, p) // 查找模块 default: - m.Error(true, ErrNotImplement) + m.ErrorNotImplement(cb) } return m } +func (m *Message) CmdAppend(arg ...string) string { + field := kit.Slice(arg, -1)[0] + return m._command(kit.Slice(arg, 0, -1), OptionFields(field)).Append(field) +} +func (m *Message) CmdMap(arg ...string) map[string]map[string]string { + field, list := kit.Slice(arg, -1)[0], map[string]map[string]string{} + m._command(kit.Slice(arg, 0, -1)).Tables(func(value Maps) { + list[value[field]] = value + }) + return list +} func (m *Message) Cmd(arg ...Any) *Message { return m._command(arg...) }